From 12d9297f68400f6957cf7d16cf35088a1c0b4945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Fournier?= Date: Tue, 19 Sep 2023 12:03:16 +0200 Subject: [PATCH] Revert "chore: improve access service" (#4773) Reverts Unleash/unleash#4689 temporarily to figure out what's the problem with the failing test --- src/lib/db/access-store.test.ts | 110 ----------------- src/lib/db/access-store.ts | 99 ++------------- src/lib/schema/role-schema.test.ts | 2 +- src/lib/schema/role-schema.ts | 4 +- src/lib/services/access-service.test.ts | 1 - src/lib/services/access-service.ts | 10 +- src/lib/types/stores/access-store.ts | 2 +- .../e2e/api/admin/api-token.auth.e2e.test.ts | 31 +++-- .../e2e/services/access-service.e2e.test.ts | 116 +++++++++++++----- src/test/fixtures/fake-access-store.ts | 4 +- src/test/fixtures/no-logger.ts | 16 +-- 11 files changed, 125 insertions(+), 270 deletions(-) delete mode 100644 src/lib/db/access-store.test.ts diff --git a/src/lib/db/access-store.test.ts b/src/lib/db/access-store.test.ts deleted file mode 100644 index 18b1228fe9..0000000000 --- a/src/lib/db/access-store.test.ts +++ /dev/null @@ -1,110 +0,0 @@ -import dbInit from '../../test/e2e/helpers/database-init'; -import getLogger from '../../test/fixtures/no-logger'; -import { PermissionRef } from 'lib/services/access-service'; -import { AccessStore } from './access-store'; - -let db; - -beforeAll(async () => { - db = await dbInit('access_store_serial', getLogger); -}); - -afterAll(async () => { - if (db) { - await db.destroy(); - } -}); - -// Helper function to make the test cases more readable -const args = (permissions: PermissionRef[], expectations?: PermissionRef[]) => { - if (expectations) { - return [permissions, expectations]; - } else { - return [permissions]; - } -}; - -test('resolvePermissions returns empty list if undefined', async () => { - const access = db.stores.accessStore as AccessStore; - const result = await access.resolvePermissions( - undefined as unknown as PermissionRef[], - ); - expect(result).toStrictEqual([]); -}); - -test('resolvePermissions returns empty list if empty list', async () => { - const access = db.stores.accessStore as AccessStore; - const result = await access.resolvePermissions([] as PermissionRef[]); - expect(result).toStrictEqual([]); -}); - -test.each([ - args([{ id: 1 }]), - args([{ id: 4, environment: 'development' }]), - args([{ id: 4, name: 'should keep the id' }]), - args([ - { id: 1, environment: 'development' }, - { id: 2, name: 'ignore this name' }, - ]), -])( - 'resolvePermissions with permission ids (%o) returns the list unmodified', - async (permissions) => { - const access = db.stores.accessStore as AccessStore; - const result = await access.resolvePermissions(permissions); - expect(result).toStrictEqual(permissions); - }, -); - -test.each([ - args( - [{ name: 'CREATE_CONTEXT_FIELD' }], - [{ id: 18, name: 'CREATE_CONTEXT_FIELD' }], - ), - args( - [{ name: 'CREATE_FEATURE', environment: 'development' }], - [{ id: 2, name: 'CREATE_FEATURE', environment: 'development' }], - ), - args( - [ - { name: 'CREATE_CONTEXT_FIELD' }, - { name: 'CREATE_FEATURE', environment: 'development' }, - ], - [ - { id: 18, name: 'CREATE_CONTEXT_FIELD' }, - { id: 2, name: 'CREATE_FEATURE', environment: 'development' }, - ], - ), -])( - 'resolvePermissions with permission names (%o) will inject the ids', - async (permissions, expected) => { - const access = db.stores.accessStore as AccessStore; - const result = await access.resolvePermissions(permissions); - expect(result).toStrictEqual(expected); - }, -); - -test.each([ - args( - [ - { name: 'CREATE_CONTEXT_FIELD' }, - { id: 3 }, - { name: 'CREATE_FEATURE', environment: 'development' }, - { id: 15, environment: 'development' }, - { name: 'UPDATE_FEATURE', environment: 'development' }, - ], - [ - { id: 18, name: 'CREATE_CONTEXT_FIELD' }, - { id: 3 }, - { id: 2, name: 'CREATE_FEATURE', environment: 'development' }, - { id: 15, environment: 'development' }, - { id: 7, name: 'UPDATE_FEATURE', environment: 'development' }, - ], - ), -])( - 'resolvePermissions mixed ids and names (%o) will inject the ids where they are missing', - async (permissions, expected) => { - const access = db.stores.accessStore as AccessStore; - const result = await access.resolvePermissions(permissions); - expect(result).toStrictEqual(expected); - }, -); diff --git a/src/lib/db/access-store.ts b/src/lib/db/access-store.ts index 072eee2673..1c8eb619c5 100644 --- a/src/lib/db/access-store.ts +++ b/src/lib/db/access-store.ts @@ -20,11 +20,7 @@ import { ROOT_PERMISSION_TYPE, } from '../util/constants'; import { Db } from './db'; -import { - IdPermissionRef, - NamePermissionRef, - PermissionRef, -} from 'lib/services/access-service'; +import { IdPermissionRef } from 'lib/services/access-service'; const T = { ROLE_USER: 'role_user', @@ -50,12 +46,6 @@ interface IPermissionRow { role_id: number; } -type ResolvedPermission = { - id: number; - name?: string; - environment?: string; -}; - export class AccessStore implements IAccessStore { private logger: Logger; @@ -73,75 +63,6 @@ export class AccessStore implements IAccessStore { }); } - private permissionHasId = (permission: PermissionRef): boolean => { - return (permission as IdPermissionRef).id !== undefined; - }; - - private permissionNamesToIds = async ( - permissions: NamePermissionRef[], - ): Promise => { - const permissionNames = (permissions ?? []) - .filter((p) => p.name !== undefined) - .map((p) => p.name); - - if (permissionNames.length === 0) { - return []; - } - - const stopTimer = this.timer('permissionNamesToIds'); - - const rows = await this.db - .select('id', 'permission') - .from(T.PERMISSIONS) - .whereIn('permission', permissionNames); - - const rowByPermissionName = rows.reduce((acc, row) => { - acc[row.permission] = row; - return acc; - }, {} as Map); - - const permissionsWithIds = permissions.map((permission) => ({ - id: rowByPermissionName[permission.name].id, - ...permission, - })); - - stopTimer(); - return permissionsWithIds; - }; - - resolvePermissions = async ( - permissions: PermissionRef[], - ): Promise => { - if (permissions === undefined || permissions.length === 0) { - return []; - } - // permissions without ids (just names) - const permissionsWithoutIds = permissions.filter( - (p) => !this.permissionHasId(p), - ) as NamePermissionRef[]; - const idPermissionsFromNamed = await this.permissionNamesToIds( - permissionsWithoutIds, - ); - - if (permissionsWithoutIds.length === permissions.length) { - // all named permissions without ids - return idPermissionsFromNamed; - } else if (permissionsWithoutIds.length === 0) { - // all permissions have ids - return permissions as ResolvedPermission[]; - } - // some permissions have ids, some don't (should not happen!) - return permissions.map((permission) => { - if (this.permissionHasId(permission)) { - return permission as ResolvedPermission; - } else { - return idPermissionsFromNamed.find( - (p) => p.name === (permission as NamePermissionRef).name, - )!; - } - }); - }; - async delete(key: number): Promise { await this.db(T.ROLES).where({ id: key }).del(); } @@ -301,11 +222,9 @@ export class AccessStore implements IAccessStore { async addEnvironmentPermissionsToRole( role_id: number, - permissions: PermissionRef[], + permissions: IdPermissionRef[], ): Promise { - const resolvedPermission = await this.resolvePermissions(permissions); - - const rows = resolvedPermission.map((permission) => { + const rows = permissions.map((permission) => { return { role_id, permission_id: permission.id, @@ -781,16 +700,18 @@ export class AccessStore implements IAccessStore { async addPermissionsToRole( role_id: number, - permissions: PermissionRef[], + permissions: string[], environment?: string, ): Promise { - // no need to pass down the environment in this particular case because it'll be overriden - const permissionsWithIds = await this.resolvePermissions(permissions); + const rows = await this.db + .select('id as permissionId') + .from(T.PERMISSIONS) + .whereIn('permission', permissions); - const newRoles = permissionsWithIds.map((p) => ({ + const newRoles = rows.map((row) => ({ role_id, environment, - permission_id: p.id, + permission_id: row.permissionId, })); return this.db.batchInsert(T.ROLE_PERMISSION, newRoles); diff --git a/src/lib/schema/role-schema.test.ts b/src/lib/schema/role-schema.test.ts index 7d2ed31935..05fb65b6d0 100644 --- a/src/lib/schema/role-schema.test.ts +++ b/src/lib/schema/role-schema.test.ts @@ -38,7 +38,7 @@ test('role schema rejects a role with a broken permission list', async () => { await roleSchema.validateAsync(role); } catch (error) { expect(error.details[0].message).toBe( - '"permissions[0]" must contain at least one of [id, name]', + '"permissions[0].id" is required', ); } }); diff --git a/src/lib/schema/role-schema.ts b/src/lib/schema/role-schema.ts index 4946efc906..67fc1d5ee7 100644 --- a/src/lib/schema/role-schema.ts +++ b/src/lib/schema/role-schema.ts @@ -3,11 +3,9 @@ import joi from 'joi'; export const permissionRoleSchema = joi .object() .keys({ - id: joi.number(), - name: joi.string(), + id: joi.number().required(), environment: joi.string().optional().allow('').allow(null).default(''), }) - .or('id', 'name') .options({ stripUnknown: true, allowUnknown: false, abortEarly: false }); export const roleSchema = joi diff --git a/src/lib/services/access-service.test.ts b/src/lib/services/access-service.test.ts index 688ce80279..6a4b72997e 100644 --- a/src/lib/services/access-service.test.ts +++ b/src/lib/services/access-service.test.ts @@ -154,7 +154,6 @@ test('should be able to validate and cleanup with additional properties', async permissions: [ { id: 1, - name: 'name', environment: 'development', }, ], diff --git a/src/lib/services/access-service.ts b/src/lib/services/access-service.ts index 46a32cd59d..2286aa41e6 100644 --- a/src/lib/services/access-service.ts +++ b/src/lib/services/access-service.ts @@ -70,7 +70,7 @@ export interface IRoleValidation { permissions?: PermissionRef[]; } -export interface IRoleUpdate { +interface IRoleUpdate { id: number; name: string; description: string; @@ -406,7 +406,7 @@ export class AccessService { } return this.store.addPermissionsToRole( roleId, - [{ name: permission }], + [permission], environment, ); } @@ -630,13 +630,11 @@ export class AccessService { const newRole = await this.roleStore.create(baseRole); if (rolePermissions) { if (roleType === CUSTOM_ROOT_ROLE_TYPE) { - // this branch uses named permissions await this.store.addPermissionsToRole( newRole.id, - rolePermissions, + rolePermissions.map((p: NamePermissionRef) => p.name), ); } else { - // this branch uses id permissions await this.store.addEnvironmentPermissionsToRole( newRole.id, rolePermissions, @@ -675,7 +673,7 @@ export class AccessService { if (roleType === CUSTOM_ROOT_ROLE_TYPE) { await this.store.addPermissionsToRole( newRole.id, - rolePermissions, + rolePermissions.map((p: NamePermissionRef) => p.name), ); } else { await this.store.addEnvironmentPermissionsToRole( diff --git a/src/lib/types/stores/access-store.ts b/src/lib/types/stores/access-store.ts index b3f5194c3f..bd1f0c9126 100644 --- a/src/lib/types/stores/access-store.ts +++ b/src/lib/types/stores/access-store.ts @@ -164,7 +164,7 @@ export interface IAccessStore extends Store { addPermissionsToRole( role_id: number, - permissions: PermissionRef[], + permissions: string[], environment?: string, ): Promise; diff --git a/src/test/e2e/api/admin/api-token.auth.e2e.test.ts b/src/test/e2e/api/admin/api-token.auth.e2e.test.ts index 97b7119719..fed77e8b52 100644 --- a/src/test/e2e/api/admin/api-token.auth.e2e.test.ts +++ b/src/test/e2e/api/admin/api-token.auth.e2e.test.ts @@ -12,7 +12,6 @@ import { UPDATE_CLIENT_API_TOKEN, } from '../../../../lib/types'; import { addDays } from 'date-fns'; -import { AccessService, UserService } from 'lib/services'; let stores; let db; @@ -176,32 +175,33 @@ test('Token-admin should be allowed to create token', async () => { test('A role with only CREATE_PROJECT_API_TOKEN can create project tokens', async () => { expect.assertions(0); - const preHook = ( - app, - config, - { - userService, - accessService, - }: { userService: UserService; accessService: AccessService }, - ) => { + const preHook = (app, config, { userService, accessService }) => { app.use('/api/admin/', async (req, res, next) => { - const role = (await accessService.getRootRole(RoleName.VIEWER))!; + const role = await accessService.getRootRole(RoleName.VIEWER); const user = await userService.createUser({ email: 'powerpuffgirls_viewer@example.com', rootRole: role.id, }); + req.user = user; const createClientApiTokenRole = await accessService.createRole({ name: 'project_client_token_creator', description: 'Can create client tokens', - permissions: [{ name: CREATE_PROJECT_API_TOKEN }], + permissions: [], type: 'root-custom', }); + await accessService.addPermissionToRole( + role.id, + CREATE_PROJECT_API_TOKEN, + ); await accessService.addUserToRole( user.id, createClientApiTokenRole.id, 'default', ); - req.user = user; + req.user = await userService.createUser({ + email: 'someguyinplaces@example.com', + rootRole: role.id, + }); next(); }); }; @@ -225,12 +225,12 @@ describe('Fine grained API token permissions', () => { test('should be allowed to create client tokens', async () => { const preHook = (app, config, { userService, accessService }) => { app.use('/api/admin/', async (req, res, next) => { - const builtInRole = await accessService.getRootRole( + const role = await accessService.getRootRole( RoleName.VIEWER, ); const user = await userService.createUser({ email: 'mylittlepony_viewer@example.com', - rootRole: builtInRole.id, + rootRole: role.id, }); req.user = user; const createClientApiTokenRole = @@ -240,9 +240,8 @@ describe('Fine grained API token permissions', () => { permissions: [], type: 'root-custom', }); - // not sure if we should add the permission to the builtin role or to the newly created role await accessService.addPermissionToRole( - builtInRole.id, + role.id, CREATE_CLIENT_API_TOKEN, ); await accessService.addUserToRole( diff --git a/src/test/e2e/services/access-service.e2e.test.ts b/src/test/e2e/services/access-service.e2e.test.ts index 40119816a5..93beeac2b0 100644 --- a/src/test/e2e/services/access-service.e2e.test.ts +++ b/src/test/e2e/services/access-service.e2e.test.ts @@ -1,15 +1,14 @@ import dbInit, { ITestDb } from '../helpers/database-init'; import getLogger from '../../fixtures/no-logger'; -import { - AccessService, - PermissionRef, -} from '../../../lib/services/access-service'; +// eslint-disable-next-line import/no-unresolved +import { AccessService } from '../../../lib/services/access-service'; import * as permissions from '../../../lib/types/permissions'; import { RoleName } from '../../../lib/types/model'; import { ICreateGroupUserModel, + IPermission, IUnleashStores, IUserAccessOverview, } from '../../../lib/types'; @@ -71,7 +70,7 @@ const createGroup = async ({ }; let roleIndex = 0; -const createRole = async (rolePermissions: PermissionRef[]) => { +const createRole = async (rolePermissions: IPermission[]) => { return accessService.createRole({ name: `Role ${roleIndex}`, description: `Role ${roleIndex++} description`, @@ -270,25 +269,6 @@ beforeAll(async () => { ); editorUser = await createUser(editorRole.id); - - const testAdmin = await createUser(adminRole.id); - await projectService.createProject( - { - id: 'some-project', - name: 'Some project', - description: 'Used in the test', - }, - testAdmin, - ); - - await projectService.createProject( - { - id: 'unusedprojectname', - name: 'Another project not used', - description: 'Also used in the test', - }, - testAdmin, - ); }); afterAll(async () => { @@ -392,12 +372,6 @@ test('should remove CREATE_FEATURE on default environment', async () => { '*', ); - // TODO: to validate the remove works, we should make sure that we had permission before removing it - // this currently does not work, just keeping the comment here for future reference - // expect( - // await accessService.hasPermission(user, CREATE_FEATURE, 'some-project'), - // ).toBe(true); - await accessService.removePermissionFromRole( editRole.id, permissions.CREATE_FEATURE, @@ -647,7 +621,7 @@ test('should support permission with "ALL" environment requirement', async () => const { CREATE_FEATURE_STRATEGY } = permissions; await accessStore.addPermissionsToRole( customRole.id, - [{ name: CREATE_FEATURE_STRATEGY }], + [CREATE_FEATURE_STRATEGY], 'production', ); await accessStore.addUserToRole(user.id, customRole.id, ALL_PROJECTS); @@ -754,10 +728,14 @@ test('Should be denied access to delete a role that is in use', async () => { { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 8, name: 'DELETE_FEATURE', + displayName: 'Delete Feature Toggles', + type: 'project', }, ]); @@ -993,6 +971,8 @@ test('Should allow user to take multiple group roles and have expected permissio { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, ]); @@ -1000,6 +980,8 @@ test('Should allow user to take multiple group roles and have expected permissio { id: 8, name: 'DELETE_FEATURE', + displayName: 'Delete Feature Toggles', + type: 'project', }, ]); @@ -1171,20 +1153,28 @@ test('if user has two roles user has union of permissions from the two roles', a { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 8, name: 'DELETE_FEATURE', + displayName: 'Delete Feature Toggles', + type: 'project', }, ]); const secondRole = await createRole([ { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 13, name: 'UPDATE_PROJECT', + displayName: 'Can update projects', + type: 'project', }, ]); @@ -1212,20 +1202,28 @@ test('calling set for user overwrites existing roles', async () => { { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 8, name: 'DELETE_FEATURE', + displayName: 'Delete Feature Toggles', + type: 'project', }, ]); const secondRole = await createRole([ { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 13, name: 'UPDATE_PROJECT', + displayName: 'Can update projects', + type: 'project', }, ]); @@ -1275,20 +1273,28 @@ test('if group has two roles user has union of permissions from the two roles', { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 8, name: 'DELETE_FEATURE', + displayName: 'Delete Feature Toggles', + type: 'project', }, ]); const secondRole = await createRole([ { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 13, name: 'UPDATE_PROJECT', + displayName: 'Can update projects', + type: 'project', }, ]); @@ -1322,20 +1328,28 @@ test('calling set for group overwrites existing roles', async () => { { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 8, name: 'DELETE_FEATURE', + displayName: 'Delete Feature Toggles', + type: 'project', }, ]); const secondRole = await createRole([ { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 13, name: 'UPDATE_PROJECT', + displayName: 'Can update projects', + type: 'project', }, ]); @@ -1391,6 +1405,8 @@ test('group with root role can be assigned a project specific role', async () => { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, ]); @@ -1458,6 +1474,8 @@ test('calling set roles for user with empty role array removes all roles', async { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, ]); @@ -1488,10 +1506,14 @@ test('calling set roles for user with empty role array should not remove root ro { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 8, name: 'DELETE_FEATURE', + displayName: 'Delete Feature Toggles', + type: 'project', }, ]); @@ -1523,10 +1545,14 @@ test('remove user access should remove all project roles', async () => { { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 8, name: 'DELETE_FEATURE', + displayName: 'Delete Feature Toggles', + type: 'project', }, ]); @@ -1534,6 +1560,8 @@ test('remove user access should remove all project roles', async () => { { id: 13, name: 'UPDATE_PROJECT', + displayName: 'Can update projects', + type: 'project', }, ]); @@ -1565,10 +1593,14 @@ test('remove user access should remove all project roles, while leaving root rol { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 8, name: 'DELETE_FEATURE', + displayName: 'Delete Feature Toggles', + type: 'project', }, ]); @@ -1576,6 +1608,8 @@ test('remove user access should remove all project roles, while leaving root rol { id: 13, name: 'UPDATE_PROJECT', + displayName: 'Can update projects', + type: 'project', }, ]); @@ -1636,6 +1670,8 @@ test('calling set roles for group with empty role array removes all roles', asyn { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, ]); @@ -1678,10 +1714,14 @@ test('calling set roles for group with empty role array should not remove root r { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 8, name: 'DELETE_FEATURE', + displayName: 'Delete Feature Toggles', + type: 'project', }, ]); @@ -1724,10 +1764,14 @@ test('remove group access should remove all project roles', async () => { { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 8, name: 'DELETE_FEATURE', + displayName: 'Delete Feature Toggles', + type: 'project', }, ]); @@ -1735,6 +1779,8 @@ test('remove group access should remove all project roles', async () => { { id: 13, name: 'UPDATE_PROJECT', + displayName: 'Can update projects', + type: 'project', }, ]); @@ -1771,10 +1817,14 @@ test('remove group access should remove all project roles, while leaving root ro { id: 2, name: 'CREATE_FEATURE', + displayName: 'Create Feature Toggles', + type: 'project', }, { id: 8, name: 'DELETE_FEATURE', + displayName: 'Delete Feature Toggles', + type: 'project', }, ]); @@ -1782,6 +1832,8 @@ test('remove group access should remove all project roles, while leaving root ro { id: 13, name: 'UPDATE_PROJECT', + displayName: 'Can update projects', + type: 'project', }, ]); @@ -1862,6 +1914,8 @@ test('access overview should have group access for groups that they are in', asy { id: 13, name: 'UPDATE_PROJECT', + displayName: 'Can update projects', + type: 'project', }, ]); diff --git a/src/test/fixtures/fake-access-store.ts b/src/test/fixtures/fake-access-store.ts index 3daa2a6646..19ef6619df 100644 --- a/src/test/fixtures/fake-access-store.ts +++ b/src/test/fixtures/fake-access-store.ts @@ -180,8 +180,8 @@ class AccessStoreMock implements IAccessStore { addPermissionsToRole( role_id: number, - permissions: PermissionRef[], - environment?: string, + permissions: string[], + projectId?: string, ): Promise { // do nothing for now return Promise.resolve(undefined); diff --git a/src/test/fixtures/no-logger.ts b/src/test/fixtures/no-logger.ts index 30f222ae9a..35c5df361e 100644 --- a/src/test/fixtures/no-logger.ts +++ b/src/test/fixtures/no-logger.ts @@ -1,27 +1,23 @@ /* eslint-disable no-console */ + import { Logger } from '../../lib/logger'; let muteError = false; -let verbose = false; + function noLoggerProvider(): Logger { // do something with the name return { - debug: verbose ? console.log : () => {}, - info: verbose ? console.log : () => {}, - warn: verbose ? console.warn : () => {}, + debug: () => {}, + info: () => {}, + warn: () => {}, error: muteError ? () => {} : console.error, fatal: console.error, }; } -noLoggerProvider.setMuteError = (mute: boolean) => { +noLoggerProvider.setMuteError = (mute) => { muteError = mute; }; -// use for debugging only, try not to commit tests with verbose set to true -noLoggerProvider.setVerbose = (beVerbose: boolean) => { - verbose = beVerbose; -}; - module.exports = noLoggerProvider; export default noLoggerProvider;