mirror of
https://github.com/inventree/InvenTree.git
synced 2025-05-07 15:58:49 +00:00
[React] Login improvements (#5752)
* Logout user if user query fails * login / logout improvements - Add timeout to request (otherwise hangs indefinitely) * Improve "checking login" page * Update login form - Disable button if logging in - Show loader * Fixed unused vars
This commit is contained in:
parent
566fef5309
commit
2be5ec26f8
@ -3,6 +3,7 @@ import {
|
|||||||
Anchor,
|
Anchor,
|
||||||
Button,
|
Button,
|
||||||
Group,
|
Group,
|
||||||
|
Loader,
|
||||||
Paper,
|
Paper,
|
||||||
PasswordInput,
|
PasswordInput,
|
||||||
Stack,
|
Stack,
|
||||||
@ -13,6 +14,7 @@ import { useForm } from '@mantine/form';
|
|||||||
import { useDisclosure } from '@mantine/hooks';
|
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 { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { doClassicLogin, doSimpleLogin } from '../../functions/auth';
|
import { doClassicLogin, doSimpleLogin } from '../../functions/auth';
|
||||||
@ -25,12 +27,18 @@ export function AuthenticationForm() {
|
|||||||
const [classicLoginMode, setMode] = useDisclosure(true);
|
const [classicLoginMode, setMode] = useDisclosure(true);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const [isLoggingIn, setIsLoggingIn] = useState<boolean>(false);
|
||||||
|
|
||||||
function handleLogin() {
|
function handleLogin() {
|
||||||
|
setIsLoggingIn(true);
|
||||||
|
|
||||||
if (classicLoginMode === true) {
|
if (classicLoginMode === true) {
|
||||||
doClassicLogin(
|
doClassicLogin(
|
||||||
classicForm.values.username,
|
classicForm.values.username,
|
||||||
classicForm.values.password
|
classicForm.values.password
|
||||||
).then((ret) => {
|
).then((ret) => {
|
||||||
|
setIsLoggingIn(false);
|
||||||
|
|
||||||
if (ret === false) {
|
if (ret === false) {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
title: t`Login failed`,
|
title: t`Login failed`,
|
||||||
@ -49,6 +57,8 @@ export function AuthenticationForm() {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
doSimpleLogin(simpleForm.values.email).then((ret) => {
|
doSimpleLogin(simpleForm.values.email).then((ret) => {
|
||||||
|
setIsLoggingIn(false);
|
||||||
|
|
||||||
if (ret?.status === 'ok') {
|
if (ret?.status === 'ok') {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
title: t`Mail delivery successful`,
|
title: t`Mail delivery successful`,
|
||||||
@ -126,11 +136,17 @@ export function AuthenticationForm() {
|
|||||||
<Trans>I will use username and password</Trans>
|
<Trans>I will use username and password</Trans>
|
||||||
)}
|
)}
|
||||||
</Anchor>
|
</Anchor>
|
||||||
<Button type="submit" onClick={handleLogin}>
|
<Button type="submit" disabled={isLoggingIn} onClick={handleLogin}>
|
||||||
{classicLoginMode ? (
|
{isLoggingIn ? (
|
||||||
<Trans>Log in</Trans>
|
<Loader size="sm" />
|
||||||
) : (
|
) : (
|
||||||
<Trans>Send mail</Trans>
|
<>
|
||||||
|
{classicLoginMode ? (
|
||||||
|
<Trans>Log In</Trans>
|
||||||
|
) : (
|
||||||
|
<Trans>Send Email</Trans>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
|
@ -20,7 +20,8 @@ export const doClassicLogin = async (username: string, password: string) => {
|
|||||||
const token = await axios
|
const token = await axios
|
||||||
.get(apiUrl(ApiPaths.user_token), {
|
.get(apiUrl(ApiPaths.user_token), {
|
||||||
auth: { username, password },
|
auth: { username, password },
|
||||||
baseURL: host.toString()
|
baseURL: host.toString(),
|
||||||
|
timeout: 5000
|
||||||
})
|
})
|
||||||
.then((response) => response.data.token)
|
.then((response) => response.data.token)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@ -62,7 +63,7 @@ export const doSimpleLogin = async (email: string) => {
|
|||||||
email: email
|
email: email
|
||||||
})
|
})
|
||||||
.then((response) => response.data)
|
.then((response) => response.data)
|
||||||
.catch((error) => {
|
.catch((_error) => {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
return mail;
|
return mail;
|
||||||
@ -107,9 +108,14 @@ export function handleReset(navigate: any, values: { email: string }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function checkLoginState(navigate: any) {
|
/**
|
||||||
|
* Check login state, and redirect the user as required
|
||||||
|
*/
|
||||||
|
export function checkLoginState(navigate: any, redirect?: string) {
|
||||||
api
|
api
|
||||||
.get(apiUrl(ApiPaths.user_token))
|
.get(apiUrl(ApiPaths.user_token), {
|
||||||
|
timeout: 5000
|
||||||
|
})
|
||||||
.then((val) => {
|
.then((val) => {
|
||||||
if (val.status === 200 && val.data.token) {
|
if (val.status === 200 && val.data.token) {
|
||||||
doTokenLogin(val.data.token);
|
doTokenLogin(val.data.token);
|
||||||
@ -120,13 +126,13 @@ export function checkLoginState(navigate: any) {
|
|||||||
color: 'green',
|
color: 'green',
|
||||||
icon: <IconCheck size="1rem" />
|
icon: <IconCheck size="1rem" />
|
||||||
});
|
});
|
||||||
|
navigate(redirect ?? '/home');
|
||||||
navigate('/home');
|
|
||||||
} else {
|
} else {
|
||||||
navigate('/login');
|
navigate('/login');
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch((error) => {
|
||||||
|
console.error('Error fetching login information:', error);
|
||||||
navigate('/login');
|
navigate('/login');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Trans } from '@lingui/macro';
|
import { Trans } from '@lingui/macro';
|
||||||
import { 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 { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
@ -14,9 +14,20 @@ export default function Logged_In() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Text>
|
<Container>
|
||||||
<Trans>Checking if you are already logged in</Trans>
|
<Stack align="center">
|
||||||
</Text>
|
<Card shadow="sm" padding="lg" radius="md">
|
||||||
|
<Stack>
|
||||||
|
<Text size="lg">
|
||||||
|
<Trans>Checking if you are already logged in</Trans>
|
||||||
|
</Text>
|
||||||
|
<Group position="center">
|
||||||
|
<Loader />
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
</Stack>
|
||||||
|
</Container>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
|
|
||||||
import { api } from '../App';
|
import { api } from '../App';
|
||||||
|
import { doClassicLogout } from '../functions/auth';
|
||||||
import { ApiPaths, apiUrl } from './ApiState';
|
import { ApiPaths, apiUrl } from './ApiState';
|
||||||
import { UserProps } from './states';
|
import { UserProps } from './states';
|
||||||
|
|
||||||
@ -19,17 +20,19 @@ export const useUserState = create<UserStateProps>((set, get) => ({
|
|||||||
username: () => {
|
username: () => {
|
||||||
const user: UserProps = get().user as UserProps;
|
const user: UserProps = get().user as UserProps;
|
||||||
|
|
||||||
if (user.first_name || user.last_name) {
|
if (user?.first_name || user?.last_name) {
|
||||||
return `${user.first_name} ${user.last_name}`.trim();
|
return `${user.first_name} ${user.last_name}`.trim();
|
||||||
} else {
|
} else {
|
||||||
return user.username;
|
return user?.username ?? '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setUser: (newUser: UserProps) => set({ user: newUser }),
|
setUser: (newUser: UserProps) => set({ user: newUser }),
|
||||||
fetchUserState: async () => {
|
fetchUserState: async () => {
|
||||||
// Fetch user data
|
// Fetch user data
|
||||||
await api
|
await api
|
||||||
.get(apiUrl(ApiPaths.user_me))
|
.get(apiUrl(ApiPaths.user_me), {
|
||||||
|
timeout: 5000
|
||||||
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
const user: UserProps = {
|
const user: UserProps = {
|
||||||
first_name: response.data?.first_name ?? '',
|
first_name: response.data?.first_name ?? '',
|
||||||
@ -41,6 +44,8 @@ export const useUserState = create<UserStateProps>((set, get) => ({
|
|||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Error fetching user data:', error);
|
console.error('Error fetching user data:', error);
|
||||||
|
// Redirect to login page
|
||||||
|
doClassicLogout();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fetch role data
|
// Fetch role data
|
||||||
|
Loading…
x
Reference in New Issue
Block a user