diff --git a/pages/api/endpoint/getappealid_api.js b/pages/api/endpoint/getappealid_api.js index ed1fefd8..d01ce523 100644 --- a/pages/api/endpoint/getappealid_api.js +++ b/pages/api/endpoint/getappealid_api.js @@ -29,40 +29,78 @@ */ import axios from "axios"; -import CryptoJS from "crypto-js"; import { azureHeaders } from "../../../actions/core/headers"; import { consoleLogger } from "../../../actions/core/logger"; import { getToken } from "../../../actions/core/token"; 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) { - var caseReference = req.query.caseReference; - var updateFormCollection = req.query.updateFormCollection; - var primaryAttribute = req.query.primaryAttribute; - var token = await getToken(); + const caseReference = req.query.caseReference; + const updateFormCollection = req.query.updateFormCollection; + const primaryAttribute = req.query.primaryAttribute; - const queryUrl = - updateFormCollection + - "?$count=true&$select=_" + - primaryAttribute + - "s_value&$filter=pinswg_name eq '" + - caseReference + - "'"; + if ( + typeof caseReference !== "string" || + caseReference.trim().length === 0 + ) { + return respondError(res, { + status: 400, + code: "CASE_REFERENCE_REQUIRED", + message: "caseReference is required" + }); + } - return axios - .get( + if ( + typeof updateFormCollection !== "string" || + updateFormCollection.trim().length === 0 + ) { + return respondError(res, { + status: 400, + code: "UPDATE_FORM_COLLECTION_REQUIRED", + message: "updateFormCollection is required" + }); + } + + if ( + typeof primaryAttribute !== "string" || + primaryAttribute.trim().length === 0 + ) { + return respondError(res, { + status: 400, + code: "PRIMARY_ATTRIBUTE_REQUIRED", + message: "primaryAttribute is required" + }); + } + + try { + const token = await getToken(); + const escapedCaseReference = caseReference.split("'").join("''"); + + const queryUrl = + updateFormCollection + + "?$count=true&$select=_" + + primaryAttribute + + "s_value&$filter=pinswg_name eq '" + + escapedCaseReference + + "'"; + + const { data } = await axios.get( WEBAPI_URL + queryUrl + hashAPIPath(queryUrl), azureHeaders(token.access_token) - ) - .then(({ data }) => { - res.status(200).json(data); - }) - .catch((error) => { - consoleLogger(error); - res.status(400).json(error); + ); + + return respondSuccess(res, data); + } catch (error) { + consoleLogger(error); + return respondError(res, { + status: 400, + code: "APPEAL_ID_FETCH_FAILED", + message: "Failed to fetch appeal id" }); + } } diff --git a/pages/api/endpoint/getappealtypes_api.js b/pages/api/endpoint/getappealtypes_api.js index dec3d896..16edd5f8 100644 --- a/pages/api/endpoint/getappealtypes_api.js +++ b/pages/api/endpoint/getappealtypes_api.js @@ -10,42 +10,45 @@ */ import axios from "axios"; -import CryptoJS from "crypto-js"; import { azureHeaders } from "../../../actions/core/headers"; import { consoleLogger } from "../../../actions/core/logger"; import { getToken } from "../../../actions/core/token"; 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) { - var token = await getToken(); + try { + const token = await getToken(); - var queryUrl = - "stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' " + - (process.env.SHOWSIPS !== "true" - ? "and attributevalue ne 846040002" - : "") + - "&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc"; + const queryUrl = + "stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' " + + (process.env.SHOWSIPS !== "true" + ? "and attributevalue ne 846040002" + : "") + + "&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc"; - // for sips - // "stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc"; + // for sips + // "stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc"; - // "stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' and value ne 'Misc Casework'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc"; - //"stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' and value ne 'Developments of National Significance' and value ne 'LDP' and value ne 'Misc Casework'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc"; + // "stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' and value ne 'Misc Casework'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc"; + //"stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' and value ne 'Developments of National Significance' and value ne 'LDP' and value ne 'Misc Casework'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc"; - return axios - .get( + const { data } = await axios.get( WEBAPI_URL + queryUrl + hashAPIPath(queryUrl), azureHeaders(token.access_token) - ) - .then(({ data }) => { - res.status(200).json(data); - }) - .catch((error) => { - consoleLogger(error); - res.status(400).json(error); + ); + + return respondSuccess(res, data); + } catch (error) { + consoleLogger(error); + return respondError(res, { + status: 400, + code: "APPEAL_TYPES_FETCH_FAILED", + message: "Failed to fetch appeal types" }); + } } diff --git a/pages/api/endpoint/getlinkedcases_api.js b/pages/api/endpoint/getlinkedcases_api.js index b08b0823..d4b9ed84 100644 --- a/pages/api/endpoint/getlinkedcases_api.js +++ b/pages/api/endpoint/getlinkedcases_api.js @@ -17,35 +17,50 @@ */ import axios from "axios"; -import CryptoJS from "crypto-js"; 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 { 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) { - var parentIncidentid = req.query.parentincidentid; - var token = await getToken(); + const parentIncidentid = req.query.parentincidentid; - var queryUrl = - "incidents?$count=true&$filter=_parentcaseid_value eq " + - parentIncidentid + - " and pinswg_appealcasetype ne null and pinswg_publishtoweb eq true &$select=title, incidentid"; + if ( + typeof parentIncidentid !== "string" || + parentIncidentid.trim().length === 0 + ) { + return respondError(res, { + status: 400, + code: "PARENT_INCIDENT_ID_REQUIRED", + message: "parentincidentid is required" + }); + } - return axios - .get( + try { + const token = await getToken(); + + const queryUrl = + "incidents?$count=true&$filter=_parentcaseid_value eq " + + parentIncidentid + + " and pinswg_appealcasetype ne null and pinswg_publishtoweb eq true &$select=title, incidentid"; + + const { data } = await axios.get( WEBAPI_URL + queryUrl + hashAPIPath(queryUrl), azureHeadersPaged(token.access_token) - ) - .then(({ data }) => { - res.status(200).json(data); - }) - .catch((error) => { - consoleLogger(error); - res.status(400).json(error); + ); + + return respondSuccess(res, data); + } catch (error) { + consoleLogger(error); + return respondError(res, { + status: 400, + code: "LINKED_CASES_FETCH_FAILED", + message: "Failed to fetch linked cases" }); + } } diff --git a/pages/api/endpoint/getlpa_api.js b/pages/api/endpoint/getlpa_api.js index 33cb9409..51a75b87 100644 --- a/pages/api/endpoint/getlpa_api.js +++ b/pages/api/endpoint/getlpa_api.js @@ -13,33 +13,35 @@ */ import axios from "axios"; -import CryptoJS from "crypto-js"; import { azureHeaders } from "../../../actions/core/headers"; import { consoleLogger } from "../../../actions/core/logger"; import { getToken } from "../../../actions/core/token"; 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) { - var token = await getToken(); + try { + const token = await getToken(); - var queryUrl = - "accounts?$count=true&$filter=pinswg_isalocalplanningauthorityaccount eq 846040000&$select=name&$orderby=name asc"; + const queryUrl = + "accounts?$count=true&$filter=pinswg_isalocalplanningauthorityaccount eq 846040000&$select=name&$orderby=name asc"; - //console.log(WEBAPI_URL + queryUrl + hashAPIPath(queryUrl)); - return axios - .get( + const { data } = await axios.get( WEBAPI_URL + queryUrl + hashAPIPath(queryUrl), azureHeaders(token.access_token) - ) - .then(({ data }) => { - res.status(200).json(data); - }) - .catch((error) => { - consoleLogger(error); - res.status(400).json(error); + ); + + return respondSuccess(res, data); + } catch (error) { + consoleLogger(error); + return respondError(res, { + status: 400, + code: "LPA_FETCH_FAILED", + message: "Failed to fetch local planning authorities" }); + } } diff --git a/pages/api/endpoint/getprojecttypes_api.js b/pages/api/endpoint/getprojecttypes_api.js index 89c681c9..8600c828 100644 --- a/pages/api/endpoint/getprojecttypes_api.js +++ b/pages/api/endpoint/getprojecttypes_api.js @@ -10,34 +10,35 @@ */ import axios from "axios"; -import CryptoJS from "crypto-js"; import { azureHeaders } from "../../../actions/core/headers"; import { consoleLogger } from "../../../actions/core/logger"; import { getToken } from "../../../actions/core/token"; 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) { - var token = await getToken(); + try { + const token = await getToken(); - var queryUrl = - "pinswg_sipsprojecttypes?$select=pinswg_name,pinswg_sipsprojecttypeid&$orderby=pinswg_name asc&$count=true"; + const queryUrl = + "pinswg_sipsprojecttypes?$select=pinswg_name,pinswg_sipsprojecttypeid&$orderby=pinswg_name asc&$count=true"; - //console.log(queryUrl); - - return axios - .get( + const { data } = await axios.get( WEBAPI_URL + queryUrl + hashAPIPath(queryUrl), azureHeaders(token.access_token) - ) - .then(({ data }) => { - res.status(200).json(data); - }) - .catch((error) => { - consoleLogger(error); - res.status(400).json(error); + ); + + return respondSuccess(res, data); + } catch (error) { + consoleLogger(error); + return respondError(res, { + status: 400, + code: "PROJECT_TYPES_FETCH_FAILED", + message: "Failed to fetch project types" }); + } } diff --git a/tests/phase21/endpoint-handler-contract.test.cjs b/tests/phase21/endpoint-handler-contract.test.cjs index 288bad06..3d73406c 100644 --- a/tests/phase21/endpoint-handler-contract.test.cjs +++ b/tests/phase21/endpoint-handler-contract.test.cjs @@ -2552,6 +2552,186 @@ test("deleteawaitingsubmissions catch path returns AWAITING_SUBMISSION_DELETE_FA ); }); +test("getlpa catch path returns LPA_FETCH_FAILED", async () => { + const mod = loadModule("pages/api/endpoint/getlpa_api.js", { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + hashAPIPath: () => "&hash=expected", + azureHeaders: () => ({}), + axios: { + get: async () => { + throw new Error("relay failed"); + } + }, + consoleLogger: () => {} + }); + + const req = { query: {} }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual(res.state.jsonBody.error.code, "LPA_FETCH_FAILED"); +}); + +test("getappealid returns CASE_REFERENCE_REQUIRED when caseReference missing", async () => { + const mod = loadModule("pages/api/endpoint/getappealid_api.js", { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + hashAPIPath: () => "&hash=expected", + azureHeaders: () => ({}), + axios: { get: async () => ({ data: { value: [] } }) }, + consoleLogger: () => {} + }); + + const req = { + query: { + updateFormCollection: "pinswg_planningappeals78s", + primaryAttribute: "pinswg_planningappeals78id" + } + }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual( + res.state.jsonBody.error.code, + "CASE_REFERENCE_REQUIRED" + ); +}); + +test("getappealid catch path returns APPEAL_ID_FETCH_FAILED", async () => { + const mod = loadModule("pages/api/endpoint/getappealid_api.js", { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + hashAPIPath: () => "&hash=expected", + azureHeaders: () => ({}), + axios: { + get: async () => { + throw new Error("relay failed"); + } + }, + consoleLogger: () => {} + }); + + const req = { + query: { + caseReference: "CAS-1", + updateFormCollection: "pinswg_planningappeals78s", + primaryAttribute: "pinswg_planningappeals78id" + } + }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual(res.state.jsonBody.error.code, "APPEAL_ID_FETCH_FAILED"); +}); + +test("getprojecttypes catch path returns PROJECT_TYPES_FETCH_FAILED", async () => { + const mod = loadModule("pages/api/endpoint/getprojecttypes_api.js", { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + hashAPIPath: () => "&hash=expected", + azureHeaders: () => ({}), + axios: { + get: async () => { + throw new Error("relay failed"); + } + }, + consoleLogger: () => {} + }); + + const req = { query: {} }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual( + res.state.jsonBody.error.code, + "PROJECT_TYPES_FETCH_FAILED" + ); +}); + +test("getappealtypes catch path returns APPEAL_TYPES_FETCH_FAILED", async () => { + const mod = loadModule("pages/api/endpoint/getappealtypes_api.js", { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + hashAPIPath: () => "&hash=expected", + azureHeaders: () => ({}), + axios: { + get: async () => { + throw new Error("relay failed"); + } + }, + consoleLogger: () => {}, + process: { env: {} } + }); + + const req = { query: {} }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual( + res.state.jsonBody.error.code, + "APPEAL_TYPES_FETCH_FAILED" + ); +}); + +test("getlinkedcases returns PARENT_INCIDENT_ID_REQUIRED when parentincidentid missing", async () => { + const mod = loadModule("pages/api/endpoint/getlinkedcases_api.js", { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + hashAPIPath: () => "&hash=expected", + azureHeadersPaged: () => ({}), + axios: { get: async () => ({ data: { value: [] } }) }, + consoleLogger: () => {} + }); + + const req = { query: {} }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual( + res.state.jsonBody.error.code, + "PARENT_INCIDENT_ID_REQUIRED" + ); +}); + +test("getlinkedcases catch path returns LINKED_CASES_FETCH_FAILED", async () => { + const mod = loadModule("pages/api/endpoint/getlinkedcases_api.js", { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + hashAPIPath: () => "&hash=expected", + azureHeadersPaged: () => ({}), + axios: { + get: async () => { + throw new Error("relay failed"); + } + }, + consoleLogger: () => {} + }); + + const req = { query: { parentincidentid: "i1" } }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual( + res.state.jsonBody.error.code, + "LINKED_CASES_FETCH_FAILED" + ); +}); + const run = async () => { let passed = 0; for (const currentTest of tests) {