Files
pedwfrontend/pages/api/endpoint/createcrmtask_api.js
T

258 lines
8.3 KiB
JavaScript

import axios from "axios";
import { isNonEmptyString, sanitizeString } from "../../../actions/core/guards";
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/";
const teamMap = {
plq: "ec48450c-7e26-ec11-a97f-00224800e98c", //PET
ipq: "7fb9e598-7d26-ec11-a97f-00224800e98c", // Infrastructure
pcpq: "8ffabad9-7c26-ec11-a97f-00224800e98c", // Casework
pi: "5554882f-4606-ec11-a97f-00224800d374", // Digital Support Team
appadvice: "cc3d987e-7c26-ec11-a97f-00224800e98c",
repadvice: "cc3d987e-7c26-ec11-a97f-00224800e98c",
ceq: "4fddd7e8-7d26-ec11-a97f-00224800e98c", // Inspector Scheduling
other: "8ffabad9-7c26-ec11-a97f-00224800e98c", // Casework
postdec: "1357e457-7e26-ec11-a97f-00224800e98c", // SLT Team
comp: "1357e457-7e26-ec11-a97f-00224800e98c" // SLT Team
};
const allowedSubjects = {
plq: [
"Questions about Planning legislation or policy",
"Planning legislation query",
"Ymholiad deddfwriaeth gynllunio"
],
ipq: [
"Questions or comments about applications for major infrastructure projects",
"Infrastructure procedure query",
"Ymholiad gweithdrefn seilwaith"
],
pcpq: [
"Questions or comments about planning and environmental appeals",
"Planning casework procedure query",
"Ymholiad gweithdrefn gwaith achos cynllunio"
],
pi: ["Query about using the Casework Portal", "Portal Issues", "Materion Porth"],
appadvice: [
"Advice How to submit an appeal",
"Appeal submission advice",
"Cyngor cyflwyno apêl"
],
repadvice: [
"Advice How to comment on an appeal or application",
"Representation submission advice",
"Cyngor cyflwyno sylwadau"
],
ceq: [
"Queries about forthcoming Hearing or Inquiry event",
"Casework Events Query",
"Ymholiad Digwyddiadau Gwaith Achos"
],
other: ["Other enquiry for PEDW", "Any Other Enquiries", "Unrhyw Ymholiadau Eraill"],
postdec: [
"Issues or questions about a case after the decision is issued",
"Post Decision",
"Ar ôl Penderfyniad"
],
comp: [
"General Complaints of Compliments",
"Complaints/Complements",
"Cwynion/Canmoliaethau"
]
};
const allowedFields = new Set([
"contactEmail",
"contactSubject",
"contactbody",
"typeOfContact"
]);
const emailRegex =
/^(?!.*(?:.+\.)?(?:burpcollaborator\.net|interactsh\.com|mailinator\.com|10minutemail\.com|yopmail\.com|trashmail\.com)$)(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}|(?:\[(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:.+)])$/;
const hasTrustedOrigin = (req) => {
const requestOrigin = req?.headers?.origin;
if (typeof requestOrigin !== "string" || requestOrigin === "null") {
return false;
}
try {
const requestUrl = new URL(requestOrigin);
if (requestOrigin !== requestUrl.origin) {
return false;
}
const trustedOrigins = [process.env.NEXTAUTH_URL, process.env.CY_API_ROOT]
.filter(
(configuredUrl) =>
typeof configuredUrl === "string" && configuredUrl.length > 0
)
.map((configuredUrl) => new URL(configuredUrl).origin);
return trustedOrigins.includes(requestUrl.origin);
} catch (_error) {
return false;
}
};
const validationError = (res, code, message) =>
respondError(res, { status: 400, code, message });
export default async function ApiProxy(req, res) {
if (req.method !== "POST") {
res.setHeader("Allow", "POST");
return respondError(res, {
status: 405,
code: "METHOD_NOT_ALLOWED",
message: "Method not allowed"
});
}
const contentType = req.headers?.["content-type"];
if (
typeof contentType !== "string" ||
contentType.split(";", 1)[0].trim().toLowerCase() !== "application/json"
) {
return respondError(res, {
status: 415,
code: "UNSUPPORTED_MEDIA_TYPE",
message: "Content-Type must be application/json"
});
}
if (!hasTrustedOrigin(req)) {
return respondError(res, {
status: 403,
code: "FORBIDDEN",
message: "Request not permitted"
});
}
const createTaskBody = req.body;
if (
createTaskBody === null ||
typeof createTaskBody !== "object" ||
Array.isArray(createTaskBody)
) {
return validationError(
res,
"INVALID_REQUEST_BODY",
"Request body must be a JSON object"
);
}
if (Object.keys(createTaskBody).some((field) => !allowedFields.has(field))) {
return validationError(
res,
"UNSUPPORTED_REQUEST_FIELD",
"Request contains an unsupported field"
);
}
const contactEmail = sanitizeString(createTaskBody?.contactEmail);
const contactSubject = sanitizeString(createTaskBody?.contactSubject);
const contactBody = sanitizeString(createTaskBody?.contactbody);
if (
typeof createTaskBody.contactEmail !== "string" ||
!isNonEmptyString(contactEmail) ||
contactEmail.length > 200 ||
!emailRegex.test(contactEmail)
) {
return validationError(
res,
"INVALID_CONTACT_EMAIL",
"contactEmail must be a valid email address of 200 characters or fewer"
);
}
if (
typeof createTaskBody.typeOfContact !== "string" ||
!Object.prototype.hasOwnProperty.call(teamMap, createTaskBody.typeOfContact)
) {
return validationError(
res,
"INVALID_CONTACT_TYPE",
"typeOfContact is not supported"
);
}
if (
typeof createTaskBody.contactbody !== "string" ||
!isNonEmptyString(contactBody) ||
contactBody.length > 800
) {
return validationError(
res,
"INVALID_CONTACT_BODY",
"contactbody must contain between 1 and 800 characters"
);
}
const contactValue = createTaskBody.typeOfContact;
if (
typeof createTaskBody.contactSubject !== "string" ||
!allowedSubjects[contactValue].includes(contactSubject)
) {
return validationError(
res,
"INVALID_CONTACT_SUBJECT",
"contactSubject does not match typeOfContact"
);
}
const queryUrl = "tasks";
const token = await getToken();
let teamId = teamMap[contactValue];
const payload = {
"subject": `Contact Us Enquiry - ${contactSubject}`,
"description": `From: ${contactEmail}\n\n${contactBody}`,
"scheduledstart": new Date().toISOString(),
"scheduledend": new Date(
new Date().getTime() + 60 * 60000 * 24
).toISOString(), // 30 mins
...(teamId && { "ownerid@odata.bind": `/teams(${teamId})` })
};
//console.log("/////Create Task:\n", payload, "\n//////////////");
const config = {
method: "post",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json",
"Prefer": 'odata.include-annotations="*",return=representation',
"Authorization": "Bearer " + token.access_token,
"Content-Type": "application/json"
},
data: JSON.stringify(payload)
};
//console.log("/////Create Task config:\n", config, "\n//////////////");
try {
const { data } = await axios(config);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "CRM_TASK_CREATE_FAILED",
message: "Failed to create CRM task"
});
}
}