Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/working tests #61

Open
wants to merge 10 commits into
base: development
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { TwoFactorUserD2Repository } from "data/user-monitoring/two-factor-monit
import { TwoFactorConfigD2Repository } from "data/user-monitoring/two-factor-monitoring/TwoFactorConfigD2Repository";
import { UserMonitoringProgramD2Repository } from "data/user-monitoring/common/UserMonitoringProgramD2Repository";
import { TwoFactorReportD2Repository } from "data/user-monitoring/two-factor-monitoring/TwoFactorReportD2Repository";
import log from "utils/log";
import { TwoFactorUserReport } from "domain/entities/user-monitoring/two-factor-monitoring/TwoFactorUserReport";
import { Async } from "domain/entities/Async";
import { NonUsersException } from "domain/entities/user-monitoring/two-factor-monitoring/exception/NonUsersException";

type TwoFactorReportResponse = { message: string; report: TwoFactorUserReport };

export class RunTwoFactorReportUseCase {
constructor(
private userRepository: TwoFactorUserD2Repository,
Expand All @@ -16,10 +17,10 @@ export class RunTwoFactorReportUseCase {
private programRepository: UserMonitoringProgramD2Repository
) {}

async execute(): Async<string> {
async execute(): Async<TwoFactorReportResponse> {
const options = await this.configRepository.get();

const twoFactorGroupUsers = await this.userRepository.getUsersByGroupId([options.twoFactorGroup.id]);

if (!twoFactorGroupUsers) {
throw new NonUsersException(
"Users not found in the group. Check the group id. " + options.twoFactorGroup.id
Expand All @@ -32,13 +33,12 @@ export class RunTwoFactorReportUseCase {
const userItems = usersWithoutTwoFactor.map(user => {
return { id: user.id, name: user.username };
});
const response: TwoFactorUserReport = {
const report: TwoFactorUserReport = {
invalidUsersCount: userItems.length,
listOfAffectedUsers: userItems,
};
log.info("Users without two factor: " + userItems.length);
const programMetadata = await this.programRepository.get(options.pushProgram.id);
const saveResponse = await this.reportRepository.save(programMetadata, response);
return saveResponse;
const saveResponse = await this.reportRepository.save(programMetadata, report);
return { message: saveResponse, report };
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import { describe, it, expect } from "vitest";

import { RunTwoFactorReportUseCase } from "../RunTwoFactorReportUseCase";
import { TwoFactorConfigD2Repository } from "data/user-monitoring/two-factor-monitoring/TwoFactorConfigD2Repository";
import { anything, deepEqual, instance, mock, when } from "ts-mockito";
import {
config,
listOfUsers,
listOfUsersWithTwoInvalid,
listOfUsersWithTwoValid,
programMetadata,
userWithoutTwoFA,
userWithTwoFA,
} from "./TwoFactorTest.data";
import { TwoFactorUserD2Repository } from "data/user-monitoring/two-factor-monitoring/TwoFactorUserD2Repository";
import { TwoFactorReportD2Repository } from "data/user-monitoring/two-factor-monitoring/TwoFactorReportD2Repository";
import { UserMonitoringProgramD2Repository } from "data/user-monitoring/common/UserMonitoringProgramD2Repository";
import { TwoFactorUser } from "domain/entities/user-monitoring/two-factor-monitoring/TwoFactorUser";
import { NonUsersException } from "domain/entities/user-monitoring/two-factor-monitoring/exception/NonUsersException";

describe("TwoFactorReportUseCase", () => {
it("Should push report with 0 affected users and empty affected user list if one user has two factor activated", async () => {
const useCase = givenUsers([userWithTwoFA]);

const result = await useCase.execute();

expect(result.report.invalidUsersCount).toEqual(0);
expect(result.report.listOfAffectedUsers).toEqual([]);
expect(result.message).toEqual("OK");
});

it("Should push report with 0 affected users and empty affected user list if all the users has two factor activated", async () => {
const useCase = givenUsers([userWithTwoFA, userWithTwoFA]);

const result = await useCase.execute();

expect(result.report.invalidUsersCount).toEqual(0);
expect(result.report.listOfAffectedUsers).toEqual([]);
expect(result.message).toEqual("OK");
});

it("Should push report with 1 affected users and 1 affected user list if 1 user has two factor deactivated", async () => {
const useCase = givenUsers([userWithoutTwoFA]);

const result = await useCase.execute();

const expectedReport = { id: userWithoutTwoFA.id, name: userWithoutTwoFA.username };
expect(result.report.invalidUsersCount).toEqual(1);
expect(result.report.listOfAffectedUsers).toEqual([expectedReport]);
expect(result.message).toEqual("OK");
});

it("Should push report 1 affected user if we provide a list with two users, and only one has two-factor authentication disabled.", async () => {
const useCase = givenUsers(listOfUsers);

const result = await useCase.execute();

const expectedReport = { id: userWithoutTwoFA.id, name: userWithoutTwoFA.username };
expect(result.report.invalidUsersCount).toEqual(1);
expect(result.report.listOfAffectedUsers).toEqual([expectedReport]);
expect(result.message).toEqual("OK");
});

it("Should push report 2 affected users and a list of 2 affected user if 2 user has two factor deactivate and 1 activated", async () => {
const useCase = givenUsers(listOfUsersWithTwoInvalid);

const result = await useCase.execute();

const expectedReport = [
{ id: userWithoutTwoFA.id, name: userWithoutTwoFA.username },
{ id: userWithoutTwoFA.id, name: userWithoutTwoFA.username },
];
expect(result.report.invalidUsersCount).toEqual(2);
expect(result.report.listOfAffectedUsers).toEqual(expectedReport);
expect(result.message).toEqual("OK");
});

it("Should push report 1 affected users and a list of 1 affected user if 1 user has two factor deactivate and 2 activated", async () => {
const useCase = givenUsers(listOfUsersWithTwoValid);

const result = await useCase.execute();

const expectedReport = [{ id: userWithoutTwoFA.id, name: userWithoutTwoFA.username }];
expect(result.report.invalidUsersCount).toEqual(1);
expect(result.report.listOfAffectedUsers).toEqual(expectedReport);
expect(result.message).toEqual("OK");
});

it("Should throw exception if no users in the given usergroup", async () => {
const useCase = givenInvalidUserGroupId();

await expect(async () => {
await useCase.execute();
}).rejects.toThrow(NonUsersException);
});
});

function givenUsers(users: TwoFactorUser[]) {
const useCase = new RunTwoFactorReportUseCase(
givenUserRepository(users, config.twoFactorGroup.id),
givenTwoFactorReportD2Repository(),
givenConfigRepository(),
givenUserMonitoringProgramD2Repository()
);
return useCase;
}
function givenInvalidUserGroupId() {
const useCase = new RunTwoFactorReportUseCase(
givenUserRepository([], "invalidGroupId"),
givenTwoFactorReportD2Repository(),
givenConfigRepository(),
givenUserMonitoringProgramD2Repository()
);
return useCase;
}

function givenUserRepository(users: TwoFactorUser[], groupId = config.twoFactorGroup.id) {
const mockedRepository = mock(TwoFactorUserD2Repository);
when(mockedRepository.getUsersByGroupId(deepEqual([groupId]))).thenReturn(Promise.resolve(users));
const configRepository = instance(mockedRepository);
return configRepository;
}
function givenTwoFactorReportD2Repository() {
const mockedRepository = mock(TwoFactorReportD2Repository);
when(mockedRepository.save(anything(), anything())).thenReturn(Promise.resolve("OK"));
const reportRepository = instance(mockedRepository);
return reportRepository;
}
function givenUserMonitoringProgramD2Repository() {
const mockedRepository = mock(UserMonitoringProgramD2Repository);
when(mockedRepository.get(deepEqual(config.pushProgram.id))).thenReturn(Promise.resolve(programMetadata));
const reportRepository = instance(mockedRepository);
return reportRepository;
}

function givenConfigRepository() {
const mockedRepository = mock(TwoFactorConfigD2Repository);
when(mockedRepository.get()).thenReturn(Promise.resolve(config));
const configRepository = instance(mockedRepository);
return configRepository;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { UserMonitoringProgramMetadata } from "domain/entities/user-monitoring/common/UserMonitoringProgramMetadata";
import { PermissionFixerUser } from "domain/entities/user-monitoring/permission-fixer/PermissionFixerUser";
import { TwoFactorUser } from "domain/entities/user-monitoring/two-factor-monitoring/TwoFactorUser";
import { TwoFactorUserOptions } from "domain/entities/user-monitoring/two-factor-monitoring/TwoFactorUserOptions";

export const config: TwoFactorUserOptions = {
pushProgram: {
id: "IKpEgoQ4S0r",
name: "Event program uid",
},
twoFactorGroup: {
id: "MkELexlZOj9",
name: "TwoFactor usergroup",
},
};

export const NoUsersReport = {
invalidUsersCount: 0,
listOfAffectedUsers: [],
};

export const programMetadata: UserMonitoringProgramMetadata = {
id: "IKpEgoQ4S0r",
programStageId: "aHbPlvAb2bu",
dataElements: [
{
id: "PDAPJ38H7Pl",
code: "ADMIN_users_without_two_factor_count_7_Events",
name: "ADMIN_users_without_two_factor_count_7_Events",
},
{
id: "Ss4ZVwDJKDe",
code: "ADMIN_users_without_two_factor_8_Events",
name: "ADMIN_users_without_two_factor_8_Events",
},
],
orgUnitId: "wLoK6XpZq8I",
};

export const userWithTwoFA: TwoFactorUser = {
id: "userUid",
twoFA: true,
username: "username",
};

export const userWithoutTwoFA: TwoFactorUser = {
id: "userUid2",
twoFA: false,
username: "username2",
};

export const listOfUsers: TwoFactorUser[] = [userWithTwoFA, userWithoutTwoFA];
export const listOfUsersWithTwoInvalid: TwoFactorUser[] = [userWithTwoFA, userWithoutTwoFA, userWithoutTwoFA];
export const listOfUsersWithTwoValid: TwoFactorUser[] = [userWithTwoFA, userWithTwoFA, userWithoutTwoFA];
4 changes: 3 additions & 1 deletion src/scripts/commands/userMonitoring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,14 @@ const run2FAReporterCmd = command({
const userMonitoringReportRepository = new TwoFactorReportD2Repository(api);
const programRepository = new UserMonitoringProgramD2Repository(api);
log.info(`Run Report users without 2FA`);
await new RunTwoFactorReportUseCase(
const response = await new RunTwoFactorReportUseCase(
usersRepository,
userMonitoringReportRepository,
externalConfigRepository,
programRepository
).execute();

log.info(JSON.stringify(response));
},
});

Expand Down