Skip to content

Commit

Permalink
fix: group roles assumption, refactor group types (#4576)
Browse files Browse the repository at this point in the history
Does what it says on the tin, should help with cleaning up
#4512 and respective schema
changes.

---------

Co-authored-by: Gastón Fournier <[email protected]>
  • Loading branch information
nunogois and gastonfournier authored Sep 5, 2023
1 parent 1ae700a commit c3216ac
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 62 deletions.
27 changes: 14 additions & 13 deletions frontend/cypress/integration/projects/access.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,6 @@ describe('project-access', () => {
id: groupAndProjectName,
name: groupAndProjectName,
});

cy.intercept('GET', `${baseUrl}/api/admin/ui-config`, req => {
req.headers['cache-control'] =
'no-cache, no-store, must-revalidate';
req.on('response', res => {
if (res.body) {
res.body.flags = {
...res.body.flags,
multipleRoles: true,
};
}
});
});
});

after(() => {
Expand All @@ -78,6 +65,20 @@ describe('project-access', () => {

beforeEach(() => {
cy.login_UI();

cy.intercept('GET', `${baseUrl}/api/admin/ui-config`, req => {
req.headers['cache-control'] =
'no-cache, no-store, must-revalidate';
req.on('response', res => {
if (res.body) {
res.body.flags = {
...res.body.flags,
multipleRoles: true,
};
}
});
});

cy.visit(`/projects/${groupAndProjectName}/settings/access`);
if (document.querySelector("[data-testid='CLOSE_SPLASH']")) {
cy.get("[data-testid='CLOSE_SPLASH']").click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,13 @@ export const ProjectAccessTable: VFC = () => {
id: 'role',
Header: 'Role',
accessor: (row: IProjectAccess) =>
row.entity.roles.length > 1
? `${row.entity.roles.length} roles`
: access?.roles.find(
({ id }) => id === row.entity.roleId
)?.name,
row.entity.roles
? row.entity.roles.length > 1
? `${row.entity.roles.length} roles`
: access?.roles.find(
({ id }) => id === row.entity.roleId
)?.name
: 'No Roles!',
Cell: ({
value,
row: { original: row },
Expand Down
4 changes: 2 additions & 2 deletions src/lib/db/group-store.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { IGroupStore, IStoreGroup } from '../types/stores/group-store';
import NotFoundError from '../error/notfound-error';
import Group, {
ICreateGroupModel,
ICreateGroupUserModel,
IGroup,
IGroupModel,
IGroupProject,
IGroupRole,
IGroupUser,
Expand Down Expand Up @@ -82,7 +82,7 @@ export default class GroupStore implements IGroupStore {
return groups.map(rowToGroup);
}

async update(group: ICreateGroupModel): Promise<IGroup> {
async update(group: IGroupModel): Promise<IGroup> {
try {
const rows = await this.db(T.GROUPS)
.where({ id: group.id })
Expand Down
2 changes: 1 addition & 1 deletion src/lib/services/access-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ test('throws error when trying to delete a project role in use by group', async
const eventStore = new FakeEventStore();
const groupStore = new FakeGroupStore();
groupStore.getAllWithId = async (): Promise<IGroup[]> => {
return [{ name: 'group' }];
return [{ id: 1, name: 'group' }];
};
const accountStore = new FakeAccountStore();
const roleStore = new FakeRoleStore();
Expand Down
21 changes: 4 additions & 17 deletions src/lib/services/group-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,7 @@ export class GroupService {
return newGroup;
}

async updateGroup(
group: ICreateGroupModel,
userName: string,
): Promise<IGroup> {
async updateGroup(group: IGroupModel, userName: string): Promise<IGroup> {
const preData = await this.groupStore.get(group.id);

await this.validateGroup(group, preData);
Expand Down Expand Up @@ -153,10 +150,10 @@ export class GroupService {

if (projectGroups.length > 0) {
const groups = await this.groupStore.getAllWithId(
projectGroups.map((g) => g.id!),
projectGroups.map((g) => g.id),
);
const groupUsers = await this.groupStore.getAllUsersByGroups(
groups.map((g) => g.id!),
groups.map((g) => g.id),
);
const users = await this.accountStore.getAllWithId(
groupUsers.map((u) => u.userId),
Expand All @@ -178,7 +175,7 @@ export class GroupService {
}

async validateGroup(
group: ICreateGroupModel,
group: IGroupModel | ICreateGroupModel,
existingGroup?: IGroup,
): Promise<void> {
if (!group.name) {
Expand All @@ -190,16 +187,6 @@ export class GroupService {
throw new NameExistsError('Group name already exists');
}
}

if (
group.id &&
group.rootRole &&
(await this.groupStore.hasProjectRole(group.id))
) {
throw new BadDataError(
'This group already has a project role and cannot also be given a root role',
);
}
}

async getRolesForProject(projectId: string): Promise<IGroupRole[]> {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/types/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Joi, { ValidationError } from 'joi';
import { IUser } from './user';

export interface IGroup {
id?: number;
id: number;
name: string;
description?: string;
mappingsSSO?: string[];
Expand Down Expand Up @@ -33,7 +33,7 @@ export interface IGroupModel extends IGroup {
projects?: string[];
}

export interface ICreateGroupModel extends IGroup {
export interface ICreateGroupModel extends Omit<IGroup, 'id'> {
users?: ICreateGroupUserModel[];
projects?: string[];
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib/types/stores/group-store.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Store } from './store';
import Group, {
ICreateGroupModel,
ICreateGroupUserModel,
IGroup,
IGroupModel,
IGroupProject,
IGroupRole,
IGroupUser,
Expand Down Expand Up @@ -48,7 +48,7 @@ export interface IGroupStore extends Store<IGroup, number> {

deleteUsersFromGroup(deletableUsers: IGroupUser[]): Promise<void>;

update(group: ICreateGroupModel): Promise<IGroup>;
update(group: IGroupModel): Promise<IGroup>;

getAllUsersByGroups(groupIds: number[]): Promise<IGroupUser[]>;

Expand Down
28 changes: 14 additions & 14 deletions src/test/e2e/services/access-service.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const createGroup = async ({
name: `Group ${groupIndex}`,
rootRole: role,
});
if (users) await groupStore.addUsersToGroup(group.id!, users, 'Admin');
if (users) await groupStore.addUsersToGroup(group.id, users, 'Admin');
return group;
};

Expand Down Expand Up @@ -1292,7 +1292,7 @@ test('if group has two roles user has union of permissions from the two roles',

await accessService.setProjectRolesForGroup(
projectName,
emptyGroup.id!,
emptyGroup.id,
[firstRole.id, secondRole.id],
'testusr',
);
Expand Down Expand Up @@ -1347,7 +1347,7 @@ test('calling set for group overwrites existing roles', async () => {

await accessService.setProjectRolesForGroup(
projectName,
emptyGroup.id!,
emptyGroup.id,
[firstRole.id, secondRole.id],
'testusr',
);
Expand All @@ -1363,7 +1363,7 @@ test('calling set for group overwrites existing roles', async () => {

await accessService.setProjectRolesForGroup(
projectName,
emptyGroup.id!,
emptyGroup.id,
[firstRole.id],
'testusr',
);
Expand Down Expand Up @@ -1404,7 +1404,7 @@ test('group with root role can be assigned a project specific role', async () =>

await accessService.setProjectRolesForGroup(
projectName,
emptyGroup.id!,
emptyGroup.id,
[firstRole.id],
'testusr',
);
Expand Down Expand Up @@ -1638,7 +1638,7 @@ test('calling set roles for group with invalid project role ids should not assig

accessService.setProjectRolesForGroup(
projectName,
emptyGroup.id!,
emptyGroup.id,
[adminRootRole.id, 9999],
'admin',
);
Expand Down Expand Up @@ -1669,7 +1669,7 @@ test('calling set roles for group with empty role array removes all roles', asyn

await accessService.setProjectRolesForGroup(
projectName,
emptyGroup.id!,
emptyGroup.id,
[role.id],
'admin',
);
Expand All @@ -1682,7 +1682,7 @@ test('calling set roles for group with empty role array removes all roles', asyn

await accessService.setProjectRolesForGroup(
projectName,
emptyGroup.id!,
emptyGroup.id,
[],
'admin',
);
Expand Down Expand Up @@ -1719,7 +1719,7 @@ test('calling set roles for group with empty role array should not remove root r

await accessService.setProjectRolesForGroup(
projectName,
group.id!,
group.id,
[role.id],
'admin',
);
Expand All @@ -1732,7 +1732,7 @@ test('calling set roles for group with empty role array should not remove root r

await accessService.setProjectRolesForGroup(
projectName,
group.id!,
group.id,
[],
'admin',
);
Expand Down Expand Up @@ -1778,7 +1778,7 @@ test('remove group access should remove all project roles', async () => {

await accessService.setProjectRolesForGroup(
projectName,
group.id!,
group.id,
[firstRole.id, secondRole.id],
'admin',
);
Expand All @@ -1789,7 +1789,7 @@ test('remove group access should remove all project roles', async () => {

expect(assignedPermissions.length).toBe(3);

await accessService.removeGroupAccess(projectName, group.id!);
await accessService.removeGroupAccess(projectName, group.id);

const newAssignedPermissions = await accessService.getPermissionsForUser(
emptyUser,
Expand Down Expand Up @@ -1831,7 +1831,7 @@ test('remove group access should remove all project roles, while leaving root ro

await accessService.setProjectRolesForGroup(
projectName,
group.id!,
group.id,
[firstRole.id, secondRole.id],
'admin',
);
Expand All @@ -1842,7 +1842,7 @@ test('remove group access should remove all project roles, while leaving root ro

expect(assignedPermissions.length).toBe(4);

await accessService.removeGroupAccess(projectName, group.id!);
await accessService.removeGroupAccess(projectName, group.id);

const newAssignedPermissions = await accessService.getPermissionsForUser(
adminUser,
Expand Down
6 changes: 2 additions & 4 deletions src/test/e2e/services/group-service.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ test('should not remove user from no SSO definition group', async () => {
expect(groups[0].name).toEqual('no_mapping_group');
});

test('adding a root role to a group with a project role should fail', async () => {
test('adding a root role to a group with a project role should not fail', async () => {
const group = await groupStore.create({
name: 'root_group',
description: 'root_group',
Expand All @@ -118,9 +118,7 @@ test('adding a root role to a group with a project role should fail', async () =
},
'test',
);
}).rejects.toThrow(
'This group already has a project role and cannot also be given a root role',
);
}).not.toThrow();

expect.assertions(1);
});
Expand Down
4 changes: 2 additions & 2 deletions src/test/fixtures/fake-group-store.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { IGroupStore, IStoreGroup } from '../../lib/types/stores/group-store';
import Group, {
ICreateGroupModel,
ICreateGroupUserModel,
IGroup,
IGroupModel,
IGroupProject,
IGroupRole,
IGroupUser,
Expand Down Expand Up @@ -63,7 +63,7 @@ export default class FakeGroupStore implements IGroupStore {
throw new Error('Method not implemented.');
}

update(group: ICreateGroupModel): Promise<IGroup> {
update(group: IGroupModel): Promise<IGroup> {
throw new Error('Method not implemented.');
}

Expand Down

0 comments on commit c3216ac

Please sign in to comment.