1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-03-18 00:19:49 +01:00

chore: add user access overview schema (#9552)

https://linear.app/unleash/issue/2-3403/add-response-schema-for-access-overview

Adds a response schema for the user access overview.
This commit is contained in:
Nuno Góis 2025-03-17 15:32:12 +00:00 committed by GitHub
parent 7efe5c5311
commit bf34ac18fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 140 additions and 10 deletions

View File

@ -209,6 +209,7 @@ export * from './update-tag-type-schema';
export * from './update-tags-schema'; export * from './update-tags-schema';
export * from './update-user-schema'; export * from './update-user-schema';
export * from './upsert-segment-schema'; export * from './upsert-segment-schema';
export * from './user-access-overview-schema';
export * from './user-schema'; export * from './user-schema';
export * from './users-groups-base-schema'; export * from './users-groups-base-schema';
export * from './users-schema'; export * from './users-schema';

View File

@ -0,0 +1,121 @@
import type { FromSchema } from 'json-schema-to-ts';
import { userSchema } from './user-schema';
import { roleSchema } from './role-schema';
const permission = {
type: 'object',
required: ['id', 'name', 'displayName', 'type'],
additionalProperties: false,
properties: {
id: {
type: 'integer',
description: 'The ID of the permission',
example: 1,
},
name: {
type: 'string',
description: 'The name of the permission',
example: 'CREATE_FEATURE_STRATEGY',
},
displayName: {
type: 'string',
description: 'The display name of the permission',
example: 'Create activation strategies',
},
type: {
type: 'string',
description: 'The type of the permission',
example: 'environment',
},
environment: {
type: 'string',
nullable: true,
description: 'The environment that the permission applies to',
example: 'dev',
},
},
} as const;
const permissionWithHasPermission = {
...permission,
required: [...permission.required, 'hasPermission'],
properties: {
...permission.properties,
hasPermission: {
type: 'boolean',
description: 'Whether the user has this permission',
example: true,
},
},
} as const;
export const userAccessOverviewSchema = {
$id: '#/components/schemas/userAccessOverviewSchema',
type: 'object',
required: ['overview', 'user', 'rootRole', 'projectRoles'],
additionalProperties: false,
description:
'Describes the access overview (list of permissions and metadata) for a user.',
properties: {
overview: {
type: 'object',
required: ['root', 'project', 'environment'],
additionalProperties: false,
description:
'The access overview (list of permissions) for the user',
properties: {
root: {
type: 'array',
description: 'The list of root permissions',
items: permissionWithHasPermission,
},
project: {
type: 'array',
description: 'The list of project permissions',
items: permissionWithHasPermission,
},
environment: {
type: 'array',
description: 'The list of environment permissions',
items: permissionWithHasPermission,
},
},
},
user: {
description: 'The user that this access overview is for',
$ref: userSchema.$id,
},
rootRole: {
description: 'The name of the root role that this user has',
$ref: roleSchema.$id,
},
projectRoles: {
type: 'array',
description:
'The list of project roles that this user has in the selected project',
items: {
type: 'object',
required: [...roleSchema.required, 'permissions'],
additionalProperties: false,
properties: {
...roleSchema.properties,
permissions: {
type: 'array',
description: 'The permissions that this role has',
items: permission,
},
},
},
},
},
components: {
schemas: {
userSchema,
roleSchema,
},
},
} as const;
export type UserAccessOverviewSchema = FromSchema<
typeof userAccessOverviewSchema
>;

View File

@ -55,6 +55,10 @@ import {
type CreateUserResponseSchema, type CreateUserResponseSchema,
} from '../../openapi/spec/create-user-response-schema'; } from '../../openapi/spec/create-user-response-schema';
import type { IRoleWithPermissions } from '../../types/stores/access-store'; import type { IRoleWithPermissions } from '../../types/stores/access-store';
import {
type UserAccessOverviewSchema,
userAccessOverviewSchema,
} from '../../openapi';
export default class UserAdminController extends Controller { export default class UserAdminController extends Controller {
private flagResolver: IFlagResolver; private flagResolver: IFlagResolver;
@ -260,7 +264,7 @@ export default class UserAdminController extends Controller {
handler: this.getPermissions, handler: this.getPermissions,
middleware: [ middleware: [
openApiService.validPath({ openApiService.validPath({
tags: ['Auth'], tags: ['Unstable'],
operationId: 'getUserPermissions', operationId: 'getUserPermissions',
summary: 'Returns the list of permissions for the user', summary: 'Returns the list of permissions for the user',
description: description:
@ -293,7 +297,7 @@ export default class UserAdminController extends Controller {
}, },
], ],
responses: { responses: {
200: emptyResponse, // TODO define schema 200: createResponseSchema(userAccessOverviewSchema.$id),
...getStandardResponses(401, 403, 415), ...getStandardResponses(401, 403, 415),
}, },
}), }),
@ -722,7 +726,7 @@ export default class UserAdminController extends Controller {
unknown, unknown,
{ project?: string; environment?: string } { project?: string; environment?: string }
>, >,
res: Response, res: Response<UserAccessOverviewSchema>,
): Promise<void> { ): Promise<void> {
const { project, environment } = req.query; const { project, environment } = req.query;
const user = await this.userService.getUser(req.params.id); const user = await this.userService.getUser(req.params.id);
@ -747,13 +751,17 @@ export default class UserAdminController extends Controller {
environment, environment,
); );
// TODO add response validation based on the schema this.openApiService.respondWithValidation(
res.status(200).json({ 200,
overview, res,
user, userAccessOverviewSchema.$id,
rootRole, {
projectRoles, overview,
}); user: serializeDates(user),
rootRole,
projectRoles,
},
);
} }
async throwIfScimUser({ async throwIfScimUser({