Skip to content

Commit 1303104

Browse files
PYIC-8798: Return 400 to the user on expired IPV Session in spinner pages. (#2426)
2 parents 7b5b212 + a71fb0b commit 1303104

5 files changed

Lines changed: 61 additions & 13 deletions

File tree

assets/javascript/app/dcmaw-async.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ function generatePollApiFunction(url) {
88
return 0; // Success
99
} else if (data.status === "PROCESSING") {
1010
return 2; // Pending
11-
} else if (data.status === "ERROR") {
11+
} else if (data.status === "SERVER_ERROR") {
12+
return 3; // Backoff
13+
} else if (data.status === "CLIENT_ERROR") {
1214
return 3; // Backoff
1315
}
1416
throw new Error(`Unexpected status: ${data.status}`);

src/app/ipv/middleware.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import fs from "fs";
88
import path from "path";
99
import { saveSessionAndRedirect } from "../shared/redirectHelper";
1010
import {
11-
postJourneyEvent,
1211
getProvenIdentityUserDetails,
12+
postJourneyEvent,
1313
} from "../../services/coreBackService";
1414
import { generateQrCodeImageData } from "../shared/qrCodeHelper";
1515
import { PHONE_TYPE } from "../../constants/device-constants";
@@ -21,16 +21,16 @@ import {
2121
} from "../../constants/update-details-journeys";
2222
import { getAppStoreRedirectUrl } from "../shared/appDownloadHelper";
2323
import {
24-
getIpvPageTemplatePath,
2524
getIpvPagePath,
25+
getIpvPageTemplatePath,
2626
getTemplatePath,
2727
} from "../../lib/paths";
2828
import PAGES from "../../constants/ipv-pages";
2929
import { getPhoneType } from "../shared/contextHelper";
3030
import {
31-
sniffPhoneType,
3231
detectAppTriageEvent,
3332
OsType,
33+
sniffPhoneType,
3434
} from "../shared/deviceSniffingHelper";
3535
import {
3636
isClientResponse,
@@ -453,7 +453,9 @@ export const checkVcReceiptStatus: RequestHandler = async (req, res, next) => {
453453
const status = await getAppVcReceiptStatusAndStoreJourneyResponse(req);
454454
if (status === AppVcReceiptStatus.PROCESSING) {
455455
await handleJourneyPageRequest(req, res, next, true);
456-
} else if (status === AppVcReceiptStatus.ERROR) {
456+
} else if (status === AppVcReceiptStatus.SERVER_ERROR) {
457+
throw new Error("Failed to get VC response status");
458+
} else if (status === AppVcReceiptStatus.CLIENT_ERROR) {
457459
throw new Error("Failed to get VC response status");
458460
} else if (status === AppVcReceiptStatus.COMPLETED) {
459461
return next();

src/app/ipv/tests/checkVcReceiptStatus.test.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,30 @@ describe("checkVcReceiptStatus middleware", () => {
6464
expect(next).to.have.not.been.calledOnce;
6565
});
6666

67-
it("should throw error if status is ERROR", async () => {
67+
it("should throw error if status is SERVER_ERROR", async () => {
6868
// Arrange
6969
const req = createRequest();
7070
const res = createResponse();
71-
getAppVcReceiptStatusAndStoreJourneyResponseStub.resolves("ERROR");
71+
getAppVcReceiptStatusAndStoreJourneyResponseStub.resolves("SERVER_ERROR");
72+
73+
// Act & Assert
74+
await expect(
75+
(async () => await checkVcReceiptStatus(req, res, next))(),
76+
).to.be.rejectedWith(Error, "Failed to get VC response status");
77+
78+
// Assert
79+
expect(
80+
getAppVcReceiptStatusAndStoreJourneyResponseStub,
81+
).to.have.been.calledWith(req);
82+
expect(res.render).to.not.have.been.called;
83+
expect(next).to.have.not.been.calledOnce;
84+
});
85+
86+
it("should throw client error if status is CLIENT_ERROR", async () => {
87+
// Arrange
88+
const req = createRequest();
89+
const res = createResponse();
90+
getAppVcReceiptStatusAndStoreJourneyResponseStub.resolves("CLIENT_ERROR");
7291

7392
// Act & Assert
7493
await expect(

src/app/vc-receipt-status/middleware.test.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,24 +66,34 @@ describe("vc receipt status middleware tests", () => {
6666
expect((req.session as any).journey).to.equal("journey/next");
6767
});
6868

69+
it("pollVcReceiptStatus should return CLIENT_ERROR status if appVcReceived returns 400", async () => {
70+
const error = { response: { status: 400 } };
71+
appVcReceivedStub.rejects(error);
72+
73+
await middleware.pollVcReceiptStatus(req as Request, res as Response, next);
74+
75+
expect(res.status).to.have.been.calledWith(400);
76+
expect(res.json).to.have.been.calledWith({ status: "CLIENT_ERROR" });
77+
});
78+
6979
it("pollVcReceiptStatus should return an error when appVcReceived does not return journey response", async () => {
7080
appVcReceivedStub.resolves({ data: {} });
7181
isJourneyResponse.returns(false);
7282

7383
await middleware.pollVcReceiptStatus(req as Request, res as Response, next);
7484

7585
expect(res.status).to.have.been.calledWith(500);
76-
expect(res.json).to.have.been.calledWith({ status: "ERROR" });
86+
expect(res.json).to.have.been.calledWith({ status: "SERVER_ERROR" });
7787
});
7888

79-
it("pollVcReceiptStatus should return ERROR status if appVcReceived throws non 404 error", async () => {
89+
it("pollVcReceiptStatus should return SERVER_ERROR status if appVcReceived throws non 400-499 error", async () => {
8090
const error = new Error("Test error");
8191
appVcReceivedStub.rejects(error);
8292

8393
await middleware.pollVcReceiptStatus(req as Request, res as Response, next);
8494

8595
expect(res.status).to.have.been.calledWith(500);
86-
expect(res.json).to.have.been.calledWith({ status: "ERROR" });
96+
expect(res.json).to.have.been.calledWith({ status: "SERVER_ERROR" });
8797
});
8898

8999
it("pollVcReceiptStatus should return COMPLETED status when query param snapshotTest is true", async () => {

src/app/vc-receipt-status/middleware.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import { logger } from "../../lib/logger";
88

99
export enum AppVcReceiptStatus {
1010
COMPLETED = "COMPLETED",
11-
ERROR = "ERROR",
1211
PROCESSING = "PROCESSING",
12+
CLIENT_ERROR = "CLIENT_ERROR",
13+
SERVER_ERROR = "SERVER_ERROR",
1314
}
1415

1516
export const getAppVcReceiptStatusAndStoreJourneyResponse = async (
@@ -28,12 +29,21 @@ export const getAppVcReceiptStatusAndStoreJourneyResponse = async (
2829
} catch (error) {
2930
if (isAxiosError(error) && error.response?.status === 404) {
3031
return AppVcReceiptStatus.PROCESSING;
32+
} else if (isAxiosError(error) && isClientError(error.response?.status)) {
33+
return AppVcReceiptStatus.CLIENT_ERROR;
3134
}
3235
logger.error(error, "Error getting app vc receipt status");
33-
return AppVcReceiptStatus.ERROR;
36+
return AppVcReceiptStatus.SERVER_ERROR;
3437
}
3538
};
3639

40+
const isClientError = (error: number | undefined): boolean => {
41+
if (!error) {
42+
return false;
43+
}
44+
return error >= 400 && error <= 499;
45+
};
46+
3747
export const pollVcReceiptStatus: RequestHandler = async (req, res) => {
3848
const isPreview = config.ENABLE_PREVIEW && req.query.preview === "true";
3949
const isSnapshot =
@@ -52,10 +62,15 @@ export const pollVcReceiptStatus: RequestHandler = async (req, res) => {
5262
}
5363

5464
const status = await getAppVcReceiptStatusAndStoreJourneyResponse(req);
55-
if (status === AppVcReceiptStatus.ERROR) {
65+
if (status === AppVcReceiptStatus.SERVER_ERROR) {
5666
res.status(500).json({ status });
5767
return;
5868
}
5969

70+
if (status === AppVcReceiptStatus.CLIENT_ERROR) {
71+
res.status(400).json({ status });
72+
return;
73+
}
74+
6075
res.status(200).json({ status });
6176
};

0 commit comments

Comments
 (0)