mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-23 00:22:19 +01:00
fix: User audit events (create, update, delete) should include rootRole. (#5399)
Audit events for USER_CREATE, USER_UPDATE and USER_DELETE did not include the users rootRole.  --------- Co-authored-by: Gastón Fournier <gaston@getunleash.io>
This commit is contained in:
parent
47e214d96f
commit
f00eac0881
@ -12,7 +12,7 @@ import {
|
|||||||
IUserRole,
|
IUserRole,
|
||||||
IUserWithProjectRoles,
|
IUserWithProjectRoles,
|
||||||
} from '../types/stores/access-store';
|
} from '../types/stores/access-store';
|
||||||
import { IPermission, IUserAccessOverview } from '../types/model';
|
import { IPermission, IUserAccessOverview, RoleType } from '../types/model';
|
||||||
import NotFoundError from '../error/notfound-error';
|
import NotFoundError from '../error/notfound-error';
|
||||||
import {
|
import {
|
||||||
ENVIRONMENT_PERMISSION_TYPE,
|
ENVIRONMENT_PERMISSION_TYPE,
|
||||||
@ -360,6 +360,7 @@ export class AccessStore implements IAccessStore {
|
|||||||
.andWhere('ru.project', projectId);
|
.andWhere('ru.project', projectId);
|
||||||
return rows.map((r) => ({
|
return rows.map((r) => ({
|
||||||
userId: r.user_id,
|
userId: r.user_id,
|
||||||
|
roleId,
|
||||||
addedAt: r.created_at,
|
addedAt: r.created_at,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -400,6 +401,16 @@ export class AccessStore implements IAccessStore {
|
|||||||
.where('ru.user_id', '=', userId);
|
.where('ru.user_id', '=', userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getRootRoleForUser(userId: number): Promise<IRole | undefined> {
|
||||||
|
return this.db
|
||||||
|
.select(['id', 'name', 'type', 'description'])
|
||||||
|
.from<IRole[]>(T.ROLES)
|
||||||
|
.innerJoin(`${T.ROLE_USER} as ru`, 'ru.role_id', 'id')
|
||||||
|
.where('ru.user_id', '=', userId)
|
||||||
|
.andWhere('type', '=', RoleType.ROOT)
|
||||||
|
.first();
|
||||||
|
}
|
||||||
|
|
||||||
async getUserIdsForRole(roleId: number): Promise<number[]> {
|
async getUserIdsForRole(roleId: number): Promise<number[]> {
|
||||||
const rows = await this.db
|
const rows = await this.db
|
||||||
.select(['user_id'])
|
.select(['user_id'])
|
||||||
|
@ -170,8 +170,7 @@ class UserController extends Controller {
|
|||||||
|
|
||||||
const projects = await this.projectService.getProjectsByUser(user.id);
|
const projects = await this.projectService.getProjectsByUser(user.id);
|
||||||
|
|
||||||
const roles = await this.accessService.getUserRootRoles(user.id);
|
const rootRole = await this.accessService.getRootRoleForUser(user.id);
|
||||||
const { project, ...rootRole } = roles[0];
|
|
||||||
const responseData: ProfileSchema = {
|
const responseData: ProfileSchema = {
|
||||||
projects,
|
projects,
|
||||||
rootRole,
|
rootRole,
|
||||||
|
@ -18,6 +18,13 @@ describe('Public Signup API', () => {
|
|||||||
...stores.accessStore,
|
...stores.accessStore,
|
||||||
addUserToRole: jest.fn(),
|
addUserToRole: jest.fn(),
|
||||||
removeRolesOfTypeForUser: jest.fn(),
|
removeRolesOfTypeForUser: jest.fn(),
|
||||||
|
getRolesForUserId: () => Promise.resolve([]),
|
||||||
|
getRootRoleForUser: () =>
|
||||||
|
Promise.resolve({
|
||||||
|
id: -1,
|
||||||
|
name: RoleName.VIEWER,
|
||||||
|
type: RoleType.ROOT,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const services = createServices(stores, config);
|
const services = createServices(stores, config);
|
||||||
|
@ -190,9 +190,8 @@ test('user with custom root role should get a user root role', async () => {
|
|||||||
};
|
};
|
||||||
await accessService.setUserRootRole(user.id, customRootRole.id);
|
await accessService.setUserRootRole(user.id, customRootRole.id);
|
||||||
|
|
||||||
const roles = await accessService.getUserRootRoles(user.id);
|
const role = await accessService.getRootRoleForUser(user.id);
|
||||||
expect(roles).toHaveLength(1);
|
expect(role.name).toBe('custom-root-role');
|
||||||
expect(roles[0].name).toBe('custom-root-role');
|
|
||||||
const events = await eventStore.getEvents();
|
const events = await eventStore.getEvents();
|
||||||
expect(events).toHaveLength(1);
|
expect(events).toHaveLength(1);
|
||||||
expect(events[0]).toEqual({
|
expect(events[0]).toEqual({
|
||||||
|
@ -8,7 +8,6 @@ import {
|
|||||||
IRole,
|
IRole,
|
||||||
IRoleDescriptor,
|
IRoleDescriptor,
|
||||||
IRoleWithPermissions,
|
IRoleWithPermissions,
|
||||||
IRoleWithProject,
|
|
||||||
IUserPermission,
|
IUserPermission,
|
||||||
IUserRole,
|
IUserRole,
|
||||||
IUserWithProjectRoles,
|
IUserWithProjectRoles,
|
||||||
@ -362,9 +361,13 @@ export class AccessService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUserRootRoles(userId: number): Promise<IRoleWithProject[]> {
|
async getRootRoleForUser(userId: number): Promise<IRole> {
|
||||||
const userRoles = await this.store.getRolesForUserId(userId);
|
const rootRole = await this.store.getRootRoleForUser(userId);
|
||||||
return userRoles.filter(({ type }) => ROOT_ROLE_TYPES.includes(type));
|
if (!rootRole) {
|
||||||
|
const defaultRole = await this.getPredefinedRole(RoleName.VIEWER);
|
||||||
|
return defaultRole;
|
||||||
|
}
|
||||||
|
return rootRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeUserFromRole(
|
async removeUserFromRole(
|
||||||
@ -602,9 +605,20 @@ export class AccessService {
|
|||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRootRole(roleName: RoleName): Promise<IRole | undefined> {
|
/*
|
||||||
const roles = await this.roleStore.getRootRoles();
|
This method is intended to give a predicable way to fetch
|
||||||
return roles.find((r) => r.name === roleName);
|
pre-defined roles defined in the RoleName enum. This method
|
||||||
|
should not be used to fetch custom root or project roles.
|
||||||
|
*/
|
||||||
|
async getPredefinedRole(roleName: RoleName): Promise<IRole> {
|
||||||
|
const roles = await this.roleStore.getRoles();
|
||||||
|
const role = roles.find((r) => r.name === roleName);
|
||||||
|
if (!role) {
|
||||||
|
throw new BadDataError(
|
||||||
|
`Could not find pre-defined role with name ${RoleName}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return role;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllRoles(): Promise<ICustomRole[]> {
|
async getAllRoles(): Promise<ICustomRole[]> {
|
||||||
|
@ -34,7 +34,7 @@ export class AccountService {
|
|||||||
|
|
||||||
async getAll(): Promise<IUserWithRole[]> {
|
async getAll(): Promise<IUserWithRole[]> {
|
||||||
const accounts = await this.store.getAll();
|
const accounts = await this.store.getAll();
|
||||||
const defaultRole = await this.accessService.getRootRole(
|
const defaultRole = await this.accessService.getPredefinedRole(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
const userRoles = await this.accessService.getRootRoleForAllUsers();
|
const userRoles = await this.accessService.getRootRoleForAllUsers();
|
||||||
|
@ -4,7 +4,7 @@ import Joi from 'joi';
|
|||||||
|
|
||||||
import { URL } from 'url';
|
import { URL } from 'url';
|
||||||
import { Logger } from '../logger';
|
import { Logger } from '../logger';
|
||||||
import User, { IUser } from '../types/user';
|
import User, { IUser, IUserWithRootRole } from '../types/user';
|
||||||
import isEmail from '../util/is-email';
|
import isEmail from '../util/is-email';
|
||||||
import { AccessService } from './access-service';
|
import { AccessService } from './access-service';
|
||||||
import ResetTokenService from './reset-token-service';
|
import ResetTokenService from './reset-token-service';
|
||||||
@ -16,7 +16,14 @@ import { IAuthOption, IUnleashConfig } from '../types/option';
|
|||||||
import SessionService from './session-service';
|
import SessionService from './session-service';
|
||||||
import { IUnleashStores } from '../types/stores';
|
import { IUnleashStores } from '../types/stores';
|
||||||
import PasswordUndefinedError from '../error/password-undefined';
|
import PasswordUndefinedError from '../error/password-undefined';
|
||||||
import { USER_UPDATED, USER_CREATED, USER_DELETED } from '../types/events';
|
import {
|
||||||
|
USER_UPDATED,
|
||||||
|
USER_CREATED,
|
||||||
|
USER_DELETED,
|
||||||
|
UserCreatedEvent,
|
||||||
|
UserUpdatedEvent,
|
||||||
|
UserDeletedEvent,
|
||||||
|
} from '../types/events';
|
||||||
import { IUserStore } from '../types/stores/user-store';
|
import { IUserStore } from '../types/stores/user-store';
|
||||||
import { RoleName } from '../types/model';
|
import { RoleName } from '../types/model';
|
||||||
import SettingService from './setting-service';
|
import SettingService from './setting-service';
|
||||||
@ -53,10 +60,6 @@ export interface ILoginUserRequest {
|
|||||||
autoCreate?: boolean;
|
autoCreate?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IUserWithRole extends IUser {
|
|
||||||
rootRole: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const saltRounds = 10;
|
const saltRounds = 10;
|
||||||
|
|
||||||
class UserService {
|
class UserService {
|
||||||
@ -173,9 +176,9 @@ class UserService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAll(): Promise<IUserWithRole[]> {
|
async getAll(): Promise<IUserWithRootRole[]> {
|
||||||
const users = await this.store.getAll();
|
const users = await this.store.getAll();
|
||||||
const defaultRole = await this.accessService.getRootRole(
|
const defaultRole = await this.accessService.getPredefinedRole(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
const userRoles = await this.accessService.getRootRoleForAllUsers();
|
const userRoles = await this.accessService.getRootRoleForAllUsers();
|
||||||
@ -187,14 +190,10 @@ class UserService {
|
|||||||
return usersWithRootRole;
|
return usersWithRootRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUser(id: number): Promise<IUserWithRole> {
|
async getUser(id: number): Promise<IUserWithRootRole> {
|
||||||
const roles = await this.accessService.getUserRootRoles(id);
|
|
||||||
const defaultRole = await this.accessService.getRootRole(
|
|
||||||
RoleName.VIEWER,
|
|
||||||
);
|
|
||||||
const roleId = roles.length > 0 ? roles[0].id : defaultRole.id;
|
|
||||||
const user = await this.store.get(id);
|
const user = await this.store.get(id);
|
||||||
return { ...user, rootRole: roleId };
|
const rootRole = await this.accessService.getRootRoleForUser(id);
|
||||||
|
return { ...user, rootRole: rootRole.id };
|
||||||
}
|
}
|
||||||
|
|
||||||
async search(query: string): Promise<IUser[]> {
|
async search(query: string): Promise<IUser[]> {
|
||||||
@ -208,7 +207,7 @@ class UserService {
|
|||||||
async createUser(
|
async createUser(
|
||||||
{ username, email, name, password, rootRole }: ICreateUser,
|
{ username, email, name, password, rootRole }: ICreateUser,
|
||||||
updatedBy?: IUser,
|
updatedBy?: IUser,
|
||||||
): Promise<IUser> {
|
): Promise<IUserWithRootRole> {
|
||||||
if (!username && !email) {
|
if (!username && !email) {
|
||||||
throw new BadDataError('You must specify username or email');
|
throw new BadDataError('You must specify username or email');
|
||||||
}
|
}
|
||||||
@ -235,36 +234,27 @@ class UserService {
|
|||||||
await this.store.setPasswordHash(user.id, passwordHash);
|
await this.store.setPasswordHash(user.id, passwordHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.eventService.storeEvent({
|
const userCreated = await this.getUser(user.id);
|
||||||
type: USER_CREATED,
|
|
||||||
createdBy: this.getCreatedBy(updatedBy),
|
|
||||||
data: this.mapUserToData(user),
|
|
||||||
});
|
|
||||||
|
|
||||||
return user;
|
await this.eventService.storeEvent(
|
||||||
|
new UserCreatedEvent({
|
||||||
|
createdBy: this.getCreatedBy(updatedBy),
|
||||||
|
userCreated,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return userCreated;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCreatedBy(updatedBy: IUser = systemUser) {
|
private getCreatedBy(updatedBy: IUser = systemUser) {
|
||||||
return updatedBy.username || updatedBy.email;
|
return updatedBy.username || updatedBy.email;
|
||||||
}
|
}
|
||||||
|
|
||||||
private mapUserToData(user?: IUser): any {
|
|
||||||
if (!user) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
id: user.id,
|
|
||||||
name: user.name,
|
|
||||||
username: user.username,
|
|
||||||
email: user.email,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateUser(
|
async updateUser(
|
||||||
{ id, name, email, rootRole }: IUpdateUser,
|
{ id, name, email, rootRole }: IUpdateUser,
|
||||||
updatedBy?: IUser,
|
updatedBy?: IUser,
|
||||||
): Promise<IUser> {
|
): Promise<IUserWithRootRole> {
|
||||||
const preUser = await this.store.get(id);
|
const preUser = await this.getUser(id);
|
||||||
|
|
||||||
if (email) {
|
if (email) {
|
||||||
Joi.assert(email, Joi.string().email(), 'Email');
|
Joi.assert(email, Joi.string().email(), 'Email');
|
||||||
@ -284,28 +274,32 @@ class UserService {
|
|||||||
? await this.store.update(id, payload)
|
? await this.store.update(id, payload)
|
||||||
: preUser;
|
: preUser;
|
||||||
|
|
||||||
await this.eventService.storeEvent({
|
const storedUser = await this.getUser(user.id);
|
||||||
type: USER_UPDATED,
|
|
||||||
createdBy: this.getCreatedBy(updatedBy),
|
|
||||||
data: this.mapUserToData(user),
|
|
||||||
preData: this.mapUserToData(preUser),
|
|
||||||
});
|
|
||||||
|
|
||||||
return user;
|
await this.eventService.storeEvent(
|
||||||
|
new UserUpdatedEvent({
|
||||||
|
createdBy: this.getCreatedBy(updatedBy),
|
||||||
|
preUser: preUser,
|
||||||
|
postUser: storedUser,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return storedUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteUser(userId: number, updatedBy?: IUser): Promise<void> {
|
async deleteUser(userId: number, updatedBy?: IUser): Promise<void> {
|
||||||
const user = await this.store.get(userId);
|
const user = await this.getUser(userId);
|
||||||
await this.accessService.wipeUserPermissions(userId);
|
await this.accessService.wipeUserPermissions(userId);
|
||||||
await this.sessionService.deleteSessionsForUser(userId);
|
await this.sessionService.deleteSessionsForUser(userId);
|
||||||
|
|
||||||
await this.store.delete(userId);
|
await this.store.delete(userId);
|
||||||
|
|
||||||
await this.eventService.storeEvent({
|
await this.eventService.storeEvent(
|
||||||
type: USER_DELETED,
|
new UserDeletedEvent({
|
||||||
createdBy: this.getCreatedBy(updatedBy),
|
createdBy: this.getCreatedBy(updatedBy),
|
||||||
preData: this.mapUserToData(user),
|
deletedUser: user,
|
||||||
});
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async loginUser(usernameOrEmail: string, password: string): Promise<IUser> {
|
async loginUser(usernameOrEmail: string, password: string): Promise<IUser> {
|
||||||
@ -479,5 +473,4 @@ class UserService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = UserService;
|
|
||||||
export default UserService;
|
export default UserService;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { extractUsernameFromUser } from '../util';
|
import { extractUsernameFromUser } from '../util';
|
||||||
import { FeatureToggle, IStrategyConfig, ITag, IVariant } from './model';
|
import { FeatureToggle, IStrategyConfig, ITag, IVariant } from './model';
|
||||||
import { IApiToken } from './models/api-token';
|
import { IApiToken } from './models/api-token';
|
||||||
import { IUser } from './user';
|
import { IUser, IUserWithRootRole } from './user';
|
||||||
|
|
||||||
export const APPLICATION_CREATED = 'application-created' as const;
|
export const APPLICATION_CREATED = 'application-created' as const;
|
||||||
|
|
||||||
@ -1096,3 +1096,52 @@ export class PotentiallyStaleOnEvent extends BaseEvent {
|
|||||||
this.project = eventData.project;
|
this.project = eventData.project;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class UserCreatedEvent extends BaseEvent {
|
||||||
|
readonly data: IUserWithRootRole;
|
||||||
|
|
||||||
|
constructor(eventData: {
|
||||||
|
createdBy: string | IUser;
|
||||||
|
userCreated: IUserWithRootRole;
|
||||||
|
}) {
|
||||||
|
super(USER_CREATED, eventData.createdBy);
|
||||||
|
this.data = mapUserToData(eventData.userCreated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UserUpdatedEvent extends BaseEvent {
|
||||||
|
readonly data: IUserWithRootRole;
|
||||||
|
readonly preData: IUserWithRootRole;
|
||||||
|
|
||||||
|
constructor(eventData: {
|
||||||
|
createdBy: string | IUser;
|
||||||
|
preUser: IUserWithRootRole;
|
||||||
|
postUser: IUserWithRootRole;
|
||||||
|
}) {
|
||||||
|
super(USER_UPDATED, eventData.createdBy);
|
||||||
|
this.preData = mapUserToData(eventData.preUser);
|
||||||
|
this.data = mapUserToData(eventData.postUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UserDeletedEvent extends BaseEvent {
|
||||||
|
readonly preData: IUserWithRootRole;
|
||||||
|
|
||||||
|
constructor(eventData: {
|
||||||
|
createdBy: string | IUser;
|
||||||
|
deletedUser: IUserWithRootRole;
|
||||||
|
}) {
|
||||||
|
super(USER_DELETED, eventData.createdBy);
|
||||||
|
this.preData = mapUserToData(eventData.deletedUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapUserToData(user: IUserWithRootRole): any {
|
||||||
|
return {
|
||||||
|
id: user.id,
|
||||||
|
name: user.name,
|
||||||
|
username: user.username,
|
||||||
|
email: user.email,
|
||||||
|
rootRole: user.rootRole,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -49,7 +49,7 @@ export interface IAccessInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IUserRole {
|
export interface IUserRole {
|
||||||
roleId?: number;
|
roleId: number;
|
||||||
userId: number;
|
userId: number;
|
||||||
addedAt?: Date;
|
addedAt?: Date;
|
||||||
}
|
}
|
||||||
@ -188,6 +188,7 @@ export interface IAccessStore extends Store<IRole, number> {
|
|||||||
projectId: string,
|
projectId: string,
|
||||||
userId: number,
|
userId: number,
|
||||||
): Promise<number[]>;
|
): Promise<number[]>;
|
||||||
|
getRootRoleForUser(userId: number): Promise<IRole | undefined>;
|
||||||
setProjectRolesForGroup(
|
setProjectRolesForGroup(
|
||||||
projectId: string,
|
projectId: string,
|
||||||
groupId: number,
|
groupId: number,
|
||||||
|
@ -92,4 +92,8 @@ export default class User implements IUser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IUserWithRootRole extends IUser {
|
||||||
|
rootRole: number;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = User;
|
module.exports = User;
|
||||||
|
@ -37,7 +37,7 @@ test('editor users should only get client or frontend tokens', async () => {
|
|||||||
|
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(RoleName.EDITOR);
|
const role = await accessService.getPredefinedRole(RoleName.EDITOR);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
email: 'editor@example.com',
|
email: 'editor@example.com',
|
||||||
rootRole: role.id,
|
rootRole: role.id,
|
||||||
@ -85,7 +85,7 @@ test('viewer users should not be allowed to fetch tokens', async () => {
|
|||||||
|
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(RoleName.VIEWER);
|
const role = await accessService.getPredefinedRole(RoleName.VIEWER);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
email: 'viewer@example.com',
|
email: 'viewer@example.com',
|
||||||
rootRole: role.id,
|
rootRole: role.id,
|
||||||
@ -122,7 +122,7 @@ test('Only token-admins should be allowed to create token', async () => {
|
|||||||
|
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(RoleName.EDITOR);
|
const role = await accessService.getPredefinedRole(RoleName.EDITOR);
|
||||||
req.user = await userService.createUser({
|
req.user = await userService.createUser({
|
||||||
email: 'editor2@example.com',
|
email: 'editor2@example.com',
|
||||||
rootRole: role.id,
|
rootRole: role.id,
|
||||||
@ -150,7 +150,7 @@ test('Token-admin should be allowed to create token', async () => {
|
|||||||
|
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(RoleName.ADMIN);
|
const role = await accessService.getPredefinedRole(RoleName.ADMIN);
|
||||||
req.user = await userService.createUser({
|
req.user = await userService.createUser({
|
||||||
email: 'admin@example.com',
|
email: 'admin@example.com',
|
||||||
rootRole: role.id,
|
rootRole: role.id,
|
||||||
@ -185,7 +185,9 @@ test('A role with only CREATE_PROJECT_API_TOKEN can create project tokens', asyn
|
|||||||
}: { userService: UserService; accessService: AccessService },
|
}: { userService: UserService; accessService: AccessService },
|
||||||
) => {
|
) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = (await accessService.getRootRole(RoleName.VIEWER))!;
|
const role = (await accessService.getPredefinedRole(
|
||||||
|
RoleName.VIEWER,
|
||||||
|
))!;
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
email: 'powerpuffgirls_viewer@example.com',
|
email: 'powerpuffgirls_viewer@example.com',
|
||||||
rootRole: role.id,
|
rootRole: role.id,
|
||||||
@ -230,7 +232,7 @@ describe('Fine grained API token permissions', () => {
|
|||||||
test('should be allowed to create client tokens', async () => {
|
test('should be allowed to create client tokens', async () => {
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const builtInRole = await accessService.getRootRole(
|
const builtInRole = await accessService.getPredefinedRole(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
@ -275,7 +277,7 @@ describe('Fine grained API token permissions', () => {
|
|||||||
test('should NOT be allowed to create frontend tokens', async () => {
|
test('should NOT be allowed to create frontend tokens', async () => {
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(
|
const role = await accessService.getPredefinedRole(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
@ -319,7 +321,7 @@ describe('Fine grained API token permissions', () => {
|
|||||||
test('should NOT be allowed to create ADMIN tokens', async () => {
|
test('should NOT be allowed to create ADMIN tokens', async () => {
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(
|
const role = await accessService.getPredefinedRole(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
@ -365,7 +367,7 @@ describe('Fine grained API token permissions', () => {
|
|||||||
test('READ_FRONTEND_API_TOKEN should be able to see FRONTEND tokens', async () => {
|
test('READ_FRONTEND_API_TOKEN should be able to see FRONTEND tokens', async () => {
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(
|
const role = await accessService.getPredefinedRole(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
@ -429,7 +431,7 @@ describe('Fine grained API token permissions', () => {
|
|||||||
test('READ_CLIENT_API_TOKEN should be able to see CLIENT tokens', async () => {
|
test('READ_CLIENT_API_TOKEN should be able to see CLIENT tokens', async () => {
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(
|
const role = await accessService.getPredefinedRole(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
@ -488,7 +490,7 @@ describe('Fine grained API token permissions', () => {
|
|||||||
test('Admin users should be able to see all tokens', async () => {
|
test('Admin users should be able to see all tokens', async () => {
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(
|
const role = await accessService.getPredefinedRole(
|
||||||
RoleName.ADMIN,
|
RoleName.ADMIN,
|
||||||
);
|
);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
@ -531,7 +533,7 @@ describe('Fine grained API token permissions', () => {
|
|||||||
test('Editor users should be able to see all tokens except ADMIN tokens', async () => {
|
test('Editor users should be able to see all tokens except ADMIN tokens', async () => {
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(
|
const role = await accessService.getPredefinedRole(
|
||||||
RoleName.EDITOR,
|
RoleName.EDITOR,
|
||||||
);
|
);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
@ -585,7 +587,7 @@ describe('Fine grained API token permissions', () => {
|
|||||||
{ userService, accessService },
|
{ userService, accessService },
|
||||||
) => {
|
) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(
|
const role = await accessService.getPredefinedRole(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
@ -634,7 +636,7 @@ describe('Fine grained API token permissions', () => {
|
|||||||
{ userService, accessService },
|
{ userService, accessService },
|
||||||
) => {
|
) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(
|
const role = await accessService.getPredefinedRole(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
@ -684,7 +686,7 @@ describe('Fine grained API token permissions', () => {
|
|||||||
{ userService, accessService },
|
{ userService, accessService },
|
||||||
) => {
|
) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(
|
const role = await accessService.getPredefinedRole(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
@ -737,7 +739,7 @@ describe('Fine grained API token permissions', () => {
|
|||||||
{ userService, accessService },
|
{ userService, accessService },
|
||||||
) => {
|
) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(
|
const role = await accessService.getPredefinedRole(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
@ -786,7 +788,7 @@ describe('Fine grained API token permissions', () => {
|
|||||||
{ userService, accessService },
|
{ userService, accessService },
|
||||||
) => {
|
) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(
|
const role = await accessService.getPredefinedRole(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
@ -835,7 +837,7 @@ describe('Fine grained API token permissions', () => {
|
|||||||
{ userService, accessService },
|
{ userService, accessService },
|
||||||
) => {
|
) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(
|
const role = await accessService.getPredefinedRole(
|
||||||
RoleName.VIEWER,
|
RoleName.VIEWER,
|
||||||
);
|
);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
|
@ -35,7 +35,7 @@ test('admin users should be able to create a token', async () => {
|
|||||||
|
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(RoleName.ADMIN);
|
const role = await accessService.getPredefinedRole(RoleName.ADMIN);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
email: 'admin@example.com',
|
email: 'admin@example.com',
|
||||||
rootRole: role.id,
|
rootRole: role.id,
|
||||||
@ -69,7 +69,7 @@ test('admin users should be able to create a token', async () => {
|
|||||||
test('no permission to validate a token', async () => {
|
test('no permission to validate a token', async () => {
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const admin = await accessService.getRootRole(RoleName.ADMIN);
|
const admin = await accessService.getPredefinedRole(RoleName.ADMIN);
|
||||||
await userService.createUser({
|
await userService.createUser({
|
||||||
email: 'admin@example.com',
|
email: 'admin@example.com',
|
||||||
username: 'admin@example.com',
|
username: 'admin@example.com',
|
||||||
@ -97,7 +97,7 @@ test('no permission to validate a token', async () => {
|
|||||||
test('should return 400 if token can not be validate', async () => {
|
test('should return 400 if token can not be validate', async () => {
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const admin = await accessService.getRootRole(RoleName.ADMIN);
|
const admin = await accessService.getPredefinedRole(RoleName.ADMIN);
|
||||||
await userService.createUser({
|
await userService.createUser({
|
||||||
email: 'admin@example.com',
|
email: 'admin@example.com',
|
||||||
username: 'admin@example.com',
|
username: 'admin@example.com',
|
||||||
@ -119,7 +119,7 @@ test('users can signup with invite-link', async () => {
|
|||||||
|
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const admin = await accessService.getRootRole(RoleName.ADMIN);
|
const admin = await accessService.getPredefinedRole(RoleName.ADMIN);
|
||||||
await userService.createUser({
|
await userService.createUser({
|
||||||
email: 'admin@example.com',
|
email: 'admin@example.com',
|
||||||
username: 'admin@example.com',
|
username: 'admin@example.com',
|
||||||
@ -164,7 +164,7 @@ test('can get a token with users', async () => {
|
|||||||
|
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(RoleName.ADMIN);
|
const role = await accessService.getPredefinedRole(RoleName.ADMIN);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
email: 'admin@example.com',
|
email: 'admin@example.com',
|
||||||
rootRole: role.id,
|
rootRole: role.id,
|
||||||
@ -209,7 +209,7 @@ test('can get a token with users', async () => {
|
|||||||
test('should not be able to set expiry further than 1 month', async () => {
|
test('should not be able to set expiry further than 1 month', async () => {
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(RoleName.ADMIN);
|
const role = await accessService.getPredefinedRole(RoleName.ADMIN);
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
email: 'admin@example.com',
|
email: 'admin@example.com',
|
||||||
rootRole: role.id,
|
rootRole: role.id,
|
||||||
|
@ -80,13 +80,13 @@ beforeAll(async () => {
|
|||||||
settingService,
|
settingService,
|
||||||
});
|
});
|
||||||
resetTokenService = new ResetTokenService(stores, config);
|
resetTokenService = new ResetTokenService(stores, config);
|
||||||
const adminRole = (await accessService.getRootRole(RoleName.ADMIN))!;
|
const adminRole = (await accessService.getPredefinedRole(RoleName.ADMIN))!;
|
||||||
adminUser = await userService.createUser({
|
adminUser = await userService.createUser({
|
||||||
username: 'admin@test.com',
|
username: 'admin@test.com',
|
||||||
rootRole: adminRole.id,
|
rootRole: adminRole.id,
|
||||||
})!;
|
})!;
|
||||||
|
|
||||||
const userRole = (await accessService.getRootRole(RoleName.EDITOR))!;
|
const userRole = (await accessService.getPredefinedRole(RoleName.EDITOR))!;
|
||||||
user = await userService.createUser({
|
user = await userService.createUser({
|
||||||
username: 'test@test.com',
|
username: 'test@test.com',
|
||||||
email: 'test@test.com',
|
email: 'test@test.com',
|
||||||
|
@ -56,7 +56,7 @@ beforeAll(async () => {
|
|||||||
sessionService,
|
sessionService,
|
||||||
settingService,
|
settingService,
|
||||||
});
|
});
|
||||||
const adminRole = await accessService.getRootRole(RoleName.ADMIN);
|
const adminRole = await accessService.getPredefinedRole(RoleName.ADMIN);
|
||||||
adminUser = await userService.createUser({
|
adminUser = await userService.createUser({
|
||||||
username: 'admin@test.com',
|
username: 'admin@test.com',
|
||||||
email: 'admin@test.com',
|
email: 'admin@test.com',
|
||||||
|
@ -7,7 +7,7 @@ let stores;
|
|||||||
|
|
||||||
const preHook = (app, config, { userService, accessService }) => {
|
const preHook = (app, config, { userService, accessService }) => {
|
||||||
app.use('/api/admin/', async (req, res, next) => {
|
app.use('/api/admin/', async (req, res, next) => {
|
||||||
const role = await accessService.getRootRole(RoleName.EDITOR);
|
const role = await accessService.getPredefinedRole(RoleName.EDITOR);
|
||||||
req.user = await userService.createUser({
|
req.user = await userService.createUser({
|
||||||
email: 'editor2@example.com',
|
email: 'editor2@example.com',
|
||||||
rootRole: role.id,
|
rootRole: role.id,
|
||||||
|
@ -18,6 +18,7 @@ import { randomId } from '../../../lib/util/random-id';
|
|||||||
import { BadDataError } from '../../../lib/error';
|
import { BadDataError } from '../../../lib/error';
|
||||||
import PasswordMismatch from '../../../lib/error/password-mismatch';
|
import PasswordMismatch from '../../../lib/error/password-mismatch';
|
||||||
import { EventService } from '../../../lib/services';
|
import { EventService } from '../../../lib/services';
|
||||||
|
import { USER_CREATED, USER_DELETED, USER_UPDATED } from '../../../lib/types';
|
||||||
|
|
||||||
let db;
|
let db;
|
||||||
let stores;
|
let stores;
|
||||||
@ -27,12 +28,13 @@ let adminRole: IRole;
|
|||||||
let viewerRole: IRole;
|
let viewerRole: IRole;
|
||||||
let sessionService: SessionService;
|
let sessionService: SessionService;
|
||||||
let settingService: SettingService;
|
let settingService: SettingService;
|
||||||
|
let eventService: EventService;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
db = await dbInit('user_service_serial', getLogger);
|
db = await dbInit('user_service_serial', getLogger);
|
||||||
stores = db.stores;
|
stores = db.stores;
|
||||||
const config = createTestConfig();
|
const config = createTestConfig();
|
||||||
const eventService = new EventService(stores, config);
|
eventService = new EventService(stores, config);
|
||||||
const groupService = new GroupService(stores, config, eventService);
|
const groupService = new GroupService(stores, config, eventService);
|
||||||
const accessService = new AccessService(
|
const accessService = new AccessService(
|
||||||
stores,
|
stores,
|
||||||
@ -124,6 +126,49 @@ test('should create user with password', async () => {
|
|||||||
expect(user.username).toBe('test');
|
expect(user.username).toBe('test');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should create user with rootRole in audit-log', async () => {
|
||||||
|
const user = await userService.createUser({
|
||||||
|
username: 'test',
|
||||||
|
rootRole: viewerRole.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { events } = await eventService.getEvents();
|
||||||
|
expect(events[0].type).toBe(USER_CREATED);
|
||||||
|
expect(events[0].data.id).toBe(user.id);
|
||||||
|
expect(events[0].data.username).toBe('test');
|
||||||
|
expect(events[0].data.rootRole).toBe(viewerRole.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should update user with rootRole in audit-log', async () => {
|
||||||
|
const user = await userService.createUser({
|
||||||
|
username: 'test',
|
||||||
|
rootRole: viewerRole.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
await userService.updateUser({ id: user.id, rootRole: adminRole.id });
|
||||||
|
|
||||||
|
const { events } = await eventService.getEvents();
|
||||||
|
expect(events[0].type).toBe(USER_UPDATED);
|
||||||
|
expect(events[0].data.id).toBe(user.id);
|
||||||
|
expect(events[0].data.username).toBe('test');
|
||||||
|
expect(events[0].data.rootRole).toBe(adminRole.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should remove user with rootRole in audit-log', async () => {
|
||||||
|
const user = await userService.createUser({
|
||||||
|
username: 'test',
|
||||||
|
rootRole: viewerRole.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
await userService.deleteUser(user.id);
|
||||||
|
|
||||||
|
const { events } = await eventService.getEvents();
|
||||||
|
expect(events[0].type).toBe(USER_DELETED);
|
||||||
|
expect(events[0].preData.id).toBe(user.id);
|
||||||
|
expect(events[0].preData.username).toBe('test');
|
||||||
|
expect(events[0].preData.rootRole).toBe(viewerRole.id);
|
||||||
|
});
|
||||||
|
|
||||||
test('should not be able to login with deleted user', async () => {
|
test('should not be able to login with deleted user', async () => {
|
||||||
const user = await userService.createUser({
|
const user = await userService.createUser({
|
||||||
username: 'deleted_user',
|
username: 'deleted_user',
|
||||||
|
16
src/test/fixtures/access-service-mock.ts
vendored
16
src/test/fixtures/access-service-mock.ts
vendored
@ -7,7 +7,7 @@ import {
|
|||||||
import User from '../../lib/types/user';
|
import User from '../../lib/types/user';
|
||||||
import noLoggerProvider from './no-logger';
|
import noLoggerProvider from './no-logger';
|
||||||
import { IRole } from '../../lib/types/stores/access-store';
|
import { IRole } from '../../lib/types/stores/access-store';
|
||||||
import { IAvailablePermissions } from '../../lib/types/model';
|
import { IAvailablePermissions, RoleName } from '../../lib/types/model';
|
||||||
|
|
||||||
class AccessServiceMock extends AccessService {
|
class AccessServiceMock extends AccessService {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -69,7 +69,11 @@ class AccessServiceMock extends AccessService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getRolesForUser(userId: number): Promise<IRole[]> {
|
getRolesForUser(userId: number): Promise<IRole[]> {
|
||||||
throw new Error('Method not implemented.');
|
return Promise.resolve([{ id: 1, name: 'Admin', type: 'root' }]);
|
||||||
|
}
|
||||||
|
|
||||||
|
getUserRootRoles(userId: number): Promise<IRole[]> {
|
||||||
|
return Promise.resolve([{ id: 1, name: 'Admin', type: 'root' }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
getUsersForRole(roleId: any): Promise<User[]> {
|
getUsersForRole(roleId: any): Promise<User[]> {
|
||||||
@ -87,6 +91,14 @@ class AccessServiceMock extends AccessService {
|
|||||||
removeDefaultProjectRoles(owner: User, projectId: string): Promise<void> {
|
removeDefaultProjectRoles(owner: User, projectId: string): Promise<void> {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getRootRole(roleName: RoleName): Promise<IRole> {
|
||||||
|
return Promise.resolve({ id: 1, name: roleName, type: 'root' });
|
||||||
|
}
|
||||||
|
|
||||||
|
getRootRoleForUser(userId: number): Promise<IRole> {
|
||||||
|
return Promise.resolve({ id: 1, name: RoleName.VIEWER, type: 'root' });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AccessServiceMock;
|
export default AccessServiceMock;
|
||||||
|
21
src/test/fixtures/fake-access-store.ts
vendored
21
src/test/fixtures/fake-access-store.ts
vendored
@ -9,8 +9,13 @@ import {
|
|||||||
IUserRole,
|
IUserRole,
|
||||||
IUserWithProjectRoles,
|
IUserWithProjectRoles,
|
||||||
} from '../../lib/types/stores/access-store';
|
} from '../../lib/types/stores/access-store';
|
||||||
import { IPermission } from 'lib/types/model';
|
import { IPermission } from '../../lib/types/model';
|
||||||
import { IRoleStore, IUserAccessOverview } from 'lib/types';
|
import {
|
||||||
|
IRoleStore,
|
||||||
|
IUserAccessOverview,
|
||||||
|
RoleName,
|
||||||
|
RoleType,
|
||||||
|
} from '../../lib/types';
|
||||||
import FakeRoleStore from './fake-role-store';
|
import FakeRoleStore from './fake-role-store';
|
||||||
import { PermissionRef } from 'lib/services/access-service';
|
import { PermissionRef } from 'lib/services/access-service';
|
||||||
import { P } from 'ts-toolbelt/out/Object/_api';
|
import { P } from 'ts-toolbelt/out/Object/_api';
|
||||||
@ -302,6 +307,18 @@ class AccessStoreMock implements IAccessStore {
|
|||||||
getUserAccessOverview(): Promise<IUserAccessOverview[]> {
|
getUserAccessOverview(): Promise<IUserAccessOverview[]> {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
getRootRoleForUser(userId: number): Promise<IRole> {
|
||||||
|
const roleId = this.userToRoleMap.get(userId);
|
||||||
|
if (roleId !== undefined) {
|
||||||
|
return Promise.resolve(this.fakeRolesStore.get(roleId));
|
||||||
|
} else {
|
||||||
|
return Promise.resolve({
|
||||||
|
id: -1,
|
||||||
|
name: RoleName.VIEWER,
|
||||||
|
type: RoleType.ROOT,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AccessStoreMock;
|
module.exports = AccessStoreMock;
|
||||||
|
Loading…
Reference in New Issue
Block a user