diff --git a/InvenTree/InvenTree/api_version.py b/InvenTree/InvenTree/api_version.py index 320b828695..dae9004125 100644 --- a/InvenTree/InvenTree/api_version.py +++ b/InvenTree/InvenTree/api_version.py @@ -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 diff --git a/InvenTree/InvenTree/social_auth_urls.py b/InvenTree/InvenTree/social_auth_urls.py index 6613c2e67c..ecfef99b96 100644 --- a/InvenTree/InvenTree/social_auth_urls.py +++ b/InvenTree/InvenTree/social_auth_urls.py @@ -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) diff --git a/src/frontend/src/components/forms/AuthenticationForm.tsx b/src/frontend/src/components/forms/AuthenticationForm.tsx index b0f6b5f0e5..e881bef147 100644 --- a/src/frontend/src/components/forms/AuthenticationForm.tsx +++ b/src/frontend/src/components/forms/AuthenticationForm.tsx @@ -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(false); @@ -96,17 +97,19 @@ export function AuthenticationForm() { placeholder={t`Your password`} {...classicForm.getInputProps('password')} /> - - navigate('/reset-password')} - > - Reset password - - + {auth_settings?.password_forgotten_enabled === true && ( + + navigate('/reset-password')} + > + Reset password + + + )} ) : ( @@ -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 ( {loginMode ? ( @@ -258,7 +264,7 @@ export function ModeSelector({ type="button" color="dimmed" size="xs" - onClick={() => setMode.toggle()} + onClick={() => setMode.close()} > Register @@ -269,7 +275,7 @@ export function ModeSelector({ type="button" color="dimmed" size="xs" - onClick={() => setMode.toggle()} + onClick={() => setMode.open()} > Go back to login diff --git a/src/frontend/src/states/ApiState.tsx b/src/frontend/src/states/ApiState.tsx index e4a17fd4c1..86e986dc74 100644 --- a/src/frontend/src/states/ApiState.tsx +++ b/src/frontend/src/states/ApiState.tsx @@ -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; @@ -16,6 +16,7 @@ interface ServerApiStateProps { setServer: (newServer: ServerAPIProps) => void; fetchServerApiState: () => void; status?: StatusLookup; + auth_settings?: AuthProps; } export const useServerApiState = create()( @@ -32,14 +33,27 @@ export const useServerApiState = create()( }) .catch(() => {}); // Fetch status data for rendering labels - 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 }); - }); + 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 }), diff --git a/src/frontend/src/states/states.tsx b/src/frontend/src/states/states.tsx index 5b44087192..27db2fc39a 100644 --- a/src/frontend/src/states/states.tsx +++ b/src/frontend/src/states/states.tsx @@ -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;