diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..01706de Binary files /dev/null and b/.DS_Store differ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3bc1499 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "workbench.colorCustomizations": { + "activityBar.background": "#521733", + "titleBar.activeBackground": "#732147", + "titleBar.activeForeground": "#FEFCFD" + } +} \ No newline at end of file diff --git a/Files-Cloud-Storage/lib/aws/upload.js b/Files-Cloud-Storage/lib/aws/upload.js index 2cac104..35833c0 100644 --- a/Files-Cloud-Storage/lib/aws/upload.js +++ b/Files-Cloud-Storage/lib/aws/upload.js @@ -201,9 +201,10 @@ module.exports = class AwsS3FileHelper { * @param {string} destFilePath - Stored file path - i.e location from bucket - ex - users/profile.png * @param {string} bucketName - aws s3 storage bucket in which action is peformed over file * @param {string} bucketRegion - aws region where bucket will be located, ex - ap-south-1 + * @param {Number} expires - link expiration in seconds * @returns {Promise} Get downloadable url link */ - static async getDownloadableUrl(destFilePath, bucketName, bucketRegion) { + static async getDownloadableUrl(destFilePath, bucketName, bucketRegion, expires = '') { if (!destFilePath) { const error = new Error('destFilePath is not passed in parameter') error.code = 500 @@ -227,13 +228,35 @@ module.exports = class AwsS3FileHelper { error.code = 500 throw error } - try { - const downloadableUrl = `https://${bucketName}.s3.${bucketRegion}.amazonaws.com/${destFilePath}` - return downloadableUrl + /* Instantiate S3 class with credentials and region */ + const s3 = new S3({ + region: bucketRegion, + }) + + // Determine expiry + const expiry = expires ? parseInt(expires) : 1800;// Default expiry: 5 min (in seconds) + + /* Get the signed URL with the specified expiry */ + const params = { + Bucket: bucketName, + Key: destFilePath, + Expires: expiry, + } + + const signedUrl = await s3.getSignedUrlPromise('getObject', params) + + return signedUrl } catch (error) { throw error } + // keeping this here to enable in 3.0 + // try { + // const downloadableUrl = `https://${bucketName}.s3.${bucketRegion}.amazonaws.com/${destFilePath}` + // return downloadableUrl + // } catch (error) { + // throw error + // } } /** diff --git a/Files-Cloud-Storage/lib/gcp/upload.js b/Files-Cloud-Storage/lib/gcp/upload.js index c6158bc..12bcd56 100644 --- a/Files-Cloud-Storage/lib/gcp/upload.js +++ b/Files-Cloud-Storage/lib/gcp/upload.js @@ -246,6 +246,81 @@ module.exports = class GcpFileHelper { } } + /** + * Get downloadable url of uploaded object + * @method + * @name getSignedDownloadableUrl + * @param {destFilePath} destFilePath - Stored file path - location from bucket - ex - users/profile.png + * @param {string} bucketName - google cloud storage bucket in which action is peformed over file + * @param {string} gcpProjectId - google cloud storage project id + * @param {string} gcpJsonFilePath - google cloud storage json configuration file absolute path for connectivity + * @param {string} expiry - downloadable url expiration time - In ms from current time - type number | string | Date + * @returns {Promise} - Downloadable url + * @see gcpProjectId - Get from gcp console + * @see gcpJsonFilePath - - Download file from manage storage api key section + */ + static async getSignedDownloadableUrl({ destFilePath, bucketName, gcpProjectId, gcpJsonFilePath, expiry }) { + // Ensure all parameters are provided + if (!destFilePath) { + const error = new Error('destFilePath is not passed in parameter') + error.code = 500 + throw error + } + + if (typeof destFilePath !== 'string') { + const error = new Error('expected destFilePath as string') + error.code = 500 + throw error + } + + if (!bucketName) { + const error = new Error('bucketName is not passed in parameter') + error.code = 500 + throw error + } + + if (!gcpProjectId) { + const error = new Error('gcpProjectId is not passed in parameter') + error.code = 500 + throw error + } + + if (!gcpJsonFilePath) { + const error = new Error('gcpJsonFilePath is not passed in parameter') + error.code = 500 + throw error + } + + if (typeof gcpJsonFilePath !== 'string') { + const error = new Error('expected gcpJsonFilePath as string') + error.code = 500 + throw error + } + // Set default expiry time to 15 minutes (if expiry is not provided) + const defaultExpiry = 30 * 60 * 1000 // 15 minutes in milliseconds + const expires = expiry || (Date.now() + defaultExpiry) + + // Instantiate the cloud storage client + const storage = new Storage({ + projectId: gcpProjectId, + keyFilename: gcpJsonFilePath + }) + + try { + // Generate a signed URL for downloading the file + const options = { + version: 'v4', + action: 'read', + expires: expires, + } + const [signedUrl] = await storage.bucket(bucketName).file(destFilePath).getSignedUrl(options) + + return signedUrl; // Return the signed URL for downloading the file + } catch (error) { + throw error + } + } + /** * Delete a folder and its contents from a GCP bucket. * @param {string} bucketName - Google Cloud Storage bucket name. diff --git a/Files-Cloud-Storage/lib/oci/upload.js b/Files-Cloud-Storage/lib/oci/upload.js index f6a5124..c328bc0 100644 --- a/Files-Cloud-Storage/lib/oci/upload.js +++ b/Files-Cloud-Storage/lib/oci/upload.js @@ -238,10 +238,12 @@ module.exports = class OCIFileHelper { * @param {string} destFilePath - Stored file path - i.e location from bucket - ex - users/profile.png * @param {string} bucketName - oci storage bucket in which action is peformed over file * @param {string} bucketRegion - oci region where bucket will be located, ex - ap-south-1 + * @param {string} accessKeyId - oci access key id + * @param {string} secretAccessKey - oci secret access key * @returns {Promise} Get downloadable url link */ - static async getDownloadableUrl({ destFilePath, bucketName, endpoint }) { + static async getDownloadableUrl({ destFilePath, bucketName, endpoint, expires = '', accessKeyId = '', secretAccessKey = '', bucketRegion = '' }) { if (!destFilePath) { const error = new Error('destFilePath is not passed in parameter') error.code = 500 @@ -265,13 +267,47 @@ module.exports = class OCIFileHelper { error.code = 500 throw error } - + try { - let downloadableUrl = `${endpoint}/${bucketName}/${destFilePath}` + /* Instantiate S3 class with credentials and region */ + + const s3Config = { + signatureVersion: 'v4', + s3ForcePathStyle: true, + endpoint: endpoint, + } + + // Add accessKeyId, secretAccessKey, and region if provided + if (accessKeyId && secretAccessKey && bucketRegion) { + s3Config.accessKeyId = accessKeyId; + s3Config.secretAccessKey = secretAccessKey; + s3Config.region = bucketRegion; + } + + const s3 = new S3(s3Config); + + const expiry = expires ? parseInt(expires) : 1800;// Default expiry: 5min (in seconds) + /* Get the signed URL with the specified expiry */ + const params = { + Bucket: bucketName, + Key: destFilePath, + Expires: expiry + } + + const downloadableUrl = await s3.getSignedUrlPromise('getObject', params) + return { downloadableUrl, filePath: destFilePath } } catch (error) { - throw error + throw error; } + + // Keeping it here. in 3.0 we have to enable this logic and move above logic to new function + // try { + // let downloadableUrl = `${endpoint}/${bucketName}/${destFilePath}` + // return { downloadableUrl, filePath: destFilePath } + // } catch (error) { + // throw error + // } } /** * Remove a folder and its contents from an OCI bucket diff --git a/Files-Cloud-Storage/package.json b/Files-Cloud-Storage/package.json index 77dfa73..682bf2a 100644 --- a/Files-Cloud-Storage/package.json +++ b/Files-Cloud-Storage/package.json @@ -1,6 +1,6 @@ { "name": "elevate-cloud-storage", - "version": "2.1.0", + "version": "2.6.4", "description": "This is npm package which exports the functions to upload file in GCP, AWS S3 and AZURE", "main": "index.js", "scripts": { diff --git a/elevate-entity-management/constants/routes.js b/elevate-entity-management/constants/routes.js new file mode 100644 index 0000000..3c59e22 --- /dev/null +++ b/elevate-entity-management/constants/routes.js @@ -0,0 +1,364 @@ +module.exports = { + routes: [ + { + sourceRoute: '/entity-management/v1/entityTypes/bulkCreate', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entityTypes/bulkCreate', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entityTypes/bulkUpdate', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entityTypes/bulkUpdate', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entityTypes/find', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entityTypes/find', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entityTypes/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entityTypes/list', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entityTypes/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entityTypes/create', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entityTypes/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entityTypes/update', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entityTypes/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entityTypes/update/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/bulkCreate', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/bulkCreate', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/entityListBasedOnEntityType', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/entityListBasedOnEntityType', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/mappingUpload', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/mappingUpload', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/bulkUpdate', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/bulkUpdate', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/add', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/add', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/update', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/update/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/userRoleExtension/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/userRoleExtension/create', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/userRoleExtension/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/userRoleExtension/update/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/userRoleExtension/find', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/userRoleExtension/find', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/userRoleExtension/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/userRoleExtension/delete/:id', + type: 'DELETE' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/targetedRoles/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/targetedRoles/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/list', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/list/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/list/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/find', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/find', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/details', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/details', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/details/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/details/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/listByEntityType', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/listByEntityType', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/listByEntityType/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/listByEntityType/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/subEntityList', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/subEntityList', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/subEntityList/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/subEntityList/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/listByIds', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/listByIds', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/subEntityListBasedOnRoleAndLocation', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/subEntityListBasedOnRoleAndLocation', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/subEntityListBasedOnRoleAndLocation/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/subEntityListBasedOnRoleAndLocation/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/listByLocationIds', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/listByLocationIds', + type: 'POST' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/relatedEntities', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/relatedEntities', + type: 'GET' + }, + }, + { + sourceRoute: '/entity-management/v1/entities/relatedEntities/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/entity-management/v1/entities/relatedEntities/:id', + type: 'GET' + }, + }, + + + ], +} + +/* const fs = require('fs') +const modifiedArray = [].map((item) => ({ + ...item, + targetRoute: { + path: item.sourceRoute, + type: item.type, + }, +})) +const modifiedArrayJSON = JSON.stringify(modifiedArray, null, 2) +const filePath = 'modifiedArray.json' +fs.writeFile(filePath, modifiedArrayJSON, 'utf8', (err) => { + if (err) { + console.error('Error writing to file:', err) + } else { + console.log('Modified array has been written to', filePath) + } +}) */ diff --git a/elevate-entity-management/controllers/entity.js b/elevate-entity-management/controllers/entity.js new file mode 100644 index 0000000..00ca2ee --- /dev/null +++ b/elevate-entity-management/controllers/entity.js @@ -0,0 +1,8 @@ +const routeConfigs = require('../constants/routes') +const requesters = require('../utils/requester') +const requestParser = require('../utils/requestParser') + +const entityController = { +} + +module.exports = entityController diff --git a/elevate-entity-management/controllers/orchestrationController.js b/elevate-entity-management/controllers/orchestrationController.js new file mode 100644 index 0000000..02bd4b4 --- /dev/null +++ b/elevate-entity-management/controllers/orchestrationController.js @@ -0,0 +1,13 @@ +const routesConfig = require('../constants/routes') +const entityController = require('../controllers/entity') +const orchestrationHandler = async (req, res, responses) => { + console.log(req.targetPackages, req.inSequence, req.orchestrated, req.sourceRoute, responses) + console.log(req.body) + const selectedRouteConfig = routesConfig.routes.find((obj) => obj.sourceRoute === req.sourceRoute) + return await entityController[selectedRouteConfig.targetRoute.functionName](req, res, responses) +} + +const orchestrationController = { + orchestrationHandler, +} +module.exports = orchestrationController diff --git a/elevate-entity-management/index.js b/elevate-entity-management/index.js new file mode 100644 index 0000000..442da49 --- /dev/null +++ b/elevate-entity-management/index.js @@ -0,0 +1,37 @@ +const express = require('express') +const router = express.Router() +const routes = require('./constants/routes') +const packageRouter = require('./router') + +const getDependencies = () => { + return ['kafka', 'kafka-connect', 'redis'] +} + +const getPackageMeta = () => { + return { + basePackageName: 'entity_management', + packageName: 'elevate-entity-management', + } +} + +const createPackage = (options) => { + return { + router: () => { + console.log('router') + }, + endpoints: [], + dependencies: [], + } +} + +router.get('/', (req, res) => { + res.send('Hello, world! From entity-management') +}) + +module.exports = { + dependencies: getDependencies(), + routes, + createPackage, + packageMeta: getPackageMeta(), + packageRouter, +} diff --git a/elevate-entity-management/package-lock.json b/elevate-entity-management/package-lock.json new file mode 100644 index 0000000..e9d2be1 --- /dev/null +++ b/elevate-entity-management/package-lock.json @@ -0,0 +1,818 @@ +{ + "name": "elevate-entity-management", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "elevate-entity-management", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "axios": "^1.4.0", + "express": "^4.18.2", + "lodash": "^4.17.21", + "node-fetch": "^2.7.0", + "path-to-regexp": "^6.2.1" + }, + "devDependencies": {} + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } +} diff --git a/elevate-entity-management/package.json b/elevate-entity-management/package.json new file mode 100644 index 0000000..01c414e --- /dev/null +++ b/elevate-entity-management/package.json @@ -0,0 +1,19 @@ +{ + "name": "elevate-entity-management", + "version": "1.0.7", + "description": "Npm package for Elevate-Entity-Management service integration with Interface service", + "main": "index.js", + "dependencies": { + "axios": "^1.4.0", + "express": "^4.18.2", + "lodash": "^4.17.21", + "node-fetch": "^2.7.0", + "path-to-regexp": "^6.2.1" + }, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Priyanka Pradeep", + "license": "ISC" +} diff --git a/elevate-entity-management/router/index.js b/elevate-entity-management/router/index.js new file mode 100644 index 0000000..a8b43a8 --- /dev/null +++ b/elevate-entity-management/router/index.js @@ -0,0 +1,10 @@ +const { passThroughRequester } = require('../utils/requester') +const { orchestrationHandler } = require('../controllers/orchestrationController') +const packageRouter = async (req, res, responses) => { + const response = req.orchestrated + ? await orchestrationHandler(req, res, responses) + : await passThroughRequester(req, res) + return response +} + +module.exports = packageRouter diff --git a/elevate-entity-management/utils/pathParamSetter.js b/elevate-entity-management/utils/pathParamSetter.js new file mode 100644 index 0000000..130b1fe --- /dev/null +++ b/elevate-entity-management/utils/pathParamSetter.js @@ -0,0 +1,6 @@ +exports.pathParamSetter = (targetPath, params) => { + return targetPath.replace(/:\w+/g, (match) => { + const fieldName = match.substring(1) + return params[fieldName] || match + }) +} diff --git a/elevate-entity-management/utils/patternMatcher.js b/elevate-entity-management/utils/patternMatcher.js new file mode 100644 index 0000000..f35cd53 --- /dev/null +++ b/elevate-entity-management/utils/patternMatcher.js @@ -0,0 +1,16 @@ +exports.matchPathsAndExtractParams = (pattern, url) => { + const paramNames = [] + const regexPattern = new RegExp( + pattern.replace(/:(\w+)/g, (_, paramName) => { + paramNames.push(paramName) + return '([a-zA-Z0-9]+)' + }) + ) + const matchResult = url.match(regexPattern) + if (!matchResult) return false + const params = {} + for (let i = 0; i < paramNames.length; i++) { + params[paramNames[i]] = matchResult[i + 1] + } + return params +} \ No newline at end of file diff --git a/elevate-entity-management/utils/requestParser.js b/elevate-entity-management/utils/requestParser.js new file mode 100644 index 0000000..ecd12e5 --- /dev/null +++ b/elevate-entity-management/utils/requestParser.js @@ -0,0 +1,6 @@ +const _ = require('lodash') + +// exports.transformUpdateUserBody = (requestBody) => { +// const allowedKeys = ['name', 'email', 'image', 'location', 'about', 'preferred_language'] +// return _.pick(requestBody, allowedKeys) +// } diff --git a/elevate-entity-management/utils/requester.js b/elevate-entity-management/utils/requester.js new file mode 100644 index 0000000..aec6ac1 --- /dev/null +++ b/elevate-entity-management/utils/requester.js @@ -0,0 +1,121 @@ +const http = require('http') +const https = require('https') +const { matchPathsAndExtractParams } = require('../utils/patternMatcher') +const routesConfig = require('../constants/routes') +const { pathParamSetter } = require('../utils/pathParamSetter') +const axios = require('axios') +const fetch = require('node-fetch') + +const handleInterfaceError = (res, err) => { + console.log('Error: ', err) + res.writeHead(500, { 'Content-Type': 'text/plain' }) + res.end('Interface Server Error') +} + +const passThroughRequester = async (req, res) => { + try { + const sourceBaseUrl = req.protocol + '://' + req.headers.host + '/' + const sourceUrl = new URL(req.originalUrl, sourceBaseUrl) + const route = routesConfig.routes.find((route) => route.sourceRoute === req.sourceRoute) + const params = matchPathsAndExtractParams(route.sourceRoute, req.originalUrl) + console.log(params,'params') + const targetRoute = pathParamSetter(route.targetRoute.path, params) + console.log(route.targetRoute.path, params,'route.targetRoute.path, params') + console.log(targetRoute,'targetRoute') + console.log(req.baseUrl,'req.baseUrl') + const parsedUrl = new URL(targetRoute, req.baseUrl) + const options = { + method: req.method, + headers: req.headers, + hostname: parsedUrl.hostname, + port: parsedUrl.port, + path: parsedUrl.pathname + sourceUrl.search, + } + console.log({ + sourceBaseUrl, + sourceUrl, + route, + params, + targetRoute, + parsedUrl, + options, + }) + const proxyReq = (parsedUrl.protocol === 'https:' ? https : http).request(options, (proxyRes) => { + res.writeHead(proxyRes.statusCode, proxyRes.headers) + proxyRes.pipe(res, { end: true }) + }) + proxyReq.on('error', (err) => { + handleInterfaceError(res, err) + }) + req.pipe(proxyReq, { end: true }) + } catch (err) { + handleInterfaceError(res, err) + } +} + +const post = (baseUrl, route, requestBody, headers) => { + const url = baseUrl + route + return axios + .post(url, requestBody, { headers }) + .then((response) => response.data) + .catch((error) => { + if (error.response) { + return error.response + } + return error + }) +} +const patch = async (baseUrl, route, requestBody, headers) => { + try { + const url = baseUrl + route + + const options = { + method: 'PATCH', + headers: headers, + body: JSON.stringify(requestBody), + } + + const response = await fetch(url, options) + + const data = await response.json() + return data + } catch (error) { + console.error(error) + throw error + } +} +const axiosPatch = async (baseUrl, route, requestBody, headers) => { + try { + const url = baseUrl + route + console.log(url, requestBody) + const config = { + headers: headers, + } + axios + .patch(url, requestBody, config) + .then((response) => { + // Handle the successful response here + console.log('PATCH request successful:', response.data) + return response.data + }) + .catch((error) => { + // Handle any errors that occurred during the PATCH request + console.error('Error making PATCH request:', error) + if (error.response) { + return error.response + } + return error + }) + } catch (error) { + console.error('Error making PATCH request:', error) + } +} + +const requesters = { + passThroughRequester, + post, + patch, + axiosPatch, +} + +module.exports = requesters \ No newline at end of file diff --git a/elevate-mentoring/constants/routes.js b/elevate-mentoring/constants/routes.js index 76a0f28..d78ab56 100644 --- a/elevate-mentoring/constants/routes.js +++ b/elevate-mentoring/constants/routes.js @@ -12,22 +12,22 @@ module.exports = { }, { sourceRoute: '/mentoring/v1/entity/read', - type: 'GET', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { path: '/mentoring/v1/entity/read', - type: 'GET', + type: 'POST', }, }, { sourceRoute: '/mentoring/v1/entity/read/:id', - type: 'GET', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { path: '/mentoring/v1/entity/read/:id', - type: 'GET', + type: 'POST', }, }, { @@ -82,22 +82,22 @@ module.exports = { }, { sourceRoute: '/mentoring/v1/form/read', - type: 'GET', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { path: '/mentoring/v1/form/read', - type: 'GET', + type: 'POST', }, }, { sourceRoute: '/mentoring/v1/form/read/:id', - type: 'GET', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { path: '/mentoring/v1/form/read/:id', - type: 'GET', + type: 'POST', }, }, { @@ -132,32 +132,32 @@ module.exports = { }, { sourceRoute: '/mentoring/v1/entity-type/read', - type: 'GET', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { path: '/mentoring/v1/entity-type/read', - type: 'GET', + type: 'POST', }, }, { sourceRoute: '/mentoring/v1/entity-type/update', - type: 'PUT', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { path: '/mentoring/v1/entity-type/update', - type: 'PUT', + type: 'POST', }, }, { sourceRoute: '/mentoring/v1/entity-type/update/:id', - type: 'PUT', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { path: '/mentoring/v1/entity-type/update/:id', - type: 'PUT', + type: 'POST', }, }, { @@ -212,22 +212,22 @@ module.exports = { }, { sourceRoute: '/mentoring/v1/sessions/share', - type: 'POST', + type: 'GET', inSequence: false, orchestrated: false, targetRoute: { path: '/mentoring/v1/sessions/share', - type: 'POST', + type: 'GET', }, }, { sourceRoute: '/mentoring/v1/sessions/share/:id', - type: 'POST', + type: 'GET', inSequence: false, orchestrated: false, targetRoute: { path: '/mentoring/v1/sessions/share/:id', - type: 'POST', + type: 'GET', }, }, { @@ -276,12 +276,10 @@ module.exports = { priority: 'MUST_HAVE', inSequence: false, orchestrated: false, - targetPackages: [ - { - basePackageName: 'mentoring', - packageName: 'elevate-mentoring', - }, - ], + targetRoute: { + path: '/mentoring/v1/sessions/start', + type: 'POST', + }, }, { sourceRoute: '/mentoring/v1/sessions/start/:id', @@ -289,12 +287,10 @@ module.exports = { priority: 'MUST_HAVE', inSequence: false, orchestrated: false, - targetPackages: [ - { - basePackageName: 'mentoring', - packageName: 'elevate-mentoring', - }, - ], + targetRoute: { + path: '/mentoring/v1/sessions/start/:id', + type: 'POST', + }, }, { sourceRoute: '/mentoring/v1/sessions/update', @@ -302,12 +298,10 @@ module.exports = { priority: 'MUST_HAVE', inSequence: false, orchestrated: false, - targetPackages: [ - { - basePackageName: 'mentoring', - packageName: 'elevate-mentoring', - }, - ], + targetRoute: { + path: '/mentoring/v1/sessions/update', + type: 'POST', + }, }, { sourceRoute: '/mentoring/v1/sessions/update/:id', @@ -315,12 +309,10 @@ module.exports = { priority: 'MUST_HAVE', inSequence: false, orchestrated: false, - targetPackages: [ - { - basePackageName: 'mentoring', - packageName: 'elevate-mentoring', - }, - ], + targetRoute: { + path: '/mentoring/v1/sessions/update/:id', + type: 'POST', + }, }, { sourceRoute: '/mentoring/v1/sessions/feedback', @@ -328,12 +320,10 @@ module.exports = { priority: 'MUST_HAVE', inSequence: false, orchestrated: false, - targetPackages: [ - { - basePackageName: 'mentoring', - packageName: 'elevate-mentoring', - }, - ], + targetRoute: { + path: '/mentoring/v1/sessions/feedback', + type: 'POST', + }, }, { sourceRoute: '/mentoring/v1/sessions/feedback/:id', @@ -341,90 +331,98 @@ module.exports = { priority: 'MUST_HAVE', inSequence: false, orchestrated: false, - targetPackages: [ - { - basePackageName: 'mentoring', - packageName: 'elevate-mentoring', - }, - ], + targetRoute: { + path: '/mentoring/v1/sessions/feedback/:id', + type: 'POST', + }, }, { sourceRoute: '/mentoring/v1/sessions/updateRecordingUrl', - type: 'POST', + type: 'PATCH', priority: 'MUST_HAVE', inSequence: false, orchestrated: false, - targetPackages: [ - { - basePackageName: 'mentoring', - packageName: 'elevate-mentoring', - }, - ], + targetRoute: { + path: '/mentoring/v1/sessions/updateRecordingUrl', + type: 'PATCH', + }, }, { sourceRoute: '/mentoring/v1/sessions/updateRecordingUrl/:id', - type: 'POST', + type: 'PATCH', priority: 'MUST_HAVE', inSequence: false, orchestrated: false, - targetPackages: [ - { - basePackageName: 'mentoring', - packageName: 'elevate-mentoring', - }, - ], + targetRoute: { + path: '/mentoring/v1/sessions/updateRecordingUrl/:id', + type: 'PATCH', + }, }, { sourceRoute: '/mentoring/v1/sessions/completed', - type: 'POST', + type: 'PATCH', priority: 'MUST_HAVE', inSequence: false, orchestrated: false, - targetPackages: [ - { - basePackageName: 'mentoring', - packageName: 'elevate-mentoring', - }, - ], + targetRoute: { + path: '/mentoring/v1/sessions/completed', + type: 'PATCH', + }, }, { sourceRoute: '/mentoring/v1/sessions/completed/:id', - type: 'POST', + type: 'PATCH', priority: 'MUST_HAVE', inSequence: false, orchestrated: false, - targetPackages: [ - { - basePackageName: 'mentoring', - packageName: 'elevate-mentoring', - }, - ], + targetRoute: { + path: '/mentoring/v1/sessions/completed/:id', + type: 'PATCH', + }, + }, + { + sourceRoute: '/mentoring/v1/sessions/completed', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/sessions/completed', + type: 'PATCH', + }, + }, + { + sourceRoute: '/mentoring/v1/sessions/completed/:id', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/sessions/completed/:id', + type: 'PATCH', + }, }, { sourceRoute: '/mentoring/v1/sessions/getRecording', - type: 'POST', + type: 'GET', priority: 'MUST_HAVE', inSequence: false, orchestrated: false, - targetPackages: [ - { - basePackageName: 'mentoring', - packageName: 'elevate-mentoring', - }, - ], + targetRoute: { + path: '/mentoring/v1/sessions/getRecording', + type: 'GET', + }, }, { sourceRoute: '/mentoring/v1/sessions/getRecording/:id', - type: 'POST', + type: 'GET', priority: 'MUST_HAVE', inSequence: false, orchestrated: false, - targetPackages: [ - { - basePackageName: 'mentoring', - packageName: 'elevate-mentoring', - }, - ], + targetRoute: { + path: '/mentoring/v1/sessions/getRecording/:id', + type: 'GET', + }, }, { sourceRoute: '/mentoring/v1/mentees/sessions', @@ -432,12 +430,10 @@ module.exports = { priority: 'MUST_HAVE', inSequence: false, orchestrated: false, - targetPackages: [ - { - basePackageName: 'mentoring', - packageName: 'elevate-mentoring', - }, - ], + targetRoute: { + path: '/mentoring/v1/mentees/sessions', + type: 'GET', + }, }, { sourceRoute: '/mentoring/v1/mentees/joinSession', @@ -595,24 +591,24 @@ module.exports = { }, { sourceRoute: '/mentoring/v1/mentors/share', - type: 'POST', + type: 'GET', priority: 'MUST_HAVE', inSequence: false, orchestrated: false, targetRoute: { path: '/mentoring/v1/mentors/share', - type: 'POST', + type: 'GET', }, }, { sourceRoute: '/mentoring/v1/mentors/share/:id', - type: 'POST', + type: 'GET', priority: 'MUST_HAVE', inSequence: false, orchestrated: false, targetRoute: { path: '/mentoring/v1/mentors/share/:id', - type: 'POST', + type: 'GET', }, }, { @@ -692,6 +688,14 @@ module.exports = { type: 'GET', }, }, + { + sourceRoute: '/mentoring/v1/feedback/forms/:id', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/feedback/forms/:id', + type: 'GET', + }, + }, { sourceRoute: '/mentoring/v1/questions/create', type: 'POST', @@ -748,54 +752,54 @@ module.exports = { }, }, { - sourceRoute: '/mentoring/v1/questionsSet/create', + sourceRoute: '/mentoring/v1/question-set/create', type: 'POST', priority: 'MUST_HAVE', inSequence: false, orchestrated: false, targetRoute: { - path: '/mentoring/v1/questionsSet/create', + path: '/mentoring/v1/question-set/create', type: 'POST', }, }, { - sourceRoute: '/mentoring/v1/questionsSet/update', - type: 'PUT', + sourceRoute: '/mentoring/v1/question-set/update', + type: 'PATCH', inSequence: false, orchestrated: false, targetRoute: { - path: '/mentoring/v1/questionsSet/update', - type: 'PUT', + path: '/mentoring/v1/question-set/update', + type: 'PATCH', }, }, { - sourceRoute: '/mentoring/v1/questionsSet/update/:id', - type: 'PUT', + sourceRoute: '/mentoring/v1/question-set/update/:id', + type: 'PATCH', inSequence: false, orchestrated: false, targetRoute: { - path: '/mentoring/v1/questionsSet/update/:id', - type: 'PUT', + path: '/mentoring/v1/question-set/update/:id', + type: 'PATCH', }, }, { - sourceRoute: '/mentoring/v1/questionsSet/read', - type: 'GET', + sourceRoute: '/mentoring/v1/question-set/read', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { - path: '/mentoring/v1/questionsSet/read', - type: 'GET', + path: '/mentoring/v1/question-set/read', + type: 'POST', }, }, { - sourceRoute: '/mentoring/v1/questionsSet/read/:id', - type: 'GET', + sourceRoute: '/mentoring/v1/question-set/read/:id', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { - path: '/mentoring/v1/questionsSet/read/:id', - type: 'GET', + path: '/mentoring/v1/question-set/read/:id', + type: 'POST', }, }, { @@ -870,5 +874,597 @@ module.exports = { functionName: 'updateUser', }, }, + { + sourceRoute: '/interface/v1/entity-type/read', + type: 'POST', + inSequence: false, + orchestrated: true, + targetRoute: { + path: '/mentoring/v1/entity-type/read', + type: 'POST', + functionName: 'entityTypeRead', + }, + }, + { + sourceRoute: '/interface/v1/account/login', + type: 'POST', + inSequence: true, + orchestrated: true, + targetRoute: { + path: '/mentoring/v1/role-permission-mapping/list', + type: 'POST', + functionName: 'rolePermissions', + }, + }, + { + sourceRoute: '/mentoring/v1/role-permission-mapping/list', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/role-permission-mapping/list', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/org-admin/inheritEntityType', + type: 'POST', + targetRoute: { + path: '/mentoring/v1/org-admin/inheritEntityType', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/org-admin/roleChange', + type: 'POST', + targetRoute: { + path: '/mentoring/v1/org-admin/roleChange', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/org-admin/setOrgPolicies', + type: 'POST', + targetRoute: { + path: '/mentoring/v1/org-admin/setOrgPolicies', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/org-admin/getOrgPolicies', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/org-admin/getOrgPolicies', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/profile/create', + type: 'POST', + targetRoute: { + path: '/mentoring/v1/profile/create', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/profile/read', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/profile/read', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/profile/update', + type: 'POST', + targetRoute: { + path: '/mentoring/v1/profile/update', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/cloud-services/getSignedUrl', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/cloud-services/getSignedUrl', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/cloud-services/getDownloadableUrl', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/cloud-services/getDownloadableUrl', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/admin/triggerPeriodicViewRefresh', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/admin/triggerPeriodicViewRefresh', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/admin/triggerViewRebuild', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/admin/triggerViewRebuild', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/admin/triggerPeriodicViewRefreshInternal', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/admin/triggerPeriodicViewRefreshInternal', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/admin/triggerViewRebuildInternal', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/admin/triggerViewRebuildInternal', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/mentors/list', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/mentors/list', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/mentors/createdSessions', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/mentors/createdSessions', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/mentors/details', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/mentors/details', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/mentors/details/:id', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/mentors/details/:id', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/notification/template', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/notification/template', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/notification/template/:id', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/notification/template/:id', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/notification/template', + type: 'PATCH', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/notification/template', + type: 'PATCH', + }, + }, + { + sourceRoute: '/mentoring/v1/org-admin/updateOrganization', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/org-admin/updateOrganization', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/org-admin/updateRelatedOrgs', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/org-admin/updateRelatedOrgs', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/org-admin/deactivateUpcomingSession', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/org-admin/deactivateUpcomingSession', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/permissions/create', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/permissions/create', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/permissions/update/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/permissions/update/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/permissions/list', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/permissions/list', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/permissions/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/permissions/delete/:id', + type: 'DELETE', + }, + }, + { + sourceRoute: '/mentoring/v1/modules/create', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/modules/create', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/modules/update/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/modules/update/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/modules/list', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/modules/list', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/modules/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/modules/delete/:id', + type: 'DELETE', + }, + }, + { + sourceRoute: '/mentoring/v1/role-permission-mapping/create/:role_id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/role-permission-mapping/create/:role_id', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/role-permission-mapping/delete/:role_id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/role-permission-mapping/delete/:role_id', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/sessions/bulkSessionCreate', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/sessions/bulkSessionCreate', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/org-admin/uploadSampleCSV', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/org-admin/uploadSampleCSV', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/sessions/getSampleCSV', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/mentoring/v1/sessions/getSampleCSV', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/organization/update', + type: 'PATCH', + targetRoute: { + path: '/mentoring/v1/organization/update', + type: 'PATCH', + }, + }, + { + sourceRoute: '/mentoring/v1/organization/eventListener', + type: 'POST', + targetRoute: { + path: '/mentoring/v1/organization/eventListener', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/manage-sessions/createdSessions', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/manage-sessions/createdSessions', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/manage-sessions/downloadSessions', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/manage-sessions/downloadSessions ', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/manage-sessions/downloadSessions', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/manage-sessions/downloadSessions ', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/mentees/list', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/mentees/list ', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/profile/filterList', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/profile/filterList ', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/sessions/addMentees', + type: 'POST', + targetRoute: { + path: '/mentoring/v1/sessions/addMentees', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/sessions/addMentees/:id', + type: 'POST', + targetRoute: { + path: '/mentoring/v1/sessions/addMentees/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/sessions/removeMentees', + type: 'POST', + targetRoute: { + path: '/mentoring/v1/sessions/removeMentees', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/sessions/removeMentees/:id', + type: 'POST', + targetRoute: { + path: '/mentoring/v1/sessions/removeMentees/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/sessions/enrolledMentees/:id', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/sessions/enrolledMentees/:id', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/sessions/enrolledMentees', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/sessions/enrolledMentees', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/sessions/bulkUpdateMentorNames', + type: 'POST', + targetRoute: { + path: '/mentoring/v1/sessions/bulkUpdateMentorNames', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/availability/create', + type: 'POST', + targetRoute: { + path: '/mentoring/v1/availability/create', + type: 'POST', + }, + }, + { + sourceRoute: '/mentoring/v1/availability/update', + type: 'PATCH', + targetRoute: { + path: '/mentoring/v1/availability/update', + type: 'PATCH', + }, + }, + { + sourceRoute: '/mentoring/v1/availability/update/:id', + type: 'PATCH', + targetRoute: { + path: '/mentoring/v1/availability/update/:id', + type: 'PATCH', + }, + }, + { + sourceRoute: '/mentoring/v1/availability/delete', + type: 'DELETE', + targetRoute: { + path: '/mentoring/v1/availability/delete', + type: 'DELETE', + }, + }, + { + sourceRoute: '/mentoring/v1/availability/delete/:id', + type: 'DELETE', + targetRoute: { + path: '/mentoring/v1/availability/delete/:id', + type: 'DELETE', + }, + }, + { + sourceRoute: '/mentoring/v1/availability/read', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/availability/read', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/availability/read/:id', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/availability/read/:id', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/availability/isAvailable', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/availability/isAvailable', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/availability/isAvailable/:id', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/availability/isAvailable/:id', + type: 'GET', + }, + }, + { + sourceRoute: '/mentoring/v1/availability/users', + type: 'GET', + targetRoute: { + path: '/mentoring/v1/availability/users', + type: 'GET', + }, + }, ], } diff --git a/elevate-mentoring/controllers/mentoring.js b/elevate-mentoring/controllers/mentoring.js index b25a290..fca2c95 100644 --- a/elevate-mentoring/controllers/mentoring.js +++ b/elevate-mentoring/controllers/mentoring.js @@ -11,13 +11,30 @@ const createProfile = async (req, res, responses) => { const updateUser = async (req, res, responses) => { const selectedConfig = routeConfigs.routes.find((obj) => obj.sourceRoute === req.sourceRoute) - const filteredRequestBody = requestParser.transformUpdateUserBody(req.body) - console.log(req.baseUrl, selectedConfig.targetRoute.path, req.headers, filteredRequestBody, 'mentoring request') - return await requesters.patch(req.baseUrl, selectedConfig.targetRoute.path, filteredRequestBody, req.headers) + //const filteredRequestBody = requestParser.transformUpdateUserBody(req.body) + console.log(req.baseUrl, selectedConfig.targetRoute.path, req.headers, req.body, 'mentoring request') + return await requesters.patch(req.baseUrl, selectedConfig.targetRoute.path, req.body, req.headers) } + +const entityTypeRead = async (req, res, responses) => { + const selectedConfig = routeConfigs.routes.find((obj) => obj.sourceRoute === req.sourceRoute) + return await requesters.post(req.baseUrl, selectedConfig.targetRoute.path, req.body, { + 'X-auth-token': req.headers['x-auth-token'], + }) +} + +const rolePermissions = async (req, res, responses) => { + const selectedConfig = routeConfigs.routes.find((obj) => obj.sourceRoute === req.sourceRoute) + return await requesters.post(req.baseUrl, selectedConfig.targetRoute.path,req.body,{ + 'X-auth-token': `bearer ${responses.user.result.access_token}`, + }) +} + mentoringController = { createProfile, updateUser, + entityTypeRead, + rolePermissions, } module.exports = mentoringController diff --git a/elevate-mentoring/package.json b/elevate-mentoring/package.json index 0f00432..2d7d8fe 100644 --- a/elevate-mentoring/package.json +++ b/elevate-mentoring/package.json @@ -1,6 +1,6 @@ { "name": "elevate-mentoring", - "version": "1.1.6", + "version": "1.1.49", "description": "Npm package for Elevate-Mentoring service integration with Interface service. ", "main": "index.js", "scripts": { diff --git a/elevate-mentoring/utils/requester.js b/elevate-mentoring/utils/requester.js index d085827..78297ec 100644 --- a/elevate-mentoring/utils/requester.js +++ b/elevate-mentoring/utils/requester.js @@ -50,60 +50,43 @@ const passThroughRequester = async (req, res) => { } const post = (baseUrl, route, requestBody, headers) => { - const url = baseUrl + route - return axios - .post(url, requestBody, { headers }) - .then((response) => response.data) - .catch((error) => { - if (error.response) { - return error.response - } - return error - }) -} -const patch = async (baseUrl, route, requestBody, headers) => { try { const url = baseUrl + route - - const options = { - method: 'PATCH', - headers: headers, - body: JSON.stringify(requestBody), - } - - const response = await fetch(url, options) - - const data = await response.json() - return data - } catch (error) { - console.error(error) - throw error + return axios + .post(url, requestBody, { headers }) + .then((response) => response.data) + .catch((error) => { + if (error.response) { + return error.response + } + return error + }) + } catch (err) { + console.log(err) + throw err } } -const axiosPatch = async (baseUrl, route, requestBody, headers) => { + +const patch = async (baseUrl, route, requestBody, headers) => { try { const url = baseUrl + route - console.log(url, requestBody) - const config = { - headers: headers, - } - axios - .patch(url, requestBody, config) - .then((response) => { - // Handle the successful response here - console.log('PATCH request successful:', response.data) - return response.data + return axios + .patch(url, requestBody, { + headers: { + 'X-auth-token': headers['x-auth-token'], + 'content-type': 'application/json', + }, }) + .then((response) => response.data) .catch((error) => { - // Handle any errors that occurred during the PATCH request - console.error('Error making PATCH request:', error) if (error.response) { return error.response } return error }) } catch (error) { - console.error('Error making PATCH request:', error) + console.error(error) + throw error // Re-throw the error to be caught by the caller } } @@ -111,7 +94,6 @@ const requesters = { passThroughRequester, post, patch, - axiosPatch, } module.exports = requesters diff --git a/elevate-notification/constants/routes.js b/elevate-notification/constants/routes.js index 8fa9655..a1a61f4 100644 --- a/elevate-notification/constants/routes.js +++ b/elevate-notification/constants/routes.js @@ -1,6 +1,12 @@ -module.exports = [ - { route: '/v1/get-user-photo', config: [{ type: 'GET' }] }, - { route: '/v1/get-user-profile', config: [{ type: 'POST' }] }, - { route: '/v1/get-sharelink', config: [{ type: 'PUT' }, { type: 'PATCH' }] }, - { route: '/v1/get-user-details', config: [{ type: 'DELETE' }] }, -]; +module.exports = { + routes: [ + { + sourceRoute: '/notification/v1/email/send', + type: 'POST', + targetRoute: { + path: '/notification/v1/email/send', + type: 'POST', + }, + } + ], +} diff --git a/elevate-notification/controllers/index.js b/elevate-notification/controllers/index.js deleted file mode 100644 index e69de29..0000000 diff --git a/elevate-notification/controllers/notification.js b/elevate-notification/controllers/notification.js new file mode 100644 index 0000000..4904313 --- /dev/null +++ b/elevate-notification/controllers/notification.js @@ -0,0 +1 @@ +// Add logic if required \ No newline at end of file diff --git a/elevate-notification/controllers/orchestrationController.js b/elevate-notification/controllers/orchestrationController.js new file mode 100644 index 0000000..88b645b --- /dev/null +++ b/elevate-notification/controllers/orchestrationController.js @@ -0,0 +1,13 @@ +const routesConfig = require('../constants/routes') +// const notificationController = require('../controllers/notification') +const orchestrationHandler = async (req, res, responses) => { + console.log(req.targetPackages, req.inSequence, req.orchestrated, req.sourceRoute, responses) + console.log(req.body) + const selectedRouteConfig = routesConfig.routes.find((obj) => obj.sourceRoute === req.sourceRoute) + // return await notificationController[selectedRouteConfig.targetRoute.functionName](req, res, responses) +} + +const orchestrationController = { + orchestrationHandler, +} +module.exports = orchestrationController diff --git a/elevate-notification/index.js b/elevate-notification/index.js index 7cba384..65db71c 100644 --- a/elevate-notification/index.js +++ b/elevate-notification/index.js @@ -1 +1,13 @@ -const routes = require('./constants/routes'); +const packageRouter = require('./router') + +const getPackageMeta = () => { + return { + basePackageName: 'notification', + packageName: 'elevate-notification', + } +} + +module.exports = { + packageMeta: getPackageMeta(), + packageRouter, +} diff --git a/elevate-notification/package.json b/elevate-notification/package.json index 8b17af0..ad82348 100644 --- a/elevate-notification/package.json +++ b/elevate-notification/package.json @@ -1,6 +1,6 @@ { "name": "elevate-notification", - "version": "1.0.0", + "version": "1.0.4", "description": "Npm package for Elevate-Notification service integration with Interface service. ", "main": "index.js", "scripts": { @@ -14,6 +14,10 @@ "author": "Joffin Joy", "license": "ISC", "dependencies": { - "express": "^4.18.2" + "express": "^4.18.2", + "axios": "^1.4.0", + "lodash": "^4.17.21", + "node-fetch": "^2.7.0", + "path-to-regexp": "^6.2.1" } } diff --git a/elevate-notification/router/index.js b/elevate-notification/router/index.js new file mode 100644 index 0000000..a8b43a8 --- /dev/null +++ b/elevate-notification/router/index.js @@ -0,0 +1,10 @@ +const { passThroughRequester } = require('../utils/requester') +const { orchestrationHandler } = require('../controllers/orchestrationController') +const packageRouter = async (req, res, responses) => { + const response = req.orchestrated + ? await orchestrationHandler(req, res, responses) + : await passThroughRequester(req, res) + return response +} + +module.exports = packageRouter diff --git a/elevate-notification/utils/pathParamSetter.js b/elevate-notification/utils/pathParamSetter.js new file mode 100644 index 0000000..130b1fe --- /dev/null +++ b/elevate-notification/utils/pathParamSetter.js @@ -0,0 +1,6 @@ +exports.pathParamSetter = (targetPath, params) => { + return targetPath.replace(/:\w+/g, (match) => { + const fieldName = match.substring(1) + return params[fieldName] || match + }) +} diff --git a/elevate-notification/utils/patternMatcher.js b/elevate-notification/utils/patternMatcher.js new file mode 100644 index 0000000..18cd428 --- /dev/null +++ b/elevate-notification/utils/patternMatcher.js @@ -0,0 +1,16 @@ +exports.matchPathsAndExtractParams = (pattern, url) => { + const paramNames = [] + const regexPattern = new RegExp( + pattern.replace(/:(\w+)/g, (_, paramName) => { + paramNames.push(paramName) + return '([a-zA-Z0-9]+)' + }) + ) + const matchResult = url.match(regexPattern) + if (!matchResult) return false + const params = {} + for (let i = 0; i < paramNames.length; i++) { + params[paramNames[i]] = matchResult[i + 1] + } + return params +} diff --git a/elevate-notification/utils/requestParser.js b/elevate-notification/utils/requestParser.js new file mode 100644 index 0000000..5021d73 --- /dev/null +++ b/elevate-notification/utils/requestParser.js @@ -0,0 +1,8 @@ +const _ = require('lodash') + +exports.transformUpdateUserBody = (requestBody) => { + // Add Keys in the array to enable validation + const allowedKeys = [] + + return _.pick(requestBody, allowedKeys) +} diff --git a/elevate-notification/utils/requester.js b/elevate-notification/utils/requester.js new file mode 100644 index 0000000..78297ec --- /dev/null +++ b/elevate-notification/utils/requester.js @@ -0,0 +1,99 @@ +const http = require('http') +const https = require('https') +const { matchPathsAndExtractParams } = require('../utils/patternMatcher') +const routesConfig = require('../constants/routes') +const { pathParamSetter } = require('../utils/pathParamSetter') +const axios = require('axios') +const fetch = require('node-fetch') + +const handleInterfaceError = (res, err) => { + console.log('Error: ', err) + res.writeHead(500, { 'Content-Type': 'text/plain' }) + res.end('Interface Server Error') +} + +const passThroughRequester = async (req, res) => { + try { + const sourceBaseUrl = req.protocol + '://' + req.headers.host + '/' + const sourceUrl = new URL(req.originalUrl, sourceBaseUrl) + const route = routesConfig.routes.find((route) => route.sourceRoute === req.sourceRoute) + const params = matchPathsAndExtractParams(route.sourceRoute, req.originalUrl) + const targetRoute = pathParamSetter(route.targetRoute.path, params) + const parsedUrl = new URL(targetRoute, req.baseUrl) + const options = { + method: req.method, + headers: req.headers, + hostname: parsedUrl.hostname, + port: parsedUrl.port, + path: parsedUrl.pathname + sourceUrl.search, + } + console.log({ + sourceBaseUrl, + sourceUrl, + route, + params, + targetRoute, + parsedUrl, + options, + }) + const proxyReq = (parsedUrl.protocol === 'https:' ? https : http).request(options, (proxyRes) => { + res.writeHead(proxyRes.statusCode, proxyRes.headers) + proxyRes.pipe(res, { end: true }) + }) + proxyReq.on('error', (err) => { + handleInterfaceError(res, err) + }) + req.pipe(proxyReq, { end: true }) + } catch (err) { + handleInterfaceError(res, err) + } +} + +const post = (baseUrl, route, requestBody, headers) => { + try { + const url = baseUrl + route + return axios + .post(url, requestBody, { headers }) + .then((response) => response.data) + .catch((error) => { + if (error.response) { + return error.response + } + return error + }) + } catch (err) { + console.log(err) + throw err + } +} + +const patch = async (baseUrl, route, requestBody, headers) => { + try { + const url = baseUrl + route + return axios + .patch(url, requestBody, { + headers: { + 'X-auth-token': headers['x-auth-token'], + 'content-type': 'application/json', + }, + }) + .then((response) => response.data) + .catch((error) => { + if (error.response) { + return error.response + } + return error + }) + } catch (error) { + console.error(error) + throw error // Re-throw the error to be caught by the caller + } +} + +const requesters = { + passThroughRequester, + post, + patch, +} + +module.exports = requesters diff --git a/elevate-project/constants/common.js b/elevate-project/constants/common.js new file mode 100644 index 0000000..51a4279 --- /dev/null +++ b/elevate-project/constants/common.js @@ -0,0 +1,19 @@ +/** + * name : constants/common.js + * author : Adithya Dinesh + * Date : 23 - Aug - 2024 + * Description : All commonly used constants through out the package + */ + +module.exports = { + PROJECT_STATUS_PUBLISHED : 'published', + PROJECT_PROJECTION_FIELDS : ["_id" , "title","createdBy","createdAt","description"], + RESOURCE_TYPE_PTOJECT : 'projects', + PROJECT_TRANSFORM_KEYS : { + _id : "id", + createdAt : "created_at", + createdBy : "created_by" + }, + AUTH_TOKEN_KEY : 'x-auth-token' + +} \ No newline at end of file diff --git a/elevate-project/constants/routes.js b/elevate-project/constants/routes.js new file mode 100644 index 0000000..4b7660f --- /dev/null +++ b/elevate-project/constants/routes.js @@ -0,0 +1,1162 @@ +module.exports = { + routes: [ + { + sourceRoute: '/project/v1/userProjects/sync', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/sync', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/sync/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/sync/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/details', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/details', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/details/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/details/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/verifyCertificate', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/verifyCertificate', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/certificateCallback', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/certificateCallback', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/certificateCallbackError', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/certificateCallbackError', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/verifyCertificate/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/verifyCertificate/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/certificateReIssue', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/certificateReIssue', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/certificateReIssue/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/certificateReIssue/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/certificateBaseTemplates/createOrUpdate', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/certificateBaseTemplates/createOrUpdate', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/certificateBaseTemplates/createOrUpdate/:id', + type: 'PATCH', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/certificateBaseTemplates/createOrUpdate/:id', + type: 'PATCH' + }, + }, + { + sourceRoute: '/project/v1/certificateTemplates/createOrUpdate', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/certificateTemplates/createOrUpdate', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/certificateTemplates/createOrUpdate/:id', + type: 'PATCH', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/certificateTemplates/createOrUpdate/:id', + type: 'PATCH' + }, + }, + { + sourceRoute: '/project/v1/certificateTemplates/uploadTemplate', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/certificateTemplates/uploadTemplate', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/certificateTemplates/uploadTemplate/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/certificateTemplates/uploadTemplate/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/certificateTemplates/createSvg', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/certificateTemplates/createSvg', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/certificates', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/certificates', + type: 'GET' + }, + }, { + sourceRoute: '/project/v1/configurations/read', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/configurations/read', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/userProjects/tasksStatus', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/tasksStatus', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/tasksStatus/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/tasksStatus/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/add', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/add', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/userAssigned', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/userAssigned', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/userProjects/share', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/share', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/userProjects/share/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/share/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/userProjects/importedProjects', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/importedProjects', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/userProjects/importedProjects/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/importedProjects/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/profile/read', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/profile/read', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/userProjects/list', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/list', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/cloud-services/files/download', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/cloud-services/files/download', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/cloud-services/files/preSignedUrls', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/cloud-services/files/preSignedUrls', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/cloud-services/files/getDownloadableUrl', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/cloud-services/files/getDownloadableUrl', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/dataPipeline/userProject', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/dataPipeline/userProject', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/dataPipeline/userProject/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/dataPipeline/userProject/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/project/templates/bulkCreate', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templates/bulkCreate', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/project/templates/bulkUpdate', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templates/bulkUpdate', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/project/templates/importProjectTemplate', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templates/importProjectTemplate', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/project/templates/importProjectTemplate/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templates/importProjectTemplate/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/project/templates/listByIds', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templates/listByIds', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/project/templates/details', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templates/details', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/project/templates/details/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templates/details/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/project/templates/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templates/update', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/project/templates/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templates/update/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/project/templates/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templates/list', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/project/templateTasks/bulkCreate', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templateTasks/bulkCreate', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/project/templateTasks/bulkCreate/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templateTasks/bulkCreate/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/project/templateTasks/bulkUpdate', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templateTasks/bulkUpdate', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/project/templateTasks/bulkUpdate/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templateTasks/bulkUpdate/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/project/templateTasks/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templateTasks/update', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/project/templateTasks/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/project/templateTasks/update/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/library/categories/projects', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/library/categories/projects', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/library/categories/projects/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/library/categories/projects/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/library/categories/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/library/categories/create', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/library/categories/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/library/categories/update', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/library/categories/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/library/categories/update/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/library/categories/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/library/categories/list', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/programs/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/update', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/programs/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/update/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/programs/details', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/details', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/programs/details/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/details/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/programs/addRolesInScope', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/addRolesInScope', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/programs/addRolesInScope/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/addRolesInScope/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/programs/removeRolesInScope', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/removeRolesInScope', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/programs/removeRolesInScope/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/removeRolesInScope/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/programs/addEntitiesInScope', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/addEntitiesInScope', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/programs/addEntitiesInScope/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/addEntitiesInScope/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/programs/removeEntitiesInScope', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/removeEntitiesInScope', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/programs/removeEntitiesInScope/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/removeEntitiesInScope/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/programs/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/list', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/programs/join', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/join', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/programs/join/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/join/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/programs/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/programs/create', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/solutions/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/create', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute:{ + path: '/project/v1/solutions/update', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute:{ + path: '/project/v1/solutions/update/:id', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/list', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/list', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/forUserRoleAndLocation', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/forUserRoleAndLocation', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/detailsBasedOnRoleAndLocation', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/detailsBasedOnRoleAndLocation', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/detailsBasedOnRoleAndLocation/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/detailsBasedOnRoleAndLocation/:id', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/addRolesInScope', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/addRolesInScope', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/addRolesInScope/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/addRolesInScope/:id', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/addEntitiesInScope', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/addEntitiesInScope', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/addEntitiesInScope/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/addEntitiesInScope/:id', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/removeRolesInScope', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/removeRolesInScope', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/removeRolesInScope/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/removeRolesInScope/:id', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/targetedSolutions', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/targetedSolutions', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/fetchLink', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/fetchLink', + type: 'GET' + } + }, + { + sourceRoute: '/project/v1/solutions/fetchLink/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/fetchLink/:id', + type: 'GET' + } + }, + { + sourceRoute: '/project/v1/solutions/verifyLink', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/verifyLink', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/verifyLink/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/verifyLink/:id', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/verifySolution/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/verifySolution/:id', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/getDetails', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/getDetails', + type: 'GET' + } + }, + { + sourceRoute: '/project/v1/solutions/getDetails/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/getDetails/:id', + type: 'GET' + } + }, + { + sourceRoute: '/project/v1/solutions/removeEntitiesInScope', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/removeEntitiesInScope', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/solutions/removeEntitiesInScope/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/removeEntitiesInScope/:id', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/userProjects/importFromLibrary', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/importFromLibrary', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/userProjects/importFromLibrary/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/userProjects/importFromLibrary/:id', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/forms/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/forms/create', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/forms/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/forms/update', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/forms/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/forms/update/:id', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/forms/read', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/forms/read', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/forms/read/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/forms/read/:id', + type: 'POST' + } + }, + { + sourceRoute: '/project/v1/admin/dbFind', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/admin/dbFind', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/admin/dbFind/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/admin/dbFind/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/reports/getProgramsByEntity/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/reports/getProgramsByEntity/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/reports/entity/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/reports/entity/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/reports/entity', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/reports/entity', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/reports/detailView', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/reports/detailView', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/reports/detailView/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/reports/detailView/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/project/v1/admin/createIndex', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/admin/createIndex', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/admin/createIndex/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/admin/createIndex/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/solutions/details', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/details', + type: 'POST' + }, + }, + { + sourceRoute: '/project/v1/solutions/details/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/project/v1/solutions/details/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/interface/v1/internal/getAllPublishedResources', + type: 'POST', + inSequence: false, + orchestrated: true, + targetRoute: { + path: '/project/v1/admin/dbFind/projectTemplates', + type: 'POST', + functionName: 'fetchProjectTemplates', + }, + } + ], +} + +/* const fs = require('fs') +const modifiedArray = [].map((item) => ({ + ...item, + targetRoute: { + path: item.sourceRoute, + type: item.type, + }, +})) +const modifiedArrayJSON = JSON.stringify(modifiedArray, null, 2) +const filePath = 'modifiedArray.json' +fs.writeFile(filePath, modifiedArrayJSON, 'utf8', (err) => { + if (err) { + console.error('Error writing to file:', err) + } else { + console.log('Modified array has been written to', filePath) + } +}) */ diff --git a/elevate-project/controllers/orchestrationController.js b/elevate-project/controllers/orchestrationController.js new file mode 100644 index 0000000..cb8e581 --- /dev/null +++ b/elevate-project/controllers/orchestrationController.js @@ -0,0 +1,13 @@ +const routesConfig = require('../constants/routes') +const unnatiController = require('../controllers/project') +const orchestrationHandler = async (req, res, responses) => { + console.log(req.targetPackages, req.inSequence, req.orchestrated, req.sourceRoute, responses) + console.log(req.body) + const selectedRouteConfig = routesConfig.routes.find((obj) => obj.sourceRoute === req.sourceRoute) + return await unnatiController[selectedRouteConfig.targetRoute.functionName](req, res, responses) +} + +const orchestrationController = { + orchestrationHandler, +} +module.exports = orchestrationController diff --git a/elevate-project/controllers/project.js b/elevate-project/controllers/project.js new file mode 100644 index 0000000..16b8718 --- /dev/null +++ b/elevate-project/controllers/project.js @@ -0,0 +1,97 @@ +/** + * name : controllers/project.js + * author : Adithya Dinesh + * Date : 22-Aug-2024 + * Description : Orchestration controller for project + */ + +const routeConfigs = require('../constants/routes') +const requesters = require('../utils/requester') +const common = require('../constants/common') +/** + * Fetch project templates from projects service. + * @name fetchProjectTemplates + * @param {Object} req + * @param {Object} res + * @param {Object} responses + * @returns {JSON} - List of project templates + */ +/** + * req.body = { + * organization_id : 1, + * resourceType : ['survey','projects'] + * } + */ + +const fetchProjectTemplates = async (req, res, responses) => { + const selectedConfig = routeConfigs.routes.find((obj) => obj.sourceRoute === req.sourceRoute) + + let response = { result: { data: [], count: 0 } } + let proceedToCallProjectService = false + let resp = {} + + // fetch the max limit from the env file for the DB Find API + const max_limit = process.env.RESOURCE_MAX_FETCH_LIMIT ? parseInt(process.env.RESOURCE_MAX_FETCH_LIMIT, 10) : 1000 + + if (req.body) { + // check if body has key resourceType else assign [] + const resourceType = req?.body?.resourceType || []; + if (Array.isArray(resourceType) && resourceType.length > 0) { + // if resource type have type = projects proceed to call api + proceedToCallProjectService = resourceType.includes(common.RESOURCE_TYPE_PTOJECT); + }else if(resourceType.length == 0){ + // if resource type have type = empty call API because the client is expecting all type of resources + proceedToCallProjectService = true + } + } + + if (proceedToCallProjectService && req.headers[common.AUTH_TOKEN_KEY]) { + let reqBody = { + "query": { + "status": common.PROJECT_STATUS_PUBLISHED + }, + "projection": common.PROJECT_PROJECTION_FIELDS, + "limit": max_limit + } + + // replace the word bearer if token has it + const x_auth_token = req.headers[common.AUTH_TOKEN_KEY].replace(/^(Bearer|bearer)\s*/, ''); + // custom header + const header = { + 'internal-access-token' : req.headers['internal_access_token'], + 'X-auth-token': x_auth_token, + 'Content-Type': 'application/json' + } + if (req?.body && req.bod?.search) { + reqBody.query.title = { + "$regex": req.body.search, + "$options": 'i' + } + } + resp = await requesters.post(req.baseUrl, selectedConfig.targetRoute.path, reqBody , header) + } + + if (resp?.result?.length > 0) { + let data = [] + // transform the result to fit in the service + resp.result.reduce((accumulateResource, projects) => { + accumulateResource = {} + for (let project in projects) { + let newKey = common.PROJECT_TRANSFORM_KEYS[project] || project + accumulateResource[newKey] = projects[project] + } + accumulateResource['type'] = common.RESOURCE_TYPE_PTOJECT + data.push(accumulateResource) + }, null) + + response.result.data = data + } + + return response +} + +const projectController = { + fetchProjectTemplates +} + +module.exports = projectController diff --git a/elevate-project/index.js b/elevate-project/index.js new file mode 100644 index 0000000..2a1a920 --- /dev/null +++ b/elevate-project/index.js @@ -0,0 +1,37 @@ +const express = require('express') +const router = express.Router() +const routes = require('./constants/routes') +const packageRouter = require('./router') + +const getDependencies = () => { + return ['kafka', 'kafka-connect', 'redis'] +} + +const getPackageMeta = () => { + return { + basePackageName: 'project', + packageName: 'elevate-project', + } +} + +const createPackage = (options) => { + return { + router: () => { + console.log('router') + }, + endpoints: [], + dependencies: [], + } +} + +router.get('/', (req, res) => { + res.send('Hello, world! From Elevate Project') +}) + +module.exports = { + dependencies: getDependencies(), + routes, + createPackage, + packageMeta: getPackageMeta(), + packageRouter, +} diff --git a/elevate-project/package.json b/elevate-project/package.json new file mode 100644 index 0000000..46a4912 --- /dev/null +++ b/elevate-project/package.json @@ -0,0 +1,18 @@ +{ + "name": "elevate-project", + "version": "1.1.9", + "description": "Npm package for Elevate-Project service integration with Interface service", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Priyanka Pradeep", + "license": "ISC", + "dependencies": { + "axios": "^1.4.0", + "express": "^4.18.2", + "lodash": "^4.17.21", + "node-fetch": "^2.7.0", + "path-to-regexp": "^6.2.1" + } +} diff --git a/elevate-project/router/index.js b/elevate-project/router/index.js new file mode 100644 index 0000000..a8b43a8 --- /dev/null +++ b/elevate-project/router/index.js @@ -0,0 +1,10 @@ +const { passThroughRequester } = require('../utils/requester') +const { orchestrationHandler } = require('../controllers/orchestrationController') +const packageRouter = async (req, res, responses) => { + const response = req.orchestrated + ? await orchestrationHandler(req, res, responses) + : await passThroughRequester(req, res) + return response +} + +module.exports = packageRouter diff --git a/elevate-project/utils/pathParamSetter.js b/elevate-project/utils/pathParamSetter.js new file mode 100644 index 0000000..130b1fe --- /dev/null +++ b/elevate-project/utils/pathParamSetter.js @@ -0,0 +1,6 @@ +exports.pathParamSetter = (targetPath, params) => { + return targetPath.replace(/:\w+/g, (match) => { + const fieldName = match.substring(1) + return params[fieldName] || match + }) +} diff --git a/elevate-project/utils/patternMatcher.js b/elevate-project/utils/patternMatcher.js new file mode 100644 index 0000000..cc70b81 --- /dev/null +++ b/elevate-project/utils/patternMatcher.js @@ -0,0 +1,16 @@ +exports.matchPathsAndExtractParams = (pattern, url) => { + const paramNames = [] + const regexPattern = new RegExp( + pattern.replace(/:(\w+)/g, (_, paramName) => { + paramNames.push(paramName) + return '([a-zA-Z0-9-]+)' + }) + ) + const matchResult = url.match(regexPattern) + if (!matchResult) return false + const params = {} + for (let i = 0; i < paramNames.length; i++) { + params[paramNames[i]] = matchResult[i + 1] + } + return params +} \ No newline at end of file diff --git a/elevate-project/utils/requestParser.js b/elevate-project/utils/requestParser.js new file mode 100644 index 0000000..ecd12e5 --- /dev/null +++ b/elevate-project/utils/requestParser.js @@ -0,0 +1,6 @@ +const _ = require('lodash') + +// exports.transformUpdateUserBody = (requestBody) => { +// const allowedKeys = ['name', 'email', 'image', 'location', 'about', 'preferred_language'] +// return _.pick(requestBody, allowedKeys) +// } diff --git a/elevate-project/utils/requester.js b/elevate-project/utils/requester.js new file mode 100644 index 0000000..aec6ac1 --- /dev/null +++ b/elevate-project/utils/requester.js @@ -0,0 +1,121 @@ +const http = require('http') +const https = require('https') +const { matchPathsAndExtractParams } = require('../utils/patternMatcher') +const routesConfig = require('../constants/routes') +const { pathParamSetter } = require('../utils/pathParamSetter') +const axios = require('axios') +const fetch = require('node-fetch') + +const handleInterfaceError = (res, err) => { + console.log('Error: ', err) + res.writeHead(500, { 'Content-Type': 'text/plain' }) + res.end('Interface Server Error') +} + +const passThroughRequester = async (req, res) => { + try { + const sourceBaseUrl = req.protocol + '://' + req.headers.host + '/' + const sourceUrl = new URL(req.originalUrl, sourceBaseUrl) + const route = routesConfig.routes.find((route) => route.sourceRoute === req.sourceRoute) + const params = matchPathsAndExtractParams(route.sourceRoute, req.originalUrl) + console.log(params,'params') + const targetRoute = pathParamSetter(route.targetRoute.path, params) + console.log(route.targetRoute.path, params,'route.targetRoute.path, params') + console.log(targetRoute,'targetRoute') + console.log(req.baseUrl,'req.baseUrl') + const parsedUrl = new URL(targetRoute, req.baseUrl) + const options = { + method: req.method, + headers: req.headers, + hostname: parsedUrl.hostname, + port: parsedUrl.port, + path: parsedUrl.pathname + sourceUrl.search, + } + console.log({ + sourceBaseUrl, + sourceUrl, + route, + params, + targetRoute, + parsedUrl, + options, + }) + const proxyReq = (parsedUrl.protocol === 'https:' ? https : http).request(options, (proxyRes) => { + res.writeHead(proxyRes.statusCode, proxyRes.headers) + proxyRes.pipe(res, { end: true }) + }) + proxyReq.on('error', (err) => { + handleInterfaceError(res, err) + }) + req.pipe(proxyReq, { end: true }) + } catch (err) { + handleInterfaceError(res, err) + } +} + +const post = (baseUrl, route, requestBody, headers) => { + const url = baseUrl + route + return axios + .post(url, requestBody, { headers }) + .then((response) => response.data) + .catch((error) => { + if (error.response) { + return error.response + } + return error + }) +} +const patch = async (baseUrl, route, requestBody, headers) => { + try { + const url = baseUrl + route + + const options = { + method: 'PATCH', + headers: headers, + body: JSON.stringify(requestBody), + } + + const response = await fetch(url, options) + + const data = await response.json() + return data + } catch (error) { + console.error(error) + throw error + } +} +const axiosPatch = async (baseUrl, route, requestBody, headers) => { + try { + const url = baseUrl + route + console.log(url, requestBody) + const config = { + headers: headers, + } + axios + .patch(url, requestBody, config) + .then((response) => { + // Handle the successful response here + console.log('PATCH request successful:', response.data) + return response.data + }) + .catch((error) => { + // Handle any errors that occurred during the PATCH request + console.error('Error making PATCH request:', error) + if (error.response) { + return error.response + } + return error + }) + } catch (error) { + console.error('Error making PATCH request:', error) + } +} + +const requesters = { + passThroughRequester, + post, + patch, + axiosPatch, +} + +module.exports = requesters \ No newline at end of file diff --git a/elevate-scheduler/.DS_Store b/elevate-scheduler/.DS_Store new file mode 100644 index 0000000..a547469 Binary files /dev/null and b/elevate-scheduler/.DS_Store differ diff --git a/elevate-scheduler/constants/index.js b/elevate-scheduler/constants/index.js deleted file mode 100644 index 7cba384..0000000 --- a/elevate-scheduler/constants/index.js +++ /dev/null @@ -1 +0,0 @@ -const routes = require('./constants/routes'); diff --git a/elevate-scheduler/constants/routes.js b/elevate-scheduler/constants/routes.js index 8fa9655..46a1b6b 100644 --- a/elevate-scheduler/constants/routes.js +++ b/elevate-scheduler/constants/routes.js @@ -1,6 +1,44 @@ -module.exports = [ - { route: '/v1/get-user-photo', config: [{ type: 'GET' }] }, - { route: '/v1/get-user-profile', config: [{ type: 'POST' }] }, - { route: '/v1/get-sharelink', config: [{ type: 'PUT' }, { type: 'PATCH' }] }, - { route: '/v1/get-user-details', config: [{ type: 'DELETE' }] }, -]; +module.exports = { + routes: [ + { + sourceRoute: '/scheduler/jobs/create', + type: 'POST', + targetRoute: { + path: '/scheduler/jobs/create', + type: 'POST', + }, + }, + { + sourceRoute: '/scheduler/jobs/updateDelay', + type: 'POST', + targetRoute: { + path: '/scheduler/jobs/updateDelay', + type: 'POST', + }, + }, + { + sourceRoute: '/scheduler/jobs/remove', + type: 'POST', + targetRoute: { + path: '/scheduler/jobs/remove', + type: 'POST', + }, + }, + { + sourceRoute: '/scheduler/jobs/list', + type: 'GET', + targetRoute: { + path: '/scheduler/jobs/list', + type: 'GET', + }, + }, + { + sourceRoute: '/scheduler/jobs/purge', + type: 'POST', + targetRoute: { + path: '/scheduler/jobs/purge', + type: 'POST', + }, + } + ], +} diff --git a/elevate-scheduler/controllers/index.js b/elevate-scheduler/controllers/index.js deleted file mode 100644 index e69de29..0000000 diff --git a/elevate-scheduler/controllers/orchestrationController.js b/elevate-scheduler/controllers/orchestrationController.js new file mode 100644 index 0000000..714538b --- /dev/null +++ b/elevate-scheduler/controllers/orchestrationController.js @@ -0,0 +1,13 @@ +const routesConfig = require('../constants/routes') +// const notificationController = require('../controllers/scheduler') +const orchestrationHandler = async (req, res, responses) => { + console.log(req.targetPackages, req.inSequence, req.orchestrated, req.sourceRoute, responses) + console.log(req.body) + const selectedRouteConfig = routesConfig.routes.find((obj) => obj.sourceRoute === req.sourceRoute) + // return await notificationController[selectedRouteConfig.targetRoute.functionName](req, res, responses) +} + +const orchestrationController = { + orchestrationHandler, +} +module.exports = orchestrationController diff --git a/elevate-scheduler/controllers/scheduler.js b/elevate-scheduler/controllers/scheduler.js new file mode 100644 index 0000000..4904313 --- /dev/null +++ b/elevate-scheduler/controllers/scheduler.js @@ -0,0 +1 @@ +// Add logic if required \ No newline at end of file diff --git a/elevate-scheduler/index.js b/elevate-scheduler/index.js new file mode 100644 index 0000000..26a48c9 --- /dev/null +++ b/elevate-scheduler/index.js @@ -0,0 +1,13 @@ +const packageRouter = require('./router') + +const getPackageMeta = () => { + return { + basePackageName: 'scheduler', + packageName: 'elevate-scheduler', + } +} + +module.exports = { + packageMeta: getPackageMeta(), + packageRouter, +} diff --git a/elevate-scheduler/package.json b/elevate-scheduler/package.json index 0e24f32..9c8f8c8 100644 --- a/elevate-scheduler/package.json +++ b/elevate-scheduler/package.json @@ -1,6 +1,6 @@ { "name": "elevate-scheduler", - "version": "1.0.0", + "version": "1.0.4", "description": "Npm package for Elevate-Scheduler service integration with Interface service. ", "main": "index.js", "scripts": { @@ -14,6 +14,10 @@ "author": "Joffin Joy", "license": "ISC", "dependencies": { - "express": "^4.18.2" + "express": "^4.18.2", + "axios": "^1.4.0", + "lodash": "^4.17.21", + "node-fetch": "^2.7.0", + "path-to-regexp": "^6.2.1" } } diff --git a/elevate-scheduler/router/index.js b/elevate-scheduler/router/index.js new file mode 100644 index 0000000..a8b43a8 --- /dev/null +++ b/elevate-scheduler/router/index.js @@ -0,0 +1,10 @@ +const { passThroughRequester } = require('../utils/requester') +const { orchestrationHandler } = require('../controllers/orchestrationController') +const packageRouter = async (req, res, responses) => { + const response = req.orchestrated + ? await orchestrationHandler(req, res, responses) + : await passThroughRequester(req, res) + return response +} + +module.exports = packageRouter diff --git a/elevate-scheduler/utils/pathParamSetter.js b/elevate-scheduler/utils/pathParamSetter.js new file mode 100644 index 0000000..130b1fe --- /dev/null +++ b/elevate-scheduler/utils/pathParamSetter.js @@ -0,0 +1,6 @@ +exports.pathParamSetter = (targetPath, params) => { + return targetPath.replace(/:\w+/g, (match) => { + const fieldName = match.substring(1) + return params[fieldName] || match + }) +} diff --git a/elevate-scheduler/utils/patternMatcher.js b/elevate-scheduler/utils/patternMatcher.js new file mode 100644 index 0000000..18cd428 --- /dev/null +++ b/elevate-scheduler/utils/patternMatcher.js @@ -0,0 +1,16 @@ +exports.matchPathsAndExtractParams = (pattern, url) => { + const paramNames = [] + const regexPattern = new RegExp( + pattern.replace(/:(\w+)/g, (_, paramName) => { + paramNames.push(paramName) + return '([a-zA-Z0-9]+)' + }) + ) + const matchResult = url.match(regexPattern) + if (!matchResult) return false + const params = {} + for (let i = 0; i < paramNames.length; i++) { + params[paramNames[i]] = matchResult[i + 1] + } + return params +} diff --git a/elevate-scheduler/utils/requestParser.js b/elevate-scheduler/utils/requestParser.js new file mode 100644 index 0000000..5021d73 --- /dev/null +++ b/elevate-scheduler/utils/requestParser.js @@ -0,0 +1,8 @@ +const _ = require('lodash') + +exports.transformUpdateUserBody = (requestBody) => { + // Add Keys in the array to enable validation + const allowedKeys = [] + + return _.pick(requestBody, allowedKeys) +} diff --git a/elevate-scheduler/utils/requester.js b/elevate-scheduler/utils/requester.js new file mode 100644 index 0000000..78297ec --- /dev/null +++ b/elevate-scheduler/utils/requester.js @@ -0,0 +1,99 @@ +const http = require('http') +const https = require('https') +const { matchPathsAndExtractParams } = require('../utils/patternMatcher') +const routesConfig = require('../constants/routes') +const { pathParamSetter } = require('../utils/pathParamSetter') +const axios = require('axios') +const fetch = require('node-fetch') + +const handleInterfaceError = (res, err) => { + console.log('Error: ', err) + res.writeHead(500, { 'Content-Type': 'text/plain' }) + res.end('Interface Server Error') +} + +const passThroughRequester = async (req, res) => { + try { + const sourceBaseUrl = req.protocol + '://' + req.headers.host + '/' + const sourceUrl = new URL(req.originalUrl, sourceBaseUrl) + const route = routesConfig.routes.find((route) => route.sourceRoute === req.sourceRoute) + const params = matchPathsAndExtractParams(route.sourceRoute, req.originalUrl) + const targetRoute = pathParamSetter(route.targetRoute.path, params) + const parsedUrl = new URL(targetRoute, req.baseUrl) + const options = { + method: req.method, + headers: req.headers, + hostname: parsedUrl.hostname, + port: parsedUrl.port, + path: parsedUrl.pathname + sourceUrl.search, + } + console.log({ + sourceBaseUrl, + sourceUrl, + route, + params, + targetRoute, + parsedUrl, + options, + }) + const proxyReq = (parsedUrl.protocol === 'https:' ? https : http).request(options, (proxyRes) => { + res.writeHead(proxyRes.statusCode, proxyRes.headers) + proxyRes.pipe(res, { end: true }) + }) + proxyReq.on('error', (err) => { + handleInterfaceError(res, err) + }) + req.pipe(proxyReq, { end: true }) + } catch (err) { + handleInterfaceError(res, err) + } +} + +const post = (baseUrl, route, requestBody, headers) => { + try { + const url = baseUrl + route + return axios + .post(url, requestBody, { headers }) + .then((response) => response.data) + .catch((error) => { + if (error.response) { + return error.response + } + return error + }) + } catch (err) { + console.log(err) + throw err + } +} + +const patch = async (baseUrl, route, requestBody, headers) => { + try { + const url = baseUrl + route + return axios + .patch(url, requestBody, { + headers: { + 'X-auth-token': headers['x-auth-token'], + 'content-type': 'application/json', + }, + }) + .then((response) => response.data) + .catch((error) => { + if (error.response) { + return error.response + } + return error + }) + } catch (error) { + console.error(error) + throw error // Re-throw the error to be caught by the caller + } +} + +const requesters = { + passThroughRequester, + post, + patch, +} + +module.exports = requesters diff --git a/elevate-self-creation-portal/constants/routes.js b/elevate-self-creation-portal/constants/routes.js new file mode 100644 index 0000000..d426df8 --- /dev/null +++ b/elevate-self-creation-portal/constants/routes.js @@ -0,0 +1,555 @@ +module.exports = { + routes: [ + { + sourceRoute: '/scp/v1/permissions/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/permissions/list', + type: 'GET' + }, + }, + { + sourceRoute: '/scp/v1/config/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/config/list', + type: 'GET' + }, + }, + { + sourceRoute: '/scp/v1/form/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/form/create', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/form/read', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/form/read', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/form/read/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/form/read/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/form/update', + type: 'PUT', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/form/update', + type: 'PUT', + }, + }, + { + sourceRoute: '/scp/v1/form/update/:id', + type: 'PUT', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/form/update/:id', + type: 'PUT', + }, + }, + { + sourceRoute: '/scp/v1/entity-types/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entity-types/create', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/entity-types/read', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entity-types/read', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/entity-types/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entity-types/update', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/entity-types/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entity-types/update/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/entity-types/delete', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entity-types/delete', + type: 'DELETE', + }, + }, + { + sourceRoute: '/scp/v1/entity-types/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entity-types/delete/:id', + type: 'DELETE', + }, + }, + { + sourceRoute: '/scp/v1/entities/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/create', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/entities/read', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/read', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/entities/read/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/read/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/entities/update', + type: 'PUT', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/update', + type: 'PUT', + }, + }, + { + sourceRoute: '/scp/v1/entities/update/:id', + type: 'PUT', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/update/:id', + type: 'PUT', + }, + }, + { + sourceRoute: '/scp/v1/entities/delete', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/delete', + type: 'DELETE', + }, + }, + { + sourceRoute: '/scp/v1/entities/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/entities/delete/:id', + type: 'DELETE', + }, + }, + { + sourceRoute: '/scp/v1/projects/details/', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/details/', + type: 'GET' + }, + }, + { + sourceRoute: '/scp/v1/projects/details/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/details/:id', + type: 'GET' + }, + }, + { + sourceRoute: '/scp/v1/cloud-services/file/fetchJsonFromCloud', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/cloud-services/file/fetchJsonFromCloud', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/projects/reviewerList', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/reviewerList', + type: 'GET' + }, + }, + { + sourceRoute: '/scp/v1/projects/update', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/update', + type: 'POST' + }, + }, + { + sourceRoute: '/scp/v1/projects/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/update/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/scp/v1/projects/update/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/update/:id', + type: 'POST' + }, + }, + { + sourceRoute: '/scp/v1/permissions/create', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/permissions/create', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/permissions/update/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/permissions/update/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/permissions/getPermissions', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/permissions/getPermissions', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/permissions/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/permissions/delete/:id', + type: 'DELETE', + }, + }, + { + sourceRoute: '/scp/v1/modules/create', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/modules/create', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/modules/update/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/modules/update/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/modules/list', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/modules/list', + type: 'GET', + }, + }, + { + sourceRoute: '/scp/v1/modules/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/modules/delete/:id', + type: 'DELETE', + }, + }, + { + sourceRoute: '/scp/v1/certificate/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/certificate/list', + type: 'GET' + }, + }, + { + sourceRoute: '/scp/v1/resource/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/resource/list', + type: 'GET' + }, + }, + { + sourceRoute: '/scp/v1/resource/upForReview', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/resource/upForReview', + type: 'GET' + }, + }, + { + sourceRoute: '/scp/v1/role-permission-mapping/delete/:role_id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/role-permission-mapping/delete/:role_id', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/role-permission-mapping/create/:role_id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/role-permission-mapping/create/:role_id', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/role-permission-mapping/list', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/role-permission-mapping/list', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/projects/submitForReview/', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/submitForReview/', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/projects/submitForReview/:resource_id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/projects/submitForReview/:resource_id', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/comments/list', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/comments/list', + type: 'GET', + }, + }, + { + sourceRoute: '/scp/v1/comments/update', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/comments/update', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/comments/update/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/comments/update/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/reviews/update/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/reviews/update/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/reviews/start/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/reviews/start/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/reviews/approve/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/reviews/approve/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/scp/v1/reviews/rejectOrReport/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/reviews/rejectOrReport/:id', + type: 'POST', + }, + }, + { + sourceRoute: "/scp/v1/resource/browseExisting", + type: 'GET', + priority: "MUST_HAVE", + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/resource/browseExisting', + type: 'GET', + }, + }, + { + sourceRoute: '/scp/v1/cloud-services/file/getSignedUrl', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/cloud-services/file/getSignedUrl', + type: 'POST' + }, + }, + { + sourceRoute: '/scp/v1/cloud-services/file/getDownloadableUrl', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/scp/v1/cloud-services/file/getDownloadableUrl', + type: 'POST' + }, + }, + + + ], +} diff --git a/elevate-self-creation-portal/controllers/orchestrationController.js b/elevate-self-creation-portal/controllers/orchestrationController.js new file mode 100644 index 0000000..24f560c --- /dev/null +++ b/elevate-self-creation-portal/controllers/orchestrationController.js @@ -0,0 +1,13 @@ +const routesConfig = require('../constants/routes') +const entityController = require('../controllers/selfcreationportal') +const orchestrationHandler = async (req, res, responses) => { + console.log(req.targetPackages, req.inSequence, req.orchestrated, req.sourceRoute, responses) + console.log(req.body) + const selectedRouteConfig = routesConfig.routes.find((obj) => obj.sourceRoute === req.sourceRoute) + return await entityController[selectedRouteConfig.targetRoute.functionName](req, res, responses) +} + +const orchestrationController = { + orchestrationHandler, +} +module.exports = orchestrationController diff --git a/elevate-self-creation-portal/controllers/selfcreationportal.js b/elevate-self-creation-portal/controllers/selfcreationportal.js new file mode 100644 index 0000000..213249d --- /dev/null +++ b/elevate-self-creation-portal/controllers/selfcreationportal.js @@ -0,0 +1,8 @@ +const routeConfigs = require('../constants/routes') +const requesters = require('../utils/requester') +const requestParser = require('../utils/requestParser') + +const creationController = { +} + +module.exports = creationController diff --git a/elevate-self-creation-portal/index.js b/elevate-self-creation-portal/index.js new file mode 100644 index 0000000..e7b1b3a --- /dev/null +++ b/elevate-self-creation-portal/index.js @@ -0,0 +1,37 @@ +const express = require('express') +const router = express.Router() +const routes = require('./constants/routes') +const packageRouter = require('./router') + +const getDependencies = () => { + return ['kafka', 'kafka-connect', 'redis'] +} + +const getPackageMeta = () => { + return { + basePackageName: 'self_creation_portal', + packageName: 'elevate-self-creation-portal', + } +} + +const createPackage = (options) => { + return { + router: () => { + console.log('router') + }, + endpoints: [], + dependencies: [], + } +} + +router.get('/', (req, res) => { + res.send('Hello, world! From self-creation-portal') +}) + +module.exports = { + dependencies: getDependencies(), + routes, + createPackage, + packageMeta: getPackageMeta(), + packageRouter, +} diff --git a/elevate-self-creation-portal/package-lock.json b/elevate-self-creation-portal/package-lock.json new file mode 100644 index 0000000..bb26c24 --- /dev/null +++ b/elevate-self-creation-portal/package-lock.json @@ -0,0 +1,582 @@ +{ + "name": "elevate-self-creation-portal", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "requires": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + } + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "requires": { + "get-intrinsic": "^1.2.4" + } + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + } + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + } + }, + "follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "requires": { + "es-define-property": "^1.0.0" + } + }, + "has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==" + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } +} diff --git a/elevate-self-creation-portal/package.json b/elevate-self-creation-portal/package.json new file mode 100644 index 0000000..a652bad --- /dev/null +++ b/elevate-self-creation-portal/package.json @@ -0,0 +1,19 @@ +{ + "name": "elevate-self-creation-portal", + "version": "1.0.24", + "description": "Npm package for Elevate-self-creation-portal service integration with Interface service", + "main": "index.js", + "dependencies": { + "axios": "^1.4.0", + "express": "^4.18.2", + "lodash": "^4.17.21", + "node-fetch": "^2.7.0", + "path-to-regexp": "^6.2.1" + }, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Adithya Dinesh", + "license": "ISC" +} diff --git a/elevate-self-creation-portal/router/index.js b/elevate-self-creation-portal/router/index.js new file mode 100644 index 0000000..a8b43a8 --- /dev/null +++ b/elevate-self-creation-portal/router/index.js @@ -0,0 +1,10 @@ +const { passThroughRequester } = require('../utils/requester') +const { orchestrationHandler } = require('../controllers/orchestrationController') +const packageRouter = async (req, res, responses) => { + const response = req.orchestrated + ? await orchestrationHandler(req, res, responses) + : await passThroughRequester(req, res) + return response +} + +module.exports = packageRouter diff --git a/elevate-self-creation-portal/utils/pathParamSetter.js b/elevate-self-creation-portal/utils/pathParamSetter.js new file mode 100644 index 0000000..130b1fe --- /dev/null +++ b/elevate-self-creation-portal/utils/pathParamSetter.js @@ -0,0 +1,6 @@ +exports.pathParamSetter = (targetPath, params) => { + return targetPath.replace(/:\w+/g, (match) => { + const fieldName = match.substring(1) + return params[fieldName] || match + }) +} diff --git a/elevate-self-creation-portal/utils/patternMatcher.js b/elevate-self-creation-portal/utils/patternMatcher.js new file mode 100644 index 0000000..f35cd53 --- /dev/null +++ b/elevate-self-creation-portal/utils/patternMatcher.js @@ -0,0 +1,16 @@ +exports.matchPathsAndExtractParams = (pattern, url) => { + const paramNames = [] + const regexPattern = new RegExp( + pattern.replace(/:(\w+)/g, (_, paramName) => { + paramNames.push(paramName) + return '([a-zA-Z0-9]+)' + }) + ) + const matchResult = url.match(regexPattern) + if (!matchResult) return false + const params = {} + for (let i = 0; i < paramNames.length; i++) { + params[paramNames[i]] = matchResult[i + 1] + } + return params +} \ No newline at end of file diff --git a/elevate-self-creation-portal/utils/requestParser.js b/elevate-self-creation-portal/utils/requestParser.js new file mode 100644 index 0000000..ecd12e5 --- /dev/null +++ b/elevate-self-creation-portal/utils/requestParser.js @@ -0,0 +1,6 @@ +const _ = require('lodash') + +// exports.transformUpdateUserBody = (requestBody) => { +// const allowedKeys = ['name', 'email', 'image', 'location', 'about', 'preferred_language'] +// return _.pick(requestBody, allowedKeys) +// } diff --git a/elevate-self-creation-portal/utils/requester.js b/elevate-self-creation-portal/utils/requester.js new file mode 100644 index 0000000..aec6ac1 --- /dev/null +++ b/elevate-self-creation-portal/utils/requester.js @@ -0,0 +1,121 @@ +const http = require('http') +const https = require('https') +const { matchPathsAndExtractParams } = require('../utils/patternMatcher') +const routesConfig = require('../constants/routes') +const { pathParamSetter } = require('../utils/pathParamSetter') +const axios = require('axios') +const fetch = require('node-fetch') + +const handleInterfaceError = (res, err) => { + console.log('Error: ', err) + res.writeHead(500, { 'Content-Type': 'text/plain' }) + res.end('Interface Server Error') +} + +const passThroughRequester = async (req, res) => { + try { + const sourceBaseUrl = req.protocol + '://' + req.headers.host + '/' + const sourceUrl = new URL(req.originalUrl, sourceBaseUrl) + const route = routesConfig.routes.find((route) => route.sourceRoute === req.sourceRoute) + const params = matchPathsAndExtractParams(route.sourceRoute, req.originalUrl) + console.log(params,'params') + const targetRoute = pathParamSetter(route.targetRoute.path, params) + console.log(route.targetRoute.path, params,'route.targetRoute.path, params') + console.log(targetRoute,'targetRoute') + console.log(req.baseUrl,'req.baseUrl') + const parsedUrl = new URL(targetRoute, req.baseUrl) + const options = { + method: req.method, + headers: req.headers, + hostname: parsedUrl.hostname, + port: parsedUrl.port, + path: parsedUrl.pathname + sourceUrl.search, + } + console.log({ + sourceBaseUrl, + sourceUrl, + route, + params, + targetRoute, + parsedUrl, + options, + }) + const proxyReq = (parsedUrl.protocol === 'https:' ? https : http).request(options, (proxyRes) => { + res.writeHead(proxyRes.statusCode, proxyRes.headers) + proxyRes.pipe(res, { end: true }) + }) + proxyReq.on('error', (err) => { + handleInterfaceError(res, err) + }) + req.pipe(proxyReq, { end: true }) + } catch (err) { + handleInterfaceError(res, err) + } +} + +const post = (baseUrl, route, requestBody, headers) => { + const url = baseUrl + route + return axios + .post(url, requestBody, { headers }) + .then((response) => response.data) + .catch((error) => { + if (error.response) { + return error.response + } + return error + }) +} +const patch = async (baseUrl, route, requestBody, headers) => { + try { + const url = baseUrl + route + + const options = { + method: 'PATCH', + headers: headers, + body: JSON.stringify(requestBody), + } + + const response = await fetch(url, options) + + const data = await response.json() + return data + } catch (error) { + console.error(error) + throw error + } +} +const axiosPatch = async (baseUrl, route, requestBody, headers) => { + try { + const url = baseUrl + route + console.log(url, requestBody) + const config = { + headers: headers, + } + axios + .patch(url, requestBody, config) + .then((response) => { + // Handle the successful response here + console.log('PATCH request successful:', response.data) + return response.data + }) + .catch((error) => { + // Handle any errors that occurred during the PATCH request + console.error('Error making PATCH request:', error) + if (error.response) { + return error.response + } + return error + }) + } catch (error) { + console.error('Error making PATCH request:', error) + } +} + +const requesters = { + passThroughRequester, + post, + patch, + axiosPatch, +} + +module.exports = requesters \ No newline at end of file diff --git a/elevate-survey/constants/common.js b/elevate-survey/constants/common.js new file mode 100644 index 0000000..29a28dd --- /dev/null +++ b/elevate-survey/constants/common.js @@ -0,0 +1,23 @@ +/** + * name : constants/common.js + * author : Adithya Dinesh + * Date : 23 - Aug - 2024 + * Description : All commonly used constants through out the package + */ + +module.exports = { + RESOURCE_STATUS_ACTIVE : 'active', + RESOURCE_PROJECTION_FIELDS : ["_id" ,'type' , "name","author","createdAt","isRubricDriven"], + RESOURCE_TYPE_OBSERVATION : 'observation', + RESOURCE_TYPE_SURVEY : 'survey', + RESOURCE_TYPE_KEY : 'type', + RESOURCE_IS_RUBRIC_DRIVEN_KEY : 'isRubricDriven', + RESOURCE_TYPE_OBSERVATION_WITH_RUBRICS : 'observation_with_rubrics', + RESOURCE_TRANSFORM_KEYS : { + _id : "id", + name : 'title', + createdAt : "created_at", + author : "created_by" + }, + AUTH_TOKEN_KEY : 'x-auth-token' +} \ No newline at end of file diff --git a/elevate-survey/constants/routes.js b/elevate-survey/constants/routes.js index cce1e25..05d2f3b 100644 --- a/elevate-survey/constants/routes.js +++ b/elevate-survey/constants/routes.js @@ -840,6 +840,27 @@ module.exports = { type: 'POST' }, }, + { + sourceRoute: '/samiksha/v1/programs/targetedPrograms', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/samiksha/v1/programs/targetedPrograms', + type: 'POST' + }, + }, + { + sourceRoute: '/interface/v1/internal/getAllPublishedResources', + type: 'POST', + inSequence: false, + orchestrated: true, + targetRoute: { + path: '/samiksha/v1/admin/dbFind/solutions', + type: 'POST', + functionName: 'fetchObserbationAndSurvey', + }, + }, ], } diff --git a/elevate-survey/controllers/orchestrationController.js b/elevate-survey/controllers/orchestrationController.js index e9513d9..2705233 100644 --- a/elevate-survey/controllers/orchestrationController.js +++ b/elevate-survey/controllers/orchestrationController.js @@ -1,10 +1,10 @@ const routesConfig = require('../constants/routes') -const samikshaController = require('./project') +const surveyController = require('./survey') const orchestrationHandler = async (req, res, responses) => { console.log(req.targetPackages, req.inSequence, req.orchestrated, req.sourceRoute, responses) console.log(req.body) const selectedRouteConfig = routesConfig.routes.find((obj) => obj.sourceRoute === req.sourceRoute) - return await samikshaController[selectedRouteConfig.targetRoute.functionName](req, res, responses) + return await surveyController[selectedRouteConfig.targetRoute.functionName](req, res, responses) } const orchestrationController = { diff --git a/elevate-survey/controllers/project.js b/elevate-survey/controllers/project.js deleted file mode 100644 index 31bcf88..0000000 --- a/elevate-survey/controllers/project.js +++ /dev/null @@ -1,29 +0,0 @@ -// const routeConfigs = require('../constants/routes') -// const requesters = require('../utils/requester') -// const requestParser = require('../utils/requestParser') - -// const createUser = async (req, res, responses) => { -// const selectedConfig = routeConfigs.routes.find((obj) => obj.sourceRoute === req.sourceRoute) -// return await requesters.post(req.baseUrl, selectedConfig.targetRoute.path, req.body) -// } -// const updateUser = async (req, res, responses) => { -// const selectedConfig = routeConfigs.routes.find((obj) => obj.sourceRoute === req.sourceRoute) - -// //const filteredRequestBody = requestParser.transformUpdateUserBody(req.body) -// return await requesters.patch(req.baseUrl, selectedConfig.targetRoute.path, req.body, req.headers) -// } - -// const entityTypeRead = async (req, res, responses) => { -// const selectedConfig = routeConfigs.routes.find((obj) => obj.sourceRoute === req.sourceRoute) -// return await requesters.post(req.baseUrl, selectedConfig.targetRoute.path, req.body, { -// 'X-auth-token': req.headers['x-auth-token'], -// }) -// } - -const userController = { - // createUser, - // updateUser, - // entityTypeRead, -} - -module.exports = userController diff --git a/elevate-survey/controllers/survey.js b/elevate-survey/controllers/survey.js new file mode 100644 index 0000000..983e37c --- /dev/null +++ b/elevate-survey/controllers/survey.js @@ -0,0 +1,116 @@ +/** + * name : controllers/project.js + * author : Adithya Dinesh + * Date : 22-Aug-2024 + * Description : Orchestration controller for Samiksha service + */ + +const routeConfigs = require('../constants/routes') +const requesters = require('../utils/requester') +const common = require('../constants/common') + +/** + * Fetch resources from Samiksha service. + * @name fetchSamikshaTemplates + * @param {Object} req + * @param {Object} res + * @param {Object} responses + * @returns {JSON} - List of resources + */ +/** + * req.body = { + * organization_id : 1, + * resourceType : ['survey','projects'] + * } + */ + + +const fetchObserbationAndSurvey = async (req, res, responses) => { + const selectedConfig = routeConfigs.routes.find((obj) => obj.sourceRoute === req.sourceRoute) + + let response = {result: {data: [],count: 0}} + let proceedToCallProjectService = false + let resp = {} + const max_limit = process.env.RESOURCE_MAX_FETCH_LIMIT ? parseInt(process.env.RESOURCE_MAX_FETCH_LIMIT, 10) : 1000 + // request body for samiksha service + let reqBody = { query : { } } + + + if(req.body){ + // check if body has key resourceType else assign [] + const resourceType = req?.body?.resourceType || []; + if (Array.isArray(resourceType) && resourceType.length > 0) { + // if resource type have type = survey , observations or observation_with_rubrics proceed to call api + proceedToCallProjectService = resourceType.includes(common.RESOURCE_TYPE_OBSERVATION) || resourceType.includes(common.RESOURCE_TYPE_OBSERVATION_WITH_RUBRICS) || resourceType.includes(common.RESOURCE_TYPE_SURVEY); + + // body queries for samiksha service - based on specific resource type + if(req?.body?.resourceType.includes(common.RESOURCE_TYPE_OBSERVATION)){ + body.query.type = common.RESOURCE_TYPE_OBSERVATION + body.query.isRubricDriven = false + }else if(req?.body?.resourceType.includes(common.RESOURCE_TYPE_OBSERVATION_WITH_RUBRICS)){ + body.query.type = common.RESOURCE_TYPE_OBSERVATION + body.query.isRubricDriven = true + }else if(req?.body?.resourceType.includes(common.RESOURCE_TYPE_SURVEY)){ + body.query.type = common.RESOURCE_TYPE_SURVEY + } + }else if(Array.isArray(resourceType) || resourceType.length == 0){ + // if resource type have type = empty call API because the client is expecting all type of resources + proceedToCallProjectService = true + } + + } + if(proceedToCallProjectService && req.headers[common.AUTH_TOKEN_KEY]){ + // body queries for samiksha service - generic + reqBody.query.isReusable = true + reqBody.query.isDeleted = false + reqBody.query.isAPrivateProgram = false + reqBody.query.status = common.RESOURCE_STATUS_ACTIVE + reqBody.projection= common.RESOURCE_PROJECTION_FIELDS + reqBody.limit = max_limit + // replace the word bearer if token has it + const x_auth_token = req.headers[common.AUTH_TOKEN_KEY].replace(/^(Bearer|bearer)\s*/, ''); + let header = { + 'internal-access-token' : req.headers['internal_access_token'], + 'Content-Type' : 'application/json', + 'X-auth-token' : x_auth_token + } + + if (req?.body && req.body?.search) { + reqBody.query.name = { + "$regex": req.body.search, + "$options": 'i' + } + } + + // fetch data from the service + resp = await requesters.post(req.baseUrl, selectedConfig.targetRoute.path, reqBody , header) + } + + if (resp?.result?.length > 0) { + let data = [] + // transform the result to fit in the service + resp.result.reduce((accumulateResource,resources) => { + accumulateResource = {} + for(let resource in resources){ + let newKey = common.RESOURCE_TRANSFORM_KEYS[resource] || resource + accumulateResource[newKey] = resources[resource] + } + // check if resource is an observation with rubrics + // if it is observation with rubrics update the type value + if(resources[common.RESOURCE_TYPE_KEY] == common.RESOURCE_TYPE_OBSERVATION && resources[common.RESOURCE_IS_RUBRIC_DRIVEN_KEY] == true) { + accumulateResource[common.RESOURCE_TYPE_KEY] = common.RESOURCE_TYPE_OBSERVATION_WITH_RUBRICS + } + data.push(accumulateResource) + },null) + + response.result.data = data + } + + return response +} + +const surveyController = { + fetchObserbationAndSurvey +} + +module.exports = surveyController diff --git a/elevate-user/constants/routes.js b/elevate-user/constants/routes.js index e8d4ad1..581b80a 100644 --- a/elevate-user/constants/routes.js +++ b/elevate-user/constants/routes.js @@ -33,6 +33,28 @@ module.exports = { functionName: 'createUser', }, }, + { + sourceRoute: '/interface/v1/entity-type/read', + type: 'POST', + inSequence: false, + orchestrated: true, + targetRoute: { + path: '/user/v1/entity-type/read', + type: 'POST', + functionName: 'entityTypeRead', + }, + }, + { + sourceRoute: '/interface/v1/account/login', + type: 'POST', + inSequence: true, + orchestrated: true, + targetRoute: { + path: '/user/v1/account/login', + type: 'POST', + functionName: 'loginUser', + }, + }, { sourceRoute: '/user/v1/account/login', type: 'POST', @@ -105,16 +127,26 @@ module.exports = { }, { sourceRoute: '/user/v1/account/registrationOtp', - type: 'GET', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { path: '/user/v1/account/registrationOtp', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/user/read/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/user/read/:id', type: 'GET', }, }, { - sourceRoute: '/user/v1/user/read/:userId', + sourceRoute: '/user/v1/user/read', type: 'GET', inSequence: false, orchestrated: false, @@ -135,24 +167,74 @@ module.exports = { }, { sourceRoute: '/user/v1/user/share', - type: 'POST', + type: 'GET', inSequence: false, orchestrated: false, targetRoute: { path: '/user/v1/user/share', - type: 'POST', + type: 'GET', }, }, { - sourceRoute: '/user/v1/userRole/list', + sourceRoute: '/user/v1/user/share/:id', type: 'GET', inSequence: false, orchestrated: false, targetRoute: { - path: '/user/v1/userRole/list', + path: '/user/v1/user/share/:id', type: 'GET', }, }, + { + sourceRoute: '/user/v1/user-role/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/user-role/list', + type: 'GET', + }, + }, + { + sourceRoute: '/user/v1/user-role/default', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/user-role/default', + type: 'GET', + }, + }, + { + sourceRoute: '/user/v1/user-role/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/user-role/create', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/user-role/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/user-role/update/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/user-role/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/user-role/delete/:id', + type: 'DELETE', + }, + }, { sourceRoute: '/user/v1/form/create', type: 'POST', @@ -165,12 +247,20 @@ module.exports = { }, { sourceRoute: '/user/v1/form/read', - type: 'GET', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { path: '/user/v1/form/read', - type: 'GET', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/form/read/:id', + type: 'POST', + targetRoute: { + path: '/user/v1/form/read/:id', + type: 'POST', }, }, { @@ -193,6 +283,14 @@ module.exports = { type: 'GET', }, }, + { + sourceRoute: '/user/v1/cloud-services/file/getDownloadableUrl', + type: 'GET', + targetRoute: { + path: '/user/v1/cloud-services/file/getDownloadableUrl', + type: 'GET', + }, + }, { sourceRoute: '/user/v1/admin/deleteUser', type: 'DELETE', @@ -203,6 +301,16 @@ module.exports = { type: 'DELETE', }, }, + { + sourceRoute: '/user/v1/admin/deleteUser/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/admin/deleteUser/:id', + type: 'DELETE', + }, + }, { sourceRoute: '/user/v1/admin/create', type: 'POST', @@ -215,12 +323,12 @@ module.exports = { }, { sourceRoute: '/user/v1/admin/login', - type: 'GET', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { path: '/user/v1/admin/login', - type: 'GET', + type: 'POST', }, }, { @@ -243,6 +351,16 @@ module.exports = { type: 'PATCH', }, }, + { + sourceRoute: '/user/v1/organization/update/:id', + type: 'PATCH', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/organization/update/:id', + type: 'PATCH', + }, + }, { sourceRoute: '/user/v1/organization/list', type: 'GET', @@ -273,14 +391,24 @@ module.exports = { type: 'PATCH', }, }, + { + sourceRoute: '/user/v1/entity-type/update/:id', + type: 'PATCH', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/entity-type/update/:id', + type: 'PATCH', + }, + }, { sourceRoute: '/user/v1/entity-type/read', - type: 'GET', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { path: '/user/v1/entity-type/read', - type: 'GET', + type: 'POST', }, }, { @@ -293,6 +421,16 @@ module.exports = { type: 'DELETE', }, }, + { + sourceRoute: '/user/v1/entity-type/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/entity-type/delete/:id', + type: 'DELETE', + }, + }, { sourceRoute: '/user/v1/entity/create', type: 'POST', @@ -314,26 +452,823 @@ module.exports = { }, }, { - sourceRoute: '/user/v1/entity/delete', + sourceRoute: '/user/v1/entity/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/entity/update/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/entity/delete/:id', type: 'DELETE', inSequence: false, orchestrated: false, targetRoute: { - path: '/user/v1/entity/delete', + path: '/user/v1/entity/delete/:id', type: 'DELETE', }, }, { sourceRoute: '/user/v1/entity/read', - type: 'GET', + type: 'POST', inSequence: false, orchestrated: false, targetRoute: { path: '/user/v1/entity/read', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/org-admin/inheritEntityType', + type: 'POST', + targetRoute: { + path: '/user/v1/org-admin/inheritEntityType', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/organization/read', + type: 'GET', + targetRoute: { + path: '/user/v1/organization/read', + type: 'GET', + }, + }, + { + sourceRoute: '/user/v1/admin/addOrgAdmin', + type: 'POST', + targetRoute: { + path: '/user/v1/admin/addOrgAdmin', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/org-admin/bulkUserCreate', + type: 'POST', + targetRoute: { + path: '/user/v1/org-admin/bulkUserCreate', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/org-admin/getBulkInvitesFilesList', + type: 'GET', + targetRoute: { + path: '/user/v1/org-admin/getBulkInvitesFilesList', + type: 'GET', + }, + }, + { + sourceRoute: '/user/v1/org-admin/getRequestDetails/:id', + type: 'GET', + targetRoute: { + path: '/user/v1/org-admin/getRequestDetails/:id', + type: 'GET', + }, + }, + { + sourceRoute: '/user/v1/org-admin/deactivateUser', + type: 'POST', + targetRoute: { + path: '/user/v1/org-admin/deactivateUser', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/org-admin/getRequests', + type: 'POST', + targetRoute: { + path: '/user/v1/org-admin/getRequests', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/org-admin/updateRequestStatus', + type: 'POST', + targetRoute: { + path: '/user/v1/org-admin/updateRequestStatus', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/organization/requestOrgRole', + type: 'POST', + targetRoute: { + path: '/user/v1/organization/requestOrgRole', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/admin/deactivateOrg/:id', + type: 'POST', + targetRoute: { + path: '/user/v1/admin/deactivateOrg/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/notification/create', + type: 'POST', + targetRoute: { + path: '/user/v1/notification/create', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/notification/update/:id', + type: 'PATCH', + targetRoute: { + path: '/user/v1/notification/update/:id', + type: 'PATCH', + }, + }, + { + sourceRoute: '/user/v1/notification/read/:id', + type: 'GET', + targetRoute: { + path: '/user/v1/notification/read/:id', + type: 'GET', + }, + }, + { + sourceRoute: '/user/v1/notification/read', + type: 'GET', + targetRoute: { + path: '/user/v1/notification/read', + type: 'GET', + }, + }, + { + sourceRoute: '/user/v1/cloud-services/file/getSampleCSV', + type: 'GET', + targetRoute: { + path: '/user/v1/cloud-services/file/getSampleCSV', + type: 'GET', + }, + }, + { + sourceRoute: '/user/v1/notification/template', + type: 'POST', + targetRoute: { + path: '/user/v1/notification/template', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/notification/template/:id', + type: 'GET', + targetRoute: { + path: '/user/v1/notification/template/:id', type: 'GET', }, }, - ], + { + sourceRoute: '/user/v1/notification/template', + type: 'PATCH', + targetRoute: { + path: '/user/v1/notification/template', + type: 'PATCH', + }, + }, + { + sourceRoute: '/user/v1/account/search', + type: 'POST', + targetRoute: { + path: '/user/v1/account/search', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/permissions/create', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/permissions/create', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/permissions/update/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/permissions/update/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/permissions/list', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/permissions/list', + type: 'GET', + }, + }, + { + sourceRoute: '/user/v1/permissions/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/permissions/delete/:id', + type: 'DELETE', + }, + }, + { + sourceRoute: '/user/v1/modules/create', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/modules/create', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/modules/update/:id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/modules/update/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/modules/list', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/modules/list', + type: 'GET', + }, + }, + { + sourceRoute: '/user/v1/modules/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/modules/delete/:id', + type: 'DELETE', + }, + }, + { + sourceRoute: '/user/v1/role-permission-mapping/delete/:role_id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/role-permission-mapping/delete/:role_id', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/role-permission-mapping/create/:role_id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/role-permission-mapping/create/:role_id', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/role-permission-mapping/list', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/role-permission-mapping/list', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/org-admin/updateUser', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/org-admin/updateUser', + type: 'POST' + }, + }, + { + sourceRoute: '/user/v1/organization/addRelatedOrg/:org_id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/organization/addRelatedOrg/:org_id', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/organization/removeRelatedOrg/:org_id', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/organization/removeRelatedOrg/:org_id', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/account/changePassword', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/account/changePassword', + type: 'POST', + }, + }, + { + sourceRoute: '/user/v1/account/searchByEmailIds', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/account/searchByEmailIds', + } + }, + { + sourceRoute: '/user/v1/account/sessions', + type: 'GET', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/account/sessions', + type: 'GET', + } + }, + { + sourceRoute: '/user/v1/account/validateUserSession', + type: 'POST', + priority: 'MUST_HAVE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/account/validateUserSession', + type: 'POST', + } + }, + { + sourceRoute: '/interface/v2/account/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v2/account/create', + type: 'POST' + }, + }, + { + sourceRoute: '/interface/v2/account/update', + type: 'PATCH', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/user/update', + type: 'POST' + }, + }, + { + sourceRoute: '/elevate-user/v2/account/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v2/account/create', + type: 'POST' + }, + }, + { + sourceRoute: '/elevate-user/v2/account/login', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v2/account/login', + type: 'POST' + }, + }, + { + sourceRoute: '/elevate-interface/v2/account/login', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/account/login', + type: 'POST' + }, + }, + { + sourceRoute: '/elevate-user/v2/account/update', + type: 'PATCH', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/user/update', + type: 'POST' + }, + }, + { + sourceRoute: '/user/v1/account/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/account/create', + type: 'POST' + }, + }, + { + sourceRoute: '/elevate-interface/v1/account/login', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/account/login', + type: 'POST' + }, + }, + { + sourceRoute: '/elevate-interface/v1/account/update', + type: 'PATCH', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/user/update', + type: 'POST' + }, + }, + { + sourceRoute: '/user/v1/org-admin/updateUser', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/org-admin/updateUser', + type: 'POST' + }, + }, + { + sourceRoute: '/elevate-user/v1/account/login', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/account/login', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/account/acceptTermsAndCondition', + type: 'PATCH', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/account/acceptTermsAndCondition', + type: 'PATCH', + }, + }, + { + sourceRoute: '/elevate-user/v1/account/resetPassword', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/account/resetPassword', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/account/generateToken', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/account/generateToken', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/account/generateOtp', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/account/generateOtp', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/account/logout', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/account/logout', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/account/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/account/list', + type: 'GET', + }, + }, + { + sourceRoute: '/elevate-user/v1/account/registrationOtp', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/account/registrationOtp', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/user/read/:id', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/user/read/:id', + type: 'GET', + }, + }, + { + sourceRoute: '/elevate-user/v1/user/read', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/user/read', + type: 'GET', + }, + }, + { + sourceRoute: '/elevate-user/v1/user/update', + type: 'PATCH', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/user/update', + type: 'PATCH', + }, + }, + { + sourceRoute: '/elevate-user/v1/user/share', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/user/share', + type: 'GET', + }, + }, + { + sourceRoute: '/elevate-user/v1/user-role/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/user-role/list', + type: 'GET', + }, + }, + { + sourceRoute: '/elevate-user/v1/user-role/default', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/user-role/default', + type: 'GET', + }, + }, + { + sourceRoute: '/elevate-user/v1/user-role/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/user-role/create', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/user-role/update/:id', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/user-role/update/:id', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/user-role/delete/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/user-role/delete/:id', + type: 'DELETE', + }, + }, + { + sourceRoute: '/elevate-user/v1/admin/deleteUser', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/admin/deleteUser', + type: 'DELETE', + }, + }, + { + sourceRoute: '/elevate-user/v1/admin/deleteUser/:id', + type: 'DELETE', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/admin/deleteUser/:id', + type: 'DELETE', + }, + }, + { + sourceRoute: '/elevate-user/v1/admin/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/admin/create', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/admin/login', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/admin/login', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/organization/create', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/organization/create', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/organization/update', + type: 'PATCH', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/organization/update', + type: 'PATCH', + }, + }, + { + sourceRoute: '/elevate-user/v1/organization/update/:id', + type: 'PATCH', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/organization/update/:id', + type: 'PATCH', + }, + }, + { + sourceRoute: '/elevate-user/v1/organization/list', + type: 'GET', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/organization/list', + type: 'GET', + }, + }, + { + sourceRoute: '/elevate-user/v1/organization/read', + type: 'GET', + targetRoute: { + path: '/elevate-user/v1/organization/read', + type: 'GET', + }, + }, + { + sourceRoute: '/elevate-user/v1/admin/addOrgAdmin', + type: 'POST', + targetRoute: { + path: '/elevate-user/v1/admin/addOrgAdmin', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/account/search', + type: 'POST', + targetRoute: { + path: '/elevate-user/v1/account/search', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/account/searchByEmailIds', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/account/searchByEmailIds', + type: 'POST', + } + }, + { + sourceRoute: '/elevate-user/v1/org-admin/updateUser', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/elevate-user/v1/org-admin/updateUser', + type: 'POST' + } + }, + { + sourceRoute: '/elevate-user/v1/account/generateOtp', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/account/generateOtp', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/account/resetPassword', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/account/resetPassword', + type: 'POST', + }, + }, + { + sourceRoute: '/elevate-user/v1/account/acceptTermsAndCondition', + type: 'PATCH', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/account/acceptTermsAndCondition', + type: 'PATCH', + }, + }, + { + sourceRoute: '/elevate-user/v1/account/logout', + type: 'POST', + inSequence: false, + orchestrated: false, + targetRoute: { + path: '/user/v1/account/logout', + type: 'POST', + }, + }, + ] } /* const fs = require('fs') diff --git a/elevate-user/controllers/user.js b/elevate-user/controllers/user.js index 7fbe7f7..a5c72cd 100644 --- a/elevate-user/controllers/user.js +++ b/elevate-user/controllers/user.js @@ -4,17 +4,37 @@ const requestParser = require('../utils/requestParser') const createUser = async (req, res, responses) => { const selectedConfig = routeConfigs.routes.find((obj) => obj.sourceRoute === req.sourceRoute) - return await requesters.post(req.baseUrl, selectedConfig.targetRoute.path, req.body) + return await requesters.post(req.baseUrl, selectedConfig.targetRoute.path, req.body,{ + 'device-info': req.headers['device-info'], + }) } const updateUser = async (req, res, responses) => { const selectedConfig = routeConfigs.routes.find((obj) => obj.sourceRoute === req.sourceRoute) - const filteredRequestBody = requestParser.transformUpdateUserBody(req.body) - return await requesters.patch(req.baseUrl, selectedConfig.targetRoute.path, filteredRequestBody, req.headers) + //const filteredRequestBody = requestParser.transformUpdateUserBody(req.body) + return await requesters.patch(req.baseUrl, selectedConfig.targetRoute.path, req.body, req.headers) } + +const entityTypeRead = async (req, res, responses) => { + const selectedConfig = routeConfigs.routes.find((obj) => obj.sourceRoute === req.sourceRoute) + return await requesters.post(req.baseUrl, selectedConfig.targetRoute.path, req.body, { + 'X-auth-token': req.headers['x-auth-token'], + }) +} + +const loginUser = async (req, res, responses) => { + const selectedConfig = routeConfigs.routes.find((obj) => obj.sourceRoute === req.sourceRoute) + return await requesters.post(req.baseUrl, selectedConfig.targetRoute.path, req.body,{ + 'captcha-token': req.headers['captcha-token'], + 'device-info': req.headers['device-info'], + }) +} + const userController = { createUser, updateUser, + entityTypeRead, + loginUser, } module.exports = userController diff --git a/elevate-user/package-lock.json b/elevate-user/package-lock.json index 54d2d05..e992df8 100644 --- a/elevate-user/package-lock.json +++ b/elevate-user/package-lock.json @@ -1,6 +1,6 @@ { "name": "elevate-user", - "version": "1.0.12", + "version": "1.1.77", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/elevate-user/package.json b/elevate-user/package.json index 29e9216..5deb0a8 100644 --- a/elevate-user/package.json +++ b/elevate-user/package.json @@ -1,6 +1,6 @@ { "name": "elevate-user", - "version": "1.1.3", + "version": "1.1.77", "description": "Npm package for Elevate-User service integration with Interface service. ", "main": "index.js", "scripts": { diff --git a/elevate-user/utils/requester.js b/elevate-user/utils/requester.js index b3dba3a..78297ec 100644 --- a/elevate-user/utils/requester.js +++ b/elevate-user/utils/requester.js @@ -63,22 +63,27 @@ const post = (baseUrl, route, requestBody, headers) => { }) } catch (err) { console.log(err) + throw err } } + const patch = async (baseUrl, route, requestBody, headers) => { try { const url = baseUrl + route - - const options = { - method: 'PATCH', - headers: headers, - body: JSON.stringify(requestBody), // Assuming requestBody is an object - } - - const response = await fetch(url, options) - - const data = await response.json() - return data + return axios + .patch(url, requestBody, { + headers: { + 'X-auth-token': headers['x-auth-token'], + 'content-type': 'application/json', + }, + }) + .then((response) => response.data) + .catch((error) => { + if (error.response) { + return error.response + } + return error + }) } catch (error) { console.error(error) throw error // Re-throw the error to be caught by the caller