mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
[PUI] Auth behaviour controls (#6314)
* optimize login layout * move auth/reg up * [PUI] Registration Fixes #6282 * [PUI] Registration Fixes #6282 * fix type * Add auth settings to API state * control showing of registration via state * small cleanups * Added registration and password forgotten to auth endpoint * control password forgotten via state * cleanup imports * bump api version
This commit is contained in:
parent
f35ce29612
commit
8f6893a6b2
@ -1,11 +1,14 @@
|
|||||||
"""InvenTree API version information."""
|
"""InvenTree API version information."""
|
||||||
|
|
||||||
# InvenTree API version
|
# InvenTree API version
|
||||||
INVENTREE_API_VERSION = 162
|
INVENTREE_API_VERSION = 163
|
||||||
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||||
|
|
||||||
INVENTREE_API_TEXT = """
|
INVENTREE_API_TEXT = """
|
||||||
|
|
||||||
|
v163 -> 2024-01-22 : https://github.com/inventree/InvenTree/pull/6314
|
||||||
|
- Extends API endpoint to expose auth configuration information for signin pages
|
||||||
|
|
||||||
v162 -> 2024-01-14 : https://github.com/inventree/InvenTree/pull/6230
|
v162 -> 2024-01-14 : https://github.com/inventree/InvenTree/pull/6230
|
||||||
- Adds API endpoints to provide information on background tasks
|
- Adds API endpoints to provide information on background tasks
|
||||||
|
|
||||||
|
@ -153,6 +153,10 @@ class SocialProviderListView(ListAPI):
|
|||||||
'sso_registration': InvenTree.sso.registration_enabled(),
|
'sso_registration': InvenTree.sso.registration_enabled(),
|
||||||
'mfa_required': InvenTreeSetting.get_setting('LOGIN_ENFORCE_MFA'),
|
'mfa_required': InvenTreeSetting.get_setting('LOGIN_ENFORCE_MFA'),
|
||||||
'providers': provider_list,
|
'providers': provider_list,
|
||||||
|
'registration_enabled': InvenTreeSetting.get_setting('LOGIN_ENABLE_REG'),
|
||||||
|
'password_forgotten_enabled': InvenTreeSetting.get_setting(
|
||||||
|
'LOGIN_ENABLE_PWD_FORGOT'
|
||||||
|
),
|
||||||
}
|
}
|
||||||
return Response(data)
|
return Response(data)
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import { useNavigate } from 'react-router-dom';
|
|||||||
import { api } from '../../App';
|
import { api } from '../../App';
|
||||||
import { ApiPaths } from '../../enums/ApiEndpoints';
|
import { ApiPaths } from '../../enums/ApiEndpoints';
|
||||||
import { doClassicLogin, doSimpleLogin } from '../../functions/auth';
|
import { doClassicLogin, doSimpleLogin } from '../../functions/auth';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl, useServerApiState } from '../../states/ApiState';
|
||||||
|
|
||||||
export function AuthenticationForm() {
|
export function AuthenticationForm() {
|
||||||
const classicForm = useForm({
|
const classicForm = useForm({
|
||||||
@ -27,6 +27,7 @@ export function AuthenticationForm() {
|
|||||||
});
|
});
|
||||||
const simpleForm = useForm({ initialValues: { email: '' } });
|
const simpleForm = useForm({ initialValues: { email: '' } });
|
||||||
const [classicLoginMode, setMode] = useDisclosure(true);
|
const [classicLoginMode, setMode] = useDisclosure(true);
|
||||||
|
const [auth_settings] = useServerApiState((state) => [state.auth_settings]);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [isLoggingIn, setIsLoggingIn] = useState<boolean>(false);
|
const [isLoggingIn, setIsLoggingIn] = useState<boolean>(false);
|
||||||
@ -96,17 +97,19 @@ export function AuthenticationForm() {
|
|||||||
placeholder={t`Your password`}
|
placeholder={t`Your password`}
|
||||||
{...classicForm.getInputProps('password')}
|
{...classicForm.getInputProps('password')}
|
||||||
/>
|
/>
|
||||||
<Group position="apart" mt="0">
|
{auth_settings?.password_forgotten_enabled === true && (
|
||||||
<Anchor
|
<Group position="apart" mt="0">
|
||||||
component="button"
|
<Anchor
|
||||||
type="button"
|
component="button"
|
||||||
color="dimmed"
|
type="button"
|
||||||
size="xs"
|
color="dimmed"
|
||||||
onClick={() => navigate('/reset-password')}
|
size="xs"
|
||||||
>
|
onClick={() => navigate('/reset-password')}
|
||||||
<Trans>Reset password</Trans>
|
>
|
||||||
</Anchor>
|
<Trans>Reset password</Trans>
|
||||||
</Group>
|
</Anchor>
|
||||||
|
</Group>
|
||||||
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
) : (
|
) : (
|
||||||
<Stack>
|
<Stack>
|
||||||
@ -248,6 +251,9 @@ export function ModeSelector({
|
|||||||
loginMode: boolean;
|
loginMode: boolean;
|
||||||
setMode: any;
|
setMode: any;
|
||||||
}) {
|
}) {
|
||||||
|
const [auth_settings] = useServerApiState((state) => [state.auth_settings]);
|
||||||
|
|
||||||
|
if (auth_settings?.registration_enabled === false) return null;
|
||||||
return (
|
return (
|
||||||
<Text ta="center" size={'xs'} mt={'md'}>
|
<Text ta="center" size={'xs'} mt={'md'}>
|
||||||
{loginMode ? (
|
{loginMode ? (
|
||||||
@ -258,7 +264,7 @@ export function ModeSelector({
|
|||||||
type="button"
|
type="button"
|
||||||
color="dimmed"
|
color="dimmed"
|
||||||
size="xs"
|
size="xs"
|
||||||
onClick={() => setMode.toggle()}
|
onClick={() => setMode.close()}
|
||||||
>
|
>
|
||||||
<Trans>Register</Trans>
|
<Trans>Register</Trans>
|
||||||
</Anchor>
|
</Anchor>
|
||||||
@ -269,7 +275,7 @@ export function ModeSelector({
|
|||||||
type="button"
|
type="button"
|
||||||
color="dimmed"
|
color="dimmed"
|
||||||
size="xs"
|
size="xs"
|
||||||
onClick={() => setMode.toggle()}
|
onClick={() => setMode.open()}
|
||||||
>
|
>
|
||||||
<Trans>Go back to login</Trans>
|
<Trans>Go back to login</Trans>
|
||||||
</Anchor>
|
</Anchor>
|
||||||
|
@ -7,7 +7,7 @@ import { statusCodeList } from '../defaults/backendMappings';
|
|||||||
import { emptyServerAPI } from '../defaults/defaults';
|
import { emptyServerAPI } from '../defaults/defaults';
|
||||||
import { ApiPaths } from '../enums/ApiEndpoints';
|
import { ApiPaths } from '../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../enums/ModelType';
|
import { ModelType } from '../enums/ModelType';
|
||||||
import { ServerAPIProps } from './states';
|
import { AuthProps, ServerAPIProps } from './states';
|
||||||
|
|
||||||
type StatusLookup = Record<ModelType | string, StatusCodeListInterface>;
|
type StatusLookup = Record<ModelType | string, StatusCodeListInterface>;
|
||||||
|
|
||||||
@ -16,6 +16,7 @@ interface ServerApiStateProps {
|
|||||||
setServer: (newServer: ServerAPIProps) => void;
|
setServer: (newServer: ServerAPIProps) => void;
|
||||||
fetchServerApiState: () => void;
|
fetchServerApiState: () => void;
|
||||||
status?: StatusLookup;
|
status?: StatusLookup;
|
||||||
|
auth_settings?: AuthProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useServerApiState = create<ServerApiStateProps>()(
|
export const useServerApiState = create<ServerApiStateProps>()(
|
||||||
@ -32,14 +33,27 @@ export const useServerApiState = create<ServerApiStateProps>()(
|
|||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
// Fetch status data for rendering labels
|
// Fetch status data for rendering labels
|
||||||
await api.get(apiUrl(ApiPaths.global_status)).then((response) => {
|
await api
|
||||||
const newStatusLookup: StatusLookup = {} as StatusLookup;
|
.get(apiUrl(ApiPaths.global_status))
|
||||||
for (const key in response.data) {
|
.then((response) => {
|
||||||
newStatusLookup[statusCodeList[key] || key] =
|
const newStatusLookup: StatusLookup = {} as StatusLookup;
|
||||||
response.data[key].values;
|
for (const key in response.data) {
|
||||||
}
|
newStatusLookup[statusCodeList[key] || key] =
|
||||||
set({ status: newStatusLookup });
|
response.data[key].values;
|
||||||
});
|
}
|
||||||
|
set({ status: newStatusLookup });
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
|
||||||
|
// Fetch login/SSO behaviour
|
||||||
|
await api
|
||||||
|
.get(apiUrl(ApiPaths.sso_providers), {
|
||||||
|
headers: { Authorization: '' }
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
set({ auth_settings: response.data });
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
},
|
},
|
||||||
status: undefined
|
status: undefined
|
||||||
}),
|
}),
|
||||||
|
@ -40,6 +40,24 @@ export interface ServerAPIProps {
|
|||||||
default_locale: null | string;
|
default_locale: null | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AuthProps {
|
||||||
|
sso_enabled: boolean;
|
||||||
|
sso_registration: boolean;
|
||||||
|
mfa_required: boolean;
|
||||||
|
providers: Provider[];
|
||||||
|
registration_enabled: boolean;
|
||||||
|
password_forgotten_enabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Provider {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
configured: boolean;
|
||||||
|
login: string;
|
||||||
|
connect: string;
|
||||||
|
display_name: string;
|
||||||
|
}
|
||||||
|
|
||||||
// Type interface defining a single 'setting' object
|
// Type interface defining a single 'setting' object
|
||||||
export interface Setting {
|
export interface Setting {
|
||||||
pk: number;
|
pk: number;
|
||||||
|
Loading…
Reference in New Issue
Block a user