From d7531276641a218e49a6707cd5048ff875a8423f Mon Sep 17 00:00:00 2001 From: Alberto Defendi <1369-ahl-berto@users.noreply.gitlab.inf.unibz.it> Date: Thu, 20 May 2021 13:48:22 +0200 Subject: [PATCH] Private/RestrictedRoute to components folder --- src/App.tsx | 2 +- src/components/AuthUser/AuthUser.tsx | 2 +- src/components/PrivateRoute/PrivateRoute.tsx | 54 +++++++++++++++++++ .../RestrictedRoute/RestrictedRoute.tsx | 45 ++++++++++++++++ 4 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 src/components/PrivateRoute/PrivateRoute.tsx create mode 100644 src/components/RestrictedRoute/RestrictedRoute.tsx diff --git a/src/App.tsx b/src/App.tsx index c745244..9c2a453 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,7 +3,7 @@ import { ThemeProvider } from '@material-ui/core/styles'; import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; import { AuthUser } from 'components/AuthUser/AuthUser'; import { LandingPage } from 'components/NonAuthUser/LandingPage/LandingPage'; -import { PrivateRoute } from 'api/PrivateRoute/PrivateRoute'; +import { PrivateRoute } from 'components/PrivateRoute/PrivateRoute'; import { AuthRoutes, NonAuthRoutes } from 'api/routes'; import { NotFound } from 'components/NonAuthUser/NotFound/NotFound'; import { ProfilePage } from 'components/AuthUser/Dashboard/ProfilePage/ProfilePage'; diff --git a/src/components/AuthUser/AuthUser.tsx b/src/components/AuthUser/AuthUser.tsx index e9e5b6f..9527c02 100644 --- a/src/components/AuthUser/AuthUser.tsx +++ b/src/components/AuthUser/AuthUser.tsx @@ -5,7 +5,7 @@ import { AuthRoutes, NonAuthRoutes } from 'api/routes'; import { SignInForm } from 'components/AuthUser/SignInForm/SignInForm'; import { SignUpForm } from 'components/AuthUser/SignUpForm/SignUpForm'; import { ChoseRole } from 'components/AuthUser/ChoseRole/ChoseRole'; -import { RestrictedRoute } from 'api/RestrictedRoute/RestrictedRoute'; +import { RestrictedRoute } from 'components/RestrictedRoute/RestrictedRoute'; export const AuthUser: FC = () => { const { path } = useRouteMatch(); diff --git a/src/components/PrivateRoute/PrivateRoute.tsx b/src/components/PrivateRoute/PrivateRoute.tsx new file mode 100644 index 0000000..b83511d --- /dev/null +++ b/src/components/PrivateRoute/PrivateRoute.tsx @@ -0,0 +1,54 @@ +import React, { useState, useEffect, useContext } from 'react'; +import { Route, Redirect, RouteProps } from 'react-router-dom'; +import { NonAuthRoutes } from 'api/routes'; +import { AuthContext } from 'components/AuthUser/AuthContext'; + +/** + * A wrapper for <Route> that redirects to the login screen if you're not yet authenticated. + * Every non-public route must be wrapped with this component. + * */ +type Props = { + Component: React.FC<RouteProps>; + path: string; + requiredRoles: string[]; +}; + +/* eslint-disable react/jsx-props-no-spreading */ +export const PrivateRoute = ({ + Component, + path, + requiredRoles, +}: Props): JSX.Element => { + const { role, isAuth } = useContext(AuthContext); + + // Check if the role is contained in the roles array (passed as props). + const userHasRequiredRole = requiredRoles.includes(role); + + const message = userHasRequiredRole + ? 'Please log in to view this page' + : 'Your role is not allowed'; + + return ( + <Route + exact={false} + path={path} + render={(props: RouteProps) => + isAuth && userHasRequiredRole ? ( + <Component {...props} /> + ) : ( + <Redirect + to={{ + pathname: !userHasRequiredRole + ? `${NonAuthRoutes.auth}${NonAuthRoutes.signIn}` + : NonAuthRoutes.unauthorized, + state: { + message, + requestedPath: path, + }, + }} + /> + ) + } + /> + ); +}; diff --git a/src/components/RestrictedRoute/RestrictedRoute.tsx b/src/components/RestrictedRoute/RestrictedRoute.tsx new file mode 100644 index 0000000..1230e56 --- /dev/null +++ b/src/components/RestrictedRoute/RestrictedRoute.tsx @@ -0,0 +1,45 @@ +import React, { useState, useEffect, useContext } from 'react'; +import { Route, Redirect, RouteProps } from 'react-router-dom'; +import { AuthRoutes, NonAuthRoutes } from 'api/routes'; +import { isAuthenticated } from 'api/isAuthenticated'; + +/** + * + * */ +type Props = { + Component: React.FC<RouteProps>; + restricted: boolean; + path: string; +}; + +/** + * Wrapper for Route that basing on if the user is authenticated, + * redirects to: + * - Entry point of the private route (the homepage); + * - Login page. + */ + +/* eslint-disable react/jsx-props-no-spreading */ +export const RestrictedRoute = ({ Component, path }: Props): JSX.Element => { + const [authUser, setAuthUser] = useState<boolean>(false); + useEffect(() => { + isAuthenticated(setAuthUser); + }); + + return ( + <Route + path={path} + render={(props: RouteProps) => + authUser ? ( + // Redirect to homepage. + <Redirect + to={{ pathname: `${AuthRoutes.dashboard}${AuthRoutes.home}` }} + /> + ) : ( + // Redirect to component. + <Component {...props} /> + ) + } + /> + ); +}; -- GitLab