Skip to content
Snippets Groups Projects
Commit d2d51b7d authored by Defendi Alberto's avatar Defendi Alberto
Browse files

Merge branch 'feature/privateroute/role' into 'dev'

Polished auth flow including ReservedRoute and role selection.

See merge request !45
parents 0d436a47 e7a755a1
No related branches found
No related tags found
2 merge requests!56Refined auth flow and new website pages.,!45Polished auth flow including ReservedRoute and role selection.
Pipeline #12231 passed
import axios from 'axios';
/**
* Ask the server all the roles of an user if the user has multiple roles.
* @returns array of roles.
*/
export const getRoles = async (): Promise<string[]> =>
axios('/api/web/login/get_roles').then((res) => res.data.roles);
import axios from 'axios';
/**
* Set the role of the user in the database.
*/
export const setRole = async (role: string): Promise<void> =>
axios.post('/api/web/login/set_role', { role });
...@@ -7,6 +7,9 @@ import { SignUpForm } from 'components/AuthUser/SignUpForm/SignUpForm'; ...@@ -7,6 +7,9 @@ import { SignUpForm } from 'components/AuthUser/SignUpForm/SignUpForm';
import { ChoseRole } from 'components/AuthUser/ChoseRole/ChoseRole'; import { ChoseRole } from 'components/AuthUser/ChoseRole/ChoseRole';
import { RestrictedRoute } from 'components/RestrictedRoute/RestrictedRoute'; import { RestrictedRoute } from 'components/RestrictedRoute/RestrictedRoute';
/**
* Keeps all components related to SignIn/SignOut logic.
*/
export const AuthUser: FC = () => { export const AuthUser: FC = () => {
const { path } = useRouteMatch(); const { path } = useRouteMatch();
return ( return (
......
import React, { FC, useContext, useEffect, useState } from 'react'; import React, { FC, useEffect, useState } from 'react';
import axios from 'axios';
import Button from '@material-ui/core/Button'; import Button from '@material-ui/core/Button';
import { AuthContext } from '../AuthContext'; import { getRoles } from 'api/getRoles';
import { setRole } from 'api/setRole';
const choseAndForward = (e: unknown): void => { import { useHistory } from 'react-router-dom';
// Do nothing. import { AuthRoutes } from 'api/routes';
};
/** /**
* Screen that let's users decide role between available roles. * Page that let's users decide role between available roles.
* This is intended to use when a user has more than one role. * This is intended to use when a user has more than one role.
* @returns ChoseRole component. * @returns ChoseRole component.
*/ */
export const ChoseRole: FC = () => { export const ChoseRole: FC = () => {
const [userRoles, setUserRoles] = useState<Array<string>>(['']); const history = useHistory();
const [userRoles, setUserRoles] = useState<string[]>(['hello', 'world']);
const choseAndForward = (role: string): void => {
// Set role in the server.
setRole(role);
// Push to homepage.
history.push(`${AuthRoutes.dashboard}${AuthRoutes.home}`);
};
useEffect(() => { useEffect(() => {
const getUserRoles = async (): Promise<unknown> => { getRoles().then((fetchedRoles) => setUserRoles(fetchedRoles));
const response = await axios('/api/web/get_role'); }, []);
setUserRoles(response.data.token);
return null;
};
getUserRoles();
}, [userRoles]);
const { role } = useContext(AuthContext);
return ( return (
<div data-testid="ChoseRole"> <div data-testid="ChoseRole">
<Button {userRoles ? (
variant="outlined" userRoles.map((role) => (
color="default" <Button
onClick={(e) => choseAndForward(e)} variant="outlined"
> color="default"
{role} key={role}
</Button> onClick={() => choseAndForward(role)}
>
{role}
</Button>
))
) : (
<h1>No roles were returned.</h1>
)}
</div> </div>
); );
}; };
...@@ -9,7 +9,7 @@ export const ProfilePage: FC = () => { ...@@ -9,7 +9,7 @@ export const ProfilePage: FC = () => {
const logout = (): void => { const logout = (): void => {
axios axios
.post('/api/web/login/logout') .get('/api/web/login/logout')
.then(() => history.replace(NonAuthRoutes.home)); .then(() => history.replace(NonAuthRoutes.home));
}; };
......
import React, { FC, useContext, useEffect, useState } from 'react'; import React, { FC, useCallback, useContext, useState } from 'react';
import axios from 'axios'; import axios from 'axios';
import { SubmitHandler, useForm } from 'react-hook-form'; import { SubmitHandler, useForm } from 'react-hook-form';
import { Button } from '@material-ui/core'; import { Button } from '@material-ui/core';
import { InputField } from 'components/AuthUser/InputField/InputField'; import { InputField } from 'components/AuthUser/InputField/InputField';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { AuthRoutes } from 'api/routes'; import { AuthRoutes, NonAuthRoutes } from 'api/routes';
import { AuthContext } from 'components/AuthUser/AuthContext'; import { AuthContext } from 'components/AuthUser/AuthContext';
import { fetchCookie } from 'api/fetchCookie'; import { fetchCookie } from 'api/fetchCookie';
import { useStyles } from './useStyles'; import { useStyles } from './useStyles';
...@@ -20,7 +20,7 @@ export const SignInForm: FC = () => { ...@@ -20,7 +20,7 @@ export const SignInForm: FC = () => {
const { setRole, setIsAuth } = useContext(AuthContext); const { setRole, setIsAuth } = useContext(AuthContext);
const [cookie, setCookie] = useState<string>(''); const [cookie, setCookie] = useState<string>('');
useEffect(() => { useCallback(() => {
let isMounted = true; let isMounted = true;
if (isMounted) if (isMounted)
fetchCookie().then((cookieResponse) => setCookie(cookieResponse)); fetchCookie().then((cookieResponse) => setCookie(cookieResponse));
...@@ -61,6 +61,8 @@ export const SignInForm: FC = () => { ...@@ -61,6 +61,8 @@ export const SignInForm: FC = () => {
type: 'server', type: 'server',
message: 'Something went wrong with password', message: 'Something went wrong with password',
}); });
} else if (response.data.status === 'role-choice-needed') {
history.replace(`${NonAuthRoutes.auth}${AuthRoutes.choseRole}`);
} else if (response.data.status === 'success') { } else if (response.data.status === 'success') {
setRole(response.data.role); setRole(response.data.role);
setIsAuth(true); setIsAuth(true);
......
...@@ -4,11 +4,10 @@ import { AuthRoutes } from 'api/routes'; ...@@ -4,11 +4,10 @@ import { AuthRoutes } from 'api/routes';
import { isAuthenticated } from 'api/isAuthenticated'; import { isAuthenticated } from 'api/isAuthenticated';
import { CircularProgress } from '@material-ui/core'; import { CircularProgress } from '@material-ui/core';
/**
*
* */
type Props = { type Props = {
/** Children where the authenticated user will be redirected. */
Component: React.FC<RouteProps>; Component: React.FC<RouteProps>;
/** Path of the children. */
path: string; path: string;
}; };
...@@ -25,19 +24,11 @@ export const RestrictedRoute = ({ Component, path }: Props): JSX.Element => { ...@@ -25,19 +24,11 @@ export const RestrictedRoute = ({ Component, path }: Props): JSX.Element => {
const [isLoading, setLoading] = useState<boolean>(false); const [isLoading, setLoading] = useState<boolean>(false);
useEffect(() => { useEffect(() => {
let isMounted = true; isAuthenticated().then((res) => {
setIsAuth(res);
isAuthenticated().then((state) => { setLoading(true);
if (isMounted) {
setIsAuth(state);
setLoading(true);
}
}); });
}, [isAuth, setLoading]);
return () => {
isMounted = false;
};
}, [isLoading]);
return !isLoading ? ( return !isLoading ? (
<CircularProgress /> <CircularProgress />
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment