github.com/minio/console@v1.4.1/web-app/src/ProtectedRoutes.tsx (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2021 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 import { useEffect, useState } from "react"; 18 import { Navigate, useLocation } from "react-router-dom"; 19 import useApi from "./screens/Console/Common/Hooks/useApi"; 20 import { ErrorResponseHandler } from "./common/types"; 21 import { ReplicationSite } from "./screens/Console/Configurations/SiteReplication/SiteReplication"; 22 import { useSelector } from "react-redux"; 23 import { SRInfoStateType } from "./types"; 24 import { AppState, useAppDispatch } from "./store"; 25 import LoadingComponent from "./common/LoadingComponent"; 26 import { fetchSession } from "./screens/LoginPage/sessionThunk"; 27 import { setSiteReplicationInfo, setLocationPath } from "./systemSlice"; 28 import { SessionCallStates } from "./screens/Console/consoleSlice.types"; 29 30 interface ProtectedRouteProps { 31 Component: any; 32 } 33 34 const ProtectedRoute = ({ Component }: ProtectedRouteProps) => { 35 const dispatch = useAppDispatch(); 36 37 const userLoggedIn = useSelector((state: AppState) => state.system.loggedIn); 38 const [componentLoading, setComponentLoading] = useState<boolean>(true); 39 const sessionLoadingState = useSelector( 40 (state: AppState) => state.console.sessionLoadingState, 41 ); 42 const anonymousMode = useSelector( 43 (state: AppState) => state.system.anonymousMode, 44 ); 45 const { pathname = "" } = useLocation(); 46 47 const StorePathAndRedirect = () => { 48 localStorage.setItem("redirect-path", pathname); 49 return <Navigate to={{ pathname: `login` }} />; 50 }; 51 52 useEffect(() => { 53 dispatch(setLocationPath(pathname)); 54 }, [dispatch, pathname]); 55 56 useEffect(() => { 57 dispatch(fetchSession()); 58 }, [dispatch]); 59 60 useEffect(() => { 61 if (sessionLoadingState === SessionCallStates.Done) { 62 setComponentLoading(false); 63 } 64 }, [dispatch, sessionLoadingState]); 65 66 const [, invokeSRInfoApi] = useApi( 67 (res: any) => { 68 const { name: curSiteName, enabled = false } = res || {}; 69 70 let siteList = res.site; 71 if (!siteList) { 72 siteList = []; 73 } 74 const isSiteNameInList = siteList.find((si: ReplicationSite) => { 75 return si.name === curSiteName; 76 }); 77 78 const isCurSite = enabled && isSiteNameInList; 79 const siteReplicationDetail: SRInfoStateType = { 80 enabled: enabled, 81 curSite: isCurSite, 82 siteName: isCurSite ? curSiteName : "", 83 }; 84 85 dispatch(setSiteReplicationInfo(siteReplicationDetail)); 86 }, 87 (err: ErrorResponseHandler) => { 88 // we will fail this call silently, but show it on the console 89 console.error(`Error loading site replication status`, err); 90 }, 91 ); 92 93 useEffect(() => { 94 if (userLoggedIn && !componentLoading && !anonymousMode) { 95 invokeSRInfoApi("GET", `api/v1/admin/site-replication`); 96 } 97 // eslint-disable-next-line react-hooks/exhaustive-deps 98 }, [userLoggedIn, componentLoading]); 99 100 // if we're still trying to retrieve user session render nothing 101 if (componentLoading) { 102 return <LoadingComponent />; 103 } 104 105 // redirect user to the right page based on session status 106 return userLoggedIn ? <Component /> : <StorePathAndRedirect />; 107 }; 108 109 export default ProtectedRoute;