Skip to content

Commit bf34ac1

Browse files
authored
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.
1 parent 7efe5c5 commit bf34ac1

File tree

3 files changed

+140
-10
lines changed

3 files changed

+140
-10
lines changed

src/lib/openapi/spec/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ export * from './update-tag-type-schema';
209209
export * from './update-tags-schema';
210210
export * from './update-user-schema';
211211
export * from './upsert-segment-schema';
212+
export * from './user-access-overview-schema';
212213
export * from './user-schema';
213214
export * from './users-groups-base-schema';
214215
export * from './users-schema';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import type { FromSchema } from 'json-schema-to-ts';
2+
import { userSchema } from './user-schema';
3+
import { roleSchema } from './role-schema';
4+
5+
const permission = {
6+
type: 'object',
7+
required: ['id', 'name', 'displayName', 'type'],
8+
additionalProperties: false,
9+
properties: {
10+
id: {
11+
type: 'integer',
12+
description: 'The ID of the permission',
13+
example: 1,
14+
},
15+
name: {
16+
type: 'string',
17+
description: 'The name of the permission',
18+
example: 'CREATE_FEATURE_STRATEGY',
19+
},
20+
displayName: {
21+
type: 'string',
22+
description: 'The display name of the permission',
23+
example: 'Create activation strategies',
24+
},
25+
type: {
26+
type: 'string',
27+
description: 'The type of the permission',
28+
example: 'environment',
29+
},
30+
environment: {
31+
type: 'string',
32+
nullable: true,
33+
description: 'The environment that the permission applies to',
34+
example: 'dev',
35+
},
36+
},
37+
} as const;
38+
39+
const permissionWithHasPermission = {
40+
...permission,
41+
required: [...permission.required, 'hasPermission'],
42+
properties: {
43+
...permission.properties,
44+
hasPermission: {
45+
type: 'boolean',
46+
description: 'Whether the user has this permission',
47+
example: true,
48+
},
49+
},
50+
} as const;
51+
52+
export const userAccessOverviewSchema = {
53+
$id: '#/components/schemas/userAccessOverviewSchema',
54+
type: 'object',
55+
required: ['overview', 'user', 'rootRole', 'projectRoles'],
56+
additionalProperties: false,
57+
description:
58+
'Describes the access overview (list of permissions and metadata) for a user.',
59+
properties: {
60+
overview: {
61+
type: 'object',
62+
required: ['root', 'project', 'environment'],
63+
additionalProperties: false,
64+
description:
65+
'The access overview (list of permissions) for the user',
66+
properties: {
67+
root: {
68+
type: 'array',
69+
description: 'The list of root permissions',
70+
items: permissionWithHasPermission,
71+
},
72+
project: {
73+
type: 'array',
74+
description: 'The list of project permissions',
75+
items: permissionWithHasPermission,
76+
},
77+
environment: {
78+
type: 'array',
79+
description: 'The list of environment permissions',
80+
items: permissionWithHasPermission,
81+
},
82+
},
83+
},
84+
user: {
85+
description: 'The user that this access overview is for',
86+
$ref: userSchema.$id,
87+
},
88+
rootRole: {
89+
description: 'The name of the root role that this user has',
90+
$ref: roleSchema.$id,
91+
},
92+
projectRoles: {
93+
type: 'array',
94+
description:
95+
'The list of project roles that this user has in the selected project',
96+
items: {
97+
type: 'object',
98+
required: [...roleSchema.required, 'permissions'],
99+
additionalProperties: false,
100+
properties: {
101+
...roleSchema.properties,
102+
permissions: {
103+
type: 'array',
104+
description: 'The permissions that this role has',
105+
items: permission,
106+
},
107+
},
108+
},
109+
},
110+
},
111+
components: {
112+
schemas: {
113+
userSchema,
114+
roleSchema,
115+
},
116+
},
117+
} as const;
118+
119+
export type UserAccessOverviewSchema = FromSchema<
120+
typeof userAccessOverviewSchema
121+
>;

src/lib/routes/admin-api/user-admin.ts

+18-10
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ import {
5555
type CreateUserResponseSchema,
5656
} from '../../openapi/spec/create-user-response-schema';
5757
import type { IRoleWithPermissions } from '../../types/stores/access-store';
58+
import {
59+
type UserAccessOverviewSchema,
60+
userAccessOverviewSchema,
61+
} from '../../openapi';
5862

5963
export default class UserAdminController extends Controller {
6064
private flagResolver: IFlagResolver;
@@ -260,7 +264,7 @@ export default class UserAdminController extends Controller {
260264
handler: this.getPermissions,
261265
middleware: [
262266
openApiService.validPath({
263-
tags: ['Auth'],
267+
tags: ['Unstable'],
264268
operationId: 'getUserPermissions',
265269
summary: 'Returns the list of permissions for the user',
266270
description:
@@ -293,7 +297,7 @@ export default class UserAdminController extends Controller {
293297
},
294298
],
295299
responses: {
296-
200: emptyResponse, // TODO define schema
300+
200: createResponseSchema(userAccessOverviewSchema.$id),
297301
...getStandardResponses(401, 403, 415),
298302
},
299303
}),
@@ -722,7 +726,7 @@ export default class UserAdminController extends Controller {
722726
unknown,
723727
{ project?: string; environment?: string }
724728
>,
725-
res: Response,
729+
res: Response<UserAccessOverviewSchema>,
726730
): Promise<void> {
727731
const { project, environment } = req.query;
728732
const user = await this.userService.getUser(req.params.id);
@@ -747,13 +751,17 @@ export default class UserAdminController extends Controller {
747751
environment,
748752
);
749753

750-
// TODO add response validation based on the schema
751-
res.status(200).json({
752-
overview,
753-
user,
754-
rootRole,
755-
projectRoles,
756-
});
754+
this.openApiService.respondWithValidation(
755+
200,
756+
res,
757+
userAccessOverviewSchema.$id,
758+
{
759+
overview,
760+
user: serializeDates(user),
761+
rootRole,
762+
projectRoles,
763+
},
764+
);
757765
}
758766

759767
async throwIfScimUser({

0 commit comments

Comments
 (0)