From 4a3c957284ea4a53c345b8b20f6d9379c32beffc Mon Sep 17 00:00:00 2001 From: Zhang Minghan Date: Thu, 11 Jan 2024 08:12:56 +0800 Subject: [PATCH] feat: router authentication guards --- app/src/router.tsx | 95 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 14 deletions(-) diff --git a/app/src/router.tsx b/app/src/router.tsx index 3b3943f4..65597cfe 100644 --- a/app/src/router.tsx +++ b/app/src/router.tsx @@ -1,12 +1,19 @@ -import { createBrowserRouter, RouterProvider } from "react-router-dom"; +import { + createBrowserRouter, + RouterProvider, + useLocation, + useNavigate, +} from "react-router-dom"; import Home from "./routes/Home.tsx"; import NotFound from "./routes/NotFound.tsx"; import Auth from "./routes/Auth.tsx"; -import { Suspense } from "react"; +import React, { Suspense, useEffect } from "react"; import { useDeeptrain } from "@/utils/env.ts"; import Register from "@/routes/Register.tsx"; import Forgot from "@/routes/Forgot.tsx"; import { lazyFactor } from "@/utils/loader.tsx"; +import { useSelector } from "react-redux"; +import { selectAdmin, selectAuthenticated } from "@/store/auth.ts"; const Generation = lazyFactor(() => import("@/routes/Generation.tsx")); const Sharing = lazyFactor(() => import("@/routes/Sharing.tsx")); @@ -32,30 +39,44 @@ const router = createBrowserRouter( { id: "login", path: "/login", - Component: Auth, + element: ( + + + + ), ErrorBoundary: NotFound, }, !useDeeptrain && ({ id: "register", path: "/register", - Component: Register, + element: ( + + + + ), ErrorBoundary: NotFound, } as any), !useDeeptrain && ({ id: "forgot", path: "/forgot", - Component: Forgot, + element: ( + + + + ), ErrorBoundary: NotFound, } as any), { id: "generation", path: "/generate", element: ( - - - + + + + + ), ErrorBoundary: NotFound, }, @@ -73,9 +94,11 @@ const router = createBrowserRouter( id: "article", path: "/article", element: ( - -
- + + +
+ + ), ErrorBoundary: NotFound, }, @@ -83,9 +106,11 @@ const router = createBrowserRouter( id: "admin", path: "/admin", element: ( - - - + + + + + ), children: [ { @@ -157,6 +182,48 @@ const router = createBrowserRouter( ].filter(Boolean), ); +export function AuthRequired({ children }: { children: React.ReactNode }) { + const authenticated = useSelector(selectAuthenticated); + const navigate = useNavigate(); + const location = useLocation(); + + useEffect(() => { + if (!authenticated) { + navigate("/login", { state: { from: location.pathname } }); + } + }, [authenticated]); + + return <>{children}; +} + +export function AuthForbidden({ children }: { children: React.ReactNode }) { + const authenticated = useSelector(selectAuthenticated); + const navigate = useNavigate(); + const location = useLocation(); + + useEffect(() => { + if (authenticated) { + navigate("/", { state: { from: location.pathname } }); + } + }, [authenticated]); + + return <>{children}; +} + +export function AdminRequired({ children }: { children: React.ReactNode }) { + const admin = useSelector(selectAdmin); + const navigate = useNavigate(); + const location = useLocation(); + + useEffect(() => { + if (!admin) { + navigate("/", { state: { from: location.pathname } }); + } + }, [admin]); + + return <>{children}; +} + export function AppRouter() { return ; }