From 0be741562d80bd101b7bbb296393ef23101ee120 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 28 Mar 2024 06:56:02 +1100 Subject: [PATCH] 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 --- src/frontend/src/components/forms/AuthenticationForm.tsx | 5 +++-- src/frontend/src/components/nav/Layout.tsx | 8 ++++++-- src/frontend/src/functions/auth.tsx | 4 +++- src/frontend/src/pages/Auth/Logged-In.tsx | 5 +++-- src/frontend/src/pages/Auth/Login.tsx | 6 +++--- src/frontend/tests/ui_plattform.spec.ts | 2 +- 6 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/frontend/src/components/forms/AuthenticationForm.tsx b/src/frontend/src/components/forms/AuthenticationForm.tsx index fdadec91ea..31c2d7c28b 100644 --- a/src/frontend/src/components/forms/AuthenticationForm.tsx +++ b/src/frontend/src/components/forms/AuthenticationForm.tsx @@ -15,7 +15,7 @@ import { useDisclosure } from '@mantine/hooks'; import { notifications } from '@mantine/notifications'; import { IconCheck } from '@tabler/icons-react'; import { useState } from 'react'; -import { useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import { api } from '../../App'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; @@ -32,6 +32,7 @@ export function AuthenticationForm() { const [classicLoginMode, setMode] = useDisclosure(true); const [auth_settings] = useServerApiState((state) => [state.auth_settings]); const navigate = useNavigate(); + const location = useLocation(); const [isLoggingIn, setIsLoggingIn] = useState(false); @@ -52,7 +53,7 @@ export function AuthenticationForm() { color: 'green', icon: }); - navigate('/home'); + navigate(location?.state?.redirectFrom ?? '/home'); } else { notifications.show({ title: t`Login failed`, diff --git a/src/frontend/src/components/nav/Layout.tsx b/src/frontend/src/components/nav/Layout.tsx index fdcbe6c578..d2fe67864c 100644 --- a/src/frontend/src/components/nav/Layout.tsx +++ b/src/frontend/src/components/nav/Layout.tsx @@ -1,5 +1,5 @@ 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 { useSessionState } from '../../states/SessionState'; @@ -9,8 +9,12 @@ import { Header } from './Header'; export const ProtectedRoute = ({ children }: { children: JSX.Element }) => { const [token] = useSessionState((state) => [state.token]); + const location = useLocation(); + if (!token) { - return ; + return ( + + ); } return children; diff --git a/src/frontend/src/functions/auth.tsx b/src/frontend/src/functions/auth.tsx index 652429d052..d0f010e9c2 100644 --- a/src/frontend/src/functions/auth.tsx +++ b/src/frontend/src/functions/auth.tsx @@ -150,7 +150,9 @@ export function checkLoginState( // Callback function when login fails const loginFailure = () => { useSessionState.getState().clearToken(); - if (!no_redirect) navigate('/login'); + if (!no_redirect) { + navigate('/login', { state: { redirectFrom: redirect } }); + } }; if (useSessionState.getState().hasToken()) { diff --git a/src/frontend/src/pages/Auth/Logged-In.tsx b/src/frontend/src/pages/Auth/Logged-In.tsx index 24f9465855..25d8d16026 100644 --- a/src/frontend/src/pages/Auth/Logged-In.tsx +++ b/src/frontend/src/pages/Auth/Logged-In.tsx @@ -1,15 +1,16 @@ import { Trans } from '@lingui/macro'; import { Card, Container, Group, Loader, Stack, Text } from '@mantine/core'; import { useEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import { checkLoginState } from '../../functions/auth'; export default function Logged_In() { const navigate = useNavigate(); + const location = useLocation(); useEffect(() => { - checkLoginState(navigate); + checkLoginState(navigate, location?.state?.redirectFrom); }, []); return ( diff --git a/src/frontend/src/pages/Auth/Login.tsx b/src/frontend/src/pages/Auth/Login.tsx index 49d571b97d..12f2fcf2b5 100644 --- a/src/frontend/src/pages/Auth/Login.tsx +++ b/src/frontend/src/pages/Auth/Login.tsx @@ -2,7 +2,7 @@ import { Trans, t } from '@lingui/macro'; import { Center, Container, Paper, Text } from '@mantine/core'; import { useDisclosure, useToggle } from '@mantine/hooks'; import { useEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import { setApiDefaults } from '../../App'; import { AuthFormOptions } from '../../components/forms/AuthFormOptions'; @@ -32,6 +32,7 @@ export default function Login() { const [hostEdit, setHostEdit] = useToggle([false, true] as const); const [loginMode, setMode] = useDisclosure(true); const navigate = useNavigate(); + const location = useLocation(); // Data manipulation functions function ChangeHost(newHost: string): void { @@ -46,8 +47,7 @@ export default function Login() { ChangeHost(defaultHostKey); } - // check if user is logged in in PUI - checkLoginState(navigate, undefined, true); + checkLoginState(navigate, location?.state?.redirectFrom, true); }, []); // Fetch server data on mount if no server data is present diff --git a/src/frontend/tests/ui_plattform.spec.ts b/src/frontend/tests/ui_plattform.spec.ts index 10c276dbd1..c5dafa5ac3 100644 --- a/src/frontend/tests/ui_plattform.spec.ts +++ b/src/frontend/tests/ui_plattform.spec.ts @@ -7,7 +7,7 @@ test('Basic Platform UI test', async ({ page }) => { await page.getByLabel('username').fill('allaccess'); await page.getByLabel('password').fill('nolimits'); await page.getByRole('button', { name: 'Log in' }).click(); - await page.waitForURL('**/platform/home'); + await page.waitForURL('**/platform'); await page.goto('./platform/'); await expect(page).toHaveTitle('InvenTree Demo Server');