refactor(api): migrate batch 10 endpoints to relayGet
This commit is contained in:
@@ -1006,3 +1006,34 @@ Validation:
|
|||||||
Follow-ups:
|
Follow-ups:
|
||||||
|
|
||||||
- Continue P2-S2 with next bounded batch from remaining legacy relay GET endpoints (`createwatchedcases_api`, `deletewatchedcasesproxy_api`, `getadvancedsearch_api`, `getadvancedsearchpaged_api`, `getbasicsearch_by_address_api`, `getbasicsearch_by_lparref_api`, `getdnscoords_api`, `getmylpacases_api`, `getportallogin_api`).
|
- Continue P2-S2 with next bounded batch from remaining legacy relay GET endpoints (`createwatchedcases_api`, `deletewatchedcasesproxy_api`, `getadvancedsearch_api`, `getadvancedsearchpaged_api`, `getbasicsearch_by_address_api`, `getbasicsearch_by_lparref_api`, `getdnscoords_api`, `getmylpacases_api`, `getportallogin_api`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### CL-027: TASK22229 P2-S2 Batch 10 (portal login + my LPA cases relay GET pair)
|
||||||
|
|
||||||
|
date: 2026-03-24
|
||||||
|
author: Cline
|
||||||
|
scope: `pages/api/endpoint/{getportallogin_api,getmylpacases_api}.js`, `tests/phase21/endpoint-handler-contract.test.cjs`
|
||||||
|
type: change
|
||||||
|
rationale: Continue bounded relay migration by moving two remaining high-use portal retrieval endpoints to shared `relayGet` while preserving existing hash/lookup guards and response contracts.
|
||||||
|
impact: Further relay boilerplate reduction and consistent forwarding behavior in portal login/LPA case retrieval flows; no intended API contract changes.
|
||||||
|
status: completed
|
||||||
|
|
||||||
|
Summary:
|
||||||
|
|
||||||
|
- Migrated Batch 10 endpoints to shared `relayGet`:
|
||||||
|
- `getportallogin_api.js` (preserved hash validation guard and error contract)
|
||||||
|
- `getmylpacases_api.js` (preserved LPA lookup/404 guard and title transform)
|
||||||
|
- Preserved endpoint-specific behavior:
|
||||||
|
- `getportallogin_api`: raw + encoded hash candidate validation before relay call
|
||||||
|
- `getmylpacases_api`: JSONPath LPA lookup with `LPA_NOT_FOUND` handling and `pinswg_title` enrichment transform
|
||||||
|
- Updated phase21 endpoint contract tests to inject `relayGet` mocks for migrated handlers in validation/catch/success paths.
|
||||||
|
|
||||||
|
Validation:
|
||||||
|
|
||||||
|
- `node tests/phase21/endpoint-handler-contract.test.cjs` -> pass (152/152)
|
||||||
|
- `npm run lint` -> warnings only (pre-existing `react-hooks/exhaustive-deps`; no new lint errors)
|
||||||
|
|
||||||
|
Follow-ups:
|
||||||
|
|
||||||
|
- Continue P2-S2 with the remaining legacy relay GET candidates (`createwatchedcases_api`, `deletewatchedcasesproxy_api`, `getadvancedsearch_api`, `getadvancedsearchpaged_api`, `getbasicsearch_by_address_api`, `getbasicsearch_by_lparref_api`, `getdnscoords_api`).
|
||||||
|
|||||||
@@ -17,18 +17,11 @@
|
|||||||
* description: Success
|
* description: Success
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import axios from "axios";
|
|
||||||
import { JSONPath as jsonpath } from "jsonpath-plus";
|
import { JSONPath as jsonpath } from "jsonpath-plus";
|
||||||
import { getLPA } from "../../../actions/services/referenceDataService";
|
import { getLPA } from "../../../actions/services/referenceDataService";
|
||||||
import { azureHeaders } from "../../../actions/core/headers";
|
import { azureHeaders } from "../../../actions/core/headers";
|
||||||
import { consoleLogger } from "../../../actions/core/logger";
|
import { respondError } from "../middleware/apiResponse";
|
||||||
import { getToken } from "../../../actions/core/token";
|
import { relayGet } from "../middleware/relayForwarding";
|
||||||
import { hashAPIPath } from "../../../actions/core/hash";
|
|
||||||
import { respondError, respondSuccess } from "../middleware/apiResponse";
|
|
||||||
|
|
||||||
const WEBAPI_URL =
|
|
||||||
process.env.RELAY_ROOT ||
|
|
||||||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
|
|
||||||
|
|
||||||
export default async function ApiProxy(req, res) {
|
export default async function ApiProxy(req, res) {
|
||||||
const lpaid = req.query.lpaid;
|
const lpaid = req.query.lpaid;
|
||||||
@@ -42,7 +35,6 @@ export default async function ApiProxy(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const token = await getToken();
|
|
||||||
const lpaList = await getLPA();
|
const lpaList = await getLPA();
|
||||||
|
|
||||||
const lpaGUID = jsonpath({
|
const lpaGUID = jsonpath({
|
||||||
@@ -74,18 +66,23 @@ export default async function ApiProxy(req, res) {
|
|||||||
|
|
||||||
//console.log("///////////\nPortal query: ", queryUrl, "<<<<end query");
|
//console.log("///////////\nPortal query: ", queryUrl, "<<<<end query");
|
||||||
|
|
||||||
const { data } = await axios.get(
|
return relayGet({
|
||||||
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
|
queryUrl,
|
||||||
azureHeaders(token.access_token)
|
res,
|
||||||
);
|
requestOptionsBuilder: (accessToken) => azureHeaders(accessToken),
|
||||||
|
transformData: (data) => {
|
||||||
data.value.forEach(function (element) {
|
data.value.forEach(function (element) {
|
||||||
element.pinswg_title = element.title;
|
element.pinswg_title = element.title;
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
errorResponse: {
|
||||||
|
status: 400,
|
||||||
|
code: "MY_LPA_CASES_FETCH_FAILED",
|
||||||
|
message: "Failed to fetch my LPA cases"
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return respondSuccess(res, data);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
consoleLogger(error);
|
|
||||||
return respondError(res, {
|
return respondError(res, {
|
||||||
status: 400,
|
status: 400,
|
||||||
code: "MY_LPA_CASES_FETCH_FAILED",
|
code: "MY_LPA_CASES_FETCH_FAILED",
|
||||||
|
|||||||
@@ -16,16 +16,10 @@
|
|||||||
* description: hello world
|
* description: hello world
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import axios from "axios";
|
|
||||||
import { azureHeadersPaged } from "../../../actions/core/headers";
|
import { azureHeadersPaged } from "../../../actions/core/headers";
|
||||||
import { consoleLogger } from "../../../actions/core/logger";
|
|
||||||
import { getToken } from "../../../actions/core/token";
|
|
||||||
import { hashAPIPath } from "../../../actions/core/hash";
|
import { hashAPIPath } from "../../../actions/core/hash";
|
||||||
import { respondError, respondSuccess } from "../middleware/apiResponse";
|
import { respondError } from "../middleware/apiResponse";
|
||||||
|
import { relayGet } from "../middleware/relayForwarding";
|
||||||
const WEBAPI_URL =
|
|
||||||
process.env.RELAY_ROOT ||
|
|
||||||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
|
|
||||||
|
|
||||||
export default async function ApiProxy(req, res) {
|
export default async function ApiProxy(req, res) {
|
||||||
const emailAddress = req.query.emailAddress;
|
const emailAddress = req.query.emailAddress;
|
||||||
@@ -66,24 +60,19 @@ export default async function ApiProxy(req, res) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const queryUrl =
|
||||||
const token = await getToken();
|
"contacts?$filter=emailaddress1 eq '" +
|
||||||
const queryUrl =
|
emailAddress +
|
||||||
"contacts?$filter=emailaddress1 eq '" +
|
"' and statuscode eq 1&$count=true&$select=emailaddress1,contactid,yomifullname,firstname,lastname";
|
||||||
emailAddress +
|
|
||||||
"' and statuscode eq 1&$count=true&$select=emailaddress1,contactid,yomifullname,firstname,lastname";
|
|
||||||
const { data } = await axios.get(
|
|
||||||
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
|
|
||||||
azureHeadersPaged(token.access_token)
|
|
||||||
);
|
|
||||||
|
|
||||||
return respondSuccess(res, data);
|
return relayGet({
|
||||||
} catch (error) {
|
queryUrl,
|
||||||
consoleLogger(error);
|
res,
|
||||||
return respondError(res, {
|
requestOptionsBuilder: (accessToken) => azureHeadersPaged(accessToken),
|
||||||
|
errorResponse: {
|
||||||
status: 400,
|
status: 400,
|
||||||
code: "PORTAL_LOGIN_FETCH_FAILED",
|
code: "PORTAL_LOGIN_FETCH_FAILED",
|
||||||
message: "Failed to fetch portal login"
|
message: "Failed to fetch portal login"
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -274,14 +274,12 @@ test("getportallogin returns HASH_REQUIRED when hash missing", async () => {
|
|||||||
const mod = loadModule("pages/api/endpoint/getportallogin_api.js", {
|
const mod = loadModule("pages/api/endpoint/getportallogin_api.js", {
|
||||||
respondError: respondErrorMock,
|
respondError: respondErrorMock,
|
||||||
respondSuccess: respondSuccessMock,
|
respondSuccess: respondSuccessMock,
|
||||||
getToken: async () => ({ access_token: "token" }),
|
relayGet: async () => ({}),
|
||||||
hashAPIPath: (input) =>
|
hashAPIPath: (input) =>
|
||||||
input && input.startsWith("/api/endpoint/getportallogin_api")
|
input && input.startsWith("/api/endpoint/getportallogin_api")
|
||||||
? "&hash=expected"
|
? "&hash=expected"
|
||||||
: "&hash=relay",
|
: "&hash=relay",
|
||||||
azureHeadersPaged: () => ({}),
|
azureHeadersPaged: () => ({})
|
||||||
axios: { get: async () => ({ data: { value: [] } }) },
|
|
||||||
consoleLogger: () => {}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const req = { query: { emailAddress: "user@test.local" } };
|
const req = { query: { emailAddress: "user@test.local" } };
|
||||||
@@ -296,14 +294,12 @@ test("getportallogin returns INVALID_HASH when hash mismatch", async () => {
|
|||||||
const mod = loadModule("pages/api/endpoint/getportallogin_api.js", {
|
const mod = loadModule("pages/api/endpoint/getportallogin_api.js", {
|
||||||
respondError: respondErrorMock,
|
respondError: respondErrorMock,
|
||||||
respondSuccess: respondSuccessMock,
|
respondSuccess: respondSuccessMock,
|
||||||
getToken: async () => ({ access_token: "token" }),
|
relayGet: async () => ({}),
|
||||||
hashAPIPath: (input) =>
|
hashAPIPath: (input) =>
|
||||||
input && input.startsWith("/api/endpoint/getportallogin_api")
|
input && input.startsWith("/api/endpoint/getportallogin_api")
|
||||||
? "&hash=expected"
|
? "&hash=expected"
|
||||||
: "&hash=relay",
|
: "&hash=relay",
|
||||||
azureHeadersPaged: () => ({}),
|
azureHeadersPaged: () => ({})
|
||||||
axios: { get: async () => ({ data: { value: [] } }) },
|
|
||||||
consoleLogger: () => {}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const req = { query: { emailAddress: "user@test.local", hash: "wrong" } };
|
const req = { query: { emailAddress: "user@test.local", hash: "wrong" } };
|
||||||
@@ -318,18 +314,13 @@ test("getportallogin catch path returns PORTAL_LOGIN_FETCH_FAILED", async () =>
|
|||||||
const mod = loadModule("pages/api/endpoint/getportallogin_api.js", {
|
const mod = loadModule("pages/api/endpoint/getportallogin_api.js", {
|
||||||
respondError: respondErrorMock,
|
respondError: respondErrorMock,
|
||||||
respondSuccess: respondSuccessMock,
|
respondSuccess: respondSuccessMock,
|
||||||
getToken: async () => ({ access_token: "token" }),
|
relayGet: async ({ res, errorResponse }) =>
|
||||||
|
respondErrorMock(res, errorResponse),
|
||||||
hashAPIPath: (input) =>
|
hashAPIPath: (input) =>
|
||||||
input && input.startsWith("/api/endpoint/getportallogin_api")
|
input && input.startsWith("/api/endpoint/getportallogin_api")
|
||||||
? "&hash=expected"
|
? "&hash=expected"
|
||||||
: "&hash=relay",
|
: "&hash=relay",
|
||||||
azureHeadersPaged: () => ({}),
|
azureHeadersPaged: () => ({})
|
||||||
axios: {
|
|
||||||
get: async () => {
|
|
||||||
throw new Error("relay failed");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
consoleLogger: () => {}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const req = {
|
const req = {
|
||||||
@@ -349,16 +340,13 @@ test("getportallogin accepts encoded email hash variant", async () => {
|
|||||||
const mod = loadModule("pages/api/endpoint/getportallogin_api.js", {
|
const mod = loadModule("pages/api/endpoint/getportallogin_api.js", {
|
||||||
respondError: respondErrorMock,
|
respondError: respondErrorMock,
|
||||||
respondSuccess: respondSuccessMock,
|
respondSuccess: respondSuccessMock,
|
||||||
getToken: async () => ({ access_token: "token" }),
|
relayGet: async ({ res }) =>
|
||||||
|
respondSuccessMock(res, { value: [{ contactid: "c1" }] }),
|
||||||
hashAPIPath: (input) =>
|
hashAPIPath: (input) =>
|
||||||
input && input.includes("emailAddress=user%2Btest%40local")
|
input && input.includes("emailAddress=user%2Btest%40local")
|
||||||
? "&hash=expected"
|
? "&hash=expected"
|
||||||
: "&hash=other",
|
: "&hash=other",
|
||||||
azureHeadersPaged: () => ({}),
|
azureHeadersPaged: () => ({})
|
||||||
axios: {
|
|
||||||
get: async () => ({ data: { value: [{ contactid: "c1" }] } })
|
|
||||||
},
|
|
||||||
consoleLogger: () => {}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const req = {
|
const req = {
|
||||||
@@ -2421,13 +2409,10 @@ test("getmylpacases returns LPA_ID_REQUIRED when lpaid missing", async () => {
|
|||||||
const mod = loadModule("pages/api/endpoint/getmylpacases_api.js", {
|
const mod = loadModule("pages/api/endpoint/getmylpacases_api.js", {
|
||||||
respondError: respondErrorMock,
|
respondError: respondErrorMock,
|
||||||
respondSuccess: respondSuccessMock,
|
respondSuccess: respondSuccessMock,
|
||||||
getToken: async () => ({ access_token: "token" }),
|
relayGet: async () => ({}),
|
||||||
getLPA: async () => [{ name: "Test LPA", accountid: "acc1" }],
|
getLPA: async () => [{ name: "Test LPA", accountid: "acc1" }],
|
||||||
jsonpath: () => [{ accountid: "acc1" }],
|
jsonpath: () => [{ accountid: "acc1" }],
|
||||||
hashAPIPath: () => "&hash=expected",
|
azureHeaders: () => ({})
|
||||||
azureHeaders: () => ({}),
|
|
||||||
axios: { get: async () => ({ data: { value: [] } }) },
|
|
||||||
consoleLogger: () => {}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const req = { query: {} };
|
const req = { query: {} };
|
||||||
@@ -2442,13 +2427,10 @@ test("getmylpacases returns LPA_NOT_FOUND when lpaid lookup misses", async () =>
|
|||||||
const mod = loadModule("pages/api/endpoint/getmylpacases_api.js", {
|
const mod = loadModule("pages/api/endpoint/getmylpacases_api.js", {
|
||||||
respondError: respondErrorMock,
|
respondError: respondErrorMock,
|
||||||
respondSuccess: respondSuccessMock,
|
respondSuccess: respondSuccessMock,
|
||||||
getToken: async () => ({ access_token: "token" }),
|
relayGet: async () => ({}),
|
||||||
getLPA: async () => [{ name: "Another LPA", accountid: "acc1" }],
|
getLPA: async () => [{ name: "Another LPA", accountid: "acc1" }],
|
||||||
jsonpath: () => [],
|
jsonpath: () => [],
|
||||||
hashAPIPath: () => "&hash=expected",
|
azureHeaders: () => ({})
|
||||||
azureHeaders: () => ({}),
|
|
||||||
axios: { get: async () => ({ data: { value: [] } }) },
|
|
||||||
consoleLogger: () => {}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const req = { query: { lpaid: "Missing LPA" } };
|
const req = { query: { lpaid: "Missing LPA" } };
|
||||||
@@ -2463,17 +2445,11 @@ test("getmylpacases catch path returns MY_LPA_CASES_FETCH_FAILED", async () => {
|
|||||||
const mod = loadModule("pages/api/endpoint/getmylpacases_api.js", {
|
const mod = loadModule("pages/api/endpoint/getmylpacases_api.js", {
|
||||||
respondError: respondErrorMock,
|
respondError: respondErrorMock,
|
||||||
respondSuccess: respondSuccessMock,
|
respondSuccess: respondSuccessMock,
|
||||||
getToken: async () => ({ access_token: "token" }),
|
relayGet: async ({ res, errorResponse }) =>
|
||||||
|
respondErrorMock(res, errorResponse),
|
||||||
getLPA: async () => [{ name: "Test LPA", accountid: "acc1" }],
|
getLPA: async () => [{ name: "Test LPA", accountid: "acc1" }],
|
||||||
jsonpath: () => [{ accountid: "acc1" }],
|
jsonpath: () => [{ accountid: "acc1" }],
|
||||||
hashAPIPath: () => "&hash=expected",
|
azureHeaders: () => ({})
|
||||||
azureHeaders: () => ({}),
|
|
||||||
axios: {
|
|
||||||
get: async () => {
|
|
||||||
throw new Error("relay failed");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
consoleLogger: () => {}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const req = { query: { lpaid: "Test LPA" } };
|
const req = { query: { lpaid: "Test LPA" } };
|
||||||
|
|||||||
Reference in New Issue
Block a user