From f68c61c0ec0643ba3034ecc7d40c22197abf32c9 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Tue, 24 Sep 2024 23:50:55 +0530 Subject: [PATCH 01/56] feat: generate api key --- server/src/api/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 server/src/api/index.ts diff --git a/server/src/api/index.ts b/server/src/api/index.ts new file mode 100644 index 00000000..33680bcb --- /dev/null +++ b/server/src/api/index.ts @@ -0,0 +1,6 @@ +const genAPIKey = () => { + //create a base-36 string that contains 30 chars in a-z,0-9 + return [...Array(30)] + .map((e) => ((Math.random() * 36) | 0).toString(36)) + .join(''); + }; \ No newline at end of file From 61d65b1e2692c7333c56c918c766131c8b2e0833 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Tue, 24 Sep 2024 23:51:36 +0530 Subject: [PATCH 02/56] chore: lint --- server/src/api/index.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/server/src/api/index.ts b/server/src/api/index.ts index 33680bcb..e1e4e5a4 100644 --- a/server/src/api/index.ts +++ b/server/src/api/index.ts @@ -1,6 +1,5 @@ const genAPIKey = () => { - //create a base-36 string that contains 30 chars in a-z,0-9 return [...Array(30)] - .map((e) => ((Math.random() * 36) | 0).toString(36)) - .join(''); - }; \ No newline at end of file + .map((e) => ((Math.random() * 36) | 0).toString(36)) + .join(''); +}; \ No newline at end of file From c6564fbf008772c8dd949efc17f871430eeed551 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 11:07:09 +0530 Subject: [PATCH 03/56] chore: lint --- server/src/server.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/server.ts b/server/src/server.ts index 849ef834..6b112e9b 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -41,12 +41,12 @@ app.use('/auth', auth); app.use('/integration', integration); app.get('/', function (req, res) { - return res.send('Maxun server started 🚀'); + return res.send('Maxun server started 🚀'); }); app.get('/csrf-token', (req, res) => { - res.json({ csrfToken: req.csrfToken() }) - }) + res.json({ csrfToken: req.csrfToken() }) +}) server.listen(SERVER_PORT, async () => { await connectDB(); From cbcd54cd3f63000fdf6ef22af07527aacb87ccdf Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 11:24:40 +0530 Subject: [PATCH 04/56] chore(deps): install @types/body-parser body-parser --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index fe5a48f9..0daed06c 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@testing-library/react": "^13.1.1", "@testing-library/user-event": "^13.5.0", "@types/bcrypt": "^5.0.2", + "@types/body-parser": "^1.19.5", "@types/csurf": "^1.11.5", "@types/jest": "^27.4.1", "@types/jsonwebtoken": "^9.0.7", @@ -25,6 +26,7 @@ "@wbr-project/wbr-interpret": "^0.9.3-marketa.1", "axios": "^0.26.0", "bcrypt": "^5.1.1", + "body-parser": "^1.20.3", "buffer": "^6.0.3", "bullmq": "^5.12.15", "cookie-parser": "^1.4.6", From 23e55deec7f41045fa8caaffa04053def3a638c3 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 11:54:04 +0530 Subject: [PATCH 05/56] feat: use body parser --- server/src/server.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/server.ts b/server/src/server.ts index 6b112e9b..01091bdc 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -6,6 +6,7 @@ import { record, workflow, storage, auth, integration } from './routes'; import { BrowserPool } from "./browser-management/classes/BrowserPool"; import logger from './logger'; import { connectDB, syncDB } from './db/config'; +import bodyParser from 'body-parser'; import cookieParser from 'cookie-parser'; import csrf from 'csurf'; import { SERVER_PORT } from "./constants/config"; @@ -30,6 +31,8 @@ export const io = new Server(server); */ export const browserPool = new BrowserPool(); +app.use(bodyParser.json({ limit: '10mb' })) +app.use(bodyParser.urlencoded({ extended: true, limit: '10mb', parameterLimit: 10000 })); // parse cookies - "cookie" is true in csrfProtection app.use(cookieParser()) app.use(csrfProtection) From 8f52bb28e18184b9f9b8b6d682a8063cd6b89edb Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 12:07:24 +0530 Subject: [PATCH 06/56] refactor: rename to AuthContext --- src/context/auth.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/context/auth.tsx b/src/context/auth.tsx index 1d410f0c..312beeab 100644 --- a/src/context/auth.tsx +++ b/src/context/auth.tsx @@ -19,7 +19,7 @@ const initialState = { user: null, }; -const Context = createContext<{ +const AuthContext = createContext<{ state: InitialStateType; dispatch: any; }>({ @@ -96,8 +96,8 @@ const Provider = ({ children }: ProviderProps) => { }, []); return ( - {children} + {children} ); }; -export { Context, Provider }; +export { AuthContext, Provider }; From 6879260623eee2f284f247bfcc1f846edcc95ecc Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 12:15:38 +0530 Subject: [PATCH 07/56] refactor: rename to AuthProvider --- src/context/auth.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/context/auth.tsx b/src/context/auth.tsx index 312beeab..cffeb924 100644 --- a/src/context/auth.tsx +++ b/src/context/auth.tsx @@ -2,7 +2,7 @@ import { useReducer, createContext, useEffect } from 'react'; import axios from 'axios'; import { useNavigate } from 'react-router-dom'; -interface ProviderProps { +interface AuthProviderProps { children: React.ReactNode; } @@ -44,7 +44,7 @@ const reducer = (state: InitialStateType, action: ActionType) => { } }; -const Provider = ({ children }: ProviderProps) => { +const AuthProvider = ({ children }: AuthProviderProps) => { const [state, dispatch] = useReducer(reducer, initialState); const navigate = useNavigate(); @@ -100,4 +100,4 @@ const Provider = ({ children }: ProviderProps) => { ); }; -export { AuthContext, Provider }; +export { AuthContext, AuthProvider }; From 6a6bc3b81115a3728571499751806bc9f2e0d077 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 13:08:51 +0530 Subject: [PATCH 08/56] feat: register ui --- src/pages/Register.tsx | 115 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/pages/Register.tsx diff --git a/src/pages/Register.tsx b/src/pages/Register.tsx new file mode 100644 index 00000000..0293e27c --- /dev/null +++ b/src/pages/Register.tsx @@ -0,0 +1,115 @@ +import { useState, useContext, useEffect } from 'react'; +import { useNavigate, Link } from 'react-router-dom'; +import axios from 'axios'; +import { AuthContext } from '../context/auth'; +import { TextField, Button, CircularProgress, Typography, Box, Container } from '@mui/material'; +import { useGlobalInfoStore } from "../context/globalInfo"; + +const Register = () => { + const [form, setForm] = useState({ + email: '', + password: '', + }); + const [loading, setLoading] = useState(false); + const { notify } = useGlobalInfoStore(); + const { email, password } = form; + + const { state, dispatch } = useContext(AuthContext); + const { user } = state; + const navigate = useNavigate(); + + useEffect(() => { + if (user !== null) navigate('/'); + }, [user, navigate]); + + const handleChange = (e: any) => { + const { name, value } = e.target; + setForm({ ...form, [name]: value }); + }; + + const submitForm = async (e: any) => { + e.preventDefault(); + setLoading(true); + try { + const { data } = await axios.post('http://localhost:8080/auth/register', { + email, + password, + }); + dispatch({ + type: 'LOGIN', + payload: data, + }); + notify('success', 'Welcome to Maxun!'); + window.localStorage.setItem('user', JSON.stringify(data)); + navigate('/'); + } catch (err: any) { + notify('error', err.response.data.message); + } finally { + setLoading(false); + } + }; + + return ( + + + + Register + + OR + + + + + + Already have an account?{' '} + + Login + + + + + + ); +}; + +export default Register; From 6a9b2f682a82da719999acb36f675d3e9d222266 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 13:09:05 +0530 Subject: [PATCH 09/56] chore: lint --- src/pages/Register.tsx | 198 ++++++++++++++++++++--------------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/src/pages/Register.tsx b/src/pages/Register.tsx index 0293e27c..76571853 100644 --- a/src/pages/Register.tsx +++ b/src/pages/Register.tsx @@ -6,110 +6,110 @@ import { TextField, Button, CircularProgress, Typography, Box, Container } from import { useGlobalInfoStore } from "../context/globalInfo"; const Register = () => { - const [form, setForm] = useState({ - email: '', - password: '', - }); - const [loading, setLoading] = useState(false); - const { notify } = useGlobalInfoStore(); - const { email, password } = form; + const [form, setForm] = useState({ + email: '', + password: '', + }); + const [loading, setLoading] = useState(false); + const { notify } = useGlobalInfoStore(); + const { email, password } = form; - const { state, dispatch } = useContext(AuthContext); - const { user } = state; - const navigate = useNavigate(); + const { state, dispatch } = useContext(AuthContext); + const { user } = state; + const navigate = useNavigate(); - useEffect(() => { - if (user !== null) navigate('/'); - }, [user, navigate]); + useEffect(() => { + if (user !== null) navigate('/'); + }, [user, navigate]); - const handleChange = (e: any) => { - const { name, value } = e.target; - setForm({ ...form, [name]: value }); - }; + const handleChange = (e: any) => { + const { name, value } = e.target; + setForm({ ...form, [name]: value }); + }; - const submitForm = async (e: any) => { - e.preventDefault(); - setLoading(true); - try { - const { data } = await axios.post('http://localhost:8080/auth/register', { - email, - password, - }); - dispatch({ - type: 'LOGIN', - payload: data, - }); - notify('success', 'Welcome to Maxun!'); - window.localStorage.setItem('user', JSON.stringify(data)); - navigate('/'); - } catch (err: any) { - notify('error', err.response.data.message); - } finally { - setLoading(false); - } - }; + const submitForm = async (e: any) => { + e.preventDefault(); + setLoading(true); + try { + const { data } = await axios.post('http://localhost:8080/auth/register', { + email, + password, + }); + dispatch({ + type: 'LOGIN', + payload: data, + }); + notify('success', 'Welcome to Maxun!'); + window.localStorage.setItem('user', JSON.stringify(data)); + navigate('/'); + } catch (err: any) { + notify('error', err.response.data.message); + } finally { + setLoading(false); + } + }; - return ( - - - - Register - - OR - - - - - - Already have an account?{' '} - - Login - - - - - - ); + return ( + + + + Register + + OR + + + + + + Already have an account?{' '} + + Login + + + + + + ); }; export default Register; From 0a99393478e7d1abf699ee26b7b438428fcbb2c2 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 13:16:58 +0530 Subject: [PATCH 10/56] feat: show error msg --- src/pages/Register.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Register.tsx b/src/pages/Register.tsx index 76571853..e3a85943 100644 --- a/src/pages/Register.tsx +++ b/src/pages/Register.tsx @@ -43,7 +43,7 @@ const Register = () => { window.localStorage.setItem('user', JSON.stringify(data)); navigate('/'); } catch (err: any) { - notify('error', err.response.data.message); + notify('error', err.response.data || 'Registration Failed. Please try again.'); } finally { setLoading(false); } From 130945259d63c39318b6bf8f8bcd44e68fb6740f Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 13:19:47 +0530 Subject: [PATCH 11/56] feat: login ui --- src/pages/Login.tsx | 125 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 src/pages/Login.tsx diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx new file mode 100644 index 00000000..7ea8c42b --- /dev/null +++ b/src/pages/Login.tsx @@ -0,0 +1,125 @@ +import axios from 'axios'; +import { useState, useContext, useEffect } from 'react'; +import { useNavigate, Link } from 'react-router-dom'; +import { AuthContext } from '../context/auth'; +import { + Box, + Typography, + TextField, + Button, + CircularProgress, +} from '@mui/material'; +import { useGlobalInfoStore } from "../context/globalInfo"; + +const SignIn = () => { + const [form, setForm] = useState({ + email: '', + password: '', + }); + const [loading, setLoading] = useState(false); + const { notify } = useGlobalInfoStore(); + const { email, password } = form; + + const { state, dispatch } = useContext(AuthContext); + const { user } = state; + + const navigate = useNavigate(); + + useEffect(() => { + if (user) { + navigate('/'); + } + }, [user, navigate]); + + const handleChange = (e: any) => { + const { name, value } = e.target; + setForm({ ...form, [name]: value }); + }; + + const submitForm = async (e: any) => { + e.preventDefault(); + setLoading(true); + try { + const { data } = await axios.post(`/api/login`, { email, password }); + dispatch({ type: 'LOGIN', payload: data }); + notify('success', 'Welcome to Maxun!'); + window.localStorage.setItem('user', JSON.stringify(data)); + navigate('/'); + } catch (err: any) { + notify('error', err.response.data || 'Login Failed. Please try again.'); + setLoading(false); + } + }; + + return ( + + + Login + + + + OR + + + {/* Login Form */} + + + + + + + {/* Redirect to Register */} + + Don’t have an account?{' '} + + Register + + + + + ); +}; + +export default SignIn; From 1117e2836d73bec53bbf4a2b89e0d6166ad73fec Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 13:19:57 +0530 Subject: [PATCH 12/56] chore: lint --- src/pages/Login.tsx | 212 ++++++++++++++++++++++---------------------- 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index 7ea8c42b..cfdb16f2 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -2,124 +2,124 @@ import axios from 'axios'; import { useState, useContext, useEffect } from 'react'; import { useNavigate, Link } from 'react-router-dom'; import { AuthContext } from '../context/auth'; -import { - Box, - Typography, - TextField, - Button, - CircularProgress, +import { + Box, + Typography, + TextField, + Button, + CircularProgress, } from '@mui/material'; import { useGlobalInfoStore } from "../context/globalInfo"; const SignIn = () => { - const [form, setForm] = useState({ - email: '', - password: '', - }); - const [loading, setLoading] = useState(false); - const { notify } = useGlobalInfoStore(); - const { email, password } = form; + const [form, setForm] = useState({ + email: '', + password: '', + }); + const [loading, setLoading] = useState(false); + const { notify } = useGlobalInfoStore(); + const { email, password } = form; - const { state, dispatch } = useContext(AuthContext); - const { user } = state; + const { state, dispatch } = useContext(AuthContext); + const { user } = state; - const navigate = useNavigate(); + const navigate = useNavigate(); - useEffect(() => { - if (user) { - navigate('/'); - } - }, [user, navigate]); + useEffect(() => { + if (user) { + navigate('/'); + } + }, [user, navigate]); - const handleChange = (e: any) => { - const { name, value } = e.target; - setForm({ ...form, [name]: value }); - }; + const handleChange = (e: any) => { + const { name, value } = e.target; + setForm({ ...form, [name]: value }); + }; - const submitForm = async (e: any) => { - e.preventDefault(); - setLoading(true); - try { - const { data } = await axios.post(`/api/login`, { email, password }); - dispatch({ type: 'LOGIN', payload: data }); - notify('success', 'Welcome to Maxun!'); - window.localStorage.setItem('user', JSON.stringify(data)); - navigate('/'); - } catch (err: any) { - notify('error', err.response.data || 'Login Failed. Please try again.'); - setLoading(false); - } - }; + const submitForm = async (e: any) => { + e.preventDefault(); + setLoading(true); + try { + const { data } = await axios.post(`/api/login`, { email, password }); + dispatch({ type: 'LOGIN', payload: data }); + notify('success', 'Welcome to Maxun!'); + window.localStorage.setItem('user', JSON.stringify(data)); + navigate('/'); + } catch (err: any) { + notify('error', err.response.data || 'Login Failed. Please try again.'); + setLoading(false); + } + }; - return ( - - - Login - - - - OR - - - {/* Login Form */} - - - - - + + Login + - {/* Redirect to Register */} - - Don’t have an account?{' '} - - Register - - - - - ); + + OR + + + {/* Login Form */} + + + + + + + {/* Redirect to Register */} + + Don’t have an account?{' '} + + Register + + + + + ); }; export default SignIn; From cec1a97d4e43549ed50557fecd357571743f97e1 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 13:20:25 +0530 Subject: [PATCH 13/56] refactor: rename to Login --- src/pages/Login.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index cfdb16f2..9c7c966b 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -11,7 +11,7 @@ import { } from '@mui/material'; import { useGlobalInfoStore } from "../context/globalInfo"; -const SignIn = () => { +const Login = () => { const [form, setForm] = useState({ email: '', password: '', @@ -122,4 +122,4 @@ const SignIn = () => { ); }; -export default SignIn; +export default Login; From 081ec0f059e0a9d0dbf48f29ca15f7bbeaa1d592 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 13:42:26 +0530 Subject: [PATCH 14/56] feat: wrap in AuthProvider --- src/pages/PageWrappper.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pages/PageWrappper.tsx b/src/pages/PageWrappper.tsx index cf43defb..ab62eb19 100644 --- a/src/pages/PageWrappper.tsx +++ b/src/pages/PageWrappper.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react'; import { NavBar } from "../components/molecules/NavBar"; import { SocketProvider } from "../context/socket"; import { BrowserDimensionsProvider } from "../context/browserDimensions"; +import { AuthProvider } from '../context/auth'; import { RecordingPage } from "./RecordingPage"; import { MainPage } from "./MainPage"; import { useGlobalInfoStore } from "../context/globalInfo"; @@ -50,6 +51,7 @@ export const PageWrapper = () => { return (
+ @@ -69,6 +71,7 @@ export const PageWrapper = () => { + {isNotification() ? Date: Wed, 25 Sep 2024 13:42:39 +0530 Subject: [PATCH 15/56] chore: lint --- src/pages/PageWrappper.tsx | 42 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/pages/PageWrappper.tsx b/src/pages/PageWrappper.tsx index ab62eb19..f77ff063 100644 --- a/src/pages/PageWrappper.tsx +++ b/src/pages/PageWrappper.tsx @@ -51,27 +51,27 @@ export const PageWrapper = () => { return (
- - - - - - } - /> - - - - } - /> - - - - + + + + + + } + /> + + + + } + /> + + + + {isNotification() ? Date: Wed, 25 Sep 2024 13:45:37 +0530 Subject: [PATCH 16/56] fix: login api route --- src/pages/Login.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index 9c7c966b..47452d17 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -40,7 +40,7 @@ const Login = () => { e.preventDefault(); setLoading(true); try { - const { data } = await axios.post(`/api/login`, { email, password }); + const { data } = await axios.post(`http://localhost:8080/auth/login`, { email, password }); dispatch({ type: 'LOGIN', payload: data }); notify('success', 'Welcome to Maxun!'); window.localStorage.setItem('user', JSON.stringify(data)); From 2591bf0a95281e03902a67b5bf12010811612070 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 14:57:40 +0530 Subject: [PATCH 17/56] fix: use data.csrfToken --- src/context/auth.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/context/auth.tsx b/src/context/auth.tsx index cffeb924..9aa1fcbd 100644 --- a/src/context/auth.tsx +++ b/src/context/auth.tsx @@ -88,9 +88,17 @@ const AuthProvider = ({ children }: AuthProviderProps) => { // csrf - include tokens in the axios header every time a request is made useEffect(() => { const getCsrfToken = async () => { - const { data } = await axios.get('http://localhost:8080/csrf-token'); - console.log('CSRFFFFF =>>>>', data); - (axios.defaults.headers as any)['X-CSRF-TOKEN'] = data.getCsrfToken; + try { + const { data } = await axios.get('http://localhost:8080/csrf-token'); + console.log('CSRF Token Response:', data); + if (data && data.csrfToken) { + (axios.defaults.headers as any)['X-CSRF-TOKEN'] = data.csrfToken; + } else { + console.error('CSRF token not found in the response'); + } + } catch (error) { + console.error('Error fetching CSRF token:', error); + } }; getCsrfToken(); }, []); From 688589bfa5cd3460a35f2dec9d4148f2335e525a Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 15:30:55 +0530 Subject: [PATCH 18/56] feat: login & register routes --- src/pages/PageWrappper.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/pages/PageWrappper.tsx b/src/pages/PageWrappper.tsx index f77ff063..a94d9dda 100644 --- a/src/pages/PageWrappper.tsx +++ b/src/pages/PageWrappper.tsx @@ -8,6 +8,8 @@ import { MainPage } from "./MainPage"; import { useGlobalInfoStore } from "../context/globalInfo"; import { getActiveBrowserId } from "../api/recording"; import { AlertSnackbar } from "../components/atoms/AlertSnackbar"; +import Login from './Login'; +import Register from './Register'; import { Routes, Route, useNavigate } from 'react-router-dom'; export const PageWrapper = () => { @@ -68,6 +70,14 @@ export const PageWrapper = () => { } /> + } + /> + } + /> From ebe46ca46822891c5c1a60c1270bc48943b3dd1a Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 15:42:07 +0530 Subject: [PATCH 19/56] feat: user route --- src/routes/userRoute.tsx | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/routes/userRoute.tsx diff --git a/src/routes/userRoute.tsx b/src/routes/userRoute.tsx new file mode 100644 index 00000000..9ca5d3c4 --- /dev/null +++ b/src/routes/userRoute.tsx @@ -0,0 +1,32 @@ +import { useState, useEffect } from 'react'; +import axios from 'axios'; +import { useNavigate } from 'react-router-dom'; +import { useGlobalInfoStore } from "../context/globalInfo"; + +const UserRoute = ({ children }) => { + const [ok, setOk] = useState(true); + const navigate = useNavigate(); + + const { notify } = useGlobalInfoStore(); + useEffect(() => { + fetchUser(); + }, []); + + const fetchUser = async () => { + try { + const { data } = await axios.get('/api/current-user'); + if (data.ok) { + setOk(true); + } + } catch (err: any) { + setOk(false); + notify('error', err.message || 'Please login again to continue'); + navigate('/'); + } + }; + + // Display loading message while fetching user data + return
{!ok ?

Loading...

: <>{children}}
; +}; + +export default UserRoute; From 8baa1288527f00e6117921be4541eff29a3b7343 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 15:43:10 +0530 Subject: [PATCH 20/56] feat: interface UserRouteProps --- src/routes/userRoute.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/routes/userRoute.tsx b/src/routes/userRoute.tsx index 9ca5d3c4..66530baf 100644 --- a/src/routes/userRoute.tsx +++ b/src/routes/userRoute.tsx @@ -1,9 +1,13 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, ReactNode } from 'react'; import axios from 'axios'; import { useNavigate } from 'react-router-dom'; import { useGlobalInfoStore } from "../context/globalInfo"; -const UserRoute = ({ children }) => { +interface UserRouteProps { + children: ReactNode; +} + +const UserRoute: React.FC = ({ children }) => { const [ok, setOk] = useState(true); const navigate = useNavigate(); From 01dc8ade023d901a9256938809d56d4b5204d882 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 15:43:24 +0530 Subject: [PATCH 21/56] chore: lint --- src/routes/userRoute.tsx | 42 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/routes/userRoute.tsx b/src/routes/userRoute.tsx index 66530baf..2ba95c4d 100644 --- a/src/routes/userRoute.tsx +++ b/src/routes/userRoute.tsx @@ -4,33 +4,33 @@ import { useNavigate } from 'react-router-dom'; import { useGlobalInfoStore } from "../context/globalInfo"; interface UserRouteProps { - children: ReactNode; + children: ReactNode; } const UserRoute: React.FC = ({ children }) => { - const [ok, setOk] = useState(true); - const navigate = useNavigate(); + const [ok, setOk] = useState(true); + const navigate = useNavigate(); - const { notify } = useGlobalInfoStore(); - useEffect(() => { - fetchUser(); - }, []); + const { notify } = useGlobalInfoStore(); + useEffect(() => { + fetchUser(); + }, []); - const fetchUser = async () => { - try { - const { data } = await axios.get('/api/current-user'); - if (data.ok) { - setOk(true); - } - } catch (err: any) { - setOk(false); - notify('error', err.message || 'Please login again to continue'); - navigate('/'); - } - }; + const fetchUser = async () => { + try { + const { data } = await axios.get('/api/current-user'); + if (data.ok) { + setOk(true); + } + } catch (err: any) { + setOk(false); + notify('error', err.message || 'Please login again to continue'); + navigate('/'); + } + }; - // Display loading message while fetching user data - return
{!ok ?

Loading...

: <>{children}}
; + // Display loading message while fetching user data + return
{!ok ?

Loading...

: <>{children}}
; }; export default UserRoute; From deaba2cead9b55cc42faad8a5a2e97990b07c688 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 15:57:31 +0530 Subject: [PATCH 22/56] feat: use User Routes --- src/pages/PageWrappper.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/pages/PageWrappper.tsx b/src/pages/PageWrappper.tsx index a94d9dda..9f8086c0 100644 --- a/src/pages/PageWrappper.tsx +++ b/src/pages/PageWrappper.tsx @@ -10,6 +10,7 @@ import { getActiveBrowserId } from "../api/recording"; import { AlertSnackbar } from "../components/atoms/AlertSnackbar"; import Login from './Login'; import Register from './Register'; +import UserRoute from '../routes/userRoute'; import { Routes, Route, useNavigate } from 'react-router-dom'; export const PageWrapper = () => { @@ -60,14 +61,20 @@ export const PageWrapper = () => { } + element={ + + + + } /> + } /> Date: Wed, 25 Sep 2024 15:59:04 +0530 Subject: [PATCH 23/56] chore: lint --- src/pages/PageWrappper.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pages/PageWrappper.tsx b/src/pages/PageWrappper.tsx index 9f8086c0..8c7ebe57 100644 --- a/src/pages/PageWrappper.tsx +++ b/src/pages/PageWrappper.tsx @@ -63,17 +63,17 @@ export const PageWrapper = () => { path="/" element={ - - - } + + + } /> - - - + + + } /> From ce7291e0484f84faab54e41132ef145b349e4b2b Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 15:59:33 +0530 Subject: [PATCH 24/56] feat: return error if !user --- server/src/routes/auth.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index e8d376e0..865e1448 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -72,6 +72,9 @@ router.get('/current-user', async (req: AuthenticatedRequest, res) => { const user = await User.findByPk(req.user.id, { attributes: { exclude: ['password'] }, }); + if (!user) { + return res.status(404).json({ ok: false, error: 'User not found' }); + } return res.status(200).json({ ok: true }); } catch (error: any) { return res.status(500).send(`Could not fetch current user : ${error.message}.`); From 289fa826ccb8990fc9a13491d55e6de0a03f35b9 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 16:00:16 +0530 Subject: [PATCH 25/56] feat: handle !user errors --- src/routes/userRoute.tsx | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/routes/userRoute.tsx b/src/routes/userRoute.tsx index 2ba95c4d..ba7da636 100644 --- a/src/routes/userRoute.tsx +++ b/src/routes/userRoute.tsx @@ -8,29 +8,38 @@ interface UserRouteProps { } const UserRoute: React.FC = ({ children }) => { - const [ok, setOk] = useState(true); + const [ok, setOk] = useState(null); // Use null to indicate loading state const navigate = useNavigate(); - const { notify } = useGlobalInfoStore(); + useEffect(() => { fetchUser(); }, []); const fetchUser = async () => { try { - const { data } = await axios.get('/api/current-user'); + const { data } = await axios.get('http://localhost:8080/auth/current-user'); if (data.ok) { setOk(true); + } else { + setOk(false); + notify('error', data.error || 'Please login again to continue'); + navigate('/login'); } } catch (err: any) { setOk(false); - notify('error', err.message || 'Please login again to continue'); - navigate('/'); + notify('error', err.response?.data?.error || 'An error occurred. Please login again.'); + navigate('/login'); } }; - // Display loading message while fetching user data - return
{!ok ?

Loading...

: <>{children}}
; + // Loading state + if (ok === null) { + return

Loading...

; + } + + // Render children if authenticated + return <>{ok ? children : null}; }; export default UserRoute; From 1f570c04c3765e0c0543ca5a61b00f004f1a166c Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 16:05:08 +0530 Subject: [PATCH 26/56] feat: redirect to login --- src/routes/userRoute.tsx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/routes/userRoute.tsx b/src/routes/userRoute.tsx index ba7da636..711f9e31 100644 --- a/src/routes/userRoute.tsx +++ b/src/routes/userRoute.tsx @@ -8,7 +8,7 @@ interface UserRouteProps { } const UserRoute: React.FC = ({ children }) => { - const [ok, setOk] = useState(null); // Use null to indicate loading state + const [ok, setOk] = useState(true); // Default to true to allow rendering while fetching const navigate = useNavigate(); const { notify } = useGlobalInfoStore(); @@ -22,24 +22,24 @@ const UserRoute: React.FC = ({ children }) => { if (data.ok) { setOk(true); } else { - setOk(false); - notify('error', data.error || 'Please login again to continue'); - navigate('/login'); + handleRedirect(); } } catch (err: any) { - setOk(false); - notify('error', err.response?.data?.error || 'An error occurred. Please login again.'); - navigate('/login'); + handleRedirect(err.response?.data?.error || 'An error occurred. Please login again.'); } }; - // Loading state - if (ok === null) { - return

Loading...

; - } + const handleRedirect = (errorMessage?: string) => { + setOk(false); + if (errorMessage) { + notify('error', errorMessage); + } + navigate('/login'); + }; - // Render children if authenticated + // If ok is true, render the children (protected route) return <>{ok ? children : null}; }; export default UserRoute; + From ecd78e2f0f15beba9985b86c4fa1c14f5a38f39a Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 16:09:23 +0530 Subject: [PATCH 27/56] feat: ensure partial rendering does not happen --- src/routes/userRoute.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/routes/userRoute.tsx b/src/routes/userRoute.tsx index 711f9e31..4a405e9d 100644 --- a/src/routes/userRoute.tsx +++ b/src/routes/userRoute.tsx @@ -8,7 +8,8 @@ interface UserRouteProps { } const UserRoute: React.FC = ({ children }) => { - const [ok, setOk] = useState(true); // Default to true to allow rendering while fetching + const [loading, setLoading] = useState(true); + const [ok, setOk] = useState(false); const navigate = useNavigate(); const { notify } = useGlobalInfoStore(); @@ -26,6 +27,8 @@ const UserRoute: React.FC = ({ children }) => { } } catch (err: any) { handleRedirect(err.response?.data?.error || 'An error occurred. Please login again.'); + } finally { + setLoading(false); // Remove loading state regardless of success or failure } }; @@ -33,13 +36,16 @@ const UserRoute: React.FC = ({ children }) => { setOk(false); if (errorMessage) { notify('error', errorMessage); + } else { + notify('error', 'Please login again to continue'); } navigate('/login'); }; - // If ok is true, render the children (protected route) + // Block rendering if loading the authentication status + if (loading) return null; + return <>{ok ? children : null}; }; export default UserRoute; - From be9697b0776ae53ecc6bb139fef2c3086cda344c Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 16:10:28 +0530 Subject: [PATCH 28/56] fix: revert --- src/routes/userRoute.tsx | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/routes/userRoute.tsx b/src/routes/userRoute.tsx index 4a405e9d..711f9e31 100644 --- a/src/routes/userRoute.tsx +++ b/src/routes/userRoute.tsx @@ -8,8 +8,7 @@ interface UserRouteProps { } const UserRoute: React.FC = ({ children }) => { - const [loading, setLoading] = useState(true); - const [ok, setOk] = useState(false); + const [ok, setOk] = useState(true); // Default to true to allow rendering while fetching const navigate = useNavigate(); const { notify } = useGlobalInfoStore(); @@ -27,8 +26,6 @@ const UserRoute: React.FC = ({ children }) => { } } catch (err: any) { handleRedirect(err.response?.data?.error || 'An error occurred. Please login again.'); - } finally { - setLoading(false); // Remove loading state regardless of success or failure } }; @@ -36,16 +33,13 @@ const UserRoute: React.FC = ({ children }) => { setOk(false); if (errorMessage) { notify('error', errorMessage); - } else { - notify('error', 'Please login again to continue'); } navigate('/login'); }; - // Block rendering if loading the authentication status - if (loading) return null; - + // If ok is true, render the children (protected route) return <>{ok ? children : null}; }; export default UserRoute; + From b55536d8fd0919d0e1ce5377238f0b3521973311 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 16:16:49 +0530 Subject: [PATCH 29/56] feat: send proper response --- server/src/routes/auth.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index 865e1448..8622a72d 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -67,7 +67,7 @@ router.get('/logout', async (req, res) => { router.get('/current-user', async (req: AuthenticatedRequest, res) => { try { if (!req.user) { - return res.status(401).send('Unauthorized'); + return res.status(401).json({ ok: false, error: 'Unauthorized' }); } const user = await User.findByPk(req.user.id, { attributes: { exclude: ['password'] }, @@ -75,8 +75,8 @@ router.get('/current-user', async (req: AuthenticatedRequest, res) => { if (!user) { return res.status(404).json({ ok: false, error: 'User not found' }); } - return res.status(200).json({ ok: true }); + return res.status(200).json({ ok: true, user: user }); } catch (error: any) { - return res.status(500).send(`Could not fetch current user : ${error.message}.`); + return res.status(500).json({ ok: false, error: `Could not fetch current user: ${error.message}` }); } }); \ No newline at end of file From aa72538e881d56210245110a3eb0ecbf76b7e7f1 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 16:25:35 +0530 Subject: [PATCH 30/56] feat: print to console --- server/src/routes/auth.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index 8622a72d..40638414 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -65,18 +65,24 @@ router.get('/logout', async (req, res) => { }) router.get('/current-user', async (req: AuthenticatedRequest, res) => { + console.log('Current user request received'); try { if (!req.user) { + console.log('No user in request'); return res.status(401).json({ ok: false, error: 'Unauthorized' }); } + console.log('Fetching user with id:', req.user.id); const user = await User.findByPk(req.user.id, { attributes: { exclude: ['password'] }, }); if (!user) { + console.log('User not found in database'); return res.status(404).json({ ok: false, error: 'User not found' }); } + console.log('User found, sending response'); return res.status(200).json({ ok: true, user: user }); } catch (error: any) { + console.error('Error in current-user route:', error); return res.status(500).json({ ok: false, error: `Could not fetch current user: ${error.message}` }); } }); \ No newline at end of file From 5911fda391a75024b5a518298bb1257e8f79f5ac Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 16:26:09 +0530 Subject: [PATCH 31/56] feat: time ou --- src/routes/userRoute.tsx | 61 +++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/src/routes/userRoute.tsx b/src/routes/userRoute.tsx index 711f9e31..d53f36cb 100644 --- a/src/routes/userRoute.tsx +++ b/src/routes/userRoute.tsx @@ -8,37 +8,58 @@ interface UserRouteProps { } const UserRoute: React.FC = ({ children }) => { - const [ok, setOk] = useState(true); // Default to true to allow rendering while fetching + const [ok, setOk] = useState(false); + const [loading, setLoading] = useState(true); const navigate = useNavigate(); const { notify } = useGlobalInfoStore(); useEffect(() => { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout + + const fetchUser = async () => { + try { + const { data } = await axios.get('http://localhost:8080/auth/current-user', { + signal: controller.signal + }); + if (data.ok) { + setOk(true); + } else { + handleRedirect('User session expired. Please login again.'); + } + } catch (err: any) { + if (axios.isCancel(err)) { + console.log('Request canceled:', err.message); + handleRedirect('Request timed out. Please try again.'); + } else { + handleRedirect(err.response?.data?.error || 'An error occurred. Please login again.'); + } + } finally { + setLoading(false); + clearTimeout(timeoutId); + } + }; + fetchUser(); + + return () => { + controller.abort(); + clearTimeout(timeoutId); + }; }, []); - const fetchUser = async () => { - try { - const { data } = await axios.get('http://localhost:8080/auth/current-user'); - if (data.ok) { - setOk(true); - } else { - handleRedirect(); - } - } catch (err: any) { - handleRedirect(err.response?.data?.error || 'An error occurred. Please login again.'); - } - }; - - const handleRedirect = (errorMessage?: string) => { + const handleRedirect = (errorMessage: string) => { setOk(false); - if (errorMessage) { - notify('error', errorMessage); - } + setLoading(false); + notify('error', errorMessage); navigate('/login'); }; - // If ok is true, render the children (protected route) - return <>{ok ? children : null}; + if (loading) { + return
Loading...
; + } + + return ok ? <>{children} : null; }; export default UserRoute; From 19150f2800ef876855aaad0523ba6b4696074f38 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 16:31:53 +0530 Subject: [PATCH 32/56] feat: use circular progress --- src/routes/userRoute.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/routes/userRoute.tsx b/src/routes/userRoute.tsx index d53f36cb..b63d74f3 100644 --- a/src/routes/userRoute.tsx +++ b/src/routes/userRoute.tsx @@ -2,6 +2,7 @@ import { useState, useEffect, ReactNode } from 'react'; import axios from 'axios'; import { useNavigate } from 'react-router-dom'; import { useGlobalInfoStore } from "../context/globalInfo"; +import { CircularProgress } from '@mui/material'; interface UserRouteProps { children: ReactNode; @@ -56,7 +57,7 @@ const UserRoute: React.FC = ({ children }) => { }; if (loading) { - return
Loading...
; + return
; } return ok ? <>{children} : null; From dc1a9488e0e90ee54e21d2d5131f4e2ea5135723 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 16:33:34 +0530 Subject: [PATCH 33/56] fix: remove OR --- src/pages/Login.tsx | 6 ------ src/pages/Register.tsx | 1 - 2 files changed, 7 deletions(-) diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index 47452d17..f6927262 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -63,12 +63,6 @@ const Login = () => { Login - - - OR - - - {/* Login Form */} { Register - OR Date: Wed, 25 Sep 2024 16:37:04 +0530 Subject: [PATCH 34/56] feat: error message not mandatory --- src/routes/userRoute.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/routes/userRoute.tsx b/src/routes/userRoute.tsx index b63d74f3..93fff684 100644 --- a/src/routes/userRoute.tsx +++ b/src/routes/userRoute.tsx @@ -33,7 +33,7 @@ const UserRoute: React.FC = ({ children }) => { console.log('Request canceled:', err.message); handleRedirect('Request timed out. Please try again.'); } else { - handleRedirect(err.response?.data?.error || 'An error occurred. Please login again.'); + handleRedirect(); } } finally { setLoading(false); @@ -49,10 +49,12 @@ const UserRoute: React.FC = ({ children }) => { }; }, []); - const handleRedirect = (errorMessage: string) => { + const handleRedirect = (errorMessage?: string) => { setOk(false); setLoading(false); - notify('error', errorMessage); + if (errorMessage) { + notify('error', errorMessage); + } navigate('/login'); }; From 9bb1d715b5747a385b4960eda1861df5b8650847 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 17:01:30 +0530 Subject: [PATCH 35/56] feat: set axios.defaults.withCredentials to true --- src/context/auth.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/context/auth.tsx b/src/context/auth.tsx index 9aa1fcbd..cb5c01df 100644 --- a/src/context/auth.tsx +++ b/src/context/auth.tsx @@ -48,6 +48,7 @@ const AuthProvider = ({ children }: AuthProviderProps) => { const [state, dispatch] = useReducer(reducer, initialState); const navigate = useNavigate(); + axios.defaults.withCredentials = true; // get user info from local storage useEffect(() => { From ec2b5d1174d42a652c98d63413596ae4bbdf23a5 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 17:01:55 +0530 Subject: [PATCH 36/56] feat: pass cors options --- server/src/server.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/src/server.ts b/server/src/server.ts index 01091bdc..503debc1 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -15,7 +15,10 @@ import { Server } from "socket.io"; const csrfProtection = csrf({ cookie: true }) const app = express(); -app.use(cors()); +app.use(cors({ + origin: 'http://localhost:3000', + credentials: true, +})); app.use(express.json()); const server = http.createServer(app); From 42e06a7405d8531f91c35dd783c262c2c2dfd54b Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 17:04:56 +0530 Subject: [PATCH 37/56] feat: welcome msg --- src/pages/Login.tsx | 2 +- src/pages/Register.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index f6927262..53f3d01e 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -61,7 +61,7 @@ const Login = () => { }} > - Login + Welcome Back! { }} > - Register + Create an account Date: Wed, 25 Sep 2024 18:02:29 +0530 Subject: [PATCH 38/56] fix: dotenv config --- server/src/server.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/src/server.ts b/server/src/server.ts index 503debc1..e8abe123 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1,7 +1,8 @@ import express from 'express'; import http from 'http'; import cors from 'cors'; -import 'dotenv/config'; +import dotenv from 'dotenv'; +dotenv.config(); import { record, workflow, storage, auth, integration } from './routes'; import { BrowserPool } from "./browser-management/classes/BrowserPool"; import logger from './logger'; @@ -54,6 +55,9 @@ app.get('/csrf-token', (req, res) => { res.json({ csrfToken: req.csrfToken() }) }) +console.log('Environment Variables:'); +console.log('SECRET:', process.env.JWT_SECRET); + server.listen(SERVER_PORT, async () => { await connectDB(); await syncDB(); From 4931bb6f96f8cbc902fe883f462608253098d7a0 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 18:08:19 +0530 Subject: [PATCH 39/56] feat: use connection string --- server/src/db/config.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/server/src/db/config.ts b/server/src/db/config.ts index 9b2221f2..9d2352e5 100644 --- a/server/src/db/config.ts +++ b/server/src/db/config.ts @@ -2,13 +2,10 @@ import { Sequelize } from 'sequelize'; import dotenv from 'dotenv'; dotenv.config(); - const sequelize = new Sequelize( - process.env.DB_NAME as string, - process.env.DB_USER as string, - process.env.DB_PASSWORD as string, + `postgresql://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`, { - host: process.env.DB_HOST, + host: 'localhost', dialect: 'postgres', logging: false, } From 6bea5a2ad145d4bff040c0878679863a70690e65 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 18:08:35 +0530 Subject: [PATCH 40/56] chore: lint --- server/src/db/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/db/config.ts b/server/src/db/config.ts index 9d2352e5..be1ee123 100644 --- a/server/src/db/config.ts +++ b/server/src/db/config.ts @@ -3,7 +3,7 @@ import dotenv from 'dotenv'; dotenv.config(); const sequelize = new Sequelize( - `postgresql://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`, + `postgresql://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`, { host: 'localhost', dialect: 'postgres', From a6e7e23114f39dd6fdb51c3c84b5d1b9358ef6b3 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 18:15:03 +0530 Subject: [PATCH 41/56] chore: remove log --- server/src/server.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/server/src/server.ts b/server/src/server.ts index e8abe123..0d0512fc 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -55,9 +55,6 @@ app.get('/csrf-token', (req, res) => { res.json({ csrfToken: req.csrfToken() }) }) -console.log('Environment Variables:'); -console.log('SECRET:', process.env.JWT_SECRET); - server.listen(SERVER_PORT, async () => { await connectDB(); await syncDB(); From b528efa75e6176f2b2a58b831a8db8c59f5de2af Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 18:36:12 +0530 Subject: [PATCH 42/56] feat: remove logic for hashing & comparsion from User model --- server/src/models/User.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/server/src/models/User.ts b/server/src/models/User.ts index 67b944b9..f51177a1 100644 --- a/server/src/models/User.ts +++ b/server/src/models/User.ts @@ -15,10 +15,6 @@ class User extends Model implements User public id!: number; public email!: string; public password!: string; - - public async isValidPassword(password: string): Promise { - return comparePassword(password, this.password); - } } User.init( @@ -44,13 +40,6 @@ User.init( { sequelize, tableName: 'user', - hooks: { - beforeCreate: async (user: User) => { - if (user.password) { - user.password = await hashPassword(user.password) as string; - } - }, - }, } ); From 5029f3728df9116c15a35f5e6e24a590837e12b2 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 18:36:28 +0530 Subject: [PATCH 43/56] chorE: remove unused import --- server/src/models/User.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/server/src/models/User.ts b/server/src/models/User.ts index f51177a1..0b92bca2 100644 --- a/server/src/models/User.ts +++ b/server/src/models/User.ts @@ -1,6 +1,5 @@ import { DataTypes, Model, Optional } from 'sequelize'; import sequelize from '../db/config'; -import { hashPassword, comparePassword } from '../utils/auth'; interface UserAttributes { id: number; From 8d29edc6345a3103ac3bb859f1d04940bd196e28 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 18:43:09 +0530 Subject: [PATCH 44/56] feat: set password as string --- server/src/utils/auth.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/utils/auth.ts b/server/src/utils/auth.ts index 4cc45644..8c4be451 100644 --- a/server/src/utils/auth.ts +++ b/server/src/utils/auth.ts @@ -1,6 +1,6 @@ import bcrypt from "bcrypt"; -export const hashPassword = (password: any) => { +export const hashPassword = (password: string) => { return new Promise((resolve, reject) => { bcrypt.genSalt(12, (err, salt) => { if (err) { @@ -17,6 +17,6 @@ export const hashPassword = (password: any) => { } // password from frontend and hash from database -export const comparePassword = (password: any, hash: any) => { +export const comparePassword = (password: string, hash: any) => { return bcrypt.compare(password, hash) } \ No newline at end of file From 037c7b597f8bcd2605c5f2f16f0b2670d43ecaec Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 18:43:43 +0530 Subject: [PATCH 45/56] feat: return Promise { +export const hashPassword = (password: string): Promise => { return new Promise((resolve, reject) => { bcrypt.genSalt(12, (err, salt) => { if (err) { From 2e10b966ed220df47ca36c433637973ba0f4cd4f Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 18:52:03 +0530 Subject: [PATCH 46/56] feat: hashing & comparison --- server/src/routes/auth.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index 40638414..db42eb17 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -1,6 +1,7 @@ import { Router, Request, Response } from 'express'; import User from '../models/User'; import jwt from 'jsonwebtoken'; +import { hashPassword, comparePassword } from '../utils/auth'; export const router = Router(); interface AuthenticatedRequest extends Request { @@ -16,8 +17,10 @@ router.post('/register', async (req, res) => { let userExist = await User.findOne({ where: { email } }); if (userExist) return res.status(400).send('User already exists') + + const hashedPassword = await hashPassword(password) - const user = await User.create({ email, password }); + const user = await User.create({ email, password: hashedPassword }); const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET as string, { expiresIn: '1h' }); user.password = undefined as unknown as string @@ -37,7 +40,9 @@ router.post('/login', async (req, res) => { if (password.length < 6) return res.status(400).send('Password must be at least 6 characters') let user = await User.findOne({ where: { email } }); - const match = await user?.isValidPassword(password); + if (!user) return res.status(400).send('User does not exist'); + + const match = await comparePassword(password, user.password) if (!match) return res.status(400).send('Invalid email or password') const token = jwt.sign({ id: user?.id }, process.env.JWT_SECRET as string, { expiresIn: '1h' }); From af62e91388dc75de34b6c7add4091dc393f9cade Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 19:19:06 +0530 Subject: [PATCH 47/56] ts: define return type --- server/src/utils/auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/utils/auth.ts b/server/src/utils/auth.ts index e853b1ed..96e121f9 100644 --- a/server/src/utils/auth.ts +++ b/server/src/utils/auth.ts @@ -17,6 +17,6 @@ export const hashPassword = (password: string): Promise => { } // password from frontend and hash from database -export const comparePassword = (password: string, hash: any) => { +export const comparePassword = (password: string, hash: string): Promise => { return bcrypt.compare(password, hash) } \ No newline at end of file From 59e563b1617afb373808c90e7f5265f203c15898 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 19:37:05 +0530 Subject: [PATCH 48/56] fix: remove UNSIGNED --- server/src/models/User.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/models/User.ts b/server/src/models/User.ts index 0b92bca2..d5a93a7a 100644 --- a/server/src/models/User.ts +++ b/server/src/models/User.ts @@ -19,7 +19,7 @@ class User extends Model implements User User.init( { id: { - type: DataTypes.INTEGER.UNSIGNED, + type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true, }, From e1846510cd8837bb60bc2d118481d5a5170c6d88 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 19:53:45 +0530 Subject: [PATCH 49/56] feat: set raw:true --- server/src/routes/auth.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index db42eb17..ddb77d40 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -39,9 +39,11 @@ router.post('/login', async (req, res) => { if (!email || !password) return res.status(400).send('Email and password are required') if (password.length < 6) return res.status(400).send('Password must be at least 6 characters') - let user = await User.findOne({ where: { email } }); + let user = await User.findOne({raw: true, where: { email } }); if (!user) return res.status(400).send('User does not exist'); + console.log('User found:', user.email, user.password); + const match = await comparePassword(password, user.password) if (!match) return res.status(400).send('Invalid email or password') @@ -57,6 +59,7 @@ router.post('/login', async (req, res) => { res.json(user) } catch (error: any) { res.status(400).send(`Could not login user - ${error.message}`) + console.log(`Could not login user - ${error}`) } }) From 7106115dda890321f34f717861cc6a694d36a25d Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 19:56:39 +0530 Subject: [PATCH 50/56] chore: remove console.log --- server/src/routes/auth.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index ddb77d40..2aa217e2 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -42,8 +42,6 @@ router.post('/login', async (req, res) => { let user = await User.findOne({raw: true, where: { email } }); if (!user) return res.status(400).send('User does not exist'); - console.log('User found:', user.email, user.password); - const match = await comparePassword(password, user.password) if (!match) return res.status(400).send('Invalid email or password') From 97cb817311ff26ca592dd4e7ca8c2fb9e98aeac0 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 20:27:56 +0530 Subject: [PATCH 51/56] feat: logout button --- src/components/molecules/NavBar.tsx | 33 +++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 15508942..e42a615a 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -1,4 +1,5 @@ -import React from 'react'; +import React, { useState, useContext } from 'react'; +import axios from 'axios'; import styled from "styled-components"; import { stopRecording } from "../../api/recording"; import { useGlobalInfoStore } from "../../context/globalInfo"; @@ -7,7 +8,8 @@ import { RecordingIcon } from "../atoms/RecorderIcon"; import { SaveRecording } from "./SaveRecording"; import { Circle } from "@mui/icons-material"; import MeetingRoomIcon from '@mui/icons-material/MeetingRoom'; -import { useNavigate } from "react-router-dom"; +import { Link, useLocation, useNavigate } from 'react-router-dom'; +import { AuthContext } from '../../context/auth'; interface NavBarProps { newRecording: () => void; @@ -18,8 +20,18 @@ interface NavBarProps { export const NavBar = ({ newRecording, recordingName, isRecording }: NavBarProps) => { const { notify, browserId, setBrowserId, recordingLength } = useGlobalInfoStore(); + const { state, dispatch } = useContext(AuthContext); + const { user } = state; const navigate = useNavigate(); + const logout = async () => { + dispatch({ type: 'LOGOUT' }); + window.localStorage.removeItem('user'); + const { data } = await axios.get('http://localhost:8080/auth/logout'); + notify('success', data.message); + navigate('/login'); + }; + // If recording is in progress, the resources and change page view by setting browserId to null // else it won't affect the page const goToMainMenu = async () => { @@ -94,6 +106,23 @@ export const NavBar = ({ newRecording, recordingName, isRecording }: NavBarProps exit : null} + { + user !== null ? ( + + ) : "" + }
From 784d4f4e9b9aba51337717ee5005cdddfcdfc02c Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 20:51:04 +0530 Subject: [PATCH 52/56] feat: use requireSignIn middleware --- server/src/routes/auth.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index 2aa217e2..b1431c10 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -2,6 +2,7 @@ import { Router, Request, Response } from 'express'; import User from '../models/User'; import jwt from 'jsonwebtoken'; import { hashPassword, comparePassword } from '../utils/auth'; +import { requireSignIn } from '../middlewares/auth'; export const router = Router(); interface AuthenticatedRequest extends Request { @@ -17,7 +18,7 @@ router.post('/register', async (req, res) => { let userExist = await User.findOne({ where: { email } }); if (userExist) return res.status(400).send('User already exists') - + const hashedPassword = await hashPassword(password) const user = await User.create({ email, password: hashedPassword }); @@ -39,7 +40,7 @@ router.post('/login', async (req, res) => { if (!email || !password) return res.status(400).send('Email and password are required') if (password.length < 6) return res.status(400).send('Password must be at least 6 characters') - let user = await User.findOne({raw: true, where: { email } }); + let user = await User.findOne({ raw: true, where: { email } }); if (!user) return res.status(400).send('User does not exist'); const match = await comparePassword(password, user.password) @@ -70,23 +71,19 @@ router.get('/logout', async (req, res) => { } }) -router.get('/current-user', async (req: AuthenticatedRequest, res) => { - console.log('Current user request received'); +router.get('/current-user', requireSignIn, async (req: AuthenticatedRequest, res) => { try { if (!req.user) { - console.log('No user in request'); return res.status(401).json({ ok: false, error: 'Unauthorized' }); } - console.log('Fetching user with id:', req.user.id); const user = await User.findByPk(req.user.id, { attributes: { exclude: ['password'] }, }); if (!user) { - console.log('User not found in database'); return res.status(404).json({ ok: false, error: 'User not found' }); + } else { + return res.status(200).json({ ok: true, user: user }); } - console.log('User found, sending response'); - return res.status(200).json({ ok: true, user: user }); } catch (error: any) { console.error('Error in current-user route:', error); return res.status(500).json({ ok: false, error: `Could not fetch current user: ${error.message}` }); From 5610d3402bc00d89eb265d1315d5dd667db840c1 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 20:51:48 +0530 Subject: [PATCH 53/56] feat: remove signal --- src/routes/userRoute.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/routes/userRoute.tsx b/src/routes/userRoute.tsx index 93fff684..0400c031 100644 --- a/src/routes/userRoute.tsx +++ b/src/routes/userRoute.tsx @@ -20,9 +20,7 @@ const UserRoute: React.FC = ({ children }) => { const fetchUser = async () => { try { - const { data } = await axios.get('http://localhost:8080/auth/current-user', { - signal: controller.signal - }); + const { data } = await axios.get('http://localhost:8080/auth/current-user'); if (data.ok) { setOk(true); } else { @@ -37,7 +35,6 @@ const UserRoute: React.FC = ({ children }) => { } } finally { setLoading(false); - clearTimeout(timeoutId); } }; @@ -45,7 +42,6 @@ const UserRoute: React.FC = ({ children }) => { return () => { controller.abort(); - clearTimeout(timeoutId); }; }, []); From 3b19c5c7e16ecae289beb7d358d6a63e116dcbb4 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 20:52:22 +0530 Subject: [PATCH 54/56] feat: remove abort controller --- src/routes/userRoute.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/routes/userRoute.tsx b/src/routes/userRoute.tsx index 0400c031..d3ae4616 100644 --- a/src/routes/userRoute.tsx +++ b/src/routes/userRoute.tsx @@ -15,9 +15,6 @@ const UserRoute: React.FC = ({ children }) => { const { notify } = useGlobalInfoStore(); useEffect(() => { - const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout - const fetchUser = async () => { try { const { data } = await axios.get('http://localhost:8080/auth/current-user'); @@ -39,10 +36,6 @@ const UserRoute: React.FC = ({ children }) => { }; fetchUser(); - - return () => { - controller.abort(); - }; }, []); const handleRedirect = (errorMessage?: string) => { From 0cf3857423efdfac93dae0aba8f735bfc4d522fa Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 21:20:06 +0530 Subject: [PATCH 55/56] feat: use user from context --- src/routes/userRoute.tsx | 60 +++++----------------------------------- 1 file changed, 7 insertions(+), 53 deletions(-) diff --git a/src/routes/userRoute.tsx b/src/routes/userRoute.tsx index d3ae4616..4e9bb7c2 100644 --- a/src/routes/userRoute.tsx +++ b/src/routes/userRoute.tsx @@ -1,58 +1,12 @@ -import { useState, useEffect, ReactNode } from 'react'; -import axios from 'axios'; -import { useNavigate } from 'react-router-dom'; -import { useGlobalInfoStore } from "../context/globalInfo"; -import { CircularProgress } from '@mui/material'; +import React from 'react'; +import { Navigate, Outlet } from 'react-router-dom'; +import { useContext } from 'react'; +import { AuthContext } from '../context/auth'; -interface UserRouteProps { - children: ReactNode; -} +const UserRoute = () => { + const { state } = useContext(AuthContext); -const UserRoute: React.FC = ({ children }) => { - const [ok, setOk] = useState(false); - const [loading, setLoading] = useState(true); - const navigate = useNavigate(); - const { notify } = useGlobalInfoStore(); - - useEffect(() => { - const fetchUser = async () => { - try { - const { data } = await axios.get('http://localhost:8080/auth/current-user'); - if (data.ok) { - setOk(true); - } else { - handleRedirect('User session expired. Please login again.'); - } - } catch (err: any) { - if (axios.isCancel(err)) { - console.log('Request canceled:', err.message); - handleRedirect('Request timed out. Please try again.'); - } else { - handleRedirect(); - } - } finally { - setLoading(false); - } - }; - - fetchUser(); - }, []); - - const handleRedirect = (errorMessage?: string) => { - setOk(false); - setLoading(false); - if (errorMessage) { - notify('error', errorMessage); - } - navigate('/login'); - }; - - if (loading) { - return
; - } - - return ok ? <>{children} : null; + return state.user ? : ; }; export default UserRoute; - From 7bb5879981ae12876d06742ae64d4d6ac55f2212 Mon Sep 17 00:00:00 2001 From: karishmas6 Date: Wed, 25 Sep 2024 21:20:32 +0530 Subject: [PATCH 56/56] feat: use UserRoute --- src/pages/PageWrappper.tsx | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/src/pages/PageWrappper.tsx b/src/pages/PageWrappper.tsx index 8c7ebe57..975db578 100644 --- a/src/pages/PageWrappper.tsx +++ b/src/pages/PageWrappper.tsx @@ -59,24 +59,16 @@ export const PageWrapper = () => { - - - - } - /> - - - - - - } - /> + }> + } /> + + }> + + + + } /> + }