mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-18 13:05:42 +00:00
save auth context
This commit is contained in:
@ -5,7 +5,7 @@ import type { AxiosRequestConfig } from 'axios';
|
|||||||
import type { Location, NavigateFunction } from 'react-router-dom';
|
import type { Location, NavigateFunction } from 'react-router-dom';
|
||||||
import { api, setApiDefaults } from '../App';
|
import { api, setApiDefaults } from '../App';
|
||||||
import { ApiEndpoints } from '../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../enums/ApiEndpoints';
|
||||||
import { apiUrl } from '../states/ApiState';
|
import { apiUrl, useServerApiState } from '../states/ApiState';
|
||||||
import { useLocalState } from '../states/LocalState';
|
import { useLocalState } from '../states/LocalState';
|
||||||
import { useUserState } from '../states/UserState';
|
import { useUserState } from '../states/UserState';
|
||||||
import { type Provider, fetchGlobalStates } from '../states/states';
|
import { type Provider, fetchGlobalStates } from '../states/states';
|
||||||
@ -66,6 +66,7 @@ export const doBasicLogin = async (
|
|||||||
) => {
|
) => {
|
||||||
const { host } = useLocalState.getState();
|
const { host } = useLocalState.getState();
|
||||||
const { clearUserState, setToken, fetchUserState } = useUserState.getState();
|
const { clearUserState, setToken, fetchUserState } = useUserState.getState();
|
||||||
|
const { setAuthContext } = useServerApiState.getState();
|
||||||
|
|
||||||
if (username.length == 0 || password.length == 0) {
|
if (username.length == 0 || password.length == 0) {
|
||||||
return;
|
return;
|
||||||
@ -90,6 +91,7 @@ export const doBasicLogin = async (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
|
setAuthContext(response.data?.data);
|
||||||
if (response.status == 200 && response.data?.meta?.is_authenticated) {
|
if (response.status == 200 && response.data?.meta?.is_authenticated) {
|
||||||
setToken(response.data.meta.access_token);
|
setToken(response.data.meta.access_token);
|
||||||
loginDone = true;
|
loginDone = true;
|
||||||
@ -98,6 +100,7 @@ export const doBasicLogin = async (
|
|||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (err?.response?.status == 401) {
|
if (err?.response?.status == 401) {
|
||||||
|
setAuthContext(err.response.data?.data);
|
||||||
const mfa_flow = err.response.data.data.flows.find(
|
const mfa_flow = err.response.data.data.flows.find(
|
||||||
(flow: any) => flow.id == 'mfa_authenticate'
|
(flow: any) => flow.id == 'mfa_authenticate'
|
||||||
);
|
);
|
||||||
@ -173,32 +176,23 @@ export function handleReset(
|
|||||||
values: { email: string }
|
values: { email: string }
|
||||||
) {
|
) {
|
||||||
ensureCsrf();
|
ensureCsrf();
|
||||||
api
|
api.post(apiUrl(ApiEndpoints.user_reset), values).then((val) => {
|
||||||
.post(
|
if (val.status === 200) {
|
||||||
apiUrl(ApiEndpoints.user_reset),
|
notifications.show({
|
||||||
values
|
title: t`Mail delivery successful`,
|
||||||
/*{
|
message: t`Check your inbox for a reset link. This only works if you have an account. Check in spam too.`,
|
||||||
headers: { Authorization: '' }
|
color: 'green',
|
||||||
|
autoClose: false
|
||||||
|
});
|
||||||
|
navigate('/login');
|
||||||
|
} else {
|
||||||
|
notifications.show({
|
||||||
|
title: t`Reset failed`,
|
||||||
|
message: t`Check your input and try again.`,
|
||||||
|
color: 'red'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
*/
|
});
|
||||||
)
|
|
||||||
.then((val) => {
|
|
||||||
if (val.status === 200) {
|
|
||||||
notifications.show({
|
|
||||||
title: t`Mail delivery successful`,
|
|
||||||
message: t`Check your inbox for a reset link. This only works if you have an account. Check in spam too.`,
|
|
||||||
color: 'green',
|
|
||||||
autoClose: false
|
|
||||||
});
|
|
||||||
navigate('/login');
|
|
||||||
} else {
|
|
||||||
notifications.show({
|
|
||||||
title: t`Reset failed`,
|
|
||||||
message: t`Check your input and try again.`,
|
|
||||||
color: 'red'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleMfaLogin(
|
export function handleMfaLogin(
|
||||||
@ -207,9 +201,11 @@ export function handleMfaLogin(
|
|||||||
values: { code: string }
|
values: { code: string }
|
||||||
) {
|
) {
|
||||||
const { setToken } = useUserState.getState();
|
const { setToken } = useUserState.getState();
|
||||||
|
const { setAuthContext } = useServerApiState.getState();
|
||||||
authApi(apiUrl(ApiEndpoints.auth_login_2fa), undefined, 'post', {
|
authApi(apiUrl(ApiEndpoints.auth_login_2fa), undefined, 'post', {
|
||||||
code: values.code
|
code: values.code
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
|
setAuthContext(response.data?.data);
|
||||||
setToken(response.data.meta.access_token);
|
setToken(response.data.meta.access_token);
|
||||||
followRedirect(navigate, location?.state);
|
followRedirect(navigate, location?.state);
|
||||||
});
|
});
|
||||||
|
@ -574,7 +574,9 @@ async function runActionWithFallback(
|
|||||||
action: () => Promise<ResultType>,
|
action: () => Promise<ResultType>,
|
||||||
getReauthText: (props: any) => any
|
getReauthText: (props: any) => any
|
||||||
) {
|
) {
|
||||||
|
const { setAuthContext } = useServerApiState.getState();
|
||||||
const rslt = await action().catch((err) => {
|
const rslt = await action().catch((err) => {
|
||||||
|
setAuthContext(err.response.data?.data);
|
||||||
// check if we need to re-authenticate
|
// check if we need to re-authenticate
|
||||||
if (err.status == 401) {
|
if (err.status == 401) {
|
||||||
if (
|
if (
|
||||||
@ -603,9 +605,14 @@ async function runActionWithFallback(
|
|||||||
name: 'TOTP',
|
name: 'TOTP',
|
||||||
description: t`Enter your TOTP or recovery code`
|
description: t`Enter your TOTP or recovery code`
|
||||||
})
|
})
|
||||||
}).then(() => {
|
})
|
||||||
action();
|
.then((response) => {
|
||||||
});
|
setAuthContext(response.data?.data);
|
||||||
|
action();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
setAuthContext(err.response.data?.data);
|
||||||
|
});
|
||||||
} else if (rslt == ResultType.reauth) {
|
} else if (rslt == ResultType.reauth) {
|
||||||
authApi(apiUrl(ApiEndpoints.auth_reauthenticate), undefined, 'post', {
|
authApi(apiUrl(ApiEndpoints.auth_reauthenticate), undefined, 'post', {
|
||||||
password: await getReauthText({
|
password: await getReauthText({
|
||||||
@ -613,9 +620,14 @@ async function runActionWithFallback(
|
|||||||
name: 'password',
|
name: 'password',
|
||||||
description: t`Enter your password`
|
description: t`Enter your password`
|
||||||
})
|
})
|
||||||
}).then(() => {
|
})
|
||||||
action();
|
.then((response) => {
|
||||||
});
|
setAuthContext(response.data?.data);
|
||||||
|
action();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
setAuthContext(err.response.data?.data);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,13 +4,15 @@ import { createJSONStorage, persist } from 'zustand/middleware';
|
|||||||
import { api } from '../App';
|
import { api } from '../App';
|
||||||
import { emptyServerAPI } from '../defaults/defaults';
|
import { emptyServerAPI } from '../defaults/defaults';
|
||||||
import { ApiEndpoints } from '../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../enums/ApiEndpoints';
|
||||||
import type { AuthConfig, ServerAPIProps } from './states';
|
import type { AuthConfig, AuthContext, ServerAPIProps } from './states';
|
||||||
|
|
||||||
interface ServerApiStateProps {
|
interface ServerApiStateProps {
|
||||||
server: ServerAPIProps;
|
server: ServerAPIProps;
|
||||||
setServer: (newServer: ServerAPIProps) => void;
|
setServer: (newServer: ServerAPIProps) => void;
|
||||||
fetchServerApiState: () => void;
|
fetchServerApiState: () => void;
|
||||||
auth_config?: AuthConfig;
|
auth_config?: AuthConfig;
|
||||||
|
auth_context?: AuthContext;
|
||||||
|
setAuthContext: (auth_context: AuthContext) => void;
|
||||||
sso_enabled: () => boolean;
|
sso_enabled: () => boolean;
|
||||||
registration_enabled: () => boolean;
|
registration_enabled: () => boolean;
|
||||||
sso_registration_enabled: () => boolean;
|
sso_registration_enabled: () => boolean;
|
||||||
@ -47,6 +49,10 @@ export const useServerApiState = create<ServerApiStateProps>()(
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
auth_config: undefined,
|
auth_config: undefined,
|
||||||
|
auth_context: undefined,
|
||||||
|
setAuthContext(auth_context) {
|
||||||
|
set({ auth_context });
|
||||||
|
},
|
||||||
sso_enabled: () => {
|
sso_enabled: () => {
|
||||||
const data = get().auth_config?.socialaccount.providers;
|
const data = get().auth_config?.socialaccount.providers;
|
||||||
return !(data === undefined || data.length == 0);
|
return !(data === undefined || data.length == 0);
|
||||||
|
@ -50,6 +50,30 @@ export interface ServerAPIProps {
|
|||||||
django_admin: null | string;
|
django_admin: null | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AuthContext {
|
||||||
|
status: number;
|
||||||
|
data: { flows: Flow[] };
|
||||||
|
meta: { is_authenticated: boolean };
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum FlowEnum {
|
||||||
|
VerifyEmail = 'verify_email',
|
||||||
|
Login = 'login',
|
||||||
|
Signup = 'signup',
|
||||||
|
ProviderRedirect = 'provider_redirect',
|
||||||
|
ProviderSignup = 'provider_signup',
|
||||||
|
ProviderToken = 'provider_token',
|
||||||
|
MfaAuthenticate = 'mfa_authenticate',
|
||||||
|
Reauthenticate = 'reauthenticate',
|
||||||
|
MfaReauthenticate = 'mfa_reauthenticate'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Flow {
|
||||||
|
id: FlowEnum;
|
||||||
|
providers?: string[];
|
||||||
|
is_pending?: boolean[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface AuthConfig {
|
export interface AuthConfig {
|
||||||
account: {
|
account: {
|
||||||
authentication_method: string;
|
authentication_method: string;
|
||||||
|
Reference in New Issue
Block a user