Skip to content

Commit

Permalink
AUT-2164: Create new service to check for fraudulent emails
Browse files Browse the repository at this point in the history
  • Loading branch information
LazarAlexandru-Constantin committed May 21, 2024
1 parent 638d4d8 commit e912dd4
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 15 deletions.
1 change: 1 addition & 0 deletions src/app.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export const API_ENDPOINTS = {
VERIFY_MFA_CODE: "/verify-mfa-code",
ACCOUNT_RECOVERY: "/account-recovery",
CHECK_REAUTH_USER: "/check-reauth-user",
CHECK_EMAIL_FRAUD_BLOCK: "/check-email-fraud-block",
};

export const ERROR_MESSAGES = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {
createApiResponse,
getRequestConfig,
Http,
http,
} from "../../utils/http";
import { API_ENDPOINTS } from "../../app.constants";
import { ApiResponseResult } from "../../types";
import {
CheckEmailFraudBlockInterface,
CheckEmailFraudBlockResponse,
} from "./types";

export function checkEmailFraudBlockService(
axios: Http = http
): CheckEmailFraudBlockInterface {
const checkEmailFraudBlock = async function (
email: string,
sessionId: string,
sourceIp: string,
clientSessionId: string,
persistentSessionId: string
): Promise<ApiResponseResult<CheckEmailFraudBlockResponse>> {
const response = await axios.client.post<CheckEmailFraudBlockResponse>(
API_ENDPOINTS.CHECK_EMAIL_FRAUD_BLOCK,
{
email: email.toLowerCase(),
},
getRequestConfig({
sessionId: sessionId,
sourceIp: sourceIp,
clientSessionId: clientSessionId,
persistentSessionId: persistentSessionId,
})
);
return createApiResponse<CheckEmailFraudBlockResponse>(response);
};
return {
checkEmailFraudBlock,
};
}
16 changes: 16 additions & 0 deletions src/components/check-email-fraud-block/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ApiResponseResult, DefaultApiResponse } from "../../types";

export interface CheckEmailFraudBlockInterface {
checkEmailFraudBlock: (
email: string,
sessionId: string,
sourceIp: string,
clientSessionId: string,
persistentSessionId: string
) => Promise<ApiResponseResult<CheckEmailFraudBlockResponse>>;
}

export interface CheckEmailFraudBlockResponse extends DefaultApiResponse {
email: string;
isBlockedStatus: string;
}
6 changes: 5 additions & 1 deletion src/components/enter-email/enter-email-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ import {
timestampNMinutesFromNow,
timestampNSecondsFromNow,
} from "../../utils/lock-helper";
import { CheckEmailFraudBlockInterface } from "../check-email-fraud-block/types";
import { checkEmailFraudBlockService } from "../check-email-fraud-block/checkEmailFraudBlockService";
import { logger } from "../../utils/logger";

export const RE_ENTER_EMAIL_TEMPLATE =
"enter-email/index-re-enter-email-account.njk";
Expand Down Expand Up @@ -60,7 +63,8 @@ export function enterEmailCreateGet(req: Request, res: Response): void {

export function enterEmailPost(
service: EnterEmailServiceInterface = enterEmailService(),
checkReauthService: CheckReauthServiceInterface = checkReauthUsersService()
checkReauthService: CheckReauthServiceInterface = checkReauthUsersService(),
checkEmailFraudService: CheckEmailFraudBlockInterface = checkEmailFraudBlockService()
): ExpressRouteFunc {
return async function (req: Request, res: Response) {
const email = req.body.email;
Expand Down
47 changes: 34 additions & 13 deletions src/components/enter-email/tests/enter-email-controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,27 @@ import { SendNotificationServiceInterface } from "../../common/send-notification
import { mockResponse, RequestOutput, ResponseOutput } from "mock-req-res";
import { CheckReauthServiceInterface } from "../../check-reauth-users/types";
import { createMockRequest } from "../../../../test/helpers/mock-request-helper";
import { CheckEmailFraudBlockInterface } from "../../check-email-fraud-block/types";

describe("enter email controller", () => {
let req: RequestOutput;
let res: ResponseOutput;
let clock: sinon.SinonFakeTimers;
const date = new Date(Date.UTC(2024, 1, 1));

const checkReauthSuccessfulFakeService: CheckReauthServiceInterface = {
checkReauthUsers: sinon.fake.returns({
success: true,
}),
} as unknown as CheckReauthServiceInterface;

const checkEmailFraudFakeSuccessfulService: CheckEmailFraudBlockInterface = {
checkEmailFraudBlock: sinon.fake.returns({
success: true,
data: { email: "[email protected]", isBlockedStatus: "Pending" },
}),
} as unknown as CheckEmailFraudBlockInterface;

beforeEach(() => {
res = mockResponse();
clock = sinon.useFakeTimers({
Expand Down Expand Up @@ -145,7 +159,11 @@ describe("enter email controller", () => {
req.body.email = "test.test.com";
res.locals.sessionId = "dsad.dds";

await enterEmailPost(fakeService)(req as Request, res as Response);
await enterEmailPost(
fakeService,
checkReauthSuccessfulFakeService,
checkEmailFraudFakeSuccessfulService
)(req as Request, res as Response);

expect(fakeService.userExists).to.have.been.calledOnce;
expect(res.redirect).to.have.calledWith(PATH_NAMES.ENTER_PASSWORD);
Expand All @@ -162,7 +180,11 @@ describe("enter email controller", () => {
req.body.email = "test.test.com";
res.locals.sessionId = "sadl990asdald";

await enterEmailPost(fakeService)(req as Request, res as Response);
await enterEmailPost(
fakeService,
checkReauthSuccessfulFakeService,
checkEmailFraudFakeSuccessfulService
)(req as Request, res as Response);

expect(res.redirect).to.have.calledWith(PATH_NAMES.ACCOUNT_NOT_FOUND);
expect(fakeService.userExists).to.have.been.calledOnce;
Expand Down Expand Up @@ -190,7 +212,11 @@ describe("enter email controller", () => {
req.body.email = "[email protected]";
res.locals.sessionId = "sadl990asdald";

await enterEmailPost(fakeService)(req as Request, res as Response);
await enterEmailPost(
fakeService,
checkReauthSuccessfulFakeService,
checkEmailFraudFakeSuccessfulService
)(req as Request, res as Response);

const expectedLockTime = new Date(
date.getTime() + lockTTlInSeconds * 1000
Expand Down Expand Up @@ -450,16 +476,11 @@ describe("enter email controller", () => {
}),
} as unknown as EnterEmailServiceInterface;

const successfulFakeService: CheckReauthServiceInterface = {
checkReauthUsers: sinon.fake.returns({
success: true,
}),
} as unknown as CheckReauthServiceInterface;

await enterEmailPost(fakeService, successfulFakeService)(
req as Request,
res as Response
);
await enterEmailPost(
fakeService,
checkReauthSuccessfulFakeService,
checkEmailFraudFakeSuccessfulService
)(req as Request, res as Response);

expect(res.redirect).to.have.calledWith(PATH_NAMES.ENTER_PASSWORD);
});
Expand Down
25 changes: 24 additions & 1 deletion src/components/enter-email/tests/enter-email-integration.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import request from "supertest";
import { describe } from "mocha";
import { expect, sinon } from "../../../../test/utils/test-utils";
import nock = require("nock");
import * as cheerio from "cheerio";
import decache from "decache";
import {
Expand All @@ -13,6 +12,7 @@ import { CheckReauthServiceInterface } from "../../check-reauth-users/types";
import { AxiosResponse } from "axios";
import { createApiResponse } from "../../../utils/http";
import { DefaultApiResponse } from "../../../types";
import nock = require("nock");

describe("Integration::enter email", () => {
let token: string | string[];
Expand All @@ -21,6 +21,7 @@ describe("Integration::enter email", () => {
let baseApi: string;

before(async () => {
process.env.SUPPORT_CHECK_EMAIL_FRAUD = "1";
decache("../../../app");
decache("../../../middleware/session-middleware");
const sessionMiddleware = require("../../../middleware/session-middleware");
Expand Down Expand Up @@ -167,6 +168,13 @@ describe("Integration::enter email", () => {
email: "[email protected]",
doesUserExist: true,
});
nock(baseApi)
.post(API_ENDPOINTS.CHECK_EMAIL_FRAUD_BLOCK)
.once()
.reply(HTTP_STATUS_CODES.OK, {
email: "[email protected]",
isBlockedStatus: "Pending",
});

request(app)
.post(PATH_NAMES.ENTER_EMAIL_SIGN_IN)
Expand All @@ -185,6 +193,13 @@ describe("Integration::enter email", () => {
email: "[email protected]",
doesUserExist: false,
});
nock(baseApi)
.post(API_ENDPOINTS.CHECK_EMAIL_FRAUD_BLOCK)
.once()
.reply(HTTP_STATUS_CODES.OK, {
email: "[email protected]",
isBlockedStatus: "Pending",
});

request(app)
.post(PATH_NAMES.ENTER_EMAIL_SIGN_IN)
Expand Down Expand Up @@ -236,6 +251,14 @@ describe("Integration::enter email", () => {
doesUserExist: true,
});

nock(baseApi)
.post(API_ENDPOINTS.CHECK_EMAIL_FRAUD_BLOCK)
.once()
.reply(HTTP_STATUS_CODES.OK, {
email: "[email protected]",
isBlockedStatus: "Pending",
});

request(app)
.post(PATH_NAMES.ENTER_EMAIL_SIGN_IN)
.type("form")
Expand Down

0 comments on commit e912dd4

Please sign in to comment.