diff --git a/client/.env.example b/client/.env.example index 6869266..93fa24a 100644 --- a/client/.env.example +++ b/client/.env.example @@ -1 +1 @@ -API_DOMAIN=http://localhost:8000 \ No newline at end of file +VITE_API_URL=http://localhost:8000 \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index 76fdb51..ef23d87 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,6 +11,7 @@ "@hcaptcha/react-hcaptcha": "^1.11.0", "@mantine/notifications": "^7.13.1", "@react-oauth/google": "^0.12.1", + "axios": "^1.7.7", "react": "^18.3.1", "react-dom": "^18.3.1" }, @@ -1499,6 +1500,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -1515,6 +1522,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1610,6 +1628,18 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1753,6 +1783,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", @@ -2296,6 +2335,26 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -2306,6 +2365,20 @@ "is-callable": "^1.1.3" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3122,6 +3195,27 @@ "loose-envify": "cli.js" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3428,6 +3522,12 @@ "react-is": "^16.13.1" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", diff --git a/client/package.json b/client/package.json index e34347d..80e77e5 100644 --- a/client/package.json +++ b/client/package.json @@ -13,6 +13,7 @@ "@hcaptcha/react-hcaptcha": "^1.11.0", "@mantine/notifications": "^7.13.1", "@react-oauth/google": "^0.12.1", + "axios": "^1.7.7", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/client/src/context/userContext.jsx b/client/src/context/userContext.jsx index e4e002b..ee5636d 100644 --- a/client/src/context/userContext.jsx +++ b/client/src/context/userContext.jsx @@ -1,4 +1,5 @@ import { createContext, useState, useEffect } from 'react'; +import axiosInstance from "../utils/axios-instance"; export const UserContext = createContext(); @@ -10,18 +11,23 @@ export const UserProvider = ({ children }) => { useEffect(() => { const checkAuthStatus = async () => { try { - const response = await fetch('/api/auth/status', { - credentials: 'include', // Include cookies if needed + const response = await axiosInstance.get('/api/auth/status', { + withCredentials: true, }); - if (response.ok) { - const data = await response.json(); + console.log(response); + if (response.status === 200) { + const data = response.data; setUser(data); - } - if (!response.ok) { + } else { + console.log('User:'); setUser(null); } } catch (error) { - console.error('Failed to check auth status:', error); + if (error.response.status === 401) { + setUser(null); + } else { + console.error('Failed to check auth status'); + } } finally { setLoading(false); } diff --git a/client/src/features/authentication/services/loginService.js b/client/src/features/authentication/services/loginService.js index 4c8bf32..d03a870 100644 --- a/client/src/features/authentication/services/loginService.js +++ b/client/src/features/authentication/services/loginService.js @@ -1,22 +1,28 @@ +import axiosInstance from "../../../utils/axios-instance"; + export const login = async (username, password) => { try { - const response = await fetch('/api/auth/login', { - method: 'POST', + const response = await axiosInstance.post('/api/auth/login', { + username, + password + }, { headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ username, password }), - credentials: 'include' // Include credentials (cookies) + withCredentials: true }); - - if (response.ok) { + console.log(response.status); + if (response.status === 200) { window.location.href = '/'; } else { - const data = await response.json(); - return data; + return response.data; } } catch (error) { - console.error('There was a problem with the fetch operation:', error); - throw error; + console.error('There was a problem with the axios operation:', error); + if (error.response) { + return error.response.data; + } else { + throw error; + } } -}; +}; \ No newline at end of file diff --git a/client/src/features/authentication/services/registerService.js b/client/src/features/authentication/services/registerService.js index da5a81e..f5d7d81 100644 --- a/client/src/features/authentication/services/registerService.js +++ b/client/src/features/authentication/services/registerService.js @@ -1,22 +1,30 @@ +import axiosInstance from "../../../utils/axios-instance"; + export const register = async (username, email, password, hCaptchaToken) => { try { - const response = await fetch('/api/users', { - method: 'POST', + const response = await axiosInstance.post('/api/users', { + username, + email, + password, + hCaptchaToken + }, { headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ username, email, password, hCaptchaToken }), - credentials: 'include' // Include credentials (cookies) + withCredentials: true }); - if (response.ok) { - return { ok: true, message: 'Registration successful' }; + if (response.status === 201) { + window.location.href = '/'; } else { - const data = await response.json(); - return { ok: false, errors: data.errors }; + return response.data; } } catch (error) { - console.error('There was a problem with the fetch operation:', error); - return { ok: false, errors: [{ path: 'server', msg: 'Server error' }] }; + console.error('There was a problem with the axios operation:', error); + if (error.response) { + return { ok: false, errors: error.response.data.errors }; + } else { + return { ok: false, errors: [{ path: 'server', msg: 'Server error' }] }; + } } }; \ No newline at end of file diff --git a/client/src/pages/home.jsx b/client/src/pages/home.jsx index 7f2705c..bc84727 100644 --- a/client/src/pages/home.jsx +++ b/client/src/pages/home.jsx @@ -2,6 +2,8 @@ import { useContext } from 'react'; import { UserContext } from '../context/userContext'; +import axiosInstance from '../utils/axios-instance'; + const Home = () => { const { user, loading } = useContext(UserContext); @@ -15,12 +17,11 @@ const Home = () => { const handleLogout = async () => { try { - const response = await fetch('/api/auth/logout', { - method: 'POST', - credentials: 'include', // Include cookies if needed + const response = await axiosInstance.post('/api/auth/logout', {}, { + withCredentials: true, }); - if (response.ok) { + if (response.status === 200) { console.log('Logout successful'); window.location.href = '/login'; } else { @@ -39,4 +40,4 @@ const Home = () => { ); }; -export default Home; +export default Home; \ No newline at end of file diff --git a/client/src/utils/axios-instance.js b/client/src/utils/axios-instance.js new file mode 100644 index 0000000..cf97119 --- /dev/null +++ b/client/src/utils/axios-instance.js @@ -0,0 +1,15 @@ +// Proxying only works in dev so i need to do this +import axios from 'axios'; + +const axiosInstance = axios.create({ baseURL: import.meta.env.VITE_API_URL }); +axiosInstance.interceptors.request.use( + config => { + console.log(config); + return config; + }, + error => { + return Promise.reject(error); + } +); + +export default axiosInstance; diff --git a/client/vite.config.js b/client/vite.config.js index 939a6ef..82c19cb 100644 --- a/client/vite.config.js +++ b/client/vite.config.js @@ -2,10 +2,12 @@ import { defineConfig, loadEnv } from 'vite' import react from '@vitejs/plugin-react-swc' -export default defineConfig(({ command, mode }) => { +export default defineConfig(({ mode }) => { // Load env file based on `mode` in the current working directory. // Set the third parameter to '' to load all env regardless of the `VITE_` prefix. + // eslint-disable-next-line no-undef const env = loadEnv(mode, process.cwd(), '') + return { // vite config define: { @@ -13,13 +15,6 @@ export default defineConfig(({ command, mode }) => { }, server: { port: 3000, - proxy: { - '/api': { - target: env.VITE_API_DOMAIN, // should make this an env variable - changeOrigin: true, - secure: env.NODE_ENV === 'production', - }, - }, }, plugins: [react()], } diff --git a/server/src/api/controllers/auth.controller.js b/server/src/api/controllers/auth.controller.js index 524e939..25f39e0 100644 --- a/server/src/api/controllers/auth.controller.js +++ b/server/src/api/controllers/auth.controller.js @@ -10,7 +10,7 @@ function localLogin(req, res) { req.login(user, (err) => { req.session.ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress; req.session.userAgent = req.headers['user-agent']; - return res.status(201).json({ message: 'Logged in successfully via local login' }); + return res.status(200).json({ message: 'Logged in successfully via local login' }); //return res.redirect(`${process.env.FRONTEND_DOMAIN}/`); }); })(req, res);