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

chore: Minor code cleanups

This commit is contained in:
sighphyre 2022-01-06 10:59:41 +02:00 committed by Ivar Conradi Østhus
parent 26db43b248
commit b56ed05db1
No known key found for this signature in database
GPG Key ID: 31AC596886B0BD09
9 changed files with 98 additions and 54 deletions

View File

@ -11,6 +11,10 @@ import {
import { IPermission } from 'lib/types/model';
import { roundToNearestMinutesWithOptions } from 'date-fns/fp';
import NotFoundError from '../error/notfound-error';
import {
ENVIRONMENT_PERMISSION_TYPE,
ROOT_PERMISSION_TYPE,
} from 'lib/util/constants';
const T = {
ROLE_USER: 'role_user',
@ -126,14 +130,17 @@ export class AccessStore implements IAccessStore {
// Since the editor should have access to the default project,
// we map the project to the project and environment specific
// permissions that are connected to the editor role.
if (row.role_id === EDITOR_ID && row.type !== 'root') {
if (row.role_id === EDITOR_ID && row.type !== ROOT_PERMISSION_TYPE) {
project = 'default';
} else if (row.type !== 'root') {
} else if (row.type !== ROOT_PERMISSION_TYPE) {
project = row.project ? row.project : undefined;
}
const environment =
row.type === 'environment' ? row.environment : undefined;
row.type === ENVIRONMENT_PERMISSION_TYPE
? row.environment
: undefined;
return {
project,
environment,
@ -170,11 +177,11 @@ export class AccessStore implements IAccessStore {
role_id: number,
permissions: IPermission[],
): Promise<void> {
const rows = permissions.map((x) => {
const rows = permissions.map((permission) => {
return {
role_id,
permission_id: x.id,
environment: x.environment,
permission_id: permission.id,
environment: permission.environment,
};
});
this.db.batchInsert(T.ROLE_PERMISSION, rows);
@ -217,7 +224,7 @@ export class AccessStore implements IAccessStore {
return rows.map((r) => r.user_id);
}
async addUserToRole(
async addUserToProjectRole(
userId: number,
roleId: number,
projecId: string,
@ -229,7 +236,7 @@ export class AccessStore implements IAccessStore {
});
}
async removeUserFromRole(
async removeUserFromProjectRole(
userId: number,
roleId: number,
projectId: string,

View File

@ -101,15 +101,6 @@ export default class RoleStore implements IRoleStore {
return result.length > 0;
}
async roleExists(name: string): Promise<boolean> {
const result = await this.db.raw(
`SELECT EXISTS (SELECT 1 FROM ${T.ROLES} WHERE name = ?) AS present`,
[name],
);
const { present } = result.rows[0];
return present;
}
async deleteAll(): Promise<void> {
return this.db(T.ROLES).del();
}
@ -181,8 +172,8 @@ export default class RoleStore implements IRoleStore {
.where('r.type', '=', 'root');
return rows.map((row) => ({
roleId: +row.id,
userId: +row.user_id,
roleId: Number(row.id),
userId: Number(row.user_id),
}));
}

View File

@ -158,8 +158,8 @@ export class AccessService {
const allEnvironmentPermissions = environments.map((env) => {
return {
name: env.name,
permissions: environmentPermissions.map((p) => {
return { environment: env.name, ...p };
permissions: environmentPermissions.map((permission) => {
return { environment: env.name, ...permission };
}),
};
});
@ -170,12 +170,12 @@ export class AccessService {
};
}
async addUserToRole(
async addUserToProjectRole(
userId: number,
roleId: number,
projectId: string,
): Promise<void> {
return this.store.addUserToRole(userId, roleId, projectId);
return this.store.addUserToProjectRole(userId, roleId, projectId);
}
async getRoleByName(roleName: string): Promise<IRole> {
@ -194,7 +194,7 @@ export class AccessService {
RoleType.ROOT,
);
await this.store.addUserToRole(
await this.store.addUserToProjectRole(
userId,
newRootRole.id,
ALL_PROJECTS,
@ -214,12 +214,12 @@ export class AccessService {
return userRoles.filter((r) => r.type === RoleType.ROOT);
}
async removeUserFromRole(
async removeUserFromProjectRole(
userId: number,
roleId: number,
projectId: string,
): Promise<void> {
return this.store.removeUserFromRole(userId, roleId, projectId);
return this.store.removeUserFromProjectRole(userId, roleId, projectId);
}
async addPermissionToRole(
@ -242,9 +242,9 @@ export class AccessService {
async removePermissionFromRole(
roleId: number,
permission: string,
projectId?: string,
environment?: string,
): Promise<void> {
if (isProjectPermission(permission) && !projectId) {
if (isProjectPermission(permission) && !environment) {
throw new Error(
`ProjectId cannot be empty for permission=${permission}`,
);
@ -252,7 +252,7 @@ export class AccessService {
return this.store.removePermissionFromRole(
roleId,
permission,
projectId,
environment,
);
}
@ -349,7 +349,11 @@ export class AccessService {
this.logger.info(
`Making ${owner.id} admin of ${projectId} via roleId=${ownerRole.id}`,
);
await this.store.addUserToRole(owner.id, ownerRole.id, projectId);
await this.store.addUserToProjectRole(
owner.id,
ownerRole.id,
projectId,
);
}
}

View File

@ -300,7 +300,11 @@ export default class ProjectService {
throw new Error(`User already has access to project=${projectId}`);
}
await this.accessService.addUserToRole(userId, role.id, projectId);
await this.accessService.addUserToProjectRole(
userId,
role.id,
projectId,
);
}
// TODO: should be an event too
@ -324,7 +328,11 @@ export default class ProjectService {
}
}
await this.accessService.removeUserFromRole(userId, role.id, projectId);
await this.accessService.removeUserFromProjectRole(
userId,
role.id,
projectId,
);
}
async getMembers(projectId: string): Promise<number> {

View File

@ -41,12 +41,12 @@ export interface IAccessStore extends Store<IRole, number> {
role_id: number,
permissions: IPermission[],
): Promise<void>;
addUserToRole(
addUserToProjectRole(
userId: number,
roleId: number,
projectId: string,
): Promise<void>;
removeUserFromRole(
removeUserFromProjectRole(
userId: number,
roleId: number,
projectId: string,

View File

@ -1 +1,5 @@
export const DEFAULT_ENV = 'default';
export const ROOT_PERMISSION_TYPE = 'root';
export const ENVIRONMENT_PERMISSION_TYPE = 'environment';
export const PROJECT_PERMISSION_TYPE = 'project';

View File

@ -28,14 +28,18 @@ let readRole;
const createUserEditorAccess = async (name, email) => {
const { userStore } = stores;
const user = await userStore.insert({ name, email });
await accessService.addUserToRole(user.id, editorRole.id, 'default');
await accessService.addUserToProjectRole(user.id, editorRole.id, 'default');
return user;
};
const createUserViewerAccess = async (name, email) => {
const { userStore } = stores;
const user = await userStore.insert({ name, email });
await accessService.addUserToRole(user.id, readRole.id, ALL_PROJECTS);
await accessService.addUserToProjectRole(
user.id,
readRole.id,
ALL_PROJECTS,
);
return user;
};
@ -178,7 +182,11 @@ const createSuperUser = async () => {
name: 'Alice Admin',
email: 'admin@getunleash.io',
});
await accessService.addUserToRole(user.id, adminRole.id, ALL_PROJECTS);
await accessService.addUserToProjectRole(
user.id,
adminRole.id,
ALL_PROJECTS,
);
return user;
};
@ -372,7 +380,7 @@ test('should grant user access to project', async () => {
await accessService.createDefaultProjectRoles(user, project);
const projectRole = await accessService.getRoleByName(RoleName.MEMBER);
await accessService.addUserToRole(sUser.id, projectRole.id, project);
await accessService.addUserToProjectRole(sUser.id, projectRole.id, project);
// // Should be able to update feature toggles inside the project
hasCommonProjectAccess(sUser, project, true);
@ -397,7 +405,7 @@ test('should not get access if not specifying project', async () => {
const projectRole = await accessService.getRoleByName(RoleName.MEMBER);
await accessService.addUserToRole(sUser.id, projectRole.id, project);
await accessService.addUserToProjectRole(sUser.id, projectRole.id, project);
// Should not be able to update feature toggles outside project
hasCommonProjectAccess(sUser, undefined, false);
@ -410,14 +418,18 @@ test('should remove user from role', async () => {
email: 'random123@getunleash.io',
});
await accessService.addUserToRole(user.id, editorRole.id, 'default');
await accessService.addUserToProjectRole(user.id, editorRole.id, 'default');
// check user has one role
const userRoles = await accessService.getRolesForUser(user.id);
expect(userRoles.length).toBe(1);
expect(userRoles[0].name).toBe(RoleName.EDITOR);
await accessService.removeUserFromRole(user.id, editorRole.id, 'default');
await accessService.removeUserFromProjectRole(
user.id,
editorRole.id,
'default',
);
const userRolesAfterRemove = await accessService.getRolesForUser(user.id);
expect(userRolesAfterRemove.length).toBe(0);
});
@ -429,7 +441,7 @@ test('should return role with users', async () => {
email: 'random2223@getunleash.io',
});
await accessService.addUserToRole(user.id, editorRole.id, 'default');
await accessService.addUserToProjectRole(user.id, editorRole.id, 'default');
const roleWithUsers = await accessService.getRoleData(editorRole.id);
expect(roleWithUsers.role.name).toBe(RoleName.EDITOR);
@ -447,7 +459,7 @@ test('should return role with permissions and users', async () => {
email: 'random2244@getunleash.io',
});
await accessService.addUserToRole(user.id, editorRole.id, 'default');
await accessService.addUserToProjectRole(user.id, editorRole.id, 'default');
const roleWithPermission = await accessService.getRoleData(editorRole.id);
@ -536,7 +548,11 @@ test('should support permission with "ALL" environment requirement', async () =>
[CREATE_FEATURE_STRATEGY],
'production',
);
await accessStore.addUserToRole(user.id, customRole.id, ALL_PROJECTS);
await accessStore.addUserToProjectRole(
user.id,
customRole.id,
ALL_PROJECTS,
);
const hasAccess = await accessService.hasPermission(
user,
@ -667,3 +683,17 @@ test('Should be denied access to delete a role that is in use', async () => {
);
}
});
test('Should be given full access to project created by user', async () => {
const user = editorUser;
const newProjectName = 'AWholeNewProject';
const project = {
id: newProjectName,
name: newProjectName,
description: 'Blah',
};
await projectService.createProject(project, user.id);
hasFullProjectAccess(user, newProjectName, true);
});

View File

@ -35,7 +35,7 @@ class AccessServiceMock extends AccessService {
throw new Error('Method not implemented.');
}
addUserToRole(userId: number, roleId: number): Promise<void> {
addUserToProjectRole(userId: number, roleId: number): Promise<void> {
throw new Error('Method not implemented.');
}
@ -43,10 +43,6 @@ class AccessServiceMock extends AccessService {
return Promise.resolve();
}
removeUserFromRole(userId: number, roleId: number): Promise<void> {
throw new Error('Method not implemented.');
}
addPermissionToRole(
roleId: number,
permission: string,

View File

@ -9,6 +9,14 @@ import {
import { IAvailablePermissions, IPermission } from 'lib/types/model';
class AccessStoreMock implements IAccessStore {
removeUserFromProjectRole(
userId: number,
roleId: number,
projectId: string,
): Promise<void> {
throw new Error('Method not implemented.');
}
wipePermissionsFromRole(role_id: number): Promise<void> {
throw new Error('Method not implemented.');
}
@ -79,11 +87,7 @@ class AccessStoreMock implements IAccessStore {
throw new Error('Method not implemented.');
}
addUserToRole(userId: number, roleId: number): Promise<void> {
throw new Error('Method not implemented.');
}
removeUserFromRole(userId: number, roleId: number): Promise<void> {
addUserToProjectRole(userId: number, roleId: number): Promise<void> {
throw new Error('Method not implemented.');
}