mirror of
https://github.com/Unleash/unleash.git
synced 2024-12-28 00:06:53 +01:00
feat: move SCIM config into separate tab (#7055)
Moves SCIM config back into separate tab ![image](https://github.com/Unleash/unleash/assets/707867/910f2128-08de-4460-a9e8-a606342669cd)
This commit is contained in:
parent
acb663df7a
commit
793cd76e93
@ -2,8 +2,10 @@ import { Alert, Tab, Tabs } from '@mui/material';
|
||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import { OidcAuth } from './OidcAuth/OidcAuth';
|
||||
import { SamlAuth } from './SamlAuth/SamlAuth';
|
||||
import { ScimSettings } from './ScimSettings/ScimSettings';
|
||||
import { PasswordAuth } from './PasswordAuth/PasswordAuth';
|
||||
import { GoogleAuth } from './GoogleAuth/GoogleAuth';
|
||||
import { PermissionGuard } from 'component/common/PermissionGuard/PermissionGuard';
|
||||
@ -14,7 +16,7 @@ import { TabPanel } from 'component/common/TabNav/TabPanel/TabPanel';
|
||||
|
||||
export const AuthSettings = () => {
|
||||
const { authenticationType } = useUiConfig().uiConfig;
|
||||
const { uiConfig } = useUiConfig();
|
||||
const { uiConfig, isEnterprise } = useUiConfig();
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
@ -37,6 +39,13 @@ export const AuthSettings = () => {
|
||||
(item) => uiConfig.flags?.googleAuthEnabled || item.label !== 'Google',
|
||||
);
|
||||
|
||||
if (isEnterprise() && useUiFlag('scimApi')) {
|
||||
tabs.push({
|
||||
label: 'SCIM',
|
||||
component: <ScimSettings />,
|
||||
});
|
||||
}
|
||||
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
|
||||
return (
|
||||
|
@ -17,10 +17,6 @@ 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,
|
||||
@ -80,24 +76,6 @@ export const SamlAuth = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const scimEnabled = useUiFlag('scimApi');
|
||||
|
||||
const {
|
||||
settings,
|
||||
enabled,
|
||||
setEnabled,
|
||||
assumeControlOfExisting,
|
||||
setAssumeControlOfExisting,
|
||||
newToken,
|
||||
tokenGenerationDialog,
|
||||
setTokenGenerationDialog,
|
||||
tokenDialog,
|
||||
setTokenDialog,
|
||||
loading: scimLoading,
|
||||
saveScimSettings,
|
||||
onGenerateNewTokenConfirm,
|
||||
} = useScim();
|
||||
|
||||
const onSubmit = async (event: React.SyntheticEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
@ -107,9 +85,6 @@ export const SamlAuth = () => {
|
||||
title: 'Settings stored',
|
||||
type: 'success',
|
||||
});
|
||||
if (scimEnabled) {
|
||||
saveScimSettings();
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
setToastApiError(formatUnknownError(error));
|
||||
}
|
||||
@ -288,31 +263,6 @@ export const SamlAuth = () => {
|
||||
setValue={setValue}
|
||||
/>
|
||||
|
||||
<ConditionallyRender
|
||||
condition={scimEnabled}
|
||||
show={
|
||||
<ScimConfigSettings
|
||||
disabled={!data.enabled}
|
||||
settings={settings}
|
||||
enabled={enabled}
|
||||
setEnabled={setEnabled}
|
||||
assumeControlOfExisting={assumeControlOfExisting}
|
||||
setAssumeControlOfExisting={
|
||||
setAssumeControlOfExisting
|
||||
}
|
||||
newToken={newToken}
|
||||
tokenGenerationDialog={tokenGenerationDialog}
|
||||
setTokenGenerationDialog={setTokenGenerationDialog}
|
||||
tokenDialog={tokenDialog}
|
||||
setTokenDialog={setTokenDialog}
|
||||
loading={scimLoading}
|
||||
onGenerateNewTokenConfirm={
|
||||
onGenerateNewTokenConfirm
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
<AutoCreateForm
|
||||
data={data}
|
||||
setValue={setValue}
|
||||
|
@ -1,51 +1,74 @@
|
||||
import { Button, FormControlLabel, Grid, Switch } from '@mui/material';
|
||||
import { Button, FormControlLabel, Grid, Switch, styled } from '@mui/material';
|
||||
import { Alert } from '@mui/material';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { ScimTokenGenerationDialog } from './ScimTokenGenerationDialog';
|
||||
import { ScimTokenDialog } from './ScimTokenDialog';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import type { ScimSettings } from 'hooks/api/getters/useScimSettings/useScimSettings';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||
import useToast from 'hooks/useToast';
|
||||
import { useScimSettingsApi } from 'hooks/api/actions/useScimSettingsApi/useScimSettingsApi';
|
||||
import { useScimSettings } from 'hooks/api/getters/useScimSettings/useScimSettings';
|
||||
|
||||
export interface IScimSettingsParameters {
|
||||
disabled: boolean;
|
||||
loading: boolean;
|
||||
enabled: boolean;
|
||||
setEnabled: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
assumeControlOfExisting: boolean;
|
||||
setAssumeControlOfExisting: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
newToken: string;
|
||||
settings: ScimSettings;
|
||||
tokenGenerationDialog: boolean;
|
||||
setTokenGenerationDialog: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
onGenerateNewTokenConfirm: () => void;
|
||||
tokenDialog: boolean;
|
||||
setTokenDialog: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
const StyledContainer = styled('div')(({ theme }) => ({
|
||||
padding: theme.spacing(3),
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
borderRadius: theme.shape.borderRadiusLarge,
|
||||
}));
|
||||
|
||||
export const ScimConfigSettings = ({
|
||||
disabled,
|
||||
loading,
|
||||
enabled,
|
||||
setEnabled,
|
||||
assumeControlOfExisting,
|
||||
setAssumeControlOfExisting,
|
||||
newToken,
|
||||
settings,
|
||||
tokenGenerationDialog,
|
||||
setTokenGenerationDialog,
|
||||
onGenerateNewTokenConfirm,
|
||||
tokenDialog,
|
||||
setTokenDialog,
|
||||
}: IScimSettingsParameters) => {
|
||||
const StyledTitleDiv = styled('div')(({ theme }) => ({
|
||||
marginBottom: theme.spacing(1),
|
||||
}));
|
||||
|
||||
export const ScimSettings = () => {
|
||||
const { uiConfig } = useUiConfig();
|
||||
const { setToastData, setToastApiError } = useToast();
|
||||
const [newToken, setNewToken] = useState('');
|
||||
const [tokenGenerationDialog, setTokenGenerationDialog] = useState(false);
|
||||
const [tokenDialog, setTokenDialog] = useState(false);
|
||||
const { settings, refetch } = useScimSettings();
|
||||
const [enabled, setEnabled] = useState(settings.enabled ?? true);
|
||||
|
||||
useEffect(() => {
|
||||
setEnabled(settings.enabled ?? false);
|
||||
}, [settings]);
|
||||
|
||||
const { saveSettings, generateNewToken, errors, loading } =
|
||||
useScimSettingsApi();
|
||||
|
||||
const onGenerateNewToken = async () => {
|
||||
setTokenGenerationDialog(true);
|
||||
};
|
||||
|
||||
const onGenerateNewTokenConfirm = async () => {
|
||||
setTokenGenerationDialog(false);
|
||||
const token = await generateNewToken();
|
||||
setNewToken(token);
|
||||
setTokenDialog(true);
|
||||
};
|
||||
|
||||
const saveScimSettings = async (enabled: boolean) => {
|
||||
try {
|
||||
setEnabled(enabled);
|
||||
await saveSettings({ enabled, assumeControlOfExisting: false });
|
||||
if (enabled && !settings.hasToken) {
|
||||
const token = await generateNewToken();
|
||||
setNewToken(token);
|
||||
setTokenDialog(true);
|
||||
}
|
||||
|
||||
setToastData({
|
||||
title: 'Settings stored',
|
||||
type: 'success',
|
||||
});
|
||||
await refetch();
|
||||
} catch (error: unknown) {
|
||||
setToastApiError(formatUnknownError(error));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<h3>SCIM Provisioning</h3>
|
||||
<Grid container sx={{ mb: 3 }}>
|
||||
<Grid item md={12}>
|
||||
<Alert severity='info'>
|
||||
@ -63,77 +86,69 @@ export const ScimConfigSettings = ({
|
||||
</Alert>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item md={5} mb={2}>
|
||||
<strong>Enable</strong>
|
||||
<p>Enable SCIM provisioning.</p>
|
||||
<StyledContainer>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item md={10.5} mb={2}>
|
||||
<StyledTitleDiv>
|
||||
<strong>SCIM provisioning</strong>
|
||||
</StyledTitleDiv>
|
||||
<p>
|
||||
Enables SCIM provisioning. If SCIM provisioning has
|
||||
not previously been enabled here this will also set
|
||||
up a new auth token to use with your SCIM client,
|
||||
and display it to the user. After the dialog has
|
||||
been closed, this token will not be displayed again.
|
||||
If you need a new token you can click the Generate
|
||||
new token button below which will replace the old
|
||||
token with a new token, and similarly display the
|
||||
new token one time to the user.
|
||||
</p>
|
||||
</Grid>
|
||||
<Grid item md={1.5}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
onChange={(_, enabled) => {
|
||||
saveScimSettings(enabled);
|
||||
}}
|
||||
value={enabled}
|
||||
name='enabled'
|
||||
checked={enabled}
|
||||
/>
|
||||
}
|
||||
label={enabled ? 'Enabled' : 'Disabled'}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
onChange={(_, enabled) => setEnabled(enabled)}
|
||||
value={enabled}
|
||||
name='enabled'
|
||||
checked={enabled}
|
||||
disabled={disabled}
|
||||
/>
|
||||
}
|
||||
label={enabled ? 'Enabled' : 'Disabled'}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid container spacing={3}>
|
||||
<Grid item md={5} mb={2}>
|
||||
<strong>Assume control</strong>
|
||||
<p>Assumes control of users and groups</p>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item md={5} mb={2}>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(settings.hasToken)}
|
||||
show={
|
||||
<Button
|
||||
variant='outlined'
|
||||
color='error'
|
||||
disabled={loading}
|
||||
onClick={onGenerateNewToken}
|
||||
>
|
||||
Generate new token
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
onChange={(_, set_enabled) =>
|
||||
setAssumeControlOfExisting(set_enabled)
|
||||
}
|
||||
value={assumeControlOfExisting}
|
||||
name='assumeControlOfExisting'
|
||||
checked={assumeControlOfExisting}
|
||||
disabled={disabled}
|
||||
/>
|
||||
}
|
||||
label={assumeControlOfExisting ? 'Enabled' : 'Disabled'}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid container spacing={3}>
|
||||
<Grid item md={5} mb={2}>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(settings.hasToken)}
|
||||
show={
|
||||
<Button
|
||||
variant='outlined'
|
||||
color='error'
|
||||
disabled={loading}
|
||||
onClick={onGenerateNewToken}
|
||||
>
|
||||
Generate new token
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<ScimTokenGenerationDialog
|
||||
open={tokenGenerationDialog}
|
||||
setOpen={setTokenGenerationDialog}
|
||||
onConfirm={onGenerateNewTokenConfirm}
|
||||
/>
|
||||
<ScimTokenDialog
|
||||
open={tokenDialog}
|
||||
setOpen={setTokenDialog}
|
||||
token={newToken}
|
||||
/>
|
||||
<ScimTokenGenerationDialog
|
||||
open={tokenGenerationDialog}
|
||||
setOpen={setTokenGenerationDialog}
|
||||
onConfirm={onGenerateNewTokenConfirm}
|
||||
/>
|
||||
<ScimTokenDialog
|
||||
open={tokenDialog}
|
||||
setOpen={setTokenDialog}
|
||||
token={newToken}
|
||||
/>
|
||||
</StyledContainer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,66 +0,0 @@
|
||||
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,
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue
Block a user