UNPKG

unleash-server

Version:

Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.

280 lines • 10.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const name_exists_error_1 = __importDefault(require("../error/name-exists-error")); const no_logger_1 = __importDefault(require("../../test/fixtures/no-logger")); const createAccessService_1 = require("../features/access/createAccessService"); const access_service_1 = require("./access-service"); const test_config_1 = require("../../test/config/test-config"); const constants_1 = require("../util/constants"); const fake_group_store_1 = __importDefault(require("../../test/fixtures/fake-group-store")); const fake_account_store_1 = require("../../test/fixtures/fake-account-store"); const fake_role_store_1 = __importDefault(require("../../test/fixtures/fake-role-store")); const fake_environment_store_1 = __importDefault(require("../features/project-environments/fake-environment-store")); const fake_access_store_1 = __importDefault(require("../../test/fixtures/fake-access-store")); const group_service_1 = require("../services/group-service"); const types_1 = require("../../lib/types"); const bad_data_error_1 = __importDefault(require("../../lib/error/bad-data-error")); const createEventsService_1 = require("../../lib/features/events/createEventsService"); const createAccessReadModel_1 = require("../features/access/createAccessReadModel"); function getSetup() { const config = (0, test_config_1.createTestConfig)({ getLogger: no_logger_1.default, }); const { accessService, eventStore, accessStore } = (0, createAccessService_1.createFakeAccessService)(config); return { accessService, eventStore, accessStore, accessReadModel: (0, createAccessReadModel_1.createFakeAccessReadModel)(accessStore), }; } test('should fail when name exists', async () => { const { accessService } = getSetup(); const existingRole = await accessService.createRole({ name: 'existing role', description: 'description', permissions: [], createdByUserId: -9999, }, types_1.SYSTEM_USER_AUDIT); expect(accessService.validateRole(existingRole)).rejects.toThrow(new name_exists_error_1.default(`There already exists a role with the name ${existingRole.name}`)); }); test('should validate a role without permissions', async () => { const { accessService } = getSetup(); const withoutPermissions = { name: 'name of the role', description: 'description', }; expect(await accessService.validateRole(withoutPermissions)).toEqual(withoutPermissions); }); test('should complete description field when not present', async () => { const { accessService } = getSetup(); const withoutDescription = { name: 'name of the role', }; expect(await accessService.validateRole(withoutDescription)).toEqual({ name: 'name of the role', description: '', }); }); test('should accept empty permissions', async () => { const { accessService } = getSetup(); const withEmptyPermissions = { name: 'name of the role', description: 'description', permissions: [], }; expect(await accessService.validateRole(withEmptyPermissions)).toEqual({ name: 'name of the role', description: 'description', permissions: [], }); }); test('should not accept empty names', async () => { const { accessService } = getSetup(); const withWhitespaceName = { name: ' ', description: 'description', permissions: [], }; await expect(accessService.validateRole(withWhitespaceName)).rejects.toThrow('"name" is not allowed to be empty'); }); test('should trim leading and trailing whitespace from names', async () => { const { accessService } = getSetup(); const withUntrimmedName = { name: ' untrimmed ', description: 'description', permissions: [], }; expect(await accessService.validateRole(withUntrimmedName)).toEqual({ name: 'untrimmed', description: 'description', permissions: [], }); }); test('should complete environment field of permissions when not present', async () => { const { accessService } = getSetup(); const withoutEnvironmentInPermissions = { 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 () => { const { accessService } = getSetup(); const roleWithAllFields = { 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 () => { const { accessService } = getSetup(); 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, name: 'name', environment: 'development', }, ], }); }); test('user with custom root role should get a user root role', async () => { const { accessService, eventStore } = getSetup(); const createRoleInput = { name: 'custom-root-role', description: 'test custom root role', type: constants_1.CUSTOM_ROOT_ROLE_TYPE, createdByUserId: -9999, permissions: [ { id: 1, environment: 'development', name: 'fake', }, { name: 'root-fake-permission', }, ], }; const customRootRole = await accessService.createRole(createRoleInput, types_1.SYSTEM_USER_AUDIT); const user = { id: 1, rootRole: customRootRole.id, }; await accessService.setUserRootRole(user.id, customRootRole.id); const role = await accessService.getRootRoleForUser(user.id); expect(role.name).toBe('custom-root-role'); const events = await eventStore.getEvents(); expect(events).toHaveLength(1); expect(events[0]).toMatchObject({ type: types_1.ROLE_CREATED, createdBy: types_1.SYSTEM_USER_AUDIT.username, createdByUserId: types_1.SYSTEM_USER.id, ip: types_1.SYSTEM_USER_AUDIT.ip, data: { id: 0, name: 'custom-root-role', description: 'test custom root role', type: constants_1.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', environment: undefined }, ], }, }); }); test('throws error when trying to delete a project role in use by group', async () => { const groupIdResultOverride = async () => { return [1]; }; const config = (0, test_config_1.createTestConfig)({ getLogger: no_logger_1.default, }); const groupStore = new fake_group_store_1.default(); groupStore.getAllWithId = async () => { return [{ id: 1, name: 'group' }]; }; const accountStore = new fake_account_store_1.FakeAccountStore(); const roleStore = new fake_role_store_1.default(); const environmentStore = new fake_environment_store_1.default(); const accessStore = new fake_access_store_1.default(); accessStore.getGroupIdsForRole = groupIdResultOverride; accessStore.getUserIdsForRole = async () => { return []; }; accessStore.get = async () => { return { id: 1, type: 'custom', name: 'project role' }; }; const eventService = (0, createEventsService_1.createFakeEventsService)(config); const groupService = new group_service_1.GroupService({ groupStore, accountStore }, { getLogger: no_logger_1.default }, eventService); const accessService = new access_service_1.AccessService({ accessStore, accountStore, roleStore, environmentStore, }, config, groupService, eventService); try { await accessService.deleteRole(1, types_1.SYSTEM_USER_AUDIT); } 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.'); } }); 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(bad_data_error_1.default); }); }); test('should return true if user has admin role', async () => { const { accessReadModel, accessStore } = getSetup(); const userId = 1; accessStore.getRolesForUserId = jest .fn() .mockResolvedValue([{ id: 1, name: 'ADMIN', type: 'custom' }]); const result = await accessReadModel.isRootAdmin(userId); expect(result).toBe(true); expect(accessStore.getRolesForUserId).toHaveBeenCalledWith(userId); }); test('should return false if user does not have admin role', async () => { const { accessReadModel, accessStore } = getSetup(); const userId = 2; accessStore.getRolesForUserId = jest .fn() .mockResolvedValue([{ id: 2, name: 'user', type: 'custom' }]); const result = await accessReadModel.isRootAdmin(userId); expect(result).toBe(false); expect(accessStore.getRolesForUserId).toHaveBeenCalledWith(userId); }); //# sourceMappingURL=access-service.test.js.map