2022-08-19 10:28:53 +02:00
import NameExistsError from '../error/name-exists-error' ;
import getLogger from '../../test/fixtures/no-logger' ;
2023-06-22 16:42:01 +02:00
import { createFakeAccessService } from '../features/access/createAccessService' ;
2023-11-24 14:22:31 +01:00
import {
AccessService ,
2024-03-18 13:58:05 +01:00
type IRoleCreation ,
type IRoleValidation ,
2023-11-24 14:22:31 +01:00
} from './access-service' ;
2023-06-14 15:40:40 +02:00
import { createTestConfig } from '../../test/config/test-config' ;
2023-06-22 16:42:01 +02:00
import { CUSTOM_ROOT_ROLE_TYPE } from '../util/constants' ;
2023-08-08 13:45:19 +02:00
import FakeGroupStore from '../../test/fixtures/fake-group-store' ;
import { FakeAccountStore } from '../../test/fixtures/fake-account-store' ;
import FakeRoleStore from '../../test/fixtures/fake-role-store' ;
2023-12-01 12:41:46 +01:00
import FakeEnvironmentStore from '../features/project-environments/fake-environment-store' ;
2023-08-08 13:45:19 +02:00
import AccessStoreMock from '../../test/fixtures/fake-access-store' ;
import { GroupService } from '../services/group-service' ;
2024-03-18 13:58:05 +01:00
import type { IRole } from '../../lib/types/stores/access-store' ;
2024-04-18 16:32:35 +02:00
import {
type IGroup ,
ROLE_CREATED ,
SYSTEM_USER ,
SYSTEM_USER_AUDIT ,
} from '../../lib/types' ;
2023-12-12 14:46:23 +01:00
import BadDataError from '../../lib/error/bad-data-error' ;
2024-01-16 13:11:28 +01:00
import { createFakeEventsService } from '../../lib/features/events/createEventsService' ;
2022-08-19 10:28:53 +02:00
2024-02-09 09:41:40 +01:00
function getSetup() {
2023-06-14 15:40:40 +02:00
const config = createTestConfig ( {
getLogger ,
} ) ;
2023-11-24 14:22:31 +01:00
return createFakeAccessService ( config ) ;
2022-08-19 10:28:53 +02:00
}
2023-06-22 16:42:01 +02:00
test ( 'should fail when name exists' , async ( ) = > {
const { accessService } = getSetup ( ) ;
2024-04-18 16:32:35 +02:00
const existingRole = await accessService . createRole (
{
name : 'existing role' ,
description : 'description' ,
permissions : [ ] ,
createdByUserId : - 9999 ,
} ,
SYSTEM_USER_AUDIT ,
) ;
2023-06-22 16:42:01 +02:00
2022-08-19 10:28:53 +02:00
expect ( accessService . validateRole ( existingRole ) ) . rejects . toThrow (
new NameExistsError (
` There already exists a role with the name ${ existingRole . name } ` ,
) ,
) ;
} ) ;
test ( 'should validate a role without permissions' , async ( ) = > {
2023-06-22 16:42:01 +02:00
const { accessService } = getSetup ( ) ;
2022-08-19 10:28:53 +02:00
const withoutPermissions : IRoleValidation = {
name : 'name of the role' ,
description : 'description' ,
} ;
expect ( await accessService . validateRole ( withoutPermissions ) ) . toEqual (
withoutPermissions ,
) ;
} ) ;
test ( 'should complete description field when not present' , async ( ) = > {
2023-06-22 16:42:01 +02:00
const { accessService } = getSetup ( ) ;
2022-08-19 10:28:53 +02:00
const withoutDescription : IRoleValidation = {
name : 'name of the role' ,
} ;
expect ( await accessService . validateRole ( withoutDescription ) ) . toEqual ( {
name : 'name of the role' ,
description : '' ,
} ) ;
} ) ;
test ( 'should accept empty permissions' , async ( ) = > {
2023-06-22 16:42:01 +02:00
const { accessService } = getSetup ( ) ;
2022-08-19 10:28:53 +02:00
const withEmptyPermissions : IRoleValidation = {
name : 'name of the role' ,
description : 'description' ,
permissions : [ ] ,
} ;
expect ( await accessService . validateRole ( withEmptyPermissions ) ) . toEqual ( {
name : 'name of the role' ,
description : 'description' ,
permissions : [ ] ,
} ) ;
} ) ;
test ( 'should complete environment field of permissions when not present' , async ( ) = > {
2023-06-22 16:42:01 +02:00
const { accessService } = getSetup ( ) ;
2022-08-19 10:28:53 +02:00
const withoutEnvironmentInPermissions : IRoleValidation = {
name : 'name of the role' ,
description : 'description' ,
permissions : [
{
id : 1 ,
} ,
] ,
} ;
expect (
await accessService . validateRole ( withoutEnvironmentInPermissions ) ,
) . toEqual ( {
name : 'name of the role' ,
description : 'description' ,
permissions : [
{
id : 1 ,
environment : '' ,
} ,
] ,
} ) ;
} ) ;
test ( 'should return the same object when all fields are valid and present' , async ( ) = > {
2023-06-22 16:42:01 +02:00
const { accessService } = getSetup ( ) ;
2022-08-19 10:28:53 +02:00
const roleWithAllFields : IRoleValidation = {
name : 'name of the role' ,
description : 'description' ,
permissions : [
{
id : 1 ,
environment : 'development' ,
} ,
] ,
} ;
expect ( await accessService . validateRole ( roleWithAllFields ) ) . toEqual ( {
name : 'name of the role' ,
description : 'description' ,
permissions : [
{
id : 1 ,
environment : 'development' ,
} ,
] ,
} ) ;
} ) ;
test ( 'should be able to validate and cleanup with additional properties' , async ( ) = > {
2023-06-22 16:42:01 +02:00
const { accessService } = getSetup ( ) ;
2022-08-19 10:28:53 +02:00
const base = {
name : 'name of the role' ,
description : 'description' ,
additional : 'property' ,
permissions : [
{
id : 1 ,
environment : 'development' ,
name : 'name' ,
displayName : 'displayName' ,
type : 'type' ,
additional : 'property' ,
} ,
] ,
} ;
expect ( await accessService . validateRole ( base ) ) . toEqual ( {
name : 'name of the role' ,
description : 'description' ,
permissions : [
{
id : 1 ,
2023-09-19 16:15:27 +02:00
name : 'name' ,
2022-08-19 10:28:53 +02:00
environment : 'development' ,
} ,
] ,
} ) ;
} ) ;
2023-06-22 16:42:01 +02:00
test ( 'user with custom root role should get a user root role' , async ( ) = > {
2024-02-09 09:41:40 +01:00
const { accessService , eventStore } = getSetup ( ) ;
2023-11-24 14:22:31 +01:00
const createRoleInput : IRoleCreation = {
2023-06-22 16:42:01 +02:00
name : 'custom-root-role' ,
description : 'test custom root role' ,
type : CUSTOM_ROOT_ROLE_TYPE ,
2023-12-14 13:45:25 +01:00
createdByUserId : - 9999 ,
2023-11-24 14:22:31 +01:00
permissions : [
{
id : 1 ,
environment : 'development' ,
name : 'fake' ,
} ,
{
name : 'root-fake-permission' ,
} ,
] ,
} ;
2024-04-18 16:32:35 +02:00
const customRootRole = await accessService . createRole (
createRoleInput ,
SYSTEM_USER_AUDIT ,
) ;
2023-06-22 16:42:01 +02:00
const user = {
id : 1 ,
rootRole : customRootRole.id ,
} ;
await accessService . setUserRootRole ( user . id , customRootRole . id ) ;
2023-11-24 16:06:37 +01:00
const role = await accessService . getRootRoleForUser ( user . id ) ;
expect ( role . name ) . toBe ( 'custom-root-role' ) ;
2023-11-24 14:22:31 +01:00
const events = await eventStore . getEvents ( ) ;
expect ( events ) . toHaveLength ( 1 ) ;
expect ( events [ 0 ] ) . toEqual ( {
type : ROLE_CREATED ,
2024-04-18 16:32:35 +02:00
createdBy : SYSTEM_USER_AUDIT.username ,
createdByUserId : SYSTEM_USER.id ,
ip : SYSTEM_USER_AUDIT.ip ,
2023-11-24 14:22:31 +01:00
data : {
id : 0 ,
name : 'custom-root-role' ,
description : 'test custom root role' ,
type : CUSTOM_ROOT_ROLE_TYPE ,
// make sure we have a cleaned up version of permissions in the event
permissions : [
{ environment : 'development' , name : 'fake' } ,
2024-04-18 16:32:35 +02:00
{ name : 'root-fake-permission' , environment : undefined } ,
2023-11-24 14:22:31 +01:00
] ,
} ,
} ) ;
2023-06-22 16:42:01 +02:00
} ) ;
2023-08-08 13:45:19 +02:00
test ( 'throws error when trying to delete a project role in use by group' , async ( ) = > {
const groupIdResultOverride = async ( ) : Promise < number [ ] > = > {
return [ 1 ] ;
} ;
const config = createTestConfig ( {
getLogger ,
} ) ;
const groupStore = new FakeGroupStore ( ) ;
groupStore . getAllWithId = async ( ) : Promise < IGroup [ ] > = > {
2023-09-05 21:30:20 +02:00
return [ { id : 1 , name : 'group' } ] ;
2023-08-08 13:45:19 +02:00
} ;
const accountStore = new FakeAccountStore ( ) ;
const roleStore = new FakeRoleStore ( ) ;
const environmentStore = new FakeEnvironmentStore ( ) ;
const accessStore = new AccessStoreMock ( ) ;
accessStore . getGroupIdsForRole = groupIdResultOverride ;
accessStore . getUserIdsForRole = async ( ) : Promise < number [ ] > = > {
return [ ] ;
} ;
accessStore . get = async ( ) : Promise < IRole > = > {
return { id : 1 , type : 'custom' , name : 'project role' } ;
} ;
2024-01-16 13:11:28 +01:00
const eventService = createFakeEventsService ( config ) ;
2023-08-08 13:45:19 +02:00
const groupService = new GroupService (
2023-09-27 15:23:05 +02:00
{ groupStore , accountStore } ,
2023-08-08 13:45:19 +02:00
{ getLogger } ,
2023-09-27 15:23:05 +02:00
eventService ,
2023-08-08 13:45:19 +02:00
) ;
const accessService = new AccessService (
{
accessStore ,
accountStore ,
roleStore ,
environmentStore ,
} ,
config ,
groupService ,
2023-11-24 14:22:31 +01:00
eventService ,
2023-08-08 13:45:19 +02:00
) ;
try {
2024-04-18 16:32:35 +02:00
await accessService . deleteRole ( 1 , SYSTEM_USER_AUDIT ) ;
2023-08-08 13:45:19 +02:00
} catch ( e ) {
expect ( e . toString ( ) ) . toBe (
'RoleInUseError: Role is in use by users(0) or groups(1). You cannot delete a role that is in use without first removing the role from the users and groups.' ,
) ;
}
} ) ;
2023-12-12 14:46:23 +01:00
describe ( 'addAccessToProject' , ( ) = > {
test ( 'should throw an error when you try add access with an empty list of roles' , async ( ) = > {
const { accessService } = getSetup ( ) ;
await expect ( ( ) = >
accessService . addAccessToProject (
[ ] ,
[ 1 ] ,
[ 1 ] ,
'projectId' ,
'createdBy' ,
) ,
) . rejects . toThrow ( BadDataError ) ;
} ) ;
} ) ;