mirror of
https://github.com/strapi/strapi.git
synced 2025-08-11 02:07:51 +00:00
parent
5a845afdad
commit
785c4e862e
@ -8,28 +8,34 @@
|
||||
*/
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import { Redirect, Route } from 'react-router-dom';
|
||||
import { Redirect, Route, useLocation } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { auth } from '@strapi/helper-plugin';
|
||||
|
||||
/* eslint-disable react/jsx-curly-newline */
|
||||
|
||||
const PrivateRoute = ({ component: Component, path, ...rest }) => (
|
||||
<Route
|
||||
path={path}
|
||||
render={props =>
|
||||
auth.getToken() !== null ? (
|
||||
<Component {...rest} {...props} />
|
||||
) : (
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: '/auth/login',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
);
|
||||
const PrivateRoute = ({ component: Component, path, ...rest }) => {
|
||||
const { pathname, search } = useLocation();
|
||||
|
||||
return (
|
||||
<Route
|
||||
path={path}
|
||||
render={props =>
|
||||
auth.getToken() !== null ? (
|
||||
<Component {...rest} {...props} />
|
||||
) : (
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: '/auth/login',
|
||||
search:
|
||||
pathname !== '/' && `?redirectTo=${encodeURIComponent(`${pathname}${search}`)}`,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
PrivateRoute.propTypes = {
|
||||
component: PropTypes.any.isRequired,
|
||||
|
@ -0,0 +1,69 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Router, Route, Switch } from 'react-router-dom';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import { auth } from '@strapi/helper-plugin';
|
||||
import PrivateRoute from '..';
|
||||
|
||||
const ProtectedPage = () => {
|
||||
return <div>You are authenticated</div>;
|
||||
};
|
||||
|
||||
const LoginPage = () => {
|
||||
return <div>Please login</div>;
|
||||
};
|
||||
|
||||
const history = createMemoryHistory();
|
||||
|
||||
describe('PrivateRoute', () => {
|
||||
const renderApp = () =>
|
||||
render(
|
||||
<Router history={history}>
|
||||
<Switch>
|
||||
<Route path="/auth/login" component={LoginPage} />
|
||||
<PrivateRoute path="/" component={ProtectedPage} />
|
||||
</Switch>
|
||||
</Router>
|
||||
);
|
||||
|
||||
afterEach(() => {
|
||||
auth.clearToken();
|
||||
});
|
||||
|
||||
it('Authenticated users should be able to access protected routes', async () => {
|
||||
// Login
|
||||
auth.setToken('access-token');
|
||||
renderApp();
|
||||
// Visit a protected route
|
||||
history.push('/protected');
|
||||
// Should see the protected route
|
||||
expect(await screen.findByText('You are authenticated'));
|
||||
});
|
||||
|
||||
it('Unauthenticated users should not be able to access protected routes and get redirected', async () => {
|
||||
renderApp();
|
||||
|
||||
// Visit `/`
|
||||
history.push('/');
|
||||
// Should redirected to `/auth/login`
|
||||
await waitFor(() => {
|
||||
expect(history.location.pathname).toBe('/auth/login');
|
||||
// No `redirectTo` in the search params
|
||||
expect(history.location.search).toBe('');
|
||||
expect(screen.getByText('Please login')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// Visit /settings/application-infos
|
||||
history.push('/settings/application-infos');
|
||||
// Should redirected to `/auth/login` and preserve the `/settings/application-infos` path
|
||||
await waitFor(() => {
|
||||
expect(history.location.pathname).toBe('/auth/login');
|
||||
// Should preserve url in the params
|
||||
expect(history.location.search).toBe(
|
||||
`?redirectTo=${encodeURIComponent('/settings/application-infos')}`
|
||||
);
|
||||
expect(screen.getByText('Please login')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
@ -14,7 +14,10 @@ import init from './init';
|
||||
import { initialState, reducer } from './reducer';
|
||||
|
||||
const AuthPage = ({ hasAdmin, setHasAdmin }) => {
|
||||
const { push } = useHistory();
|
||||
const {
|
||||
push,
|
||||
location: { search },
|
||||
} = useHistory();
|
||||
const { changeLocale } = useLocalesProvider();
|
||||
const { setSkipped } = useGuidedTour();
|
||||
const { trackUsage } = useTracking();
|
||||
@ -119,7 +122,7 @@ const AuthPage = ({ hasAdmin, setHasAdmin }) => {
|
||||
auth.setToken(token, body.rememberMe);
|
||||
auth.setUserInfo(user, body.rememberMe);
|
||||
|
||||
push('/');
|
||||
redirectToPreviousLocation();
|
||||
} catch (err) {
|
||||
if (err.response) {
|
||||
const errorMessage = get(
|
||||
@ -189,8 +192,7 @@ const AuthPage = ({ hasAdmin, setHasAdmin }) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Redirect to the homePage
|
||||
push('/');
|
||||
redirectToPreviousLocation();
|
||||
} catch (err) {
|
||||
trackUsage('didNotCreateFirstAdmin');
|
||||
|
||||
@ -238,6 +240,12 @@ const AuthPage = ({ hasAdmin, setHasAdmin }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const redirectToPreviousLocation = () => {
|
||||
const locationBeforeAuthenticated = decodeURIComponent(query.get('redirectTo'));
|
||||
const redirectUrl = locationBeforeAuthenticated || '/';
|
||||
push(redirectUrl);
|
||||
};
|
||||
|
||||
// Redirect the user to the login page if
|
||||
// the endpoint does not exist or
|
||||
// there is already an admin user oo
|
||||
@ -248,7 +256,16 @@ const AuthPage = ({ hasAdmin, setHasAdmin }) => {
|
||||
|
||||
// Redirect the user to the register-admin if it is the first user
|
||||
if (!hasAdmin && authType !== 'register-admin') {
|
||||
return <Redirect to="/auth/register-admin" />;
|
||||
return (
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: '/auth/register-admin',
|
||||
// Forward the `?redirectTo` from /auth/login
|
||||
// /abc => /auth/login?redirectTo=%2Fabc => /auth/register-admin?redirectTo=%2Fabc
|
||||
search,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
Loading…
x
Reference in New Issue
Block a user