From aef9f915be2d58ebd266e4d12723af9e209e1d6f Mon Sep 17 00:00:00 2001 From: gf-rog Date: Wed, 22 Nov 2023 18:06:03 +0100 Subject: [PATCH 1/4] Move types into separate folder --- backend/src/routes/authRoute.ts | 15 +++------------ backend/src/routes/usersRoute.ts | 24 +++++++----------------- backend/src/types/authResponse.ts | 10 ++++++++++ backend/src/types/userResponse.ts | 19 +++++++++++++++++++ 4 files changed, 39 insertions(+), 29 deletions(-) create mode 100644 backend/src/types/authResponse.ts create mode 100644 backend/src/types/userResponse.ts diff --git a/backend/src/routes/authRoute.ts b/backend/src/routes/authRoute.ts index ce5e7788..14da4783 100644 --- a/backend/src/routes/authRoute.ts +++ b/backend/src/routes/authRoute.ts @@ -1,23 +1,14 @@ -import { Router, Request, Response } from "express"; +import { Router, Request } from "express"; import driver from "../driver/driver"; import { generateAccessToken, generateRefreshToken } from "../misc/jwt"; -import { - CustomResponse, - JWTResponse, - AuthResponse, - ErrorResponse, - OkResponse, -} from "../models/Response"; import jwt, { JwtPayload } from "jsonwebtoken"; +import { TokenErrorResponse } from "../types/authResponse"; +import { CustomResponse, OkResponse } from "../models/Response"; const authRouter = Router(); -type TokenErrorResponse = CustomResponse< - JWTResponse | AuthResponse | ErrorResponse ->; - function generateTokens(res: TokenErrorResponse, userId: string) { const token = generateAccessToken(userId); const refreshToken = generateRefreshToken(userId); diff --git a/backend/src/routes/usersRoute.ts b/backend/src/routes/usersRoute.ts index e39285f6..55dd8776 100644 --- a/backend/src/routes/usersRoute.ts +++ b/backend/src/routes/usersRoute.ts @@ -4,19 +4,17 @@ import { Session } from "neo4j-driver"; import chatRouter from "./chatsRoute"; import driver from "../driver/driver"; -import { - CustomResponse, - ErrorResponse, - OkResponse, - UserResponse, - UsersResponse, - FriendsResponse, - UsersSearchResponse, -} from "../models/Response"; import wordToVec from "../misc/wordToVec"; import User from "../models/User"; import { JWTRequest, authenticateToken } from "../misc/jwt"; +import { + FriendsErrorResponse, + OkErrorResponse, + UserErrorResponse, + UsersErrorResponse, + UsersSearchErrorResponse, +} from "../types/userResponse"; const usersRouter = Router(); @@ -39,14 +37,6 @@ async function userExists( return userExistsResult.records[0].get("u").properties as User; } -type UsersErrorResponse = CustomResponse; -type UserErrorResponse = CustomResponse; -type OkErrorResponse = CustomResponse; -type FriendsErrorResponse = CustomResponse; -type UsersSearchErrorResponse = CustomResponse< - UsersSearchResponse | ErrorResponse ->; - usersRouter.get("/", async (_req: Request, res: UsersErrorResponse) => { try { const session = driver.session(); diff --git a/backend/src/types/authResponse.ts b/backend/src/types/authResponse.ts new file mode 100644 index 00000000..3244d3b6 --- /dev/null +++ b/backend/src/types/authResponse.ts @@ -0,0 +1,10 @@ +import { + CustomResponse, + JWTResponse, + AuthResponse, + ErrorResponse, +} from "../models/Response"; + +export type TokenErrorResponse = CustomResponse< + JWTResponse | AuthResponse | ErrorResponse +>; diff --git a/backend/src/types/userResponse.ts b/backend/src/types/userResponse.ts new file mode 100644 index 00000000..f5c1ad53 --- /dev/null +++ b/backend/src/types/userResponse.ts @@ -0,0 +1,19 @@ +import { + CustomResponse, + ErrorResponse, + OkResponse, + UserResponse, + UsersResponse, + FriendsResponse, + UsersSearchResponse, +} from "../models/Response"; + +export type UsersErrorResponse = CustomResponse; +export type UserErrorResponse = CustomResponse; +export type OkErrorResponse = CustomResponse; +export type FriendsErrorResponse = CustomResponse< + FriendsResponse | ErrorResponse +>; +export type UsersSearchErrorResponse = CustomResponse< + UsersSearchResponse | ErrorResponse +>; From 548c242acc86fbb204b388f2744d711d60a16a57 Mon Sep 17 00:00:00 2001 From: gf-rog Date: Wed, 22 Nov 2023 18:10:41 +0100 Subject: [PATCH 2/4] Redirect to /messages on successful login --- frontend/src/components/LoginBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/LoginBox.tsx b/frontend/src/components/LoginBox.tsx index 166017ab..de1e0263 100644 --- a/frontend/src/components/LoginBox.tsx +++ b/frontend/src/components/LoginBox.tsx @@ -25,7 +25,7 @@ function LoginBox() { if (window.history.state && window.history.state.idx > 0) { navigate(-1 as any, { replace: true }); } else { - navigate("/", { replace: true }); + navigate("/messages", { replace: true }); } setLoginMsg("Logging in..."); } From 84e68d561dc79e1c80986b434d95b6dee1bf3f5c Mon Sep 17 00:00:00 2001 From: gf-rog Date: Thu, 23 Nov 2023 12:30:15 +0100 Subject: [PATCH 3/4] Set userID to empty string if not logged in --- frontend/src/helpers/UserProvider.tsx | 23 ++++++++++++++++------- frontend/src/pages/ProfilePage.tsx | 2 +- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/frontend/src/helpers/UserProvider.tsx b/frontend/src/helpers/UserProvider.tsx index 2563fad4..e57028ea 100644 --- a/frontend/src/helpers/UserProvider.tsx +++ b/frontend/src/helpers/UserProvider.tsx @@ -57,15 +57,19 @@ function UserProvider({ children }: { children: React.ReactNode }) { // Try to use refresh token from cookies const refreshTokenStr = Cookies.get("refreshToken"); - if (!refreshTokenStr) return; + if (refreshTokenStr) { + const response = await fetchData("/auth/refresh", "POST", { + headers: { + "Content-Type": "application/json", + }, + }); - const response = await fetchData("/auth/refresh", "POST", { - headers: { - "Content-Type": "application/json", - }, - }); + if (trySetToken(response.token)) { + return; + } + } - trySetToken(response.token); + setUserId(""); }; const login = async (mail: string, password: string) => { @@ -144,10 +148,15 @@ function UserProvider({ children }: { children: React.ReactNode }) { }, [token]); if (firstRefresh.current) { + console.log("FIRST REFRESH"); firstRefresh.current = false; getAccessToken(); } + useEffect(() => { + console.log(userId); + }, [userId]); + return ( { - if (!userId) navigate("/login"); + if (userId === "") navigate("/login"); }, [userId]); return ( From d71d7dadbab68f4febe00a00fc8f4d9853a8c50a Mon Sep 17 00:00:00 2001 From: gf-rog Date: Thu, 23 Nov 2023 12:46:27 +0100 Subject: [PATCH 4/4] Separate user not logged in and unknown state --- frontend/src/components/LoginBox.tsx | 4 ++-- frontend/src/helpers/UserProvider.tsx | 22 +++++++++++++--------- frontend/src/pages/ProfilePage.tsx | 2 +- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/LoginBox.tsx b/frontend/src/components/LoginBox.tsx index de1e0263..b0b09604 100644 --- a/frontend/src/components/LoginBox.tsx +++ b/frontend/src/components/LoginBox.tsx @@ -17,9 +17,9 @@ function LoginBox() { }; useEffect(() => { - if (userId === null) return; + if (userId === undefined) return; - if (userId === "") { + if (userId === null) { setLoginMsg("Bad credentials"); } else { if (window.history.state && window.history.state.idx > 0) { diff --git a/frontend/src/helpers/UserProvider.tsx b/frontend/src/helpers/UserProvider.tsx index e57028ea..0b7fc658 100644 --- a/frontend/src/helpers/UserProvider.tsx +++ b/frontend/src/helpers/UserProvider.tsx @@ -11,9 +11,9 @@ import { fetchData } from "../services/fetchData"; import User from "../models/user.model"; export interface UserContextValue { - userId: string | null; - user: User | null; - setUser: React.Dispatch>; + userId: string | null | undefined; + user: User | null | undefined; + setUser: React.Dispatch>; login: (mail: string, password: string) => Promise; logout: () => Promise; updateUser: () => Promise; @@ -32,8 +32,12 @@ function useUser() { } function UserProvider({ children }: { children: React.ReactNode }) { - const [userId, setUserId] = useState(null); - const [user, setUser] = useState(null); + // userId: + // undefined -> user state is loading + // null -> user not logged in + // string -> user logged in, userID correct + const [userId, setUserId] = useState(undefined); + const [user, setUser] = useState(null); const [token, setToken] = useState(null); const firstRefresh = useRef(true); @@ -69,7 +73,7 @@ function UserProvider({ children }: { children: React.ReactNode }) { } } - setUserId(""); + setUserId(null); }; const login = async (mail: string, password: string) => { @@ -86,7 +90,7 @@ function UserProvider({ children }: { children: React.ReactNode }) { }); if (response.status != "ok") { - setUserId(""); + setUserId(null); return; } @@ -129,6 +133,7 @@ function UserProvider({ children }: { children: React.ReactNode }) { const response = await fetchData(`/users/${user.id}`, "DELETE"); if (response.status === "ok") { + setUserId(null); setUser(null); return true; } @@ -141,14 +146,13 @@ function UserProvider({ children }: { children: React.ReactNode }) { if (token) { const newUserId = (token as any).userId; fetchData(`/users/${newUserId}`, "GET").then((response) => { - setUser(response.user as any); setUserId(newUserId); + setUser(response.user as any); }); } }, [token]); if (firstRefresh.current) { - console.log("FIRST REFRESH"); firstRefresh.current = false; getAccessToken(); } diff --git a/frontend/src/pages/ProfilePage.tsx b/frontend/src/pages/ProfilePage.tsx index 98b3c55c..03e1f01a 100644 --- a/frontend/src/pages/ProfilePage.tsx +++ b/frontend/src/pages/ProfilePage.tsx @@ -31,7 +31,7 @@ function ProfilePage() { }; useEffect(() => { - if (userId === "") navigate("/login"); + if (userId === null) navigate("/login"); }, [userId]); return (