From f4468d40100a4f68ada484277011e0a721718c65 Mon Sep 17 00:00:00 2001 From: Keannu Bernasol Date: Sun, 19 Nov 2023 16:46:04 +0800 Subject: [PATCH] Added revalidation component to restore previous user sessions --- src/App.tsx | 15 +++++- src/Components/API/API.tsx | 53 ++++++++++++++++++++-- src/Components/Header/Header.tsx | 16 +------ src/Components/Revalidator/Revalidator.tsx | 39 ++++++++++++++++ 4 files changed, 103 insertions(+), 20 deletions(-) create mode 100644 src/Components/Revalidator/Revalidator.tsx diff --git a/src/App.tsx b/src/App.tsx index d25be6c..15f25b2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -8,17 +8,28 @@ import { ToastContainer } from "react-toastify"; import "react-toastify/dist/ReactToastify.css"; import ErrorPage from "./Pages/ErrorPage/ErrorPage"; import DashboardPage from "./Pages/DashboardPage/DashboardPage"; +import Revalidator from "./Components/Revalidator/Revalidator"; const queryClient = new QueryClient(); const router = createHashRouter([ { path: "/", - element: , + element: ( + <> + + + + ), errorElement: , }, { path: "/dashboard", - element: , + element: ( + <> + + + + ), errorElement: , }, ]); diff --git a/src/Components/API/API.tsx b/src/Components/API/API.tsx index b92b7f2..93e20cc 100644 --- a/src/Components/API/API.tsx +++ b/src/Components/API/API.tsx @@ -1,10 +1,40 @@ +/* eslint-disable react-refresh/only-export-components */ import axios from "axios"; import { ActivationType, LoginType, RegisterType } from "../Types/Types"; -// Product APIs const instance = axios.create({ baseURL: "http://localhost:8000/", }); +// Token Handling +export async function getAccessToken() { + const accessToken = await localStorage.getItem("access_token"); + return accessToken; +} + +export async function getRefreshToken() { + const refreshToken = await localStorage.getItem("refresh_token"); + return refreshToken; +} + +export async function setAccessToken(access: string) { + await localStorage.setItem("access_token", access); + return true; +} + +export async function setRefreshToken(refresh: string) { + await localStorage.setItem("refresh_token", refresh); + return true; +} + +// Header Config Template for REST +export async function GetConfig() { + const accessToken = await getAccessToken(); + return { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }; +} // User APIs @@ -25,7 +55,10 @@ export function LoginAPI(user: LoginType) { return instance .post("api/v1/accounts/jwt/create/", user) .then(async (response) => { - localStorage.setItem("token", JSON.stringify(response.data.auth_token)); + console.log(response.data); + setAccessToken(response.data.access); + setRefreshToken(response.data.refresh); + console.log("Login Success "); return true; }) @@ -35,6 +68,21 @@ export function LoginAPI(user: LoginType) { }); } +export async function JWTRefreshAPI() { + const refresh = await getRefreshToken(); + return instance + .post("api/v1/accounts/jwt/refresh/", { + refresh: refresh, + }) + .then(async (response) => { + setAccessToken(response.data.access); + return true; + }) + .catch(() => { + return false; + }); +} + export function UserAPI() { const token = JSON.parse(localStorage.getItem("token") || "{}"); return instance @@ -44,7 +92,6 @@ export function UserAPI() { }, }) .then((response) => { - console.log(response.data); return response.data; }) .catch(() => { diff --git a/src/Components/Header/Header.tsx b/src/Components/Header/Header.tsx index 424e57d..b650641 100644 --- a/src/Components/Header/Header.tsx +++ b/src/Components/Header/Header.tsx @@ -1,28 +1,14 @@ -import { useEffect, useState } from "react"; +import { useState } from "react"; import styles, { colors } from "../../styles"; import MenuIcon from "@mui/icons-material/Menu"; import SidebarModal from "../SidebarModal/SidebarModal"; import { Drawer } from "@mui/material"; -import { useSelector } from "react-redux"; -import { RootState } from "../Plugins/Redux/Store/Store"; -import { useNavigate } from "react-router-dom"; - export interface props { label: string; } export default function Header(props: props) { const [SidebarOpen, SetSidebarOpen] = useState(false); - const authenticated = useSelector((state: RootState) => state.auth.value); - const navigate = useNavigate(); - - useEffect(() => { - if (!authenticated) { - navigate("/"); - console.log("Not logged in. Redirecting to landing page"); - } - }, [authenticated, navigate]); - return (
state.auth.value); + const [rechecked, setRechecked] = useState(false); + + useEffect(() => { + if (!authenticated && rechecked) { + navigate("/"); + console.log("Not logged in"); + } + }, [authenticated, navigate, rechecked]); + + useEffect(() => { + if (!authenticated) { + JWTRefreshAPI().then(async (response) => { + if (response) { + await dispatch(auth_toggle()); + navigate("/dashboard"); + console.log("User session restored"); + } else { + await setRefreshToken(""); + await setAccessToken(""); + console.log("User session expired"); + } + setRechecked(true); + }); + } + }, []); + + return <>; +}