mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-03 22:55:43 +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:
		@@ -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`,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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()) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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 (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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');
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user