2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-28 11:36:44 +00:00

Implement URL redirect for PUI (#6872)

* Implement URL redirect for PUI

- Return from login page to redirect URL
- Return from auth check to redirect URL

* fix PUI test assumption

---------

Co-authored-by: Matthias Mair <code@mjmair.com>
This commit is contained in:
Oliver 2024-03-28 06:56:02 +11:00 committed by GitHub
parent bc77b2eb5f
commit 0be741562d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 19 additions and 11 deletions

View File

@ -15,7 +15,7 @@ import { useDisclosure } from '@mantine/hooks';
import { notifications } from '@mantine/notifications'; import { notifications } from '@mantine/notifications';
import { IconCheck } from '@tabler/icons-react'; import { IconCheck } from '@tabler/icons-react';
import { useState } from 'react'; import { useState } from 'react';
import { useNavigate } from 'react-router-dom'; import { useLocation, useNavigate } from 'react-router-dom';
import { api } from '../../App'; import { api } from '../../App';
import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../enums/ApiEndpoints';
@ -32,6 +32,7 @@ export function AuthenticationForm() {
const [classicLoginMode, setMode] = useDisclosure(true); const [classicLoginMode, setMode] = useDisclosure(true);
const [auth_settings] = useServerApiState((state) => [state.auth_settings]); const [auth_settings] = useServerApiState((state) => [state.auth_settings]);
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation();
const [isLoggingIn, setIsLoggingIn] = useState<boolean>(false); const [isLoggingIn, setIsLoggingIn] = useState<boolean>(false);
@ -52,7 +53,7 @@ export function AuthenticationForm() {
color: 'green', color: 'green',
icon: <IconCheck size="1rem" /> icon: <IconCheck size="1rem" />
}); });
navigate('/home'); navigate(location?.state?.redirectFrom ?? '/home');
} else { } else {
notifications.show({ notifications.show({
title: t`Login failed`, title: t`Login failed`,

View File

@ -1,5 +1,5 @@
import { Container, Flex, Space } from '@mantine/core'; import { Container, Flex, Space } from '@mantine/core';
import { Navigate, Outlet } from 'react-router-dom'; import { Navigate, Outlet, useLocation, useNavigate } from 'react-router-dom';
import { InvenTreeStyle } from '../../globalStyle'; import { InvenTreeStyle } from '../../globalStyle';
import { useSessionState } from '../../states/SessionState'; import { useSessionState } from '../../states/SessionState';
@ -9,8 +9,12 @@ import { Header } from './Header';
export const ProtectedRoute = ({ children }: { children: JSX.Element }) => { export const ProtectedRoute = ({ children }: { children: JSX.Element }) => {
const [token] = useSessionState((state) => [state.token]); const [token] = useSessionState((state) => [state.token]);
const location = useLocation();
if (!token) { if (!token) {
return <Navigate to="/logged-in" replace />; return (
<Navigate to="/logged-in" state={{ redirectFrom: location.pathname }} />
);
} }
return children; return children;

View File

@ -150,7 +150,9 @@ export function checkLoginState(
// Callback function when login fails // Callback function when login fails
const loginFailure = () => { const loginFailure = () => {
useSessionState.getState().clearToken(); useSessionState.getState().clearToken();
if (!no_redirect) navigate('/login'); if (!no_redirect) {
navigate('/login', { state: { redirectFrom: redirect } });
}
}; };
if (useSessionState.getState().hasToken()) { if (useSessionState.getState().hasToken()) {

View File

@ -1,15 +1,16 @@
import { Trans } from '@lingui/macro'; import { Trans } from '@lingui/macro';
import { Card, Container, Group, Loader, Stack, Text } from '@mantine/core'; import { Card, Container, Group, Loader, Stack, Text } from '@mantine/core';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; import { useLocation, useNavigate } from 'react-router-dom';
import { checkLoginState } from '../../functions/auth'; import { checkLoginState } from '../../functions/auth';
export default function Logged_In() { export default function Logged_In() {
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation();
useEffect(() => { useEffect(() => {
checkLoginState(navigate); checkLoginState(navigate, location?.state?.redirectFrom);
}, []); }, []);
return ( return (

View File

@ -2,7 +2,7 @@ import { Trans, t } from '@lingui/macro';
import { Center, Container, Paper, Text } from '@mantine/core'; import { Center, Container, Paper, Text } from '@mantine/core';
import { useDisclosure, useToggle } from '@mantine/hooks'; import { useDisclosure, useToggle } from '@mantine/hooks';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; import { useLocation, useNavigate } from 'react-router-dom';
import { setApiDefaults } from '../../App'; import { setApiDefaults } from '../../App';
import { AuthFormOptions } from '../../components/forms/AuthFormOptions'; import { AuthFormOptions } from '../../components/forms/AuthFormOptions';
@ -32,6 +32,7 @@ export default function Login() {
const [hostEdit, setHostEdit] = useToggle([false, true] as const); const [hostEdit, setHostEdit] = useToggle([false, true] as const);
const [loginMode, setMode] = useDisclosure(true); const [loginMode, setMode] = useDisclosure(true);
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation();
// Data manipulation functions // Data manipulation functions
function ChangeHost(newHost: string): void { function ChangeHost(newHost: string): void {
@ -46,8 +47,7 @@ export default function Login() {
ChangeHost(defaultHostKey); ChangeHost(defaultHostKey);
} }
// check if user is logged in in PUI checkLoginState(navigate, location?.state?.redirectFrom, true);
checkLoginState(navigate, undefined, true);
}, []); }, []);
// Fetch server data on mount if no server data is present // Fetch server data on mount if no server data is present

View File

@ -7,7 +7,7 @@ test('Basic Platform UI test', async ({ page }) => {
await page.getByLabel('username').fill('allaccess'); await page.getByLabel('username').fill('allaccess');
await page.getByLabel('password').fill('nolimits'); await page.getByLabel('password').fill('nolimits');
await page.getByRole('button', { name: 'Log in' }).click(); await page.getByRole('button', { name: 'Log in' }).click();
await page.waitForURL('**/platform/home'); await page.waitForURL('**/platform');
await page.goto('./platform/'); await page.goto('./platform/');
await expect(page).toHaveTitle('InvenTree Demo Server'); await expect(page).toHaveTitle('InvenTree Demo Server');