Require accessToken to browse pages

This commit is contained in:
Charles Bochet 2023-04-21 15:36:10 +02:00 committed by Anders Borch
parent 4655544197
commit 049664b98e
8 changed files with 115 additions and 27 deletions

View File

@ -5,6 +5,7 @@ import AuthCallback from './pages/auth/Callback';
import Login from './pages/auth/Login';
import AppLayout from './layout/AppLayout';
import { Routes, Route, Navigate } from 'react-router-dom';
import RequireAuth from './components/auth/RequireAuth';
function App() {
const user = {
@ -25,9 +26,30 @@ function App() {
{
<AppLayout user={user} workspace={workspace}>
<Routes>
<Route path="/" element={<Navigate to="/people" replace />} />
<Route path="/people" element={<People />} />
<Route path="/companies" element={<Companies />} />
<Route
path="/"
element={
<RequireAuth>
<Navigate to="/people" replace />
</RequireAuth>
}
/>
<Route
path="/people"
element={
<RequireAuth>
<People />
</RequireAuth>
}
/>
<Route
path="/companies"
element={
<RequireAuth>
<Companies />
</RequireAuth>
}
/>
<Route path="/auth/callback" element={<AuthCallback />} />
<Route path="/auth/login" element={<Login />} />
</Routes>

View File

@ -0,0 +1,19 @@
import { useNavigate } from 'react-router-dom';
import { useHasAccessToken } from '../../hooks/auth/useHasAccessToken';
import { useEffect } from 'react';
function RequireAuth({ children }: { children: JSX.Element }): JSX.Element {
const hasAccessToken = useHasAccessToken();
const navigate = useNavigate();
useEffect(() => {
if (!hasAccessToken) {
navigate('/auth/login');
}
}, [hasAccessToken, navigate]);
return children;
}
export default RequireAuth;

View File

@ -0,0 +1,17 @@
import { MemoryRouter } from 'react-router-dom';
import RequireAuth from '../RequireAuth';
const component = {
title: 'RequireAuth',
component: RequireAuth,
};
export default component;
export const RequireAuthWithHelloChild = () => (
<MemoryRouter>
<RequireAuth>
<div>Hello</div>
</RequireAuth>
</MemoryRouter>
);

View File

@ -0,0 +1,9 @@
import { render } from '@testing-library/react';
import { RequireAuthWithHelloChild } from '../__stories__/RequireAuth.stories';
it('Checks the Require Auth renders', () => {
const { getAllByText } = render(<RequireAuthWithHelloChild />);
expect(getAllByText('Hello')).toBeTruthy();
});

View File

@ -0,0 +1,32 @@
import { render, waitFor } from '@testing-library/react';
import { useHasAccessToken } from '../useHasAccessToken';
function TestComponent() {
const hasAccessToken = useHasAccessToken();
return (
<div>{hasAccessToken && <div data-testid="has-access-token"></div>}</div>
);
}
test('useHasAccessToken works properly if access token is present', async () => {
localStorage.setItem('accessToken', 'test-access-token');
const { getByTestId } = render(<TestComponent />);
await waitFor(() => {
expect(getByTestId('has-access-token')).toBeDefined();
});
});
test('useHasAccessToken works properly if access token is not present', async () => {
localStorage.removeItem('accessToken');
const { container } = render(<TestComponent />);
await waitFor(() => {
expect(container.firstChild).toBeEmptyDOMElement();
});
});
afterEach(() => {
jest.clearAllMocks();
});

View File

@ -1,25 +1,6 @@
import { render, waitFor } from '@testing-library/react';
import { useRefreshToken } from '../useRefreshToken';
const localStorageMock = (function () {
let store: { [key: string]: string } = {};
return {
getItem: function (key: string) {
return store[key];
},
setItem: function (key: string, value: string) {
store[key] = value.toString();
},
clear: function () {
store = {};
},
removeItem: function (key: string) {
delete store[key];
},
};
})();
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
function TestComponent() {
const { loading } = useRefreshToken();
@ -47,10 +28,11 @@ test('useRefreshToken works properly', async () => {
render(<TestComponent />);
await waitFor(() => {
expect(localStorageMock.getItem('accessToken')).toBe('test-access-token');
expect(localStorage.getItem('accessToken')).toBe('test-access-token');
});
});
afterEach(() => {
jest.clearAllMocks();
localStorage.removeItem('refreshToken');
});

View File

@ -0,0 +1,5 @@
export const useHasAccessToken = () => {
const accessToken = localStorage.getItem('accessToken');
return accessToken ? true : false;
};

View File

@ -1,16 +1,18 @@
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useHasAccessToken } from '../../hooks/auth/useHasAccessToken';
function Login() {
const refreshToken = localStorage.getItem('refreshToken');
const hasAccessToken = useHasAccessToken();
const navigate = useNavigate();
useEffect(() => {
if (!refreshToken) {
if (!hasAccessToken) {
window.location.href =
process.env.REACT_APP_AUTH_URL + '/signin/provider/google' || '';
} else {
navigate('/');
}
navigate('/');
}, [refreshToken, navigate]);
}, [hasAccessToken, navigate]);
return <></>;
}