Skip to content

Commit

Permalink
feat: audit roles (#5408)
Browse files Browse the repository at this point in the history
## About the changes
Audit changes to roles both root and project roles.
  • Loading branch information
gastonfournier committed Nov 24, 2023
1 parent 295b0c0 commit d680e50
Show file tree
Hide file tree
Showing 17 changed files with 197 additions and 53 deletions.
14 changes: 11 additions & 3 deletions src/lib/features/access/createAccessService.ts
Expand Up @@ -14,6 +14,7 @@ import FakeEnvironmentStore from '../../../test/fixtures/fake-environment-store'
import FakeAccessStore from '../../../test/fixtures/fake-access-store';
import FeatureTagStore from '../../db/feature-tag-store';
import FakeFeatureTagStore from '../../../test/fixtures/fake-feature-tag-store';
import { IEventStore } from '../../types';

export const createAccessService = (
db: Db,
Expand All @@ -38,15 +39,16 @@ export const createAccessService = (
);

return new AccessService(
{ accessStore, accountStore, roleStore, environmentStore, groupStore },
{ accessStore, accountStore, roleStore, environmentStore },
{ getLogger, flagResolver },
groupService,
eventService,
);
};

export const createFakeAccessService = (
config: IUnleashConfig,
): AccessService => {
): { accessService: AccessService; eventStore: IEventStore } => {
const { getLogger, flagResolver } = config;
const eventStore = new FakeEventStore();
const groupStore = new FakeGroupStore();
Expand All @@ -65,9 +67,15 @@ export const createFakeAccessService = (
eventService,
);

return new AccessService(
const accessService = new AccessService(
{ accessStore, accountStore, roleStore, environmentStore, groupStore },
{ getLogger, flagResolver },
groupService,
eventService,
);

return {
accessService,
eventStore,
};
};
Expand Up @@ -71,7 +71,7 @@ export const createFakeExportImportTogglesService = (
const eventStore = new FakeEventStore();
const featureStrategiesStore = new FakeFeatureStrategiesStore();
const featureEnvironmentStore = new FakeFeatureEnvironmentStore();
const accessService = createFakeAccessService(config);
const { accessService } = createFakeAccessService(config);
const featureToggleService = createFakeFeatureToggleService(config);
const privateProjectChecker = createFakePrivateProjectChecker();

Expand Down
Expand Up @@ -110,9 +110,10 @@ export const createFeatureToggleService = (
eventService,
);
const accessService = new AccessService(
{ accessStore, accountStore, roleStore, environmentStore, groupStore },
{ accessStore, accountStore, roleStore, environmentStore },
{ getLogger, flagResolver },
groupService,
eventService,
);
const segmentService = createSegmentService(db, config);
const changeRequestAccessReadModel = createChangeRequestAccessReadModel(
Expand Down Expand Up @@ -180,6 +181,7 @@ export const createFakeFeatureToggleService = (
{ accessStore, accountStore, roleStore, environmentStore, groupStore },
{ getLogger, flagResolver },
groupService,
eventService,
);
const segmentService = createFakeSegmentService(config);
const changeRequestAccessReadModel = createFakeChangeRequestAccessService();
Expand Down
2 changes: 1 addition & 1 deletion src/lib/features/project/createProjectService.ts
Expand Up @@ -134,7 +134,7 @@ export const createFakeProjectService = (
const environmentStore = new FakeEnvironmentStore();
const featureEnvironmentStore = new FakeFeatureEnvironmentStore();
const projectStatsStore = new FakeProjectStatsStore();
const accessService = createFakeAccessService(config);
const { accessService } = createFakeAccessService(config);
const featureToggleService = createFakeFeatureToggleService(config);
const favoriteFeaturesStore = new FakeFavoriteFeaturesStore();
const favoriteProjectsStore = new FakeFavoriteProjectsStore();
Expand Down
52 changes: 41 additions & 11 deletions src/lib/services/access-service.test.ts
@@ -1,7 +1,11 @@
import NameExistsError from '../error/name-exists-error';
import getLogger from '../../test/fixtures/no-logger';
import { createFakeAccessService } from '../features/access/createAccessService';
import { AccessService, IRoleValidation } from './access-service';
import {
AccessService,
IRoleCreation,
IRoleValidation,
} from './access-service';
import { createTestConfig } from '../../test/config/test-config';
import { CUSTOM_ROOT_ROLE_TYPE } from '../util/constants';
import FakeGroupStore from '../../test/fixtures/fake-group-store';
Expand All @@ -11,8 +15,8 @@ import FakeEnvironmentStore from '../../test/fixtures/fake-environment-store';
import AccessStoreMock from '../../test/fixtures/fake-access-store';
import { GroupService } from '../services/group-service';
import FakeEventStore from '../../test/fixtures/fake-event-store';
import { IRole } from 'lib/types/stores/access-store';
import { IGroup } from 'lib/types';
import { IRole } from '../../lib/types/stores/access-store';
import { IGroup, ROLE_CREATED } from '../../lib/types';
import EventService from './event-service';
import FakeFeatureTagStore from '../../test/fixtures/fake-feature-tag-store';

Expand All @@ -26,9 +30,7 @@ function getSetup(customRootRolesKillSwitch: boolean = true) {
},
});

return {
accessService: createFakeAccessService(config),
};
return createFakeAccessService(config);
}

test('should fail when name exists', async () => {
Expand Down Expand Up @@ -164,13 +166,24 @@ test('should be able to validate and cleanup with additional properties', async
});

test('user with custom root role should get a user root role', async () => {
const { accessService } = getSetup(false);
const customRootRole = await accessService.createRole({
const { accessService, eventStore } = getSetup(false);
const createRoleInput: IRoleCreation = {
name: 'custom-root-role',
description: 'test custom root role',
type: CUSTOM_ROOT_ROLE_TYPE,
permissions: [],
});
permissions: [
{
id: 1,
environment: 'development',
name: 'fake',
},
{
name: 'root-fake-permission',
},
],
};

const customRootRole = await accessService.createRole(createRoleInput);
const user = {
id: 1,
rootRole: customRootRole.id,
Expand All @@ -180,6 +193,23 @@ test('user with custom root role should get a user root role', async () => {
const roles = await accessService.getUserRootRoles(user.id);
expect(roles).toHaveLength(1);
expect(roles[0].name).toBe('custom-root-role');
const events = await eventStore.getEvents();
expect(events).toHaveLength(1);
expect(events[0]).toEqual({
type: ROLE_CREATED,
createdBy: 'unknown',
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' },
{ name: 'root-fake-permission' },
],
},
});
});

test('throws error when trying to delete a project role in use by group', async () => {
Expand Down Expand Up @@ -222,10 +252,10 @@ test('throws error when trying to delete a project role in use by group', async
accountStore,
roleStore,
environmentStore,
groupStore,
},
config,
groupService,
eventService,
);

try {
Expand Down

0 comments on commit d680e50

Please sign in to comment.