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

Grouping access endpoing (#1858)

* Grouping access endpoing

* Add username
This commit is contained in:
sjaanus 2022-07-26 11:39:55 +00:00 committed by GitHub
parent b9c95c5272
commit 5f8b88aa0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 156 additions and 9 deletions

View File

@ -104,6 +104,7 @@ import { URL } from 'url';
import { groupSchema } from './spec/group-schema'; import { groupSchema } from './spec/group-schema';
import { groupsSchema } from './spec/groups-schema'; import { groupsSchema } from './spec/groups-schema';
import { groupUserModelSchema } from './spec/group-user-model-schema'; import { groupUserModelSchema } from './spec/group-user-model-schema';
import { usersGroupsBaseSchema } from './spec/users-groups-base-schema';
// All schemas in `openapi/spec` should be listed here. // All schemas in `openapi/spec` should be listed here.
export const schemas = { export const schemas = {
@ -198,6 +199,7 @@ export const schemas = {
updateUserSchema, updateUserSchema,
upsertContextFieldSchema, upsertContextFieldSchema,
upsertStrategySchema, upsertStrategySchema,
usersGroupsBaseSchema,
userSchema, userSchema,
usersSchema, usersSchema,
usersSearchSchema, usersSearchSchema,

View File

@ -5,8 +5,8 @@ import { userSchema } from './user-schema';
export const groupSchema = { export const groupSchema = {
$id: '#/components/schemas/groupSchema', $id: '#/components/schemas/groupSchema',
type: 'object', type: 'object',
additionalProperties: false, additionalProperties: true,
required: ['name', 'users'], required: ['name'],
properties: { properties: {
id: { id: {
type: 'number', type: 'number',

View File

@ -0,0 +1,15 @@
import { validateSchema } from '../validate';
import { UsersGroupsBaseSchema } from './users-groups-base-schema';
test('usersGroupsBaseSchema', () => {
const data: UsersGroupsBaseSchema = {
users: [
{
id: 1,
},
],
};
expect(
validateSchema('#/components/schemas/usersGroupsBaseSchema', data),
).toBeUndefined();
});

View File

@ -0,0 +1,33 @@
import { FromSchema } from 'json-schema-to-ts';
import { groupSchema } from './group-schema';
import { userSchema } from './user-schema';
import { groupUserModelSchema } from './group-user-model-schema';
export const usersGroupsBaseSchema = {
$id: '#/components/schemas/usersGroupsBaseSchema',
type: 'object',
additionalProperties: false,
properties: {
groups: {
type: 'array',
items: {
$ref: '#/components/schemas/groupSchema',
},
},
users: {
type: 'array',
items: {
$ref: '#/components/schemas/userSchema',
},
},
},
components: {
schemas: {
groupSchema,
groupUserModelSchema,
userSchema,
},
},
} as const;
export type UsersGroupsBaseSchema = FromSchema<typeof usersGroupsBaseSchema>;

View File

@ -4,10 +4,9 @@ import { ADMIN, NONE } from '../../types/permissions';
import UserService from '../../services/user-service'; import UserService from '../../services/user-service';
import { AccessService } from '../../services/access-service'; import { AccessService } from '../../services/access-service';
import { Logger } from '../../logger'; import { Logger } from '../../logger';
import { IUnleashConfig } from '../../types/option'; import { IUnleashConfig, IUnleashServices } from '../../types';
import { EmailService } from '../../services/email-service'; import { EmailService } from '../../services/email-service';
import ResetTokenService from '../../services/reset-token-service'; import ResetTokenService from '../../services/reset-token-service';
import { IUnleashServices } from '../../types/services';
import { IAuthRequest } from '../unleash-types'; import { IAuthRequest } from '../unleash-types';
import SettingService from '../../services/setting-service'; import SettingService from '../../services/setting-service';
import { IUser, SimpleAuthSettings } from '../../server-impl'; import { IUser, SimpleAuthSettings } from '../../server-impl';
@ -32,6 +31,12 @@ import {
ResetPasswordSchema, ResetPasswordSchema,
} from '../../openapi/spec/reset-password-schema'; } from '../../openapi/spec/reset-password-schema';
import { emptyResponse } from '../../openapi/util/standard-responses'; import { emptyResponse } from '../../openapi/util/standard-responses';
import { GroupService } from '../../services/group-service';
import {
UsersGroupsBaseSchema,
usersGroupsBaseSchema,
} from '../../openapi/spec/users-groups-base-schema';
import { IGroup } from '../../types/group';
export default class UserAdminController extends Controller { export default class UserAdminController extends Controller {
private anonymise: boolean = false; private anonymise: boolean = false;
@ -50,6 +55,8 @@ export default class UserAdminController extends Controller {
private openApiService: OpenApiService; private openApiService: OpenApiService;
private groupService: GroupService;
readonly unleashUrl: string; readonly unleashUrl: string;
constructor( constructor(
@ -61,6 +68,7 @@ export default class UserAdminController extends Controller {
resetTokenService, resetTokenService,
settingService, settingService,
openApiService, openApiService,
groupService,
}: Pick< }: Pick<
IUnleashServices, IUnleashServices,
| 'userService' | 'userService'
@ -69,6 +77,7 @@ export default class UserAdminController extends Controller {
| 'resetTokenService' | 'resetTokenService'
| 'settingService' | 'settingService'
| 'openApiService' | 'openApiService'
| 'groupService'
>, >,
) { ) {
super(config); super(config);
@ -78,6 +87,7 @@ export default class UserAdminController extends Controller {
this.resetTokenService = resetTokenService; this.resetTokenService = resetTokenService;
this.settingService = settingService; this.settingService = settingService;
this.openApiService = openApiService; this.openApiService = openApiService;
this.groupService = groupService;
this.logger = config.getLogger('routes/user-controller.ts'); this.logger = config.getLogger('routes/user-controller.ts');
this.unleashUrl = config.server.unleashUrl; this.unleashUrl = config.server.unleashUrl;
this.anonymise = config.experimental?.anonymiseEventLog; this.anonymise = config.experimental?.anonymiseEventLog;
@ -147,7 +157,7 @@ export default class UserAdminController extends Controller {
method: 'get', method: 'get',
path: '/search', path: '/search',
handler: this.searchUsers, handler: this.searchUsers,
permission: ADMIN, permission: NONE,
middleware: [ middleware: [
openApiService.validPath({ openApiService.validPath({
tags: ['admin'], tags: ['admin'],
@ -157,6 +167,22 @@ export default class UserAdminController extends Controller {
], ],
}); });
this.route({
method: 'get',
path: '/access',
handler: this.getBaseUsersAndGroups,
permission: NONE,
middleware: [
openApiService.validPath({
tags: ['admin'],
operationId: 'getBaseUsersAndGroups',
responses: {
200: createResponseSchema('usersGroupsBaseSchema'),
},
}),
],
});
this.route({ this.route({
method: 'post', method: 'post',
path: '', path: '',
@ -279,6 +305,39 @@ export default class UserAdminController extends Controller {
); );
} }
async getBaseUsersAndGroups(
req: Request,
res: Response<UsersGroupsBaseSchema>,
): Promise<void> {
let allUsers = await this.userService.getAll();
let users = allUsers.map((u) => {
return {
id: u.id,
name: u.name,
username: u.username,
email: u.email,
} as IUser;
});
let allGroups = await this.groupService.getAll();
let groups = allGroups.map((g) => {
return {
id: g.id,
name: g.name,
userCount: g.users.length,
} as IGroup;
});
this.openApiService.respondWithValidation(
200,
res,
usersGroupsBaseSchema.$id,
{
users: serializeDates(users),
groups: serializeDates(groups),
},
);
}
async getUser(req: Request, res: Response<UserSchema>): Promise<void> { async getUser(req: Request, res: Response<UserSchema>): Promise<void> {
const { id } = req.params; const { id } = req.params;
const user = await this.userService.getUser(Number(id)); const user = await this.userService.getUser(Number(id));

View File

@ -4,8 +4,9 @@ import { IUser } from './user';
export interface IGroup { export interface IGroup {
id?: number; id?: number;
name: string; name: string;
description: string; description?: string;
createdAt?: Date; createdAt?: Date;
userCount?: number;
createdBy?: string; createdBy?: string;
} }

View File

@ -10,7 +10,7 @@ import {
export interface IStoreGroup { export interface IStoreGroup {
name: string; name: string;
description: string; description?: string;
} }
export interface IGroupStore extends Store<IGroup, number> { export interface IGroupStore extends Store<IGroup, number> {

View File

@ -1469,7 +1469,7 @@ Object {
"type": "object", "type": "object",
}, },
"groupSchema": Object { "groupSchema": Object {
"additionalProperties": false, "additionalProperties": true,
"properties": Object { "properties": Object {
"createdAt": Object { "createdAt": Object {
"format": "date-time", "format": "date-time",
@ -1504,7 +1504,6 @@ Object {
}, },
"required": Array [ "required": Array [
"name", "name",
"users",
], ],
"type": "object", "type": "object",
}, },
@ -2728,6 +2727,24 @@ Object {
], ],
"type": "object", "type": "object",
}, },
"usersGroupsBaseSchema": Object {
"additionalProperties": false,
"properties": Object {
"groups": Object {
"items": Object {
"$ref": "#/components/schemas/groupSchema",
},
"type": "array",
},
"users": Object {
"items": Object {
"$ref": "#/components/schemas/userSchema",
},
"type": "array",
},
},
"type": "object",
},
"usersSchema": Object { "usersSchema": Object {
"additionalProperties": false, "additionalProperties": false,
"properties": Object { "properties": Object {
@ -5710,6 +5727,26 @@ If the provided project does not exist, the list of events will be empty.",
], ],
}, },
}, },
"/api/admin/user-admin/access": Object {
"get": Object {
"operationId": "getBaseUsersAndGroups",
"responses": Object {
"200": Object {
"content": Object {
"application/json": Object {
"schema": Object {
"$ref": "#/components/schemas/usersGroupsBaseSchema",
},
},
},
"description": "usersGroupsBaseSchema",
},
},
"tags": Array [
"admin",
],
},
},
"/api/admin/user-admin/reset-password": Object { "/api/admin/user-admin/reset-password": Object {
"post": Object { "post": Object {
"operationId": "resetUserPassword", "operationId": "resetUserPassword",