From 90c5ea3e6e15cc45a1b1c1a55a06a83c67ba7017 Mon Sep 17 00:00:00 2001 From: Andrii Bilous Date: Thu, 14 Nov 2024 12:14:55 +0100 Subject: [PATCH 1/5] initial --- client/Dockerfile | 28 +++++++++++++ client/src/App.js | 5 ++- client/src/components/Header.js | 2 +- client/src/components/RequireAuth.js | 2 +- client/src/pages/ErrorPage.js | 2 +- client/src/pages/Home.js | 2 +- client/src/pages/Login.js | 5 +-- .../pages/SmallBusinessLoan/SubmittedLoan.js | 2 +- .../TrafficTicket/SubmittedTrafficTicket.js | 2 +- docker-compose.yml | 40 +++++++++++++++++++ server/Dockerfile | 20 ++++++++++ server/controllers/jwtController.js | 3 +- server/package-lock.json | 34 +++++++++++++--- server/package.json | 3 +- server/server.js | 37 ++++++++++++++--- 15 files changed, 164 insertions(+), 23 deletions(-) create mode 100644 client/Dockerfile create mode 100644 docker-compose.yml create mode 100644 server/Dockerfile diff --git a/client/Dockerfile b/client/Dockerfile new file mode 100644 index 0000000..1966ddd --- /dev/null +++ b/client/Dockerfile @@ -0,0 +1,28 @@ +# Use a Node.js base image for building +FROM node:20.14 AS builder + +# Set the working directory +WORKDIR /app + +# Copy package.json and package-lock.json +COPY ./package.json ./package-lock.json ./ + +# Install dependencies +RUN npm install + +# Copy source code +COPY . . + +# Pass build-time environment variables (only available during build stage) +ARG REACT_APP_API_URL +ENV REACT_APP_API_URL=$REACT_APP_API_URL + +# Build the frontend app +RUN npm run build + +# Use Nginx to serve the frontend build +FROM nginx:1.23.2-alpine +COPY --from=builder /app/build /usr/share/nginx/html + +# Expose necessary ports +EXPOSE 80 diff --git a/client/src/App.js b/client/src/App.js index f324c13..aa578c8 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -42,8 +42,9 @@ function App() { // populate the app. async function getTextContent() { try { - let response = await axios.get('/assets/text.json'); - + console.log('env',process.env) + const response = await axios.get('http://localhost:5000/assets/text.json'); + console.log('response',response) // Only set states if the component is mounted, otherwise return null. if (!mountedRef.current) return null; diff --git a/client/src/components/Header.js b/client/src/components/Header.js index 2b5ec92..8442a4d 100644 --- a/client/src/components/Header.js +++ b/client/src/components/Header.js @@ -3,7 +3,7 @@ import { Link, useLocation } from 'react-router-dom'; function Header({ text }) { const appName = 'MyGovernment'; - const logoUrl = '/assets/img/logo.svg'; + const logoUrl = 'http://localhost:5000/assets/img/logo.svg'; let location = useLocation(); return ( diff --git a/client/src/components/RequireAuth.js b/client/src/components/RequireAuth.js index 30a0250..b4f30ff 100644 --- a/client/src/components/RequireAuth.js +++ b/client/src/components/RequireAuth.js @@ -19,7 +19,7 @@ function RequireAuth() { async function isLoggedIn() { try { - let response = await axios.get('/auth/isLoggedIn'); + let response = await axios.get(`${process.env.REACT_APP_API_URL}/api/auth/isLoggedIn`); // Only set states if the component is mounted, otherwise return null. if (!mountedRef.current) return null; diff --git a/client/src/pages/ErrorPage.js b/client/src/pages/ErrorPage.js index 0d0da1b..ab96bb6 100644 --- a/client/src/pages/ErrorPage.js +++ b/client/src/pages/ErrorPage.js @@ -21,7 +21,7 @@ function ErrorPage() { )} diff --git a/client/src/pages/Home.js b/client/src/pages/Home.js index e26ef8f..3c3293e 100644 --- a/client/src/pages/Home.js +++ b/client/src/pages/Home.js @@ -17,7 +17,7 @@ function Home({ text, footerText }) { // stored for making Docusign API calls. async function getUserInfo() { try { - let response = await axios.get('/auth/login'); + let response = await axios.get(`${process.env.REACT_APP_API_URL}/api/auth/login`); // If the user revoked consent after logging in, check to make // sure they still have consent diff --git a/client/src/pages/Login.js b/client/src/pages/Login.js index b69ccb9..48bfce0 100644 --- a/client/src/pages/Login.js +++ b/client/src/pages/Login.js @@ -7,7 +7,7 @@ import Popup from '../components/Popup'; function Login({ text, githubText, btsText }) { const [submitted, setSubmitted] = useState(false); const [isOpen, setIsOpen] = useState(false); - const heroUrl = '/assets/img/hero.png'; + const heroUrl = `${process.env.REACT_APP_API_URL}/assets/img/hero.png`; let navigate = useNavigate(); // Logs the user in, and redirects the user to a consent window if @@ -15,8 +15,7 @@ function Login({ text, githubText, btsText }) { async function handleLogin() { try { setSubmitted(true); - - let response = await axios.get('/auth/login'); + let response = await axios.get(`${process.env.REACT_APP_API_URL}/api/auth/login`); // If user has never logged in before, redirect to consent screen if (response.status === 210) { diff --git a/client/src/pages/SmallBusinessLoan/SubmittedLoan.js b/client/src/pages/SmallBusinessLoan/SubmittedLoan.js index 8d9b117..370f36a 100644 --- a/client/src/pages/SmallBusinessLoan/SubmittedLoan.js +++ b/client/src/pages/SmallBusinessLoan/SubmittedLoan.js @@ -25,7 +25,7 @@ function SubmittedLoan({ text }) { // and sets the lender name accordingly. async function getLoanAmount() { try { - let response = await axios.get('/loanApplication/submitted'); + let response = await axios.get('/api/loanApplication/submitted'); // Only set states if the component is mounted, otherwise return null. if (!mountedRef.current) return null; diff --git a/client/src/pages/TrafficTicket/SubmittedTrafficTicket.js b/client/src/pages/TrafficTicket/SubmittedTrafficTicket.js index 3eb38ff..8780ff4 100644 --- a/client/src/pages/TrafficTicket/SubmittedTrafficTicket.js +++ b/client/src/pages/TrafficTicket/SubmittedTrafficTicket.js @@ -33,7 +33,7 @@ function SubmittedTrafficTicket({ text }) { // description of the page accordingly. async function getUserChoice() { try { - let response = await axios.get('/trafficTicket/submitted'); + let response = await axios.get('/api/trafficTicket/submitted'); // Only set states if the component is mounted, otherwise return null. if (!mountedRef.current) return null; diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..347c75d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,40 @@ +version: "3.9" + +services: + backend: + build: + context: ./server + dockerfile: Dockerfile + container_name: my-backend + ports: + - "5000:5000" + env_file: + - ./server/.env + volumes: + - ./server:/app + - ./server/assets/public:/app/assets/public:ro + networks: + - mynetwork + + frontend: + build: + context: ./client + dockerfile: Dockerfile + args: + REACT_APP_API_URL: "http://localhost:5000" + container_name: my-frontend + ports: + - "3000:80" + environment: + - REACT_APP_API_URL=http://localhost:5000 + - REACT_APP_NODE_ENV=development + depends_on: + - backend + env_file: + - ./client/.env + networks: + - mynetwork + +networks: + mynetwork: + driver: bridge diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000..895c4e1 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,20 @@ +# Use a Node.js base image +FROM node:20.14 + +# Set the working directory +WORKDIR /app + +# Copy package.json and package-lock.json +COPY ./package.json ./package-lock.json ./ + +# Install dependencies +RUN npm install + +# Copy the rest of the backend code +COPY . . + +# Expose the backend port +EXPOSE 5000 + +# Run the backend +CMD ["npm", "start"] diff --git a/server/controllers/jwtController.js b/server/controllers/jwtController.js index 84734da..7f3080d 100644 --- a/server/controllers/jwtController.js +++ b/server/controllers/jwtController.js @@ -14,7 +14,7 @@ const oAuth = eSignSdk.ApiClient.OAuth; const restApi = eSignSdk.ApiClient.RestApi; // Constants -const rsaKey = fs.readFileSync(path.resolve(__dirname, '../../private.key')); +const rsaKey = fs.readFileSync(path.resolve(__dirname, '../private.key')); const jwtLifeSec = 60 * 60; // Request lifetime of JWT token is 60 minutes const scopes = 'signature'; @@ -123,6 +123,7 @@ const getUserInfo = async (req) => { * redirected to a login screen. */ const login = async (req, res, next) => { + console.log("Login route reached"); try { // As long as the user has attempted to login before, they have either successfully // logged in or was redirected to the consent URL and then redirected back to the diff --git a/server/package-lock.json b/server/package-lock.json index 3e5249a..6d286a3 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -14,9 +14,10 @@ "concurrently": "^8.2.2", "cookie-parser": "^1.4.6", "cookie-session": "^2.0.0", + "cors": "^2.8.5", "dayjs": "^1.11.10", "docusign-esign": "6.3.0", - "dotenv": "^16.3.1", + "dotenv": "^16.4.5", "express": "^4.19.2", "helmet": "^7.1.0" }, @@ -428,6 +429,19 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/csv-stringify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-1.1.2.tgz", @@ -518,14 +532,15 @@ } }, "node_modules/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" + "url": "https://dotenvx.com" } }, "node_modules/ecdsa-sig-formatter": { @@ -1231,6 +1246,15 @@ "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", diff --git a/server/package.json b/server/package.json index b2714c2..e18610d 100644 --- a/server/package.json +++ b/server/package.json @@ -21,9 +21,10 @@ "concurrently": "^8.2.2", "cookie-parser": "^1.4.6", "cookie-session": "^2.0.0", + "cors": "^2.8.5", "dayjs": "^1.11.10", "docusign-esign": "6.3.0", - "dotenv": "^16.3.1", + "dotenv": "^16.4.5", "express": "^4.19.2", "helmet": "^7.1.0" }, diff --git a/server/server.js b/server/server.js index ef3e1a0..706101e 100644 --- a/server/server.js +++ b/server/server.js @@ -1,6 +1,7 @@ require('dotenv').config({ path: `${process.env.PWD}/.env` }); const path = require('path'); const express = require('express'); +const cors = require('cors'); const cookieParser = require('cookie-parser'); const cookieSession = require('cookie-session'); const bodyParser = require('body-parser'); @@ -17,6 +18,11 @@ const trafficRouter = require('./routes/trafficRouter'); // Max session age const maxSessionAge = 1000 * 60 * 60 * 24 * 1; // One day +const corsOptions = { + origin: 'http://localhost:3000', + credentials: true, +}; + // Configure server const app = express() .use(helmet()) @@ -33,16 +39,30 @@ const app = express() }) ); + app.use(cors()); + + app.use((req, res, next) => { + res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin'); + next(); + }); + + app.use((req, res, next) => { + console.log('Request Origin:', req.headers.origin); + next(); + }); + app.get('/', (req, res) => { res.send('Server started'); res.end(); }); // Routing -app.use('/auth', authRouter); -app.use('/passportApplication', passportRouter); -app.use('/loanApplication', loanRouter); -app.use('/trafficTicket', trafficRouter); +app.use('/api/auth', authRouter); +app.use('/api/passportApplication', passportRouter); +app.use('/api/loanApplication', loanRouter); +app.use('/api/trafficTicket', trafficRouter); + + // Error handler app.use((err, req, res, next) => { @@ -77,12 +97,19 @@ app.use((err, req, res, next) => { } }); + + +console.log('process.env.NODE_ENV',process.env.NODE_ENV) + // Serve static assets if in production if (process.env.NODE_ENV === 'production') { - console.log('In production'); + console.log('Serving static assets from:', path.join(__dirname, 'assets', 'public')); app.use('/assets', express.static(path.join(__dirname, 'assets', 'public'))); } + + + const port = process.env.PORT_NUMBER; app.listen(port, () => { console.log(`Server started and listening on port ${port}`); From bf5a2c0429c4033a0086725f42550fd14c27bc63 Mon Sep 17 00:00:00 2001 From: andriibiloussigma Date: Thu, 14 Nov 2024 14:39:02 +0100 Subject: [PATCH 2/5] rm logs --- client/src/App.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/src/App.js b/client/src/App.js index aa578c8..ca9174c 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -42,9 +42,7 @@ function App() { // populate the app. async function getTextContent() { try { - console.log('env',process.env) const response = await axios.get('http://localhost:5000/assets/text.json'); - console.log('response',response) // Only set states if the component is mounted, otherwise return null. if (!mountedRef.current) return null; From 7ef727d764692aaa60e5e9e4ce8d612c2ed8a789 Mon Sep 17 00:00:00 2001 From: andriibiloussigma Date: Fri, 15 Nov 2024 12:24:14 +0100 Subject: [PATCH 3/5] add request urls --- client/src/App.js | 4 +- client/src/components/BehindTheScenes.js | 4 +- client/src/components/Header.js | 2 +- client/src/pages/Home.js | 6 +- client/src/pages/Passport.js | 4 +- .../SmallBusinessLoan/SmallBusinessLoan.js | 4 +- .../pages/SmallBusinessLoan/SubmittedLoan.js | 8 +- .../TrafficTicket/SubmittedTrafficTicket.js | 6 +- .../src/pages/TrafficTicket/TrafficTicket.js | 4 +- .../pages/TrafficTicket/WitnessStatement.js | 6 +- server/controllers/jwtController.js | 193 +++++++----------- server/server.js | 16 +- 12 files changed, 103 insertions(+), 154 deletions(-) diff --git a/client/src/App.js b/client/src/App.js index ca9174c..e553e29 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -24,6 +24,8 @@ import Header from './components/Header'; import WitnessStatement from './pages/TrafficTicket/WitnessStatement'; import { handleError } from './api/apiHelper'; +axios.defaults.withCredentials = true; + function App() { let mountedRef = useRef(true); const [textContent, setTextContent] = useState(''); @@ -42,7 +44,7 @@ function App() { // populate the app. async function getTextContent() { try { - const response = await axios.get('http://localhost:5000/assets/text.json'); + const response = await axios.get(`${process.env.REACT_APP_API_URL}/assets/text.json`); // Only set states if the component is mounted, otherwise return null. if (!mountedRef.current) return null; diff --git a/client/src/components/BehindTheScenes.js b/client/src/components/BehindTheScenes.js index ace5be0..3e081d9 100644 --- a/client/src/components/BehindTheScenes.js +++ b/client/src/components/BehindTheScenes.js @@ -3,8 +3,8 @@ import parse from 'html-react-parser'; function BehindTheScenes({ title, description }) { const parsedDescription = parse(description); - const upCaretUrl = '/assets/img/up_caret.svg'; - const downCaretUrl = '/assets/img/down_caret.svg'; + const upCaretUrl = `${process.env.REACT_APP_API_URL}/assets/img/up_caret.svg`; + const downCaretUrl = `${process.env.REACT_APP_API_URL}/assets/img/down_caret.svg`; const [showDesc, setShowDesc] = useState(false); return ( diff --git a/client/src/components/Header.js b/client/src/components/Header.js index 8442a4d..700cbf6 100644 --- a/client/src/components/Header.js +++ b/client/src/components/Header.js @@ -3,7 +3,7 @@ import { Link, useLocation } from 'react-router-dom'; function Header({ text }) { const appName = 'MyGovernment'; - const logoUrl = 'http://localhost:5000/assets/img/logo.svg'; + const logoUrl = `${process.env.REACT_APP_API_URL}/assets/img/logo.svg`; let location = useLocation(); return ( diff --git a/client/src/pages/Home.js b/client/src/pages/Home.js index 3c3293e..da27bf6 100644 --- a/client/src/pages/Home.js +++ b/client/src/pages/Home.js @@ -41,7 +41,7 @@ function Home({ text, footerText }) {
{ - // Get API client and set the base paths - const eSignApi = new eSignSdk.ApiClient(); - eSignApi.setOAuthBasePath(oAuthBasePath); - - // Request a JWT token - let results; - - results = await eSignApi.requestJWTUserToken( - process.env.INTEGRATION_KEY, - process.env.USER_ID, - scopes, - rsaKey, - jwtLifeSec - ); - - // Save the access token and the expiration timestamp - const expiresAt = dayjs().add(results.body.expires_in, 's'); // TODO: subtract tokenReplaceMin? - req.session.accessToken = results.body.access_token; - req.session.tokenExpirationTimestamp = expiresAt; + try { + const eSignApi = new eSignSdk.ApiClient(); + eSignApi.setOAuthBasePath(oAuthBasePath); + + const results = await eSignApi.requestJWTUserToken( + process.env.INTEGRATION_KEY, + process.env.USER_ID, + scopes, + rsaKey, + jwtLifeSec + ); + + const expiresAt = dayjs().add(results.body.expires_in, 's'); + req.session.accessToken = results.body.access_token; + req.session.tokenExpirationTimestamp = expiresAt; + } catch (error) { + throw error; + } }; -/** - * Checks to see that the current access token is still valid, and if not, - * updates the token. - * Must be called before every Docusign API call. - */ const checkToken = async (req) => { try { - const noToken = - !req.session.accessToken || !req.session.tokenExpirationTimestamp, - currentTime = dayjs(), - bufferTime = 1; // One minute buffer time - - // Check to see if we have a token or if the token is expired - let needToken = - noToken || - dayjs(req.session.tokenExpirationTimestamp) - .subtract(bufferTime, 'm') - .isBefore(currentTime); - - // Update the token if needed + const noToken = !req.session.accessToken || !req.session.tokenExpirationTimestamp; + const currentTime = dayjs(); + const bufferTime = 1; + + let needToken = noToken || dayjs(req.session.tokenExpirationTimestamp) + .subtract(bufferTime, 'm') + .isBefore(currentTime); + if (needToken) { await getToken(req); } } catch (error) { - if ( - error.response.body.error && - error.response.body.error === 'consent_required' - ) { + if (error.response && error.response.body.error === 'consent_required') { throw new Error('Consent required'); } else { throw error; @@ -83,65 +55,45 @@ const checkToken = async (req) => { } }; -/** - * Gets the account ID, account name, and base path of the user using the access token. - */ const getUserInfo = async (req) => { - // Get API client - const eSignApi = new eSignSdk.ApiClient(), - targetAccountId = process.env.targetAccountId, - baseUriSuffix = '/restapi'; - eSignApi.setOAuthBasePath(oAuthBasePath); - - // Get user info using access token - const results = await eSignApi.getUserInfo(req.session.accessToken); - - let accountInfo; - if (!Boolean(targetAccountId)) { - // Find the default account - accountInfo = results.accounts.find( - (account) => account.isDefault === 'true' - ); - } else { - // Find the matching account - accountInfo = results.accounts.find( - (account) => account.accountId == targetAccountId - ); - } - if (typeof accountInfo === 'undefined') { - throw new Error(`Target account ${targetAccountId} not found!`); - } + try { + const eSignApi = new eSignSdk.ApiClient(); + const targetAccountId = process.env.targetAccountId; + const baseUriSuffix = '/restapi'; + eSignApi.setOAuthBasePath(oAuthBasePath); + + const results = await eSignApi.getUserInfo(req.session.accessToken); - // Save user information in session. - req.session.accountId = accountInfo.accountId; - req.session.basePath = accountInfo.baseUri + baseUriSuffix; + let accountInfo; + if (!Boolean(targetAccountId)) { + accountInfo = results.accounts.find(account => account.isDefault === 'true'); + } else { + accountInfo = results.accounts.find(account => account.accountId == targetAccountId); + } + + if (typeof accountInfo === 'undefined') { + throw new Error(`Target account ${targetAccountId} not found!`); + } + + req.session.accountId = accountInfo.accountId; + req.session.basePath = accountInfo.baseUri + baseUriSuffix; + } catch (error) { + throw error; + } }; -/** - * First checks if there is already a valid access token, updates it if it's expired, - * then gets some user info. If the user has never provided consent, then they are - * redirected to a login screen. - */ const login = async (req, res, next) => { - console.log("Login route reached"); try { - // As long as the user has attempted to login before, they have either successfully - // logged in or was redirected to the consent URL and then redirected back to the - // app. Only set the user to logged out if an unknown error occurred during the - // login process. req.session.isLoggedIn = true; await checkToken(req); await getUserInfo(req); res.status(200).send('Successfully logged in.'); } catch (error) { - // User has not provided consent yet, send the redirect URL to user. if (error.message === 'Consent required') { - let consent_scopes = scopes + '%20impersonation', - consent_url = - `${process.env.DS_OAUTH_SERVER}/oauth/auth?response_type=code&` + - `scope=${consent_scopes}&client_id=${process.env.INTEGRATION_KEY}&` + - `redirect_uri=${process.env.REDIRECT_URI_HOME}`; - + const consent_scopes = scopes + '%20impersonation'; + const consent_url = `${process.env.DS_OAUTH_SERVER}/oauth/auth?response_type=code&` + + `scope=${consent_scopes}&client_id=${process.env.INTEGRATION_KEY}&` + + `redirect_uri=${process.env.REDIRECT_URI_HOME}`; res.status(210).send(consent_url); } else { req.session.isLoggedIn = false; @@ -150,27 +102,22 @@ const login = async (req, res, next) => { } }; -/** - * Logs the user out by destroying the session. - */ const logout = (req, res) => { - req.session = null; - console.log('Successfully logged out!'); - res.status(200).send('Success: you have logged out'); + try { + req.session = null; + res.status(200).send('Success: you have logged out'); + } catch (error) { + res.status(500).send("Error logging out"); + } }; -/** - * Sends back "true" if the user is logged in, false otherwise. - */ const isLoggedIn = (req, res) => { - let isLoggedIn; - if (req.session.isLoggedIn === undefined) { - isLoggedIn = false; - } else { - isLoggedIn = req.session.isLoggedIn; + try { + let isLoggedIn = req.session.isLoggedIn || false; + res.status(200).send(isLoggedIn); + } catch (error) { + res.status(500).send("Error checking login status"); } - - res.status(200).send(isLoggedIn); }; module.exports = { diff --git a/server/server.js b/server/server.js index 706101e..846b6ba 100644 --- a/server/server.js +++ b/server/server.js @@ -23,7 +23,6 @@ const corsOptions = { credentials: true, }; -// Configure server const app = express() .use(helmet()) .use(bodyParser.json()) @@ -32,30 +31,31 @@ const app = express() cookieSession({ name: 'MyGovernmentApp', maxAge: maxSessionAge, - secret: process.env.SESSION_SECRET, + keys: [process.env.SESSION_SECRET], httpOnly: true, - secure: false, // Set to false when testing on localhost, otherwise to "true" + secure: false, sameSite: 'lax', }) ); - app.use(cors()); + app.use(cors(corsOptions)); app.use((req, res, next) => { res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin'); next(); }); - app.use((req, res, next) => { - console.log('Request Origin:', req.headers.origin); - next(); - }); app.get('/', (req, res) => { res.send('Server started'); res.end(); }); +app.get('/check-session', (req, res) => { + console.log('Session data:', req.session); + res.json(req.session); +}); + // Routing app.use('/api/auth', authRouter); app.use('/api/passportApplication', passportRouter); From a6e939a94bef55dd861cd6eb11128a88ba8d23f8 Mon Sep 17 00:00:00 2001 From: andriibiloussigma Date: Mon, 18 Nov 2024 10:27:49 +0100 Subject: [PATCH 4/5] fixes docker-compose --- docker-compose.yml | 7 +------ server/server.js | 5 +++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 347c75d..bcb9fc9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,8 +6,6 @@ services: context: ./server dockerfile: Dockerfile container_name: my-backend - ports: - - "5000:5000" env_file: - ./server/.env volumes: @@ -21,13 +19,10 @@ services: context: ./client dockerfile: Dockerfile args: - REACT_APP_API_URL: "http://localhost:5000" + REACT_APP_API_URL: "http://backend:5000" container_name: my-frontend ports: - "3000:80" - environment: - - REACT_APP_API_URL=http://localhost:5000 - - REACT_APP_NODE_ENV=development depends_on: - backend env_file: diff --git a/server/server.js b/server/server.js index 846b6ba..b258637 100644 --- a/server/server.js +++ b/server/server.js @@ -19,7 +19,7 @@ const trafficRouter = require('./routes/trafficRouter'); const maxSessionAge = 1000 * 60 * 60 * 24 * 1; // One day const corsOptions = { - origin: 'http://localhost:3000', + origin: ['http://frontend:3000', 'http://localhost:3000'], credentials: true, }; @@ -111,6 +111,7 @@ if (process.env.NODE_ENV === 'production') { const port = process.env.PORT_NUMBER; -app.listen(port, () => { +console.log('port on server',port) +app.listen(port,'0.0.0.0', () => { console.log(`Server started and listening on port ${port}`); }); From 21125f1739f16cd0c444e38d7dbabc90cf9b3ed3 Mon Sep 17 00:00:00 2001 From: andriibiloussigma Date: Mon, 18 Nov 2024 10:28:55 +0100 Subject: [PATCH 5/5] fixes docker-compose --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index bcb9fc9..04db379 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,7 +22,7 @@ services: REACT_APP_API_URL: "http://backend:5000" container_name: my-frontend ports: - - "3000:80" + - "80:80" depends_on: - backend env_file: