diff --git a/src/App.tsx b/src/App.tsx index c7452444f0e085704487e1764235f57d4350bc77..9c2a453fd1e9c58ddff27b485f7116ce0fe0bf86 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 e9e5b6f4e3df56ff7d437753e9d5aae9743f20de..9527c02574bf81977345fb59003cd6e2ad9676fa 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 0000000000000000000000000000000000000000..b83511d1f735bae4c735e9f49991241ac2db27fa --- /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 0000000000000000000000000000000000000000..1230e56b9ad91772a34c829e52516b29cc97b6e6 --- /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} /> + ) + } + /> + ); +};