Skip to content

Commit

Permalink
Move to RoleService and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ivov committed Dec 18, 2023
1 parent bc43fa2 commit c3c0246
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 20 deletions.
18 changes: 18 additions & 0 deletions packages/cli/src/services/role.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,22 @@ export class RoleService {
})
.then((shared) => shared?.role);
}

/**
* Counts the number of users in each role, e.g. `{ admin: 2, member: 6, owner: 1 }`
*/
async countUsersByRole() {
const result: Array<{ role_name: string; count: number }> = await this.roleRepository
.createQueryBuilder('role')
.select('role.name')
.addSelect('COUNT(user.id)', 'count')
.innerJoin('user', 'user', 'role.id = user.globalRoleId')
.groupBy('role.name')
.getRawMany();

return result.reduce<Record<string, number>>((acc, item) => {
acc[item.role_name] = item.count;
return acc;
}, {});
}
}
18 changes: 0 additions & 18 deletions packages/cli/src/services/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,22 +308,4 @@ export class UserService {

return { usersInvited, usersCreated: toCreateUsers.map(({ email }) => email) };
}

/**
* Counts the number of users in each role, e.g. `{ admin: 2, member: 6, owner: 1 }`
*/
async countUsersByRole() {
const result: Array<{ role_name: string; count: number }> = await Container.get(RoleRepository)
.createQueryBuilder('role')
.select('role.name')
.addSelect('COUNT(user.id)', 'count')
.innerJoin('user', 'user', 'role.id = user.globalRoleId')
.groupBy('role.name')
.getRawMany();

return result.reduce<Record<string, number>>((acc, item) => {
acc[item.role_name] = item.count;
return acc;
}, {});
}
}
4 changes: 2 additions & 2 deletions packages/cli/src/telemetry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { LicenseService } from '@/license/License.service';
import { N8N_VERSION } from '@/constants';
import { SourceControlPreferencesService } from '../environments/sourceControl/sourceControlPreferences.service.ee';
import { InstanceSettings } from 'n8n-core';
import { UserService } from '@/services/user.service';
import { RoleService } from '@/services/role.service';

type ExecutionTrackDataKey = 'manual_error' | 'manual_success' | 'prod_error' | 'prod_success';

Expand Down Expand Up @@ -109,7 +109,7 @@ export class Telemetry {
plan_name_current: this.license.getPlanName(),
quota: this.license.getTriggerLimit(),
usage: await LicenseService.getActiveTriggerCount(),
role_count: await Container.get(UserService).countUsersByRole(),
role_count: await Container.get(RoleService).countUsersByRole(),
source_control_set_up: Container.get(SourceControlPreferencesService).isSourceControlSetup(),
branchName: sourceControlPreferences.branchName,
read_only_instance: sourceControlPreferences.branchReadOnly,
Expand Down
48 changes: 48 additions & 0 deletions packages/cli/test/integration/role.service.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { RoleService } from '@/services/role.service';
import { createAdmin, createMember, createOwner } from './shared/db/users';
import * as testDb from './shared/testDb';
import { mock } from 'jest-mock-extended';
import { RoleRepository } from '@/databases/repositories/role.repository';
import Container from 'typedi';
import { SharedWorkflowRepository } from '@/databases/repositories/sharedWorkflow.repository';

describe('RoleService', () => {
let roleService: RoleService;

beforeAll(async () => {
await testDb.init();

roleService = new RoleService(
Container.get(RoleRepository),
Container.get(SharedWorkflowRepository),
mock(),
);

testDb.truncate(['User']);

Check failure on line 21 in packages/cli/test/integration/role.service.test.ts

View workflow job for this annotation

GitHub Actions / Lint changes

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator
});

afterEach(async () => {
await testDb.truncate(['SharedWorkflow']);
});

afterAll(async () => {
await testDb.terminate();
});

describe('countUsersByRole()', () => {
test('should return the number of users in each role', async () => {
await Promise.all([
createOwner(),
createAdmin(),
createAdmin(),
createMember(),
createMember(),
createMember(),
]);

const usersByRole = await roleService.countUsersByRole();

expect(usersByRole).toStrictEqual({ admin: 2, member: 3, owner: 1 });
});
});
});

0 comments on commit c3c0246

Please sign in to comment.