diff --git a/frontend/src/component/admin/auth/AuthSettings.tsx b/frontend/src/component/admin/auth/AuthSettings.tsx index db1eb4aaa9..255dd7e754 100644 --- a/frontend/src/component/admin/auth/AuthSettings.tsx +++ b/frontend/src/component/admin/auth/AuthSettings.tsx @@ -11,15 +11,11 @@ import { ADMIN } from '@server/types/permissions'; import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature'; import { useState } from 'react'; import { TabPanel } from 'component/common/TabNav/TabPanel/TabPanel'; -import { useUiFlag } from 'hooks/useUiFlag'; -import { ScimSettings } from './ScimSettings/ScimSettings'; export const AuthSettings = () => { const { authenticationType } = useUiConfig().uiConfig; const { uiConfig } = useUiConfig(); - const scimEnabled = useUiFlag('scimApi'); - const tabs = [ { label: 'OpenID Connect', @@ -41,13 +37,6 @@ export const AuthSettings = () => { (item) => uiConfig.flags?.googleAuthEnabled || item.label !== 'Google', ); - if (scimEnabled) { - tabs.push({ - label: 'Provisioning (SCIM)', - component: , - }); - } - const [activeTab, setActiveTab] = useState(0); return ( diff --git a/frontend/src/component/admin/auth/OidcAuth/OidcAuth.tsx b/frontend/src/component/admin/auth/OidcAuth/OidcAuth.tsx index 70ab4e5151..570e8bb988 100644 --- a/frontend/src/component/admin/auth/OidcAuth/OidcAuth.tsx +++ b/frontend/src/component/admin/auth/OidcAuth/OidcAuth.tsx @@ -21,6 +21,10 @@ import { formatUnknownError } from 'utils/formatUnknownError'; import { removeEmptyStringFields } from 'utils/removeEmptyStringFields'; import { SsoGroupSettings } from '../SsoGroupSettings'; import type { IRole } from 'interfaces/role'; +import { useUiFlag } from 'hooks/useUiFlag'; +import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; +import { useScim } from 'hooks/useScim'; +import { ScimConfigSettings } from '../ScimSettings/ScimSettings'; const initialState = { enabled: false, @@ -85,6 +89,22 @@ export const OidcAuth = () => { }); }; + const { + settings, + enabled, + setEnabled, + assumeControlOfExisting, + setAssumeControlOfExisting, + newToken, + tokenGenerationDialog, + setTokenGenerationDialog, + tokenDialog, + setTokenDialog, + loading: scimLoading, + saveScimSettings, + onGenerateNewTokenConfirm, + } = useScim(); + const onSubmit = async (event: React.SyntheticEvent) => { event.preventDefault(); @@ -94,11 +114,14 @@ export const OidcAuth = () => { title: 'Settings stored', type: 'success', }); + saveScimSettings(); } catch (error: unknown) { setToastApiError(formatUnknownError(error)); } }; + const scimEnabled = useUiFlag('scimApi'); + return ( <> @@ -255,6 +278,32 @@ export const OidcAuth = () => { data={data} setValue={setValue} /> + + + } + /> + { + - - Generate new token - - } - /> - + + + Assume control +

Assumes control of users and groups

- + + + setAssumeControlOfExisting(set_enabled) + } + value={assumeControlOfExisting} + name='assumeControlOfExisting' + checked={assumeControlOfExisting} + disabled={disabled} + /> + } + label={assumeControlOfExisting ? 'Enabled' : 'Disabled'} + /> + +
+ + + + + Generate new token + + } + /> + + { diff --git a/frontend/src/hooks/useScim.ts b/frontend/src/hooks/useScim.ts new file mode 100644 index 0000000000..80a1ebaa8f --- /dev/null +++ b/frontend/src/hooks/useScim.ts @@ -0,0 +1,66 @@ +import { useScimSettingsApi } from 'hooks/api/actions/useScimSettingsApi/useScimSettingsApi'; +import { useEffect, useState } from 'react'; +import { formatUnknownError } from 'utils/formatUnknownError'; +import useToast from 'hooks/useToast'; +import { useScimSettings } from './api/getters/useScimSettings/useScimSettings'; + +export const useScim = () => { + const [newToken, setNewToken] = useState(''); + const [enabled, setEnabled] = useState(false); + const [tokenGenerationDialog, setTokenGenerationDialog] = useState(false); + const [tokenDialog, setTokenDialog] = useState(false); + const [assumeControlOfExisting, setAssumeControlOfExisting] = + useState(false); + + const { saveSettings, generateNewToken, errors, loading } = + useScimSettingsApi(); + + const { settings, refetch } = useScimSettings(); + const { setToastData, setToastApiError } = useToast(); + const saveScimSettings = async () => { + try { + await saveSettings({ enabled, assumeControlOfExisting }); + if (enabled && !settings.hasToken) { + const token = await generateNewToken(); + setNewToken(token); + setTokenDialog(true); + } + + setToastData({ + title: 'Settings stored', + type: 'success', + }); + refetch(); + } catch (error: unknown) { + setToastApiError(formatUnknownError(error)); + } + }; + + const onGenerateNewTokenConfirm = async () => { + setTokenGenerationDialog(false); + const token = await generateNewToken(); + setNewToken(token); + setTokenDialog(true); + }; + + useEffect(() => { + setEnabled(settings.enabled ?? false); + setAssumeControlOfExisting(settings.assumeControlOfExisting ?? false); + }, [settings]); + + return { + settings, + enabled, + setEnabled, + assumeControlOfExisting, + setAssumeControlOfExisting, + newToken, + tokenGenerationDialog, + setTokenGenerationDialog, + tokenDialog, + setTokenDialog, + loading, + saveScimSettings, + onGenerateNewTokenConfirm, + }; +};