1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-08 01:15:49 +02:00

Fix/remove group owner concept (#1905)

* fix: remove group user role
This commit is contained in:
Simon Hornby 2022-08-11 08:23:08 +02:00 committed by GitHub
parent 0c8ebd4dcc
commit 38e428dacf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 26 additions and 56 deletions

View File

@ -42,7 +42,6 @@ const rowToGroupUser = (row) => {
return { return {
userId: row.user_id, userId: row.user_id,
groupId: row.group_id, groupId: row.group_id,
role: row.role,
joinedAt: row.created_at, joinedAt: row.created_at,
}; };
}; };
@ -112,7 +111,7 @@ export default class GroupStore implements IGroupStore {
async getAllUsersByGroups(groupIds: number[]): Promise<IGroupUser[]> { async getAllUsersByGroups(groupIds: number[]): Promise<IGroupUser[]> {
const rows = await this.db const rows = await this.db
.select('gu.group_id', 'u.id as user_id', 'role', 'gu.created_at') .select('gu.group_id', 'u.id as user_id', 'gu.created_at')
.from(`${T.GROUP_USER} AS gu`) .from(`${T.GROUP_USER} AS gu`)
.join(`${T.USERS} AS u`, 'u.id', 'gu.user_id') .join(`${T.USERS} AS u`, 'u.id', 'gu.user_id')
.whereIn('gu.group_id', groupIds); .whereIn('gu.group_id', groupIds);
@ -174,32 +173,12 @@ export default class GroupStore implements IGroupStore {
return { return {
group_id: groupId, group_id: groupId,
user_id: user.user.id, user_id: user.user.id,
role: user.role,
created_by: userName, created_by: userName,
}; };
}); });
return (transaction || this.db).batchInsert(T.GROUP_USER, rows); return (transaction || this.db).batchInsert(T.GROUP_USER, rows);
} }
async updateExistingUsersInGroup(
groupId: number,
existingUsers: IGroupUserModel[],
transaction?: Transaction,
): Promise<void> {
const queries = [];
existingUsers.forEach((user) => {
queries.push(
(transaction || this.db)(T.GROUP_USER)
.where({ group_id: groupId, user_id: user.user.id })
.update({ role: user.role })
.transacting(transaction),
);
});
await Promise.all(queries);
}
async deleteOldUsersFromGroup( async deleteOldUsersFromGroup(
deletableUsers: IGroupUser[], deletableUsers: IGroupUser[],
transaction?: Transaction, transaction?: Transaction,
@ -221,7 +200,6 @@ export default class GroupStore implements IGroupStore {
): Promise<void> { ): Promise<void> {
await this.db.transaction(async (tx) => { await this.db.transaction(async (tx) => {
await this.addNewUsersToGroup(groupId, newUsers, userName, tx); await this.addNewUsersToGroup(groupId, newUsers, userName, tx);
await this.updateExistingUsersInGroup(groupId, existingUsers, tx);
await this.deleteOldUsersFromGroup(deletableUsers, tx); await this.deleteOldUsersFromGroup(deletableUsers, tx);
}); });
} }

View File

@ -5,15 +5,12 @@ export const groupUserModelSchema = {
$id: '#/components/schemas/groupUserModelSchema', $id: '#/components/schemas/groupUserModelSchema',
type: 'object', type: 'object',
additionalProperties: false, additionalProperties: false,
required: ['role', 'user'], required: ['user'],
properties: { properties: {
joinedAt: { joinedAt: {
type: 'string', type: 'string',
format: 'date-time', format: 'date-time',
}, },
role: {
type: 'string',
},
user: { user: {
$ref: '#/components/schemas/userSchema', $ref: '#/components/schemas/userSchema',
}, },

View File

@ -9,7 +9,6 @@ test('groupsSchema', () => {
name: 'Group', name: 'Group',
users: [ users: [
{ {
role: 'Owner',
user: { user: {
id: 3, id: 3,
}, },

View File

@ -176,7 +176,7 @@ export class GroupService {
} }
async validateGroup( async validateGroup(
{ name, users }: IGroupModel, { name }: IGroupModel,
existingGroup?: IGroup, existingGroup?: IGroup,
): Promise<void> { ): Promise<void> {
if (!name) { if (!name) {
@ -188,10 +188,6 @@ export class GroupService {
throw new NameExistsError('Group name already exists'); throw new NameExistsError('Group name already exists');
} }
} }
if (users.length == 0 || !users.some((u) => u.role == 'Owner')) {
throw new BadDataError('Group needs to have at least one Owner');
}
} }
async getRolesForProject(projectId: string): Promise<IGroupRole[]> { async getRolesForProject(projectId: string): Promise<IGroupRole[]> {
@ -215,7 +211,6 @@ export class GroupService {
return { return {
user: user, user: user,
joinedAt: roleUser.joinedAt, joinedAt: roleUser.joinedAt,
role: roleUser.role,
}; };
}); });
return { ...group, users: finalUsers }; return { ...group, users: finalUsers };

View File

@ -13,7 +13,6 @@ export interface IGroup {
export interface IGroupUser { export interface IGroupUser {
groupId: number; groupId: number;
userId: number; userId: number;
role: string;
joinedAt: Date; joinedAt: Date;
seenAt?: Date; seenAt?: Date;
} }
@ -37,7 +36,6 @@ export interface IGroupProject {
export interface IGroupUserModel { export interface IGroupUserModel {
user: IUser; user: IUser;
role: string;
joinedAt?: Date; joinedAt?: Date;
} }

View File

@ -40,11 +40,6 @@ export interface IGroupStore extends Store<IGroup, number> {
userName: string, userName: string,
): Promise<void>; ): Promise<void>;
updateExistingUsersInGroup(
groupId: number,
users: IGroupUserModel[],
): Promise<void>;
existsWithName(name: string): Promise<boolean>; existsWithName(name: string): Promise<boolean>;
create(group: IStoreGroup): Promise<IGroup>; create(group: IStoreGroup): Promise<IGroup>;

View File

@ -0,0 +1,19 @@
'use strict';
exports.up = function (db, cb) {
db.runSql(
`
ALTER TABLE group_user DROP COLUMN IF EXISTS role;
`,
cb,
);
};
exports.down = function (db, cb) {
db.runSql(
`
ALTER TABLE group_user ADD COLUMN role text check(role in ('Owner', 'Member')) default 'Member';
`,
cb,
);
};

View File

@ -1359,15 +1359,11 @@ Object {
"format": "date-time", "format": "date-time",
"type": "string", "type": "string",
}, },
"role": Object {
"type": "string",
},
"user": Object { "user": Object {
"$ref": "#/components/schemas/userSchema", "$ref": "#/components/schemas/userSchema",
}, },
}, },
"required": Array [ "required": Array [
"role",
"user", "user",
], ],
"type": "object", "type": "object",

View File

@ -882,7 +882,7 @@ test('Should be allowed move feature toggle to project when given access through
await groupStore.addNewUsersToGroup( await groupStore.addNewUsersToGroup(
groupWithProjectAccess.id, groupWithProjectAccess.id,
[{ user: viewerUser, role: 'Owner' }], [{ user: viewerUser }],
'Admin', 'Admin',
); );
@ -919,7 +919,7 @@ test('Should not lose user role access when given permissions from a group', asy
await groupStore.addNewUsersToGroup( await groupStore.addNewUsersToGroup(
groupWithNoAccess.id, groupWithNoAccess.id,
[{ user: user, role: 'Owner' }], [{ user: user }],
'Admin', 'Admin',
); );
@ -968,13 +968,13 @@ test('Should allow user to take multiple group roles and have expected permissio
await groupStore.addNewUsersToGroup( await groupStore.addNewUsersToGroup(
groupWithCreateAccess.id, groupWithCreateAccess.id,
[{ user: viewerUser, role: 'Owner' }], [{ user: viewerUser }],
'Admin', 'Admin',
); );
await groupStore.addNewUsersToGroup( await groupStore.addNewUsersToGroup(
groupWithDeleteAccess.id, groupWithDeleteAccess.id,
[{ user: viewerUser, role: 'Owner' }], [{ user: viewerUser }],
'Admin', 'Admin',
); );

View File

@ -50,13 +50,6 @@ export default class FakeGroupStore implements IGroupStore {
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');
} }
updateExistingUsersInGroup(
id: number,
users: IGroupUserModel[],
): Promise<void> {
throw new Error('Method not implemented.');
}
getAllUsersByGroups(groupIds: number[]): Promise<IGroupUser[]> { getAllUsersByGroups(groupIds: number[]): Promise<IGroupUser[]> {
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');
} }