mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-04 00:18:01 +01:00
fix: changeRole to assign roles without existing members
Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
This commit is contained in:
parent
d264f30fa0
commit
d4521a1c0c
23
src/lib/error/project-without-owner-error.ts
Normal file
23
src/lib/error/project-without-owner-error.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
export default class ProjectWithoutOwnerError extends Error {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
Error.captureStackTrace(this, this.constructor);
|
||||||
|
|
||||||
|
this.name = this.constructor.name;
|
||||||
|
this.message = 'A project must have at least one owner';
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(): any {
|
||||||
|
const obj = {
|
||||||
|
isJoi: true,
|
||||||
|
name: this.constructor.name,
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
validationErrors: [],
|
||||||
|
message: this.message,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
@ -66,6 +66,8 @@ export const handleErrors: (
|
|||||||
return res.status(409).json(error).end();
|
return res.status(409).json(error).end();
|
||||||
case 'RoleInUseError':
|
case 'RoleInUseError':
|
||||||
return res.status(400).json(error).end();
|
return res.status(400).json(error).end();
|
||||||
|
case 'ProjectWithoutOwnerError':
|
||||||
|
return res.status(409).json(error).end();
|
||||||
default:
|
default:
|
||||||
logger.error('Server failed executing request', error);
|
logger.error('Server failed executing request', error);
|
||||||
return res.status(500).end();
|
return res.status(500).end();
|
||||||
|
@ -36,6 +36,7 @@ import NoAccessError from '../error/no-access-error';
|
|||||||
import IncompatibleProjectError from '../error/incompatible-project-error';
|
import IncompatibleProjectError from '../error/incompatible-project-error';
|
||||||
import { DEFAULT_PROJECT } from '../types/project';
|
import { DEFAULT_PROJECT } from '../types/project';
|
||||||
import { IFeatureTagStore } from 'lib/types/stores/feature-tag-store';
|
import { IFeatureTagStore } from 'lib/types/stores/feature-tag-store';
|
||||||
|
import ProjectWithoutOwnerError from '../error/project-without-owner-error';
|
||||||
|
|
||||||
const getCreatedBy = (user: User) => user.email || user.username;
|
const getCreatedBy = (user: User) => user.email || user.username;
|
||||||
|
|
||||||
@ -349,7 +350,7 @@ export default class ProjectService {
|
|||||||
projectId,
|
projectId,
|
||||||
);
|
);
|
||||||
if (users.length < 2) {
|
if (users.length < 2) {
|
||||||
throw new Error('A project must have at least one owner');
|
throw new ProjectWithoutOwnerError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -360,8 +361,6 @@ export default class ProjectService {
|
|||||||
userId: number,
|
userId: number,
|
||||||
createdBy: string,
|
createdBy: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const role = await this.findProjectRole(projectId, roleId);
|
|
||||||
|
|
||||||
const usersWithRoles = await this.getUsersWithAccess(projectId);
|
const usersWithRoles = await this.getUsersWithAccess(projectId);
|
||||||
const user = usersWithRoles.users.find((u) => u.id === userId);
|
const user = usersWithRoles.users.find((u) => u.id === userId);
|
||||||
const currentRole = usersWithRoles.roles.find(
|
const currentRole = usersWithRoles.roles.find(
|
||||||
@ -380,6 +379,7 @@ export default class ProjectService {
|
|||||||
roleId,
|
roleId,
|
||||||
projectId,
|
projectId,
|
||||||
);
|
);
|
||||||
|
const role = await this.findProjectRole(projectId, roleId);
|
||||||
|
|
||||||
await this.eventStore.store(
|
await this.eventStore.store(
|
||||||
new ProjectUserUpdateRoleEvent({
|
new ProjectUserUpdateRoleEvent({
|
||||||
|
@ -685,6 +685,43 @@ test('should update role for user on project', async () => {
|
|||||||
expect(ownerUsers).toHaveLength(2);
|
expect(ownerUsers).toHaveLength(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should able to assign role without existing members', async () => {
|
||||||
|
const project = {
|
||||||
|
id: 'update-users-test',
|
||||||
|
name: 'New project',
|
||||||
|
description: 'Blah',
|
||||||
|
};
|
||||||
|
await projectService.createProject(project, user);
|
||||||
|
|
||||||
|
const projectMember1 = await stores.userStore.insert({
|
||||||
|
name: 'Some Member',
|
||||||
|
email: 'update1999@getunleash.io',
|
||||||
|
});
|
||||||
|
|
||||||
|
const testRole = await stores.roleStore.create({
|
||||||
|
name: 'Power user',
|
||||||
|
roleType: 'custom',
|
||||||
|
description: 'Grants access to modify all environments',
|
||||||
|
});
|
||||||
|
|
||||||
|
const memberRole = await stores.roleStore.getRoleByName(RoleName.MEMBER);
|
||||||
|
|
||||||
|
await projectService.addUser(project.id, memberRole.id, projectMember1.id);
|
||||||
|
await projectService.changeRole(
|
||||||
|
project.id,
|
||||||
|
testRole.id,
|
||||||
|
projectMember1.id,
|
||||||
|
'test',
|
||||||
|
);
|
||||||
|
|
||||||
|
const { users } = await projectService.getUsersWithAccess(project.id, user);
|
||||||
|
const memberUsers = users.filter((user) => user.roleId === memberRole.id);
|
||||||
|
const testUsers = users.filter((user) => user.roleId === testRole.id);
|
||||||
|
|
||||||
|
expect(memberUsers).toHaveLength(0);
|
||||||
|
expect(testUsers).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
test('should not update role for user on project when she is the owner', async () => {
|
test('should not update role for user on project when she is the owner', async () => {
|
||||||
const project = {
|
const project = {
|
||||||
id: 'update-users-not-allowed',
|
id: 'update-users-not-allowed',
|
||||||
|
Loading…
Reference in New Issue
Block a user