[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:
Matthias Mair 2024-01-23 12:27:41 +00:00 committed by GitHub
parent f35ce29612
commit 8f6893a6b2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 69 additions and 24 deletions

View File

@ -1,11 +1,14 @@
"""InvenTree API version information."""
# 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."""
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
- Adds API endpoints to provide information on background tasks

View File

@ -153,6 +153,10 @@ class SocialProviderListView(ListAPI):
'sso_registration': InvenTree.sso.registration_enabled(),
'mfa_required': InvenTreeSetting.get_setting('LOGIN_ENFORCE_MFA'),
'providers': provider_list,
'registration_enabled': InvenTreeSetting.get_setting('LOGIN_ENABLE_REG'),
'password_forgotten_enabled': InvenTreeSetting.get_setting(
'LOGIN_ENABLE_PWD_FORGOT'
),
}
return Response(data)

View File

@ -19,7 +19,7 @@ import { useNavigate } from 'react-router-dom';
import { api } from '../../App';
import { ApiPaths } from '../../enums/ApiEndpoints';
import { doClassicLogin, doSimpleLogin } from '../../functions/auth';
import { apiUrl } from '../../states/ApiState';
import { apiUrl, useServerApiState } from '../../states/ApiState';
export function AuthenticationForm() {
const classicForm = useForm({
@ -27,6 +27,7 @@ export function AuthenticationForm() {
});
const simpleForm = useForm({ initialValues: { email: '' } });
const [classicLoginMode, setMode] = useDisclosure(true);
const [auth_settings] = useServerApiState((state) => [state.auth_settings]);
const navigate = useNavigate();
const [isLoggingIn, setIsLoggingIn] = useState<boolean>(false);
@ -96,6 +97,7 @@ export function AuthenticationForm() {
placeholder={t`Your password`}
{...classicForm.getInputProps('password')}
/>
{auth_settings?.password_forgotten_enabled === true && (
<Group position="apart" mt="0">
<Anchor
component="button"
@ -107,6 +109,7 @@ export function AuthenticationForm() {
<Trans>Reset password</Trans>
</Anchor>
</Group>
)}
</Stack>
) : (
<Stack>
@ -248,6 +251,9 @@ export function ModeSelector({
loginMode: boolean;
setMode: any;
}) {
const [auth_settings] = useServerApiState((state) => [state.auth_settings]);
if (auth_settings?.registration_enabled === false) return null;
return (
<Text ta="center" size={'xs'} mt={'md'}>
{loginMode ? (
@ -258,7 +264,7 @@ export function ModeSelector({
type="button"
color="dimmed"
size="xs"
onClick={() => setMode.toggle()}
onClick={() => setMode.close()}
>
<Trans>Register</Trans>
</Anchor>
@ -269,7 +275,7 @@ export function ModeSelector({
type="button"
color="dimmed"
size="xs"
onClick={() => setMode.toggle()}
onClick={() => setMode.open()}
>
<Trans>Go back to login</Trans>
</Anchor>

View File

@ -7,7 +7,7 @@ import { statusCodeList } from '../defaults/backendMappings';
import { emptyServerAPI } from '../defaults/defaults';
import { ApiPaths } from '../enums/ApiEndpoints';
import { ModelType } from '../enums/ModelType';
import { ServerAPIProps } from './states';
import { AuthProps, ServerAPIProps } from './states';
type StatusLookup = Record<ModelType | string, StatusCodeListInterface>;
@ -16,6 +16,7 @@ interface ServerApiStateProps {
setServer: (newServer: ServerAPIProps) => void;
fetchServerApiState: () => void;
status?: StatusLookup;
auth_settings?: AuthProps;
}
export const useServerApiState = create<ServerApiStateProps>()(
@ -32,14 +33,27 @@ export const useServerApiState = create<ServerApiStateProps>()(
})
.catch(() => {});
// Fetch status data for rendering labels
await api.get(apiUrl(ApiPaths.global_status)).then((response) => {
await api
.get(apiUrl(ApiPaths.global_status))
.then((response) => {
const newStatusLookup: StatusLookup = {} as StatusLookup;
for (const key in response.data) {
newStatusLookup[statusCodeList[key] || key] =
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
}),

View File

@ -40,6 +40,24 @@ export interface ServerAPIProps {
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
export interface Setting {
pk: number;