diff --git a/src/App.tsx b/src/App.tsx index e5cf11ca04b0514606273bed02a369290f0c8fd0..801d8e3a0e8309cf87d3a0c5f54c226dc5920831 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -16,23 +16,22 @@ import { Dashboard } from 'components/AuthUser/Dashboard/Dashboard'; import { isAuthenticated } from 'api/isAuthenticated'; import { muiTheme } from 'App.style'; import { getRole } from 'api/getRole'; +import { withAuthorization } from 'components/Authorization/Authorization'; +import { useRole } from 'hooks/useRole'; +import { useAuth } from 'hooks/useAuth'; + +const Personal = withAuthorization(Dashboard); /** * Entry point of the app. */ export const App: FC = () => { configDjangoCookieName(); - const [role, setRole] = useState(''); - const [isAuth, setIsAuth] = useState<boolean>(false); + const [role, setRole] = useRole(); + const [isAuth, setIsAuth] = useAuth(); const value = { role, setRole, isAuth, setIsAuth }; - useEffect(() => { - // Initialize asking the server if this session is already logged in. - isAuthenticated().then((responseState) => setIsAuth(responseState)); - getRole().then((responseRole) => setRole(responseRole)); - }, [isAuth, role]); - return ( <div data-testid="App"> <ThemeProvider theme={muiTheme}> @@ -42,20 +41,13 @@ export const App: FC = () => { <Route exact path={NonAuthRoutes.home} component={LandingPage} /> <Route path={NonAuthRoutes.auth} component={AuthUser} /> - <PrivateRoute - Component={Dashboard} - path={AuthRoutes.dashboard} - requiredRoles={[Roles.admin, Roles.operator, Roles.senior]} - /> - <PrivateRoute - Component={HomePage} + <Route path={AuthRoutes.dashboard} - requiredRoles={[Roles.admin, Roles.operator, Roles.senior]} - /> - <PrivateRoute - Component={ProfilePage} - path={AuthRoutes.profile} - requiredRoles={[Roles.admin, Roles.operator, Roles.senior]} + render={() => ( + <Personal + allowedRoles={['admin', 'driver', 'senior', 'operator']} + /> + )} /> <Route path={NonAuthRoutes.unauthorized} diff --git a/src/components/AuthUser/AuthUser.tsx b/src/components/AuthUser/AuthUser.tsx index 7388e5924a2842b4e94ac71d78afdb5db273790e..2206e221488202e33fad82d0c84258812c9355f9 100644 --- a/src/components/AuthUser/AuthUser.tsx +++ b/src/components/AuthUser/AuthUser.tsx @@ -1,6 +1,6 @@ import React, { FC } from 'react'; import Container from '@material-ui/core/Container'; -import { Route, useRouteMatch } from 'react-router-dom'; +import { Redirect, Route, useRouteMatch } from 'react-router-dom'; import { AuthRoutes, NonAuthRoutes } from 'api/routes'; import { SignInForm } from 'components/AuthUser/SignInForm/SignInForm'; import { SignUpForm } from 'components/AuthUser/SignUpForm/SignUpForm'; @@ -14,10 +14,7 @@ export const AuthUser: FC = () => { const { path } = useRouteMatch(); return ( <Container maxWidth="sm"> - <RestrictedRoute - path={`${path}${NonAuthRoutes.signIn}`} - Component={SignInForm} - /> + <Route path={`${path}${NonAuthRoutes.signIn}`} component={SignInForm} /> <Route path={`${path}${NonAuthRoutes.signUp}`} component={SignUpForm} /> <Route path={`${path}${AuthRoutes.choseRole}`} component={ChoseRole} /> </Container> diff --git a/src/components/AuthUser/ChoseRole/ChoseRole.md b/src/components/AuthUser/ChoseRole/ChoseRole.md new file mode 100644 index 0000000000000000000000000000000000000000..f62b0c2e7d51d362ed2975ebf07eb9d310f09a93 --- /dev/null +++ b/src/components/AuthUser/ChoseRole/ChoseRole.md @@ -0,0 +1,7 @@ +Chose role. + +``` +const role = ["operator", "driver",]; + +<ChoseRole role={role} /> +``` \ No newline at end of file diff --git a/src/components/AuthUser/ChoseRole/ChoseRole.tsx b/src/components/AuthUser/ChoseRole/ChoseRole.tsx index c6fe0f5025f5c98b0a9cb9bc30b6e084e3f53318..ce2688cef4be323d88f8f1377f84698f6924595f 100644 --- a/src/components/AuthUser/ChoseRole/ChoseRole.tsx +++ b/src/components/AuthUser/ChoseRole/ChoseRole.tsx @@ -12,7 +12,7 @@ import { AuthRoutes } from 'api/routes'; */ export const ChoseRole: FC = () => { const history = useHistory(); - const [userRoles, setUserRoles] = useState<string[]>(['hello', 'world']); + const [userRoles, setUserRoles] = useState<string[]>(['']); const choseAndForward = (role: string): void => { // Set role in the server. diff --git a/src/components/AuthUser/SignInForm/SignInForm.tsx b/src/components/AuthUser/SignInForm/SignInForm.tsx index 528252e4896ebc948ba244a2c676aa25248414b4..8d9d8be38f17394c0182967a94ffea9639102b28 100644 --- a/src/components/AuthUser/SignInForm/SignInForm.tsx +++ b/src/components/AuthUser/SignInForm/SignInForm.tsx @@ -64,8 +64,6 @@ export const SignInForm: FC = () => { } else if (response.data.status === 'role-choice-needed') { history.replace(`${NonAuthRoutes.auth}${AuthRoutes.choseRole}`); } else if (response.data.status === 'success') { - setRole(response.data.role); - setIsAuth(true); history.replace(`${AuthRoutes.dashboard}${AuthRoutes.home}`); } }); diff --git a/src/components/Authorization/Authorization.tsx b/src/components/Authorization/Authorization.tsx index 5cf6d15cea3ac4ccf0c314e8c69a3db13bed78d4..3a03f1f5ba2277ef38873820ac64d62a49f2baf7 100644 --- a/src/components/Authorization/Authorization.tsx +++ b/src/components/Authorization/Authorization.tsx @@ -1,5 +1,20 @@ +import React, { ComponentType, FC, useContext } from 'react'; +import { BlurCircular } from '@material-ui/icons'; +import { NonAuthRoutes } from 'api/routes'; +import { AuthContext } from 'components/AuthUser/AuthContext'; import { Unauthorized } from 'components/NonAuthUser/Unauthorized/Unauthorized'; -import React, { ComponentType, FC } from 'react'; +import { useAuth } from 'hooks/useAuth'; +import { useRole } from 'hooks/useRole'; +import { Redirect } from 'react-router-dom'; + +const HandleIsAuth: FC<{ isAuth: boolean }> = ({ isAuth }) => + isAuth ? ( + <Unauthorized /> + ) : ( + <Redirect + to={{ pathname: `${NonAuthRoutes.auth}${NonAuthRoutes.signIn}` }} + /> + ); interface WithAuthProps { allowedRoles: string[]; @@ -25,14 +40,15 @@ export const withAuthorization = <T extends WithAuthProps = WithAuthProps>( ) => { const { allowedRoles } = props as T; - const role = 'admin'; - const isAuth = true; + const { role, isAuth } = useContext(AuthContext); + + console.log(`ROLE ${role} AUTH ${isAuth}`); // props comes afterwards so the can override the default ones. return allowedRoles.includes(role) && isAuth ? ( <WrappedComponent {...(props as T)} /> ) : ( - <Unauthorized /> + <HandleIsAuth isAuth={isAuth} /> ); }; diff --git a/src/hooks/useAuth.ts b/src/hooks/useAuth.ts new file mode 100644 index 0000000000000000000000000000000000000000..0479313fa68645acd8ff0ef33ff64e1b24e9ee6d --- /dev/null +++ b/src/hooks/useAuth.ts @@ -0,0 +1,28 @@ +import { isAuthenticated } from 'api/isAuthenticated'; +import { useEffect, useState } from 'react'; + +/** + * Custom hook that uses the call is_authenticated. + * {@link isAuthenticated} + * + * @returns {boolean | null} isAuth: true if user is authenticated, false otherwise or null if the request has not finished. + */ +export const useAuth = (): [ + boolean, + React.Dispatch<React.SetStateAction<boolean>>, +] => { + let isMounted = true; + const [isAuth, setIsAuth] = useState<boolean>(false); + useEffect(() => { + isAuthenticated().then((state) => { + if (isMounted) { + setIsAuth(state); + } + }); + + return () => { + isMounted = false; + }; + }, []); + return [isAuth, setIsAuth]; +}; diff --git a/src/hooks/useCookie.ts b/src/hooks/useCookie.ts new file mode 100644 index 0000000000000000000000000000000000000000..d2fc2eaad555d1a00ab5dfefe43a64103d6f5b22 --- /dev/null +++ b/src/hooks/useCookie.ts @@ -0,0 +1,27 @@ +import { fetchCookie } from 'api/fetchCookie'; +import { useCallback, useEffect, useState } from 'react'; + +/** + * Custom hook that return csrf cookie fetched from server. + * + * @return cookie + */ +export const useCookie = (): string => { + const [cookie, setCookie] = useState(''); + + const askCookie = useCallback(() => { + let isMounted = true; + if (isMounted) + fetchCookie().then((cookieResponse) => setCookie(cookieResponse)); + + return () => { + isMounted = false; + }; + }, []); + + useEffect(() => { + askCookie(); + }, [askCookie]); + + return cookie; +}; diff --git a/src/hooks/useRole.ts b/src/hooks/useRole.ts new file mode 100644 index 0000000000000000000000000000000000000000..785a9793d68e38bc9aad578169aa195a0d84f9fc --- /dev/null +++ b/src/hooks/useRole.ts @@ -0,0 +1,24 @@ +import { getRole } from 'api/getRole'; +import { useEffect, useState } from 'react'; + +export const useRole = (): [ + string, + React.Dispatch<React.SetStateAction<string>>, +] => { + const [role, setRole] = useState(''); + + useEffect(() => { + let isMounted = true; + // Initialize asking the server if this session is already logged in. + + getRole().then((responseRole) => { + if (isMounted) { + setRole(responseRole); + } + }); + return () => { + isMounted = false; + }; + }, []); + return [role, setRole]; +};