Adding esslGetUserDetails
This commit is contained in:
parent
e517367967
commit
47bd8610d2
18
functions/package-lock.json
generated
18
functions/package-lock.json
generated
@ -25,13 +25,15 @@
|
|||||||
"node-fetch": "^2.7.0",
|
"node-fetch": "^2.7.0",
|
||||||
"pdfjs-dist": "^5.0.375",
|
"pdfjs-dist": "^5.0.375",
|
||||||
"pdfmake": "^0.2.20",
|
"pdfmake": "^0.2.20",
|
||||||
"twilio": "^5.4.0"
|
"twilio": "^5.4.0",
|
||||||
|
"xmldom": "^0.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/long": "^5.0.0",
|
"@types/long": "^5.0.0",
|
||||||
"@types/mime-types": "^2.1.4",
|
"@types/mime-types": "^2.1.4",
|
||||||
"@types/node": "^22.13.14",
|
"@types/node": "^22.13.14",
|
||||||
"@types/pdfmake": "^0.2.11",
|
"@types/pdfmake": "^0.2.11",
|
||||||
|
"@types/xmldom": "^0.1.34",
|
||||||
"firebase-functions-test": "^3.1.0",
|
"firebase-functions-test": "^3.1.0",
|
||||||
"typescript": "^5.8.2"
|
"typescript": "^5.8.2"
|
||||||
},
|
},
|
||||||
@ -2946,6 +2948,12 @@
|
|||||||
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
|
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/xmldom": {
|
||||||
|
"version": "0.1.34",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/xmldom/-/xmldom-0.1.34.tgz",
|
||||||
|
"integrity": "sha512-7eZFfxI9XHYjJJuugddV6N5YNeXgQE1lArWOcd1eCOKWb/FGs5SIjacSYuEJuwhsGS3gy4RuZ5EUIcqYscuPDA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/yargs": {
|
"node_modules/@types/yargs": {
|
||||||
"version": "17.0.33",
|
"version": "17.0.33",
|
||||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
|
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
|
||||||
@ -8324,6 +8332,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
|
||||||
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="
|
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/xmldom": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/y18n": {
|
"node_modules/y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
|||||||
@ -32,13 +32,15 @@
|
|||||||
"node-fetch": "^2.7.0",
|
"node-fetch": "^2.7.0",
|
||||||
"pdfjs-dist": "^5.0.375",
|
"pdfjs-dist": "^5.0.375",
|
||||||
"pdfmake": "^0.2.20",
|
"pdfmake": "^0.2.20",
|
||||||
"twilio": "^5.4.0"
|
"twilio": "^5.4.0",
|
||||||
|
"xmldom": "^0.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/long": "^5.0.0",
|
"@types/long": "^5.0.0",
|
||||||
"@types/mime-types": "^2.1.4",
|
"@types/mime-types": "^2.1.4",
|
||||||
"@types/node": "^22.13.14",
|
"@types/node": "^22.13.14",
|
||||||
"@types/pdfmake": "^0.2.11",
|
"@types/pdfmake": "^0.2.11",
|
||||||
|
"@types/xmldom": "^0.1.34",
|
||||||
"firebase-functions-test": "^3.1.0",
|
"firebase-functions-test": "^3.1.0",
|
||||||
"typescript": "^5.8.2"
|
"typescript": "^5.8.2"
|
||||||
},
|
},
|
||||||
|
|||||||
7
functions/src/dooraccess/doorAccessUser.ts
Normal file
7
functions/src/dooraccess/doorAccessUser.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export type DoorAccessUser = {
|
||||||
|
name: string;
|
||||||
|
location: string;
|
||||||
|
role: string;
|
||||||
|
expireFrom: Date | null;
|
||||||
|
expireTo: Date | null;
|
||||||
|
};
|
||||||
162
functions/src/dooraccess/essl.ts
Normal file
162
functions/src/dooraccess/essl.ts
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import { onRequest } from "firebase-functions/https";
|
||||||
|
import { DoorAccessUser } from "./doorAccessUser";
|
||||||
|
import { Request } from "firebase-functions/v2/https";
|
||||||
|
import { Response } from "express";
|
||||||
|
import { getCorsHandler } from "../shared/middleware";
|
||||||
|
import { getLogger } from "../shared/config";
|
||||||
|
import { DOMParser } from 'xmldom';
|
||||||
|
|
||||||
|
const logger = getLogger();
|
||||||
|
const corsHandler = getCorsHandler();
|
||||||
|
|
||||||
|
const escapeXml = (str: string) => {
|
||||||
|
return str
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''');
|
||||||
|
};
|
||||||
|
|
||||||
|
function createGetEmployeeDetailsRequest(username: string, password: string, employeeCode: string) {
|
||||||
|
const soapRequest = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
|
||||||
|
<soap12:Body>
|
||||||
|
<GetEmployeeDetails xmlns="http://tempuri.org/">
|
||||||
|
<UserName>${escapeXml(username)}</UserName>
|
||||||
|
<Password>${escapeXml(password)}</Password>
|
||||||
|
<EmployeeCode>${escapeXml(employeeCode)}</EmployeeCode>
|
||||||
|
</GetEmployeeDetails>
|
||||||
|
</soap12:Body>
|
||||||
|
</soap12:Envelope>`;
|
||||||
|
|
||||||
|
return soapRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseGetEmployeeDetailsResponse(soapResponse: string): DoorAccessUser {
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const xmlDoc = parser.parseFromString(soapResponse, "text/xml");
|
||||||
|
if (xmlDoc.documentElement.tagName !== 'soap:Envelope') {
|
||||||
|
throw new Error("Invalid SOAP response");
|
||||||
|
}
|
||||||
|
if (null == xmlDoc.documentElement.firstChild) {
|
||||||
|
throw new Error("Invalid SOAP response");
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentElement = xmlDoc.documentElement.firstChild as HTMLElement;
|
||||||
|
if (currentElement.tagName !== 'soap:Body') {
|
||||||
|
throw new Error("Invalid SOAP response");
|
||||||
|
}
|
||||||
|
|
||||||
|
currentElement = currentElement.firstChild as HTMLElement;
|
||||||
|
if (currentElement.tagName !== 'GetEmployeeDetailsResponse') {
|
||||||
|
throw new Error("Invalid SOAP response");
|
||||||
|
}
|
||||||
|
|
||||||
|
currentElement = currentElement.firstChild as HTMLElement;
|
||||||
|
if (currentElement.tagName !== 'GetEmployeeDetailsResult') {
|
||||||
|
throw new Error("Invalid SOAP response");
|
||||||
|
}
|
||||||
|
|
||||||
|
const resultText = currentElement.textContent;
|
||||||
|
if (!resultText) {
|
||||||
|
throw new Error("GetEmployeeDetailsResult is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
const userDetails: DoorAccessUser =
|
||||||
|
{
|
||||||
|
name: '',
|
||||||
|
location: '',
|
||||||
|
role: '',
|
||||||
|
expireFrom: null,
|
||||||
|
expireTo: null
|
||||||
|
};
|
||||||
|
const pairs = resultText.split(',');
|
||||||
|
pairs.forEach(pair => {
|
||||||
|
const [key, value] = pair.split('=');
|
||||||
|
if (key && value !== undefined) {
|
||||||
|
const cleanKey = key.trim();
|
||||||
|
const cleanValue = value.trim();
|
||||||
|
switch (cleanKey) {
|
||||||
|
case 'EmployeeName':
|
||||||
|
userDetails.name = cleanValue;
|
||||||
|
break;
|
||||||
|
case 'EmployeeLocation':
|
||||||
|
userDetails.location = cleanValue;
|
||||||
|
break;
|
||||||
|
case 'EmployeeRole':
|
||||||
|
userDetails.role = cleanValue;
|
||||||
|
break;
|
||||||
|
case 'EmployeeExpiryFrom':
|
||||||
|
userDetails.expireFrom = new Date(cleanValue);
|
||||||
|
break;
|
||||||
|
case 'EmployeeExpiryTo':
|
||||||
|
userDetails.expireTo = new Date(cleanValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return userDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendSoapRequest(soapRequest: string, endpoint: string) {
|
||||||
|
try {
|
||||||
|
const headers: any = {
|
||||||
|
'Content-Type': 'application/soap+xml; charset=utf-8',
|
||||||
|
'Content-Length': soapRequest.length.toString()
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await fetch(endpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: headers,
|
||||||
|
body: soapRequest
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await response.text();
|
||||||
|
} catch (error: any) {
|
||||||
|
throw new Error(`SOAP request failed: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getUserDetails(username: string,
|
||||||
|
password: string,
|
||||||
|
employeeCode: string, endpoint: string) {
|
||||||
|
const soapRequest = createGetEmployeeDetailsRequest(username, password, employeeCode);
|
||||||
|
const soapResponse = await sendSoapRequest(soapRequest, endpoint);
|
||||||
|
const parsedResponse = parseGetEmployeeDetailsResponse(soapResponse);
|
||||||
|
return parsedResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const esslGetUserDetails = onRequest({
|
||||||
|
region: '#{SERVICES_RGN}#'
|
||||||
|
}, async (request: Request, response: Response) => {
|
||||||
|
return corsHandler(request, response, async () => {
|
||||||
|
try {
|
||||||
|
const username = request.body.username;
|
||||||
|
const password = request.body.password;
|
||||||
|
const employeeCode = request.body.employeeCode;
|
||||||
|
const endpoint = request.body.endpoint;
|
||||||
|
if ((!username) || (!password)) {
|
||||||
|
throw new Error('Missing username or password');
|
||||||
|
}
|
||||||
|
if (!employeeCode) {
|
||||||
|
throw new Error('Missing employee code');
|
||||||
|
}
|
||||||
|
if (!endpoint) {
|
||||||
|
throw new Error('Missing endpoint');
|
||||||
|
}
|
||||||
|
const userDetails = await getUserDetails(username, password, employeeCode, endpoint);
|
||||||
|
response.send(userDetails);
|
||||||
|
} catch (error: any) {
|
||||||
|
logger.error(error);
|
||||||
|
response.status(500).send({ error: error.message });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
1
functions/src/dooraccess/index.ts
Normal file
1
functions/src/dooraccess/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { esslGetUserDetails } from './essl';
|
||||||
@ -63,7 +63,7 @@ async function sendSimpleEmail(data: EmailRequest, recipients: string[]) {
|
|||||||
|
|
||||||
async function sendEmailWithAttachments(data: EmailRequest, recipients: string[]) {
|
async function sendEmailWithAttachments(data: EmailRequest, recipients: string[]) {
|
||||||
const ses = new SESClient({
|
const ses = new SESClient({
|
||||||
region: 'ap-south-1',
|
region: '#{SERVICES_RGN}#',
|
||||||
credentials: {
|
credentials: {
|
||||||
accessKeyId: process.env.AWS_ACCESS_KEY_ID || '',
|
accessKeyId: process.env.AWS_ACCESS_KEY_ID || '',
|
||||||
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || ''
|
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || ''
|
||||||
|
|||||||
@ -17,3 +17,4 @@ export { processNotificationOnCreate } from './notifications';
|
|||||||
export * from './payments';
|
export * from './payments';
|
||||||
export { getPlaceDetails, getPlacesAutocomplete } from './places';
|
export { getPlaceDetails, getPlacesAutocomplete } from './places';
|
||||||
export { registerClient } from './users';
|
export { registerClient } from './users';
|
||||||
|
export { esslGetUserDetails } from './dooraccess';
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user