mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-12 13:48:35 +02:00
chore: Refactor role/access stores into more logical domains
This commit is contained in:
parent
f97f8b03bc
commit
30de5f4b39
@ -7,7 +7,6 @@ import {
|
|||||||
IAccessStore,
|
IAccessStore,
|
||||||
IRole,
|
IRole,
|
||||||
IUserPermission,
|
IUserPermission,
|
||||||
IUserRole,
|
|
||||||
} from '../types/stores/access-store';
|
} from '../types/stores/access-store';
|
||||||
import {
|
import {
|
||||||
IAvailablePermissions,
|
IAvailablePermissions,
|
||||||
@ -61,10 +60,6 @@ export class AccessStore implements IAccessStore {
|
|||||||
await this.db.batchInsert(T.PERMISSIONS, rows);
|
await this.db.batchInsert(T.PERMISSIONS, rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRoleByName(name: string): Promise<IRole> {
|
|
||||||
return this.db(T.ROLES).where({ name }).first();
|
|
||||||
}
|
|
||||||
|
|
||||||
async delete(key: number): Promise<void> {
|
async delete(key: number): Promise<void> {
|
||||||
await this.db(T.ROLES).where({ id: key }).del();
|
await this.db(T.ROLES).where({ id: key }).del();
|
||||||
}
|
}
|
||||||
@ -186,34 +181,17 @@ export class AccessStore implements IAccessStore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRoles(): Promise<IRole[]> {
|
async addEnvironmentPermissionsToRole(
|
||||||
return this.db
|
role_id: number,
|
||||||
.select(['id', 'name', 'type', 'description'])
|
permissions: IPermission[],
|
||||||
.from<IRole>(T.ROLES);
|
): Promise<void> {
|
||||||
}
|
const rows = permissions.map((x) => {
|
||||||
|
return {
|
||||||
async getRoleWithId(id: number): Promise<IRole> {
|
role_id,
|
||||||
return this.db
|
permission_id: x.id,
|
||||||
.select(['id', 'name', 'type', 'description'])
|
};
|
||||||
.where('id', id)
|
});
|
||||||
.first()
|
this.db.batchInsert(T.ROLE_PERMISSION, rows);
|
||||||
.from<IRole>(T.ROLES);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getProjectRoles(): Promise<IRole[]> {
|
|
||||||
return this.db
|
|
||||||
.select(['id', 'name', 'type', 'description'])
|
|
||||||
.from<IRole>(T.ROLES)
|
|
||||||
.where('type', 'custom')
|
|
||||||
.orWhere('type', 'project');
|
|
||||||
}
|
|
||||||
|
|
||||||
async getRolesForProject(projectId: string): Promise<IRole[]> {
|
|
||||||
return this.db
|
|
||||||
.select(['r.id', 'r.name', 'r.type', 'ru.project', 'r.description'])
|
|
||||||
.from<IRole>(`${T.ROLE_USER} as ru`)
|
|
||||||
.innerJoin(`${T.ROLES} as r`, 'ru.role_id', 'r.id')
|
|
||||||
.where('project', projectId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async unlinkUserRoles(userId: number): Promise<void> {
|
async unlinkUserRoles(userId: number): Promise<void> {
|
||||||
@ -224,19 +202,17 @@ export class AccessStore implements IAccessStore {
|
|||||||
.delete();
|
.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRootRoles(): Promise<IRole[]> {
|
async getProjectUserIdsForRole(
|
||||||
return this.db
|
roleId: number,
|
||||||
.select(['id', 'name', 'type', 'description'])
|
projectId?: string,
|
||||||
.from<IRole>(T.ROLES)
|
): Promise<number[]> {
|
||||||
.andWhere('type', 'root');
|
const rows = await this.db
|
||||||
}
|
.select(['user_id'])
|
||||||
|
.from<IRole>(`${T.ROLE_USER} AS ru`)
|
||||||
async removeRolesForProject(projectId: string): Promise<void> {
|
.join(`${T.ROLES} as r`, 'ru.role_id', 'id')
|
||||||
return this.db(T.ROLE_USER)
|
.where('r.id', roleId)
|
||||||
.where({
|
.andWhere('ru.project', projectId);
|
||||||
project: projectId,
|
return rows.map((r) => r.user_id);
|
||||||
})
|
|
||||||
.delete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRolesForUserId(userId: number): Promise<IRole[]> {
|
async getRolesForUserId(userId: number): Promise<IRole[]> {
|
||||||
@ -255,19 +231,6 @@ export class AccessStore implements IAccessStore {
|
|||||||
return rows.map((r) => r.user_id);
|
return rows.map((r) => r.user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getProjectUserIdsForRole(
|
|
||||||
roleId: number,
|
|
||||||
projectId?: string,
|
|
||||||
): Promise<number[]> {
|
|
||||||
const rows = await this.db
|
|
||||||
.select(['user_id'])
|
|
||||||
.from<IRole>(`${T.ROLE_USER} AS ru`)
|
|
||||||
.join(`${T.ROLES} as r`, 'ru.role_id', 'id')
|
|
||||||
.where('r.id', roleId)
|
|
||||||
.andWhere('ru.project', projectId);
|
|
||||||
return rows.map((r) => r.user_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
async addUserToRole(
|
async addUserToRole(
|
||||||
userId: number,
|
userId: number,
|
||||||
roleId: number,
|
roleId: number,
|
||||||
@ -308,39 +271,6 @@ export class AccessStore implements IAccessStore {
|
|||||||
.delete();
|
.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
async createRole(
|
|
||||||
name: string,
|
|
||||||
type: string,
|
|
||||||
description?: string,
|
|
||||||
): Promise<IRole> {
|
|
||||||
const [id] = await this.db(T.ROLES)
|
|
||||||
.insert({
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
type,
|
|
||||||
})
|
|
||||||
.returning('id');
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
type,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async addEnvironmentPermissionsToRole(
|
|
||||||
role_id: number,
|
|
||||||
permissions: IPermission[],
|
|
||||||
): Promise<void> {
|
|
||||||
const rows = permissions.map((x) => {
|
|
||||||
return {
|
|
||||||
role_id,
|
|
||||||
permission_id: x.id,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
this.db.batchInsert(T.ROLE_PERMISSION, rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
async addPermissionsToRole(
|
async addPermissionsToRole(
|
||||||
role_id: number,
|
role_id: number,
|
||||||
permissions: string[],
|
permissions: string[],
|
||||||
@ -388,18 +318,4 @@ export class AccessStore implements IAccessStore {
|
|||||||
})
|
})
|
||||||
.delete();
|
.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRootRoleForAllUsers(): Promise<IUserRole[]> {
|
|
||||||
const rows = await this.db
|
|
||||||
.select('id', 'user_id')
|
|
||||||
.distinctOn('user_id')
|
|
||||||
.from(`${T.ROLES} AS r`)
|
|
||||||
.leftJoin(`${T.ROLE_USER} AS ru`, 'r.id', 'ru.role_id')
|
|
||||||
.where('r.type', '=', 'root');
|
|
||||||
|
|
||||||
return rows.map((row) => ({
|
|
||||||
roleId: +row.id,
|
|
||||||
userId: +row.user_id,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,13 @@ import {
|
|||||||
ICustomRoleInsert,
|
ICustomRoleInsert,
|
||||||
ICustomRoleUpdate,
|
ICustomRoleUpdate,
|
||||||
} from 'lib/types/stores/role-store';
|
} from 'lib/types/stores/role-store';
|
||||||
|
import { IRole, IUserRole } from 'lib/types/stores/access-store';
|
||||||
|
|
||||||
|
const T = {
|
||||||
|
ROLE_USER: 'role_user',
|
||||||
|
ROLES: 'roles',
|
||||||
|
};
|
||||||
|
|
||||||
const TABLE = 'roles';
|
|
||||||
const COLUMNS = ['id', 'name', 'description', 'type'];
|
const COLUMNS = ['id', 'name', 'description', 'type'];
|
||||||
|
|
||||||
interface IRoleRow {
|
interface IRoleRow {
|
||||||
@ -34,14 +39,14 @@ export default class RoleStore {
|
|||||||
async getAll(): Promise<ICustomRole[]> {
|
async getAll(): Promise<ICustomRole[]> {
|
||||||
const rows = await this.db
|
const rows = await this.db
|
||||||
.select(COLUMNS)
|
.select(COLUMNS)
|
||||||
.from(TABLE)
|
.from(T.ROLES)
|
||||||
.orderBy('name', 'asc');
|
.orderBy('name', 'asc');
|
||||||
|
|
||||||
return rows.map(this.mapRow);
|
return rows.map(this.mapRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(role: ICustomRoleInsert): Promise<ICustomRole> {
|
async create(role: ICustomRoleInsert): Promise<ICustomRole> {
|
||||||
const row = await this.db(TABLE)
|
const row = await this.db(T.ROLES)
|
||||||
.insert({
|
.insert({
|
||||||
name: role.name,
|
name: role.name,
|
||||||
description: role.description,
|
description: role.description,
|
||||||
@ -52,16 +57,16 @@ export default class RoleStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async delete(id: number): Promise<void> {
|
async delete(id: number): Promise<void> {
|
||||||
return this.db(TABLE).where({ id }).del();
|
return this.db(T.ROLES).where({ id }).del();
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(id: number): Promise<ICustomRole> {
|
async get(id: number): Promise<ICustomRole> {
|
||||||
const rows = await this.db.select(COLUMNS).from(TABLE).where({ id });
|
const rows = await this.db.select(COLUMNS).from(T.ROLES).where({ id });
|
||||||
return this.mapRow(rows[0]);
|
return this.mapRow(rows[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(role: ICustomRoleUpdate): Promise<ICustomRole> {
|
async update(role: ICustomRoleUpdate): Promise<ICustomRole> {
|
||||||
const rows = await this.db(TABLE)
|
const rows = await this.db(T.ROLES)
|
||||||
.where({
|
.where({
|
||||||
id: role.id,
|
id: role.id,
|
||||||
})
|
})
|
||||||
@ -76,7 +81,7 @@ export default class RoleStore {
|
|||||||
|
|
||||||
async exists(id: number): Promise<boolean> {
|
async exists(id: number): Promise<boolean> {
|
||||||
const result = await this.db.raw(
|
const result = await this.db.raw(
|
||||||
`SELECT EXISTS (SELECT 1 FROM ${TABLE} WHERE id = ?) AS present`,
|
`SELECT EXISTS (SELECT 1 FROM ${T.ROLES} WHERE id = ?) AS present`,
|
||||||
[id],
|
[id],
|
||||||
);
|
);
|
||||||
const { present } = result.rows[0];
|
const { present } = result.rows[0];
|
||||||
@ -84,7 +89,7 @@ export default class RoleStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async deleteAll(): Promise<void> {
|
async deleteAll(): Promise<void> {
|
||||||
return this.db(TABLE).del();
|
return this.db(T.ROLES).del();
|
||||||
}
|
}
|
||||||
|
|
||||||
mapRow(row: IRoleRow): ICustomRole {
|
mapRow(row: IRoleRow): ICustomRole {
|
||||||
@ -100,6 +105,69 @@ export default class RoleStore {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getRoles(): Promise<IRole[]> {
|
||||||
|
return this.db
|
||||||
|
.select(['id', 'name', 'type', 'description'])
|
||||||
|
.from<IRole>(T.ROLES);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRoleWithId(id: number): Promise<IRole> {
|
||||||
|
return this.db
|
||||||
|
.select(['id', 'name', 'type', 'description'])
|
||||||
|
.where('id', id)
|
||||||
|
.first()
|
||||||
|
.from<IRole>(T.ROLES);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getProjectRoles(): Promise<IRole[]> {
|
||||||
|
return this.db
|
||||||
|
.select(['id', 'name', 'type', 'description'])
|
||||||
|
.from<IRole>(T.ROLES)
|
||||||
|
.where('type', 'custom')
|
||||||
|
.orWhere('type', 'project');
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRolesForProject(projectId: string): Promise<IRole[]> {
|
||||||
|
return this.db
|
||||||
|
.select(['r.id', 'r.name', 'r.type', 'ru.project', 'r.description'])
|
||||||
|
.from<IRole>(`${T.ROLE_USER} as ru`)
|
||||||
|
.innerJoin(`${T.ROLES} as r`, 'ru.role_id', 'r.id')
|
||||||
|
.where('project', projectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRootRoles(): Promise<IRole[]> {
|
||||||
|
return this.db
|
||||||
|
.select(['id', 'name', 'type', 'description'])
|
||||||
|
.from<IRole>(T.ROLES)
|
||||||
|
.where('type', 'root');
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeRolesForProject(projectId: string): Promise<void> {
|
||||||
|
return this.db(T.ROLE_USER)
|
||||||
|
.where({
|
||||||
|
project: projectId,
|
||||||
|
})
|
||||||
|
.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRootRoleForAllUsers(): Promise<IUserRole[]> {
|
||||||
|
const rows = await this.db
|
||||||
|
.select('id', 'user_id')
|
||||||
|
.distinctOn('user_id')
|
||||||
|
.from(`${T.ROLES} AS r`)
|
||||||
|
.leftJoin(`${T.ROLE_USER} AS ru`, 'r.id', 'ru.role_id')
|
||||||
|
.where('r.type', '=', 'root');
|
||||||
|
|
||||||
|
return rows.map((row) => ({
|
||||||
|
roleId: +row.id,
|
||||||
|
userId: +row.user_id,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRoleByName(name: string): Promise<IRole> {
|
||||||
|
return this.db(T.ROLES).where({ name }).first();
|
||||||
|
}
|
||||||
|
|
||||||
destroy(): void {}
|
destroy(): void {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import User, { IUser } from '../types/user';
|
|||||||
import {
|
import {
|
||||||
IAccessStore,
|
IAccessStore,
|
||||||
IRole,
|
IRole,
|
||||||
|
IRoleWithPermissions,
|
||||||
IUserPermission,
|
IUserPermission,
|
||||||
IUserRole,
|
IUserRole,
|
||||||
} from '../types/stores/access-store';
|
} from '../types/stores/access-store';
|
||||||
@ -11,12 +12,14 @@ import { Logger } from '../logger';
|
|||||||
import { IUnleashStores } from '../types/stores';
|
import { IUnleashStores } from '../types/stores';
|
||||||
import {
|
import {
|
||||||
IAvailablePermissions,
|
IAvailablePermissions,
|
||||||
|
ICustomRole,
|
||||||
IPermission,
|
IPermission,
|
||||||
IRoleData,
|
IRoleData,
|
||||||
IUserWithRole,
|
IUserWithRole,
|
||||||
RoleName,
|
RoleName,
|
||||||
RoleType,
|
RoleType,
|
||||||
} from '../types/model';
|
} from '../types/model';
|
||||||
|
import { IRoleStore } from 'lib/types/stores/role-store';
|
||||||
|
|
||||||
export const ALL_PROJECTS = '*';
|
export const ALL_PROJECTS = '*';
|
||||||
export const ALL_ENVS = '*';
|
export const ALL_ENVS = '*';
|
||||||
@ -37,6 +40,19 @@ const PROJECT_REGULAR = [
|
|||||||
permissions.DELETE_FEATURE,
|
permissions.DELETE_FEATURE,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
interface IRoleCreation {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
permissions?: IPermission[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IRoleUpdate {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
permissions?: IPermission[];
|
||||||
|
}
|
||||||
|
|
||||||
const isProjectPermission = (permission) => PROJECT_ADMIN.includes(permission);
|
const isProjectPermission = (permission) => PROJECT_ADMIN.includes(permission);
|
||||||
|
|
||||||
export class AccessService {
|
export class AccessService {
|
||||||
@ -44,26 +60,22 @@ export class AccessService {
|
|||||||
|
|
||||||
private userStore: IUserStore;
|
private userStore: IUserStore;
|
||||||
|
|
||||||
private logger: Logger;
|
private roleStore: IRoleStore;
|
||||||
|
|
||||||
private permissions: IPermission[];
|
private logger: Logger;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
{
|
{
|
||||||
accessStore,
|
accessStore,
|
||||||
userStore,
|
userStore,
|
||||||
}: Pick<IUnleashStores, 'accessStore' | 'userStore'>,
|
roleStore,
|
||||||
|
}: Pick<IUnleashStores, 'accessStore' | 'userStore' | 'roleStore'>,
|
||||||
{ getLogger }: { getLogger: Function },
|
{ getLogger }: { getLogger: Function },
|
||||||
) {
|
) {
|
||||||
this.store = accessStore;
|
this.store = accessStore;
|
||||||
this.userStore = userStore;
|
this.userStore = userStore;
|
||||||
|
this.roleStore = roleStore;
|
||||||
this.logger = getLogger('/services/access-service.ts');
|
this.logger = getLogger('/services/access-service.ts');
|
||||||
// this.permissions = Object.values(permissions).map((p) => ({
|
|
||||||
// name: p,
|
|
||||||
// type: isProjectPermission(p)
|
|
||||||
// ? PermissionType.project
|
|
||||||
// : PermissionType.root,
|
|
||||||
// }));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,7 +145,7 @@ export class AccessService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getRoleByName(roleName: string): Promise<IRole> {
|
async getRoleByName(roleName: string): Promise<IRole> {
|
||||||
return this.store.getRoleByName(roleName);
|
return this.roleStore.getRoleByName(roleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
async setUserRootRole(
|
async setUserRootRole(
|
||||||
@ -148,11 +160,11 @@ export class AccessService {
|
|||||||
RoleType.ROOT,
|
RoleType.ROOT,
|
||||||
);
|
);
|
||||||
|
|
||||||
const editorRole = await this.store.getRoleByName(
|
const editorRole = await this.roleStore.getRoleByName(
|
||||||
RoleName.EDITOR,
|
RoleName.EDITOR,
|
||||||
);
|
);
|
||||||
if (newRootRole.id === editorRole.id) {
|
if (newRootRole.id === editorRole.id) {
|
||||||
const viewerRole = await this.store.getRoleByName(
|
const viewerRole = await this.roleStore.getRoleByName(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
await this.store.addUserToRole(
|
await this.store.addUserToRole(
|
||||||
@ -230,10 +242,19 @@ export class AccessService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getRoles(): Promise<IRole[]> {
|
async getRoles(): Promise<IRole[]> {
|
||||||
return this.store.getRoles();
|
return this.roleStore.getRoles();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRole(roleId: number): Promise<IRoleData> {
|
async getRole(id: number): Promise<IRoleWithPermissions> {
|
||||||
|
const role = await this.store.get(id);
|
||||||
|
const rolePermissions = await this.store.getPermissionsForRole(role.id);
|
||||||
|
return {
|
||||||
|
...role,
|
||||||
|
permissions: rolePermissions,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRoleData(roleId: number): Promise<IRoleData> {
|
||||||
const [role, rolePerms, users] = await Promise.all([
|
const [role, rolePerms, users] = await Promise.all([
|
||||||
this.store.get(roleId),
|
this.store.get(roleId),
|
||||||
this.store.getPermissionsForRole(roleId),
|
this.store.getPermissionsForRole(roleId),
|
||||||
@ -243,11 +264,11 @@ export class AccessService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getProjectRoles(): Promise<IRole[]> {
|
async getProjectRoles(): Promise<IRole[]> {
|
||||||
return this.store.getProjectRoles();
|
return this.roleStore.getProjectRoles();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRolesForProject(projectId: string): Promise<IRole[]> {
|
async getRolesForProject(projectId: string): Promise<IRole[]> {
|
||||||
return this.store.getRolesForProject(projectId);
|
return this.roleStore.getRolesForProject(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRolesForUser(userId: number): Promise<IRole[]> {
|
async getRolesForUser(userId: number): Promise<IRole[]> {
|
||||||
@ -284,7 +305,7 @@ export class AccessService {
|
|||||||
async getProjectRoleUsers(
|
async getProjectRoleUsers(
|
||||||
projectId: string,
|
projectId: string,
|
||||||
): Promise<[IRole[], IUserWithRole[]]> {
|
): Promise<[IRole[], IUserWithRole[]]> {
|
||||||
const roles = await this.store.getProjectRoles();
|
const roles = await this.roleStore.getProjectRoles();
|
||||||
|
|
||||||
const users = await Promise.all(
|
const users = await Promise.all(
|
||||||
roles.map(async (role) => {
|
roles.map(async (role) => {
|
||||||
@ -306,7 +327,7 @@ export class AccessService {
|
|||||||
throw new Error('ProjectId cannot be empty');
|
throw new Error('ProjectId cannot be empty');
|
||||||
}
|
}
|
||||||
|
|
||||||
const ownerRole = await this.store.getRoleByName(RoleName.OWNER);
|
const ownerRole = await this.roleStore.getRoleByName(RoleName.OWNER);
|
||||||
|
|
||||||
await this.store.addPermissionsToRole(
|
await this.store.addPermissionsToRole(
|
||||||
ownerRole.id,
|
ownerRole.id,
|
||||||
@ -322,7 +343,7 @@ export class AccessService {
|
|||||||
await this.store.addUserToRole(owner.id, ownerRole.id, projectId);
|
await this.store.addUserToRole(owner.id, ownerRole.id, projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const memberRole = await this.store.getRoleByName(RoleName.MEMBER);
|
const memberRole = await this.roleStore.getRoleByName(RoleName.MEMBER);
|
||||||
|
|
||||||
await this.store.addPermissionsToRole(
|
await this.store.addPermissionsToRole(
|
||||||
memberRole.id,
|
memberRole.id,
|
||||||
@ -336,15 +357,15 @@ export class AccessService {
|
|||||||
projectId: string,
|
projectId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
this.logger.info(`Removing project roles for ${projectId}`);
|
this.logger.info(`Removing project roles for ${projectId}`);
|
||||||
return this.store.removeRolesForProject(projectId);
|
return this.roleStore.removeRolesForProject(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRootRoleForAllUsers(): Promise<IUserRole[]> {
|
async getRootRoleForAllUsers(): Promise<IUserRole[]> {
|
||||||
return this.store.getRootRoleForAllUsers();
|
return this.roleStore.getRootRoleForAllUsers();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRootRoles(): Promise<IRole[]> {
|
async getRootRoles(): Promise<IRole[]> {
|
||||||
return this.store.getRootRoles();
|
return this.roleStore.getRootRoles();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async resolveRootRole(rootRole: number | RoleName): Promise<IRole> {
|
public async resolveRootRole(rootRole: number | RoleName): Promise<IRole> {
|
||||||
@ -359,7 +380,51 @@ export class AccessService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getRootRole(roleName: RoleName): Promise<IRole> {
|
async getRootRole(roleName: RoleName): Promise<IRole> {
|
||||||
const roles = await this.store.getRootRoles();
|
const roles = await this.roleStore.getRootRoles();
|
||||||
return roles.find((r) => r.name === roleName);
|
return roles.find((r) => r.name === roleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getAllRoles(): Promise<ICustomRole[]> {
|
||||||
|
return this.roleStore.getAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
async createRole(role: IRoleCreation): Promise<ICustomRole> {
|
||||||
|
const baseRole = {
|
||||||
|
name: role.name,
|
||||||
|
description: role.description,
|
||||||
|
roleType: 'custom',
|
||||||
|
};
|
||||||
|
const rolePermissions = role.permissions;
|
||||||
|
const newRole = await this.roleStore.create(baseRole);
|
||||||
|
if (rolePermissions) {
|
||||||
|
this.store.addEnvironmentPermissionsToRole(
|
||||||
|
newRole.id,
|
||||||
|
rolePermissions,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return newRole;
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateRole(role: IRoleUpdate): Promise<ICustomRole> {
|
||||||
|
const baseRole = {
|
||||||
|
id: role.id,
|
||||||
|
name: role.name,
|
||||||
|
description: role.description,
|
||||||
|
roleType: 'custom',
|
||||||
|
};
|
||||||
|
const rolePermissions = role.permissions;
|
||||||
|
const newRole = await this.roleStore.update(baseRole);
|
||||||
|
if (rolePermissions) {
|
||||||
|
this.store.wipePermissionsFromRole(newRole.id);
|
||||||
|
this.store.addEnvironmentPermissionsToRole(
|
||||||
|
newRole.id,
|
||||||
|
rolePermissions,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return newRole;
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteRole(id: number): Promise<void> {
|
||||||
|
return this.roleStore.delete(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ import EnvironmentService from './environment-service';
|
|||||||
import FeatureTagService from './feature-tag-service';
|
import FeatureTagService from './feature-tag-service';
|
||||||
import ProjectHealthService from './project-health-service';
|
import ProjectHealthService from './project-health-service';
|
||||||
import UserSplashService from './user-splash-service';
|
import UserSplashService from './user-splash-service';
|
||||||
import RoleService from './role-service';
|
|
||||||
|
|
||||||
export const createServices = (
|
export const createServices = (
|
||||||
stores: IUnleashStores,
|
stores: IUnleashStores,
|
||||||
@ -76,8 +75,6 @@ export const createServices = (
|
|||||||
);
|
);
|
||||||
const userSplashService = new UserSplashService(stores, config);
|
const userSplashService = new UserSplashService(stores, config);
|
||||||
|
|
||||||
const roleService = new RoleService(stores, config);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
accessService,
|
accessService,
|
||||||
addonService,
|
addonService,
|
||||||
@ -106,7 +103,6 @@ export const createServices = (
|
|||||||
featureTagService,
|
featureTagService,
|
||||||
projectHealthService,
|
projectHealthService,
|
||||||
userSplashService,
|
userSplashService,
|
||||||
roleService,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
import { IUnleashConfig } from 'lib/server-impl';
|
|
||||||
import { IUnleashStores } from 'lib/types';
|
|
||||||
import { ICustomRole, IPermission } from 'lib/types/model';
|
|
||||||
import {
|
|
||||||
IAccessStore,
|
|
||||||
IRoleWithPermissions,
|
|
||||||
} from 'lib/types/stores/access-store';
|
|
||||||
import { IRoleStore } from 'lib/types/stores/role-store';
|
|
||||||
import { Logger } from '../logger';
|
|
||||||
|
|
||||||
interface IRoleCreation {
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
permissions?: IPermission[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IRoleUpdate {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
permissions?: IPermission[];
|
|
||||||
}
|
|
||||||
export default class RoleService {
|
|
||||||
private logger: Logger;
|
|
||||||
|
|
||||||
private store: IRoleStore;
|
|
||||||
|
|
||||||
private accessStore: IAccessStore;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
{
|
|
||||||
roleStore,
|
|
||||||
accessStore,
|
|
||||||
}: Pick<IUnleashStores, 'roleStore' | 'accessStore'>,
|
|
||||||
{ getLogger }: Pick<IUnleashConfig, 'getLogger'>,
|
|
||||||
) {
|
|
||||||
this.logger = getLogger('lib/services/session-service.ts');
|
|
||||||
this.store = roleStore;
|
|
||||||
this.accessStore = accessStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAll(): Promise<ICustomRole[]> {
|
|
||||||
return this.store.getAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
async get(id: number): Promise<IRoleWithPermissions> {
|
|
||||||
const role = await this.store.get(id);
|
|
||||||
const permissions = await this.accessStore.getPermissionsForRole(
|
|
||||||
role.id,
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
...role,
|
|
||||||
permissions,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async create(role: IRoleCreation): Promise<ICustomRole> {
|
|
||||||
const baseRole = {
|
|
||||||
name: role.name,
|
|
||||||
description: role.description,
|
|
||||||
roleType: 'custom',
|
|
||||||
};
|
|
||||||
const permissions = role.permissions;
|
|
||||||
const newRole = await this.store.create(baseRole);
|
|
||||||
if (permissions) {
|
|
||||||
this.accessStore.addEnvironmentPermissionsToRole(
|
|
||||||
newRole.id,
|
|
||||||
permissions,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return newRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
async update(role: IRoleUpdate): Promise<ICustomRole> {
|
|
||||||
const baseRole = {
|
|
||||||
id: role.id,
|
|
||||||
name: role.name,
|
|
||||||
description: role.description,
|
|
||||||
roleType: 'custom',
|
|
||||||
};
|
|
||||||
const permissions = role.permissions;
|
|
||||||
const newRole = await this.store.update(baseRole);
|
|
||||||
if (permissions) {
|
|
||||||
this.accessStore.wipePermissionsFromRole(newRole.id);
|
|
||||||
this.accessStore.addEnvironmentPermissionsToRole(
|
|
||||||
newRole.id,
|
|
||||||
permissions,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return newRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
async delete(id: number): Promise<void> {
|
|
||||||
return this.store.delete(id);
|
|
||||||
}
|
|
||||||
}
|
|
@ -349,7 +349,7 @@ class UserService {
|
|||||||
token,
|
token,
|
||||||
);
|
);
|
||||||
const user = await this.getUser(userId);
|
const user = await this.getUser(userId);
|
||||||
const role = await this.accessService.getRole(user.rootRole);
|
const role = await this.accessService.getRoleData(user.rootRole);
|
||||||
return {
|
return {
|
||||||
token,
|
token,
|
||||||
createdBy,
|
createdBy,
|
||||||
|
@ -24,7 +24,6 @@ import FeatureTagService from '../services/feature-tag-service';
|
|||||||
import ProjectHealthService from '../services/project-health-service';
|
import ProjectHealthService from '../services/project-health-service';
|
||||||
import ClientMetricsServiceV2 from '../services/client-metrics/metrics-service-v2';
|
import ClientMetricsServiceV2 from '../services/client-metrics/metrics-service-v2';
|
||||||
import UserSplashService from '../services/user-splash-service';
|
import UserSplashService from '../services/user-splash-service';
|
||||||
import RoleService from 'lib/services/role-service';
|
|
||||||
|
|
||||||
export interface IUnleashServices {
|
export interface IUnleashServices {
|
||||||
accessService: AccessService;
|
accessService: AccessService;
|
||||||
@ -54,5 +53,4 @@ export interface IUnleashServices {
|
|||||||
userService: UserService;
|
userService: UserService;
|
||||||
versionService: VersionService;
|
versionService: VersionService;
|
||||||
userSplashService: UserSplashService;
|
userSplashService: UserSplashService;
|
||||||
roleService: RoleService;
|
|
||||||
}
|
}
|
||||||
|
@ -29,16 +29,10 @@ export interface IUserRole {
|
|||||||
userId: number;
|
userId: number;
|
||||||
}
|
}
|
||||||
export interface IAccessStore extends Store<IRole, number> {
|
export interface IAccessStore extends Store<IRole, number> {
|
||||||
getRoleByName(name: string): Promise<IRole>;
|
|
||||||
getAvailablePermissions(): Promise<IAvailablePermissions>;
|
getAvailablePermissions(): Promise<IAvailablePermissions>;
|
||||||
getPermissionsForUser(userId: number): Promise<IUserPermission[]>;
|
getPermissionsForUser(userId: number): Promise<IUserPermission[]>;
|
||||||
getPermissionsForRole(roleId: number): Promise<IPermission[]>;
|
getPermissionsForRole(roleId: number): Promise<IPermission[]>;
|
||||||
getRoles(): Promise<IRole[]>;
|
|
||||||
getRolesForProject(projectId: string): Promise<IRole[]>;
|
|
||||||
unlinkUserRoles(userId: number): Promise<void>;
|
unlinkUserRoles(userId: number): Promise<void>;
|
||||||
getProjectRoles(): Promise<IRole[]>;
|
|
||||||
getRootRoles(): Promise<IRole[]>;
|
|
||||||
removeRolesForProject(projectId: string): Promise<void>;
|
|
||||||
getRolesForUserId(userId: number): Promise<IRole[]>;
|
getRolesForUserId(userId: number): Promise<IRole[]>;
|
||||||
getProjectUserIdsForRole(roleId: number, projectId?: string);
|
getProjectUserIdsForRole(roleId: number, projectId?: string);
|
||||||
getUserIdsForRole(roleId: number, projectId?: string): Promise<number[]>;
|
getUserIdsForRole(roleId: number, projectId?: string): Promise<number[]>;
|
||||||
@ -62,12 +56,6 @@ export interface IAccessStore extends Store<IRole, number> {
|
|||||||
projectId: string,
|
projectId: string,
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
removeRolesOfTypeForUser(userId: number, roleType: string): Promise<void>;
|
removeRolesOfTypeForUser(userId: number, roleType: string): Promise<void>;
|
||||||
createRole(
|
|
||||||
name: string,
|
|
||||||
type: string,
|
|
||||||
project?: string,
|
|
||||||
description?: string,
|
|
||||||
): Promise<IRole>;
|
|
||||||
addPermissionsToRole(
|
addPermissionsToRole(
|
||||||
role_id: number,
|
role_id: number,
|
||||||
permissions: string[],
|
permissions: string[],
|
||||||
@ -78,5 +66,4 @@ export interface IAccessStore extends Store<IRole, number> {
|
|||||||
permission: string,
|
permission: string,
|
||||||
projectId?: string,
|
projectId?: string,
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
getRootRoleForAllUsers(): Promise<IUserRole[]>;
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { ICustomRole } from '../model';
|
import { ICustomRole } from '../model';
|
||||||
|
import { IRole, IUserRole } from './access-store';
|
||||||
import { Store } from './store';
|
import { Store } from './store';
|
||||||
|
|
||||||
export interface ICustomRoleInsert {
|
export interface ICustomRoleInsert {
|
||||||
@ -19,4 +20,11 @@ export interface IRoleStore extends Store<ICustomRole, number> {
|
|||||||
create(role: ICustomRoleInsert): Promise<ICustomRole>;
|
create(role: ICustomRoleInsert): Promise<ICustomRole>;
|
||||||
update(role: ICustomRoleUpdate): Promise<ICustomRole>;
|
update(role: ICustomRoleUpdate): Promise<ICustomRole>;
|
||||||
delete(id: number): Promise<void>;
|
delete(id: number): Promise<void>;
|
||||||
|
getRoles(): Promise<IRole[]>;
|
||||||
|
getRoleByName(name: string): Promise<IRole>;
|
||||||
|
getRolesForProject(projectId: string): Promise<IRole[]>;
|
||||||
|
removeRolesForProject(projectId: string): Promise<void>;
|
||||||
|
getProjectRoles(): Promise<IRole[]>;
|
||||||
|
getRootRoles(): Promise<IRole[]>;
|
||||||
|
getRootRoleForAllUsers(): Promise<IUserRole[]>;
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,11 @@ import {
|
|||||||
USER_DELETED,
|
USER_DELETED,
|
||||||
USER_UPDATED,
|
USER_UPDATED,
|
||||||
} from '../../../../lib/types/events';
|
} from '../../../../lib/types/events';
|
||||||
import { IAccessStore, IRole } from '../../../../lib/types/stores/access-store';
|
import { IRole } from '../../../../lib/types/stores/access-store';
|
||||||
import { IEventStore } from '../../../../lib/types/stores/event-store';
|
import { IEventStore } from '../../../../lib/types/stores/event-store';
|
||||||
import { IUserStore } from '../../../../lib/types/stores/user-store';
|
import { IUserStore } from '../../../../lib/types/stores/user-store';
|
||||||
import { RoleName } from '../../../../lib/types/model';
|
import { RoleName } from '../../../../lib/types/model';
|
||||||
|
import { IRoleStore } from 'lib/types/stores/role-store';
|
||||||
|
|
||||||
let stores;
|
let stores;
|
||||||
let db;
|
let db;
|
||||||
@ -17,7 +18,7 @@ let app;
|
|||||||
|
|
||||||
let userStore: IUserStore;
|
let userStore: IUserStore;
|
||||||
let eventStore: IEventStore;
|
let eventStore: IEventStore;
|
||||||
let accessStore: IAccessStore;
|
let roleStore: IRoleStore;
|
||||||
let editorRole: IRole;
|
let editorRole: IRole;
|
||||||
let adminRole: IRole;
|
let adminRole: IRole;
|
||||||
|
|
||||||
@ -27,9 +28,9 @@ beforeAll(async () => {
|
|||||||
app = await setupApp(stores);
|
app = await setupApp(stores);
|
||||||
|
|
||||||
userStore = stores.userStore;
|
userStore = stores.userStore;
|
||||||
accessStore = stores.accessStore;
|
|
||||||
eventStore = stores.eventStore;
|
eventStore = stores.eventStore;
|
||||||
const roles = await accessStore.getRootRoles();
|
roleStore = stores.roleStore;
|
||||||
|
const roles = await roleStore.getRootRoles();
|
||||||
editorRole = roles.find((r) => r.name === RoleName.EDITOR);
|
editorRole = roles.find((r) => r.name === RoleName.EDITOR);
|
||||||
adminRole = roles.find((r) => r.name === RoleName.ADMIN);
|
adminRole = roles.find((r) => r.name === RoleName.ADMIN);
|
||||||
});
|
});
|
||||||
|
@ -366,7 +366,7 @@ test('should return role with permissions and users', async () => {
|
|||||||
|
|
||||||
await accessService.addUserToRole(user.id, editorRole.id, 'default');
|
await accessService.addUserToRole(user.id, editorRole.id, 'default');
|
||||||
|
|
||||||
const roleWithPermission = await accessService.getRole(editorRole.id);
|
const roleWithPermission = await accessService.getRoleData(editorRole.id);
|
||||||
|
|
||||||
expect(roleWithPermission.role.name).toBe(RoleName.EDITOR);
|
expect(roleWithPermission.role.name).toBe(RoleName.EDITOR);
|
||||||
expect(roleWithPermission.permissions.length > 2).toBe(true);
|
expect(roleWithPermission.permissions.length > 2).toBe(true);
|
||||||
@ -436,7 +436,7 @@ test('should not crash if user does not have permission', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should support permission with "ALL" environment requirement', async () => {
|
test('should support permission with "ALL" environment requirement', async () => {
|
||||||
const { userStore, accessStore } = stores;
|
const { userStore, roleStore, accessStore } = stores;
|
||||||
|
|
||||||
const user = await userStore.insert({
|
const user = await userStore.insert({
|
||||||
name: 'Some User',
|
name: 'Some User',
|
||||||
@ -445,11 +445,11 @@ test('should support permission with "ALL" environment requirement', async () =>
|
|||||||
|
|
||||||
await accessService.setUserRootRole(user.id, readRole.id);
|
await accessService.setUserRootRole(user.id, readRole.id);
|
||||||
|
|
||||||
const customRole = await accessStore.createRole(
|
const customRole = await roleStore.create({
|
||||||
'Power user',
|
name: 'Power user',
|
||||||
'custom',
|
roleType: 'custom',
|
||||||
'Grants access to modify all environments',
|
description: 'Grants access to modify all environments',
|
||||||
);
|
});
|
||||||
|
|
||||||
const { CREATE_FEATURE_STRATEGY } = permissions;
|
const { CREATE_FEATURE_STRATEGY } = permissions;
|
||||||
await accessStore.addPermissionsToRole(
|
await accessStore.addPermissionsToRole(
|
||||||
|
@ -3,12 +3,7 @@ import getLogger from '../../fixtures/no-logger';
|
|||||||
import FeatureToggleService from '../../../lib/services/feature-toggle-service';
|
import FeatureToggleService from '../../../lib/services/feature-toggle-service';
|
||||||
import ProjectService from '../../../lib/services/project-service';
|
import ProjectService from '../../../lib/services/project-service';
|
||||||
import { AccessService } from '../../../lib/services/access-service';
|
import { AccessService } from '../../../lib/services/access-service';
|
||||||
import {
|
import { CREATE_FEATURE, UPDATE_FEATURE } from '../../../lib/types/permissions';
|
||||||
CREATE_FEATURE,
|
|
||||||
UPDATE_FEATURE,
|
|
||||||
UPDATE_PROJECT,
|
|
||||||
} from '../../../lib/types/permissions';
|
|
||||||
import NotFoundError from '../../../lib/error/notfound-error';
|
|
||||||
import { createTestConfig } from '../../config/test-config';
|
import { createTestConfig } from '../../config/test-config';
|
||||||
import { RoleName } from '../../../lib/types/model';
|
import { RoleName } from '../../../lib/types/model';
|
||||||
|
|
||||||
@ -216,8 +211,8 @@ test('should get list of users with access to project', async () => {
|
|||||||
await projectService.createProject(project, user);
|
await projectService.createProject(project, user);
|
||||||
const { users } = await projectService.getUsersWithAccess(project.id, user);
|
const { users } = await projectService.getUsersWithAccess(project.id, user);
|
||||||
|
|
||||||
const member = await stores.accessStore.getRoleByName(RoleName.MEMBER);
|
const member = await stores.roleStore.getRoleByName(RoleName.MEMBER);
|
||||||
const owner = await stores.accessStore.getRoleByName(RoleName.OWNER);
|
const owner = await stores.roleStore.getRoleByName(RoleName.OWNER);
|
||||||
|
|
||||||
expect(users).toHaveLength(1);
|
expect(users).toHaveLength(1);
|
||||||
expect(users[0].id).toBe(user.id);
|
expect(users[0].id).toBe(user.id);
|
||||||
@ -243,7 +238,7 @@ test('should add a member user to the project', async () => {
|
|||||||
email: 'member2@getunleash.io',
|
email: 'member2@getunleash.io',
|
||||||
});
|
});
|
||||||
|
|
||||||
const memberRole = await stores.accessStore.getRoleByName(RoleName.MEMBER);
|
const memberRole = await stores.roleStore.getRoleByName(RoleName.MEMBER);
|
||||||
|
|
||||||
await projectService.addUser(project.id, memberRole.id, projectMember1.id);
|
await projectService.addUser(project.id, memberRole.id, projectMember1.id);
|
||||||
await projectService.addUser(project.id, memberRole.id, projectMember2.id);
|
await projectService.addUser(project.id, memberRole.id, projectMember2.id);
|
||||||
@ -275,7 +270,7 @@ test('should add admin users to the project', async () => {
|
|||||||
email: 'admin2@getunleash.io',
|
email: 'admin2@getunleash.io',
|
||||||
});
|
});
|
||||||
|
|
||||||
const ownerRole = await stores.accessStore.getRoleByName(RoleName.OWNER);
|
const ownerRole = await stores.roleStore.getRoleByName(RoleName.OWNER);
|
||||||
|
|
||||||
await projectService.addUser(project.id, ownerRole.id, projectAdmin1.id);
|
await projectService.addUser(project.id, ownerRole.id, projectAdmin1.id);
|
||||||
await projectService.addUser(project.id, ownerRole.id, projectAdmin2.id);
|
await projectService.addUser(project.id, ownerRole.id, projectAdmin2.id);
|
||||||
@ -304,7 +299,7 @@ test('add user should fail if user already have access', async () => {
|
|||||||
email: 'member42@getunleash.io',
|
email: 'member42@getunleash.io',
|
||||||
});
|
});
|
||||||
|
|
||||||
const memberRole = await stores.accessStore.getRoleByName(RoleName.MEMBER);
|
const memberRole = await stores.roleStore.getRoleByName(RoleName.MEMBER);
|
||||||
|
|
||||||
await projectService.addUser(project.id, memberRole.id, projectMember1.id);
|
await projectService.addUser(project.id, memberRole.id, projectMember1.id);
|
||||||
|
|
||||||
@ -328,7 +323,7 @@ test('should remove user from the project', async () => {
|
|||||||
email: 'member99@getunleash.io',
|
email: 'member99@getunleash.io',
|
||||||
});
|
});
|
||||||
|
|
||||||
const memberRole = await stores.accessStore.getRoleByName(RoleName.MEMBER);
|
const memberRole = await stores.roleStore.getRoleByName(RoleName.MEMBER);
|
||||||
|
|
||||||
await projectService.addUser(project.id, memberRole.id, projectMember1.id);
|
await projectService.addUser(project.id, memberRole.id, projectMember1.id);
|
||||||
await projectService.removeUser(
|
await projectService.removeUser(
|
||||||
@ -351,7 +346,7 @@ test('should not remove user from the project', async () => {
|
|||||||
};
|
};
|
||||||
await projectService.createProject(project, user);
|
await projectService.createProject(project, user);
|
||||||
|
|
||||||
const roles = await stores.accessStore.getRolesForProject(project.id);
|
const roles = await stores.roleStore.getRolesForProject(project.id);
|
||||||
const ownerRole = roles.find((r) => r.name === RoleName.OWNER);
|
const ownerRole = roles.find((r) => r.name === RoleName.OWNER);
|
||||||
|
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
|
10
src/test/fixtures/access-service-mock.ts
vendored
10
src/test/fixtures/access-service-mock.ts
vendored
@ -13,7 +13,11 @@ import {
|
|||||||
class AccessServiceMock extends AccessService {
|
class AccessServiceMock extends AccessService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(
|
super(
|
||||||
{ accessStore: undefined, userStore: undefined },
|
{
|
||||||
|
accessStore: undefined,
|
||||||
|
userStore: undefined,
|
||||||
|
roleStore: undefined,
|
||||||
|
},
|
||||||
{ getLogger: noLoggerProvider },
|
{ getLogger: noLoggerProvider },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -62,10 +66,6 @@ class AccessServiceMock extends AccessService {
|
|||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
getRole(roleId: number): Promise<IRoleData> {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
|
|
||||||
getRolesForProject(projectId: string): Promise<IRole[]> {
|
getRolesForProject(projectId: string): Promise<IRole[]> {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
9
src/test/fixtures/fake-access-store.ts
vendored
9
src/test/fixtures/fake-access-store.ts
vendored
@ -94,15 +94,6 @@ class AccessStoreMock implements IAccessStore {
|
|||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
createRole(
|
|
||||||
name: string,
|
|
||||||
type: string,
|
|
||||||
project?: string,
|
|
||||||
description?: string,
|
|
||||||
): Promise<IRole> {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
|
|
||||||
addPermissionsToRole(
|
addPermissionsToRole(
|
||||||
role_id: number,
|
role_id: number,
|
||||||
permissions: string[],
|
permissions: string[],
|
||||||
|
88
src/test/fixtures/fake-role-store.ts
vendored
88
src/test/fixtures/fake-role-store.ts
vendored
@ -1,62 +1,70 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
import { ICustomRole } from 'lib/types/model';
|
import { ICustomRole } from 'lib/types/model';
|
||||||
|
import { IRole, IUserRole } from 'lib/types/stores/access-store';
|
||||||
import {
|
import {
|
||||||
ICustomRoleInsert,
|
ICustomRoleInsert,
|
||||||
ICustomRoleUpdate,
|
ICustomRoleUpdate,
|
||||||
IRoleStore,
|
IRoleStore,
|
||||||
} from 'lib/types/stores/role-store';
|
} from 'lib/types/stores/role-store';
|
||||||
import {
|
|
||||||
IUserFeedback,
|
|
||||||
IUserFeedbackKey,
|
|
||||||
IUserFeedbackStore,
|
|
||||||
} from '../../lib/types/stores/user-feedback-store';
|
|
||||||
|
|
||||||
export default class FakeRoleStore implements IRoleStore {
|
export default class FakeRoleStore implements IRoleStore {
|
||||||
async update(role: ICustomRoleUpdate): Promise<ICustomRole> {
|
getAll(): Promise<ICustomRole[]> {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(key: number): Promise<ICustomRole> {
|
|
||||||
return Promise.resolve({
|
|
||||||
id: 1,
|
|
||||||
name: 'Role',
|
|
||||||
description: 'Hello',
|
|
||||||
type: 'custom',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAll(): Promise<ICustomRole[]> {
|
|
||||||
return Promise.resolve([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'Role',
|
|
||||||
description: 'Hello',
|
|
||||||
type: 'custom',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
async exists(): Promise<boolean> {
|
|
||||||
return Promise.resolve(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
create(role: ICustomRoleInsert): Promise<ICustomRole> {
|
create(role: ICustomRoleInsert): Promise<ICustomRole> {
|
||||||
return Promise.resolve({
|
throw new Error('Method not implemented.');
|
||||||
id: 1,
|
}
|
||||||
name: 'Role',
|
|
||||||
description: 'Hello',
|
update(role: ICustomRoleUpdate): Promise<ICustomRole> {
|
||||||
type: 'custom',
|
throw new Error('Method not implemented.');
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(id: number): Promise<void> {
|
delete(id: number): Promise<void> {
|
||||||
return Promise.resolve();
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy(): Promise<void> {
|
getRoles(): Promise<IRole[]> {
|
||||||
return Promise.resolve();
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
getRoleByName(name: string): Promise<IRole> {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
getRolesForProject(projectId: string): Promise<IRole[]> {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
removeRolesForProject(projectId: string): Promise<void> {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
getProjectRoles(): Promise<IRole[]> {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
getRootRoles(): Promise<IRole[]> {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
getRootRoleForAllUsers(): Promise<IUserRole[]> {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
get(key: number): Promise<ICustomRole> {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
exists(key: number): Promise<boolean> {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteAll(): Promise<void> {
|
deleteAll(): Promise<void> {
|
||||||
return Promise.resolve();
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy(): void {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user