mirror of
https://github.com/Unleash/unleash.git
synced 2025-03-04 00:18:40 +01:00
feat: list all root roles in SSO config (#5887)
Lists all root roles in SSO config, including custom root roles. 
This commit is contained in:
parent
9d839299e2
commit
0ba37e8622
@ -3,40 +3,49 @@ import {
|
||||
FormControl,
|
||||
FormControlLabel,
|
||||
Grid,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
Switch,
|
||||
TextField,
|
||||
SelectChangeEvent,
|
||||
} from '@mui/material';
|
||||
import { RoleSelect } from 'component/common/RoleSelect/RoleSelect';
|
||||
import { useRoles } from 'hooks/api/getters/useRoles/useRoles';
|
||||
import { IRole } from 'interfaces/role';
|
||||
|
||||
interface IAutoCreateFormProps {
|
||||
data?: {
|
||||
enabled: boolean;
|
||||
autoCreate: boolean;
|
||||
defaultRootRole?: string;
|
||||
defaultRootRoleId?: number;
|
||||
emailDomains?: string;
|
||||
};
|
||||
setValue: (name: string, value: string | boolean) => void;
|
||||
setValue: (
|
||||
name: string,
|
||||
value: string | boolean | number | undefined,
|
||||
) => void;
|
||||
}
|
||||
|
||||
export const AutoCreateForm = ({
|
||||
data = { enabled: false, autoCreate: false },
|
||||
setValue,
|
||||
}: IAutoCreateFormProps) => {
|
||||
const { roles } = useRoles();
|
||||
|
||||
const updateAutoCreate = () => {
|
||||
setValue('autoCreate', !data.autoCreate);
|
||||
};
|
||||
|
||||
const updateDefaultRootRole = (evt: SelectChangeEvent) => {
|
||||
setValue('defaultRootRole', evt.target.value);
|
||||
const updateDefaultRootRoleId = (role: IRole | null) => {
|
||||
setValue('defaultRootRoleId', role?.id);
|
||||
};
|
||||
|
||||
const updateField = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setValue(e.target.name, e.target.value);
|
||||
};
|
||||
|
||||
const roleIdToRole = (rootRoleId: number | undefined): IRole | null => {
|
||||
return roles.find((role: IRole) => role.id === rootRoleId) || null;
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid container spacing={3} mb={2}>
|
||||
@ -69,24 +78,15 @@ export const AutoCreateForm = ({
|
||||
</p>
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<FormControl style={{ minWidth: '200px' }}>
|
||||
<InputLabel id='defaultRootRole-label'>
|
||||
Default Role
|
||||
</InputLabel>
|
||||
<Select
|
||||
label='Default Role'
|
||||
labelId='defaultRootRole-label'
|
||||
id='defaultRootRole'
|
||||
name='defaultRootRole'
|
||||
<FormControl style={{ width: '400px' }}>
|
||||
<RoleSelect
|
||||
roles={roles}
|
||||
value={roleIdToRole(data.defaultRootRoleId)}
|
||||
setValue={updateDefaultRootRoleId}
|
||||
disabled={!data.autoCreate || !data.enabled}
|
||||
value={data.defaultRootRole || 'Editor'}
|
||||
onChange={updateDefaultRootRole}
|
||||
>
|
||||
{/*consider these from API or constants. */}
|
||||
<MenuItem value='Viewer'>Viewer</MenuItem>
|
||||
<MenuItem value='Editor'>Editor</MenuItem>
|
||||
<MenuItem value='Admin'>Admin</MenuItem>
|
||||
</Select>
|
||||
required
|
||||
hideDescription
|
||||
/>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
@ -60,7 +60,10 @@ export const OidcAuth = () => {
|
||||
setData({ ...data, enableSingleSignOut: !data.enableSingleSignOut });
|
||||
};
|
||||
|
||||
const setValue = (name: string, value: string | boolean) => {
|
||||
const setValue = (
|
||||
name: string,
|
||||
value: string | boolean | number | undefined,
|
||||
) => {
|
||||
setData({
|
||||
...data,
|
||||
[name]: value,
|
||||
|
@ -51,7 +51,10 @@ export const SamlAuth = () => {
|
||||
setData({ ...data, enabled: !data.enabled });
|
||||
};
|
||||
|
||||
const setValue = (name: string, value: string | boolean) => {
|
||||
const setValue = (
|
||||
name: string,
|
||||
value: string | boolean | number | undefined,
|
||||
) => {
|
||||
setData({
|
||||
...data,
|
||||
[name]: value,
|
||||
|
@ -23,6 +23,7 @@ interface IRoleSelectProps
|
||||
value: IRole | null;
|
||||
setValue: (role: IRole | null) => void;
|
||||
required?: boolean;
|
||||
hideDescription?: boolean;
|
||||
}
|
||||
|
||||
export const RoleSelect = ({
|
||||
@ -30,6 +31,7 @@ export const RoleSelect = ({
|
||||
value,
|
||||
setValue,
|
||||
required,
|
||||
hideDescription,
|
||||
...rest
|
||||
}: IRoleSelectProps) => {
|
||||
const renderRoleOption = (
|
||||
@ -60,7 +62,7 @@ export const RoleSelect = ({
|
||||
{...rest}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(value)}
|
||||
condition={Boolean(value) && !hideDescription}
|
||||
show={() => (
|
||||
<RoleDescription sx={{ marginTop: 1 }} roleId={value!.id} />
|
||||
)}
|
||||
|
@ -12,12 +12,13 @@ import {
|
||||
IUserRole,
|
||||
IUserWithProjectRoles,
|
||||
} from '../types/stores/access-store';
|
||||
import { IPermission, IUserAccessOverview, RoleType } from '../types/model';
|
||||
import { IPermission, IUserAccessOverview } from '../types/model';
|
||||
import NotFoundError from '../error/notfound-error';
|
||||
import {
|
||||
ENVIRONMENT_PERMISSION_TYPE,
|
||||
PROJECT_ROLE_TYPES,
|
||||
ROOT_PERMISSION_TYPE,
|
||||
ROOT_ROLE_TYPES,
|
||||
} from '../util/constants';
|
||||
import { Db } from './db';
|
||||
import {
|
||||
@ -407,8 +408,8 @@ export class AccessStore implements IAccessStore {
|
||||
.select(['id', 'name', 'type', 'description'])
|
||||
.from<IRole[]>(T.ROLES)
|
||||
.innerJoin(`${T.ROLE_USER} as ru`, 'ru.role_id', 'id')
|
||||
.where('ru.user_id', '=', userId)
|
||||
.andWhere('type', '=', RoleType.ROOT)
|
||||
.whereIn('type', ROOT_ROLE_TYPES)
|
||||
.andWhere('ru.user_id', '=', userId)
|
||||
.first();
|
||||
}
|
||||
|
||||
|
@ -18,12 +18,14 @@ import { BadDataError } from '../../../lib/error';
|
||||
import PasswordMismatch from '../../../lib/error/password-mismatch';
|
||||
import { EventService } from '../../../lib/services';
|
||||
import {
|
||||
CREATE_ADDON,
|
||||
IUnleashStores,
|
||||
IUserStore,
|
||||
USER_CREATED,
|
||||
USER_DELETED,
|
||||
USER_UPDATED,
|
||||
} from '../../../lib/types';
|
||||
import { CUSTOM_ROOT_ROLE_TYPE } from '../../../lib/util';
|
||||
|
||||
let db: ITestDb;
|
||||
let stores: IUnleashStores;
|
||||
@ -31,9 +33,11 @@ let userService: UserService;
|
||||
let userStore: IUserStore;
|
||||
let adminRole: IRole;
|
||||
let viewerRole: IRole;
|
||||
let customRole: IRole;
|
||||
let sessionService: SessionService;
|
||||
let settingService: SettingService;
|
||||
let eventService: EventService;
|
||||
let accessService: AccessService;
|
||||
|
||||
beforeAll(async () => {
|
||||
db = await dbInit('user_service_serial', getLogger);
|
||||
@ -41,7 +45,7 @@ beforeAll(async () => {
|
||||
const config = createTestConfig();
|
||||
eventService = new EventService(stores, config);
|
||||
const groupService = new GroupService(stores, config, eventService);
|
||||
const accessService = new AccessService(
|
||||
accessService = new AccessService(
|
||||
stores,
|
||||
config,
|
||||
groupService,
|
||||
@ -64,6 +68,17 @@ beforeAll(async () => {
|
||||
const rootRoles = await accessService.getRootRoles();
|
||||
adminRole = rootRoles.find((r) => r.name === RoleName.ADMIN)!;
|
||||
viewerRole = rootRoles.find((r) => r.name === RoleName.VIEWER)!;
|
||||
customRole = await accessService.createRole({
|
||||
name: 'Custom role',
|
||||
type: CUSTOM_ROOT_ROLE_TYPE,
|
||||
description: 'A custom role',
|
||||
permissions: [
|
||||
{
|
||||
name: CREATE_ADDON,
|
||||
},
|
||||
],
|
||||
createdByUserId: 1,
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
@ -401,3 +416,41 @@ test('should throw if autoCreate is false via SSO', async () => {
|
||||
}),
|
||||
).rejects.toThrow(new NotFoundError('No user found'));
|
||||
});
|
||||
|
||||
test('should support a root role id when logging in and creating user via SSO', async () => {
|
||||
const name = 'root-role-id';
|
||||
const email = `${name}@test.com`;
|
||||
const user = await userService.loginUserSSO({
|
||||
email,
|
||||
rootRole: viewerRole.id,
|
||||
name,
|
||||
autoCreate: true,
|
||||
});
|
||||
|
||||
const userWithRole = await userService.getUser(user.id);
|
||||
expect(user.email).toBe(email);
|
||||
expect(user.name).toBe(name);
|
||||
expect(userWithRole.name).toBe(name);
|
||||
expect(userWithRole.rootRole).toBe(viewerRole.id);
|
||||
});
|
||||
|
||||
test('should support a custom root role id when logging in and creating user via SSO', async () => {
|
||||
const name = 'custom-root-role-id';
|
||||
const email = `${name}@test.com`;
|
||||
const user = await userService.loginUserSSO({
|
||||
email,
|
||||
rootRole: customRole.id,
|
||||
name,
|
||||
autoCreate: true,
|
||||
});
|
||||
|
||||
const userWithRole = await userService.getUser(user.id);
|
||||
expect(user.email).toBe(email);
|
||||
expect(user.name).toBe(name);
|
||||
expect(userWithRole.name).toBe(name);
|
||||
expect(userWithRole.rootRole).toBe(customRole.id);
|
||||
|
||||
const permissions = await accessService.getPermissionsForUser(user);
|
||||
expect(permissions).toHaveLength(1);
|
||||
expect(permissions[0].permission).toBe(CREATE_ADDON);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user