From 021b5202f4e9457179e8c4b9b61508cd70312ce0 Mon Sep 17 00:00:00 2001 From: sujith-juego Date: Fri, 18 Aug 2023 11:51:28 +0530 Subject: [PATCH 1/4] Updating njs2 base for PHP --- base/executor.class.js | 103 +++++++++++++++++++++++++++++++++---- helper/baseHelper.class.js | 22 ++++++++ 2 files changed, 115 insertions(+), 10 deletions(-) diff --git a/base/executor.class.js b/base/executor.class.js index 542714d..e22cad1 100644 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -11,6 +11,10 @@ const ParameterProcessor = require('./parameterProcessor.class'); const { encrypt, decrypt } = require('../helper/encryption'); const { ENC_MODE, DEFAULT_LNG_KEY, ENC_ENABLED } = require('../helper/globalConstants'); const jwt = require('../helper/jwt'); +const responseStructure = require(path.resolve( + process.cwd(), + "src/config/responseStructure.json" +)); class executor { constructor() { @@ -23,7 +27,9 @@ class executor { this.setResponse('UNKNOWN_ERROR'); // Initializng basic variables - const { lng_key: lngKey, access_token: accessToken, enc_state: encState } = request.headers; + const { lng_key: lngKey, enc_state: encState } = request.headers; + + let accessToken = baseHelper.getAccessTokenForPHP(request); // Decide encryption mode. And enforce enc_state to be true if encryption is Strict const { ENCRYPTION_MODE } = JSON.parse(process.env.ENCRYPTION); @@ -46,6 +52,12 @@ class executor { methodName = customMethodName; } + // Getting the methodName + const { NODE_METHOD_NAME } = JSON.parse(process.env.LEGACY_PHP); + if(methodName && methodName === NODE_METHOD_NAME) { + methodName = baseHelper.getMethodNameForPHP(request); + } + // Resolve path from methodName const pathName = baseHelper.getMethodPath(methodName); const methodClasses = baseHelper.getMethodClasses(pathName); @@ -119,24 +131,95 @@ class executor { this.responseData = encrypt(this.responseData); } - return { - responseCode, - responseMessage, - responseData: this.responseData - }; + let responseObj = this.getCustomResponse(responseCode, responseMessage, this.responseData); + + return responseObj; } catch (e) { console.log("Exception caught", e); - const { responseCode, responseMessage } = this.getResponse(); + const { responseCode, responseMessage } = this.getResponse(e === "NODE_VERSION_ERROR" ? e : ""); if (process.env.MODE == "DEV" && e.message) this.setDebugMessage(e.message); + + let responseObj = this.getCustomResponse(responseCode, responseMessage); + return responseObj; + } + } + + /** HELPER METHODS */ + isValidResponseStructure(responseStructure) { + + if(responseStructure && typeof responseStructure === "object") { + + // Check if type Array and array is not empty + if(Array.isArray(responseStructure) && responseStructure.length !== 0) { + return { type: "array", valid: true }; + } + + // Check if type Object and object is not empty + if(Object.keys(responseStructure).length !== 0) { + return { type: "object", valid: true }; + } + + } + return { valid: false }; + } + + getCustomResponse = (responseCode, responseMessage, responseData={}) => { + + const response = this.isValidResponseStructure(responseStructure); + + // If no response structure specified or response structure is invalid then return default response + if(!response.valid) { return { responseCode, responseMessage, - responseData: {} + responseData: responseData }; } - } - /** HELPER METHODS */ + // If response structure is array + if(response.type === "array") { + const responseArray = []; + + for(let response of responseStructure) { + if(response === "responseCode") { + responseArray.push(responseCode); + } else if(response === "responseMessage") { + responseArray.push(responseMessage); + } else if(response === "responseData") { + responseArray.push(responseData.responseData); + } else { + // TODO: handling additional data + // responseArray.push() + } + } + return responseArray; + } + + if(response.type === "object") { + let responseObj = {}; + const responseStructureArray = Object.entries(responseStructure); + + for(const responseDetails of responseStructureArray) { + const [ responseKey, responseValue ] = responseDetails; + if(responseKey === "responseCode") { + responseObj[responseValue.key] = responseCode; + } else if(responseKey === "responseMessage") { + responseObj[responseValue.key] = responseMessage; + } else if(responseKey === "responseData") { + responseObj[responseValue.key] = responseData; + } else { + // TODO: get additional data from API response else assign default value + responseObj[responseValue.key] = responseData.responseKey ? responseData.responseKey : responseValue.default; + } + } + + // responseObj[[responseStructure["responseCode"]]] = responseCode; + // responseObj[[responseStructure["responseMessage"]]] = responseMessage; + // responseObj[[responseStructure["responseData"]]] = responseData; + + return responseObj; + } + } // TODO: In future we will move this to an Authorization class validateAccesstoken = async (accessToken) => { diff --git a/helper/baseHelper.class.js b/helper/baseHelper.class.js index edd8d26..084d3f0 100644 --- a/helper/baseHelper.class.js +++ b/helper/baseHelper.class.js @@ -4,6 +4,28 @@ const path = require("path"); const httpRequest = require(path.join(process.cwd(), "src/config/route.json")); const baseMethodsPath = path.join(process.cwd(), "src/methods/"); class baseHelper { + + static getMethodNameForPHP(request) { + const { METHOD_KEY } = JSON.parse(process.env.LEGACY_PHP); + if (request.headers && request.headers[METHOD_KEY]) { + return request.headers[METHOD_KEY]; + } else if (request.queryStringParameters && request.queryStringParameters[METHOD_KEY]) { + return request.queryStringParameters[METHOD_KEY]; + } else if (request.body && request.body[METHOD_KEY]) { + return request.body[METHOD_KEY]; + } + } + + static getAccessTokenForPHP(request) { + if(request.queryStringParameters && request.queryStringParameters.access_token) { + return request.queryStringParameters.access_token; + } else if(request.body && request.body.access_token) { + return request.body.access_token; + } else if(request.headers && request.headers.access_token) { + return request.headers.access_token; + } + } + static getMethodName(pathParameters) { return pathParameters ? pathParameters.proxy : pathParameters; } From 55460436060087e466ef9f406712c0dd71d305c5 Mon Sep 17 00:00:00 2001 From: sujith-juego Date: Mon, 4 Sep 2023 18:13:20 +0530 Subject: [PATCH 2/4] Feedback changes --- base/executor.class.js | 158 +++++++++++++------------------------ helper/baseHelper.class.js | 42 +++++----- 2 files changed, 77 insertions(+), 123 deletions(-) diff --git a/base/executor.class.js b/base/executor.class.js index e22cad1..43117ae 100644 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -11,10 +11,8 @@ const ParameterProcessor = require('./parameterProcessor.class'); const { encrypt, decrypt } = require('../helper/encryption'); const { ENC_MODE, DEFAULT_LNG_KEY, ENC_ENABLED } = require('../helper/globalConstants'); const jwt = require('../helper/jwt'); -const responseStructure = require(path.resolve( - process.cwd(), - "src/config/responseStructure.json" -)); +const _ = require("lodash"); +const multiReplace = require('string-multiple-replace'); class executor { constructor() { @@ -26,10 +24,9 @@ class executor { try { this.setResponse('UNKNOWN_ERROR'); - // Initializng basic variables + // Initializing basic variables const { lng_key: lngKey, enc_state: encState } = request.headers; - - let accessToken = baseHelper.getAccessTokenForPHP(request); + const accessToken = baseHelper.getAccessToken(request); // Decide encryption mode. And enforce enc_state to be true if encryption is Strict const { ENCRYPTION_MODE } = JSON.parse(process.env.ENCRYPTION); @@ -44,7 +41,11 @@ class executor { if (lngKey) this.setMemberVariable('lng_key', lngKey); // Finalize methodName including custom route - let methodName = baseHelper.getMethodName(request.pathParameters); + let methodName = baseHelper.getMethodName(request); + if (methodName.error) { + this.setResponse("METHOD_NOT_FOUND"); + throw new Error(methodName.error); + } request.pathParameters = null; const { customMethodName, pathParameters } = baseHelper.getCustomRoute(methodName); if (customMethodName) { @@ -52,12 +53,6 @@ class executor { methodName = customMethodName; } - // Getting the methodName - const { NODE_METHOD_NAME } = JSON.parse(process.env.LEGACY_PHP); - if(methodName && methodName === NODE_METHOD_NAME) { - methodName = baseHelper.getMethodNameForPHP(request); - } - // Resolve path from methodName const pathName = baseHelper.getMethodPath(methodName); const methodClasses = baseHelper.getMethodClasses(pathName); @@ -98,7 +93,7 @@ class executor { const isFileExpected = baseHelper.isFileExpected(params); let requestData = baseHelper.parseRequestData(request, isFileExpected); - // If encyption is enabled, then decrypt the request data + // If encryption is enabled, then decrypt the request data if (!isFileExpected && encryptionState) { requestData = decrypt(requestData.data); if (typeof requestData === 'string') @@ -106,7 +101,7 @@ class executor { } requestData = requestData ? requestData : {}; - // Proccess and validate each parameters and set it as member variable + // Process and validate each parameters and set it as member variable for (let paramName in params) { let param = params[paramName]; const parsedData = await parameterProcessor.processParameter(requestData[param.name]); @@ -131,94 +126,22 @@ class executor { this.responseData = encrypt(this.responseData); } - let responseObj = this.getCustomResponse(responseCode, responseMessage, this.responseData); - - return responseObj; + return { + responseCode, + responseMessage, + responseData: this.responseData + }; } catch (e) { console.log("Exception caught", e); - const { responseCode, responseMessage } = this.getResponse(e === "NODE_VERSION_ERROR" ? e : ""); + const { responseCode, responseMessage } = this.getResponse(); if (process.env.MODE == "DEV" && e.message) this.setDebugMessage(e.message); - - let responseObj = this.getCustomResponse(responseCode, responseMessage); - return responseObj; - } - } - - /** HELPER METHODS */ - isValidResponseStructure(responseStructure) { - - if(responseStructure && typeof responseStructure === "object") { - - // Check if type Array and array is not empty - if(Array.isArray(responseStructure) && responseStructure.length !== 0) { - return { type: "array", valid: true }; - } - - // Check if type Object and object is not empty - if(Object.keys(responseStructure).length !== 0) { - return { type: "object", valid: true }; - } - - } - return { valid: false }; - } - - getCustomResponse = (responseCode, responseMessage, responseData={}) => { - - const response = this.isValidResponseStructure(responseStructure); - // If no response structure specified or response structure is invalid then return default response - if(!response.valid) { return { responseCode, responseMessage, - responseData: responseData + responseData: {} }; } - - // If response structure is array - if(response.type === "array") { - const responseArray = []; - - for(let response of responseStructure) { - if(response === "responseCode") { - responseArray.push(responseCode); - } else if(response === "responseMessage") { - responseArray.push(responseMessage); - } else if(response === "responseData") { - responseArray.push(responseData.responseData); - } else { - // TODO: handling additional data - // responseArray.push() - } - } - return responseArray; - } - - if(response.type === "object") { - let responseObj = {}; - const responseStructureArray = Object.entries(responseStructure); - - for(const responseDetails of responseStructureArray) { - const [ responseKey, responseValue ] = responseDetails; - if(responseKey === "responseCode") { - responseObj[responseValue.key] = responseCode; - } else if(responseKey === "responseMessage") { - responseObj[responseValue.key] = responseMessage; - } else if(responseKey === "responseData") { - responseObj[responseValue.key] = responseData; - } else { - // TODO: get additional data from API response else assign default value - responseObj[responseValue.key] = responseData.responseKey ? responseData.responseKey : responseValue.default; - } - } - - // responseObj[[responseStructure["responseCode"]]] = responseCode; - // responseObj[[responseStructure["responseMessage"]]] = responseMessage; - // responseObj[[responseStructure["responseData"]]] = responseData; - - return responseObj; - } } // TODO: In future we will move this to an Authorization class @@ -275,6 +198,8 @@ class executor { const BASE_RESPONSE = require(path.resolve(process.cwd(), `src/global/i18n/response.js`)).RESPONSE; const PROJECT_RESPONSE = require(`../i18n/response.js`).RESPONSE; + const CUSTOM_RESPONSE_TEMPLATE = require(path.resolve(process.cwd(), `src/config/responseTemplate.json`)); + let RESP = { ...PROJECT_RESPONSE, ...BASE_RESPONSE }; if (packageName) { @@ -289,25 +214,50 @@ class executor { if (!RESP[this.responseString]) { RESP = RESP["RESPONSE_CODE_NOT_FOUND"]; } else { - RESP = RESP[this.responseString]; + RESP = {...RESP[this.responseString]}; } - this.responseCode = RESP.responseCode; - this.responseMessage = this.lng_key && RESP.responseMessage[this.lng_key] + RESP.responseMessage = this.lng_key && RESP.responseMessage[this.lng_key] ? RESP.responseMessage[this.lng_key] : RESP.responseMessage[DEFAULT_LNG_KEY]; + RESP.responseData = this.responseData; + if (this.responseOptions) Object.keys(this.responseOptions).map(keyName => { - this.responseMessage = this.responseMessage.replace(keyName, this.responseOptions[keyName]); + RESP.responseMessage = RESP.responseMessage.replace(keyName, this.responseOptions[keyName]); }); + + return this.parseResponseData(CUSTOM_RESPONSE_TEMPLATE,RESP); + } + + parseResponseData(CUSTOM_RESPONSE_TEMPLATE,RESP){ + try{ + Object.entries(RESP).forEach(array => { + const [key,value] = array; + if(typeof value === 'object'){ + RESP[key] = JSON.stringify(value); + } }); + + const compiled = _.template(typeof CUSTOM_RESPONSE_TEMPLATE === 'string' ? CUSTOM_RESPONSE_TEMPLATE : JSON.stringify(CUSTOM_RESPONSE_TEMPLATE)); - return { - responseCode: this.responseCode, - responseMessage: this.responseMessage, - responseData: this.responseData - }; + const resultTemplate = compiled(RESP); + + const matcherObj = { + '"{': '{', + '}"': '}', + '"[': '[', + ']"': ']' + } + + const replacedString =multiReplace(resultTemplate, matcherObj); + + return typeof CUSTOM_RESPONSE_TEMPLATE === 'string' ? replacedString : JSON.parse(replacedString); + }catch(error){ + throw new Error("parseResponseData Error:"+error); + } } + } module.exports = executor; \ No newline at end of file diff --git a/helper/baseHelper.class.js b/helper/baseHelper.class.js index 084d3f0..c976407 100644 --- a/helper/baseHelper.class.js +++ b/helper/baseHelper.class.js @@ -5,29 +5,33 @@ const httpRequest = require(path.join(process.cwd(), "src/config/route.json")); const baseMethodsPath = path.join(process.cwd(), "src/methods/"); class baseHelper { - static getMethodNameForPHP(request) { - const { METHOD_KEY } = JSON.parse(process.env.LEGACY_PHP); - if (request.headers && request.headers[METHOD_KEY]) { - return request.headers[METHOD_KEY]; - } else if (request.queryStringParameters && request.queryStringParameters[METHOD_KEY]) { - return request.queryStringParameters[METHOD_KEY]; - } else if (request.body && request.body[METHOD_KEY]) { - return request.body[METHOD_KEY]; - } - } - - static getAccessTokenForPHP(request) { - if(request.queryStringParameters && request.queryStringParameters.access_token) { - return request.queryStringParameters.access_token; + static getAccessToken(request) { + let access_token = "" + if(request.headers && request.headers.access_token) { + access_token = request.headers.access_token; + } else if(request.queryStringParameters && request.queryStringParameters.access_token) { + access_token = request.queryStringParameters.access_token; } else if(request.body && request.body.access_token) { - return request.body.access_token; - } else if(request.headers && request.headers.access_token) { - return request.headers.access_token; + access_token = request.body.access_token; } + return access_token; } - static getMethodName(pathParameters) { - return pathParameters ? pathParameters.proxy : pathParameters; + static getMethodName(request) { + let methodName = request.pathParameters ? request.pathParameters.proxy : request.pathParameters; + // Getting the methodName for legacy php + const { NODE_METHOD_NAME, METHOD_KEY } = JSON.parse(process.env.LEGACY_PHP); + if(methodName === NODE_METHOD_NAME) { + if (request.headers && request.headers[METHOD_KEY]) { + methodName = request.headers[METHOD_KEY]; + } else if (request.queryStringParameters && request.queryStringParameters[METHOD_KEY]) { + methodName = request.queryStringParameters[METHOD_KEY]; + } else if (request.body && request.body[METHOD_KEY]) { + methodName = request.body[METHOD_KEY]; + } + } + if(!methodName) throw "METHOD_NOT_FOUND"; + return methodName; } static capitalizeFirstLetter(string) { From 56d103b8fa0dd724725bc0d2b79735e528f206d1 Mon Sep 17 00:00:00 2001 From: sujith-juego Date: Tue, 5 Sep 2023 10:04:36 +0530 Subject: [PATCH 3/4] Fixes --- base/executor.class.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/base/executor.class.js b/base/executor.class.js index 43117ae..d2648d2 100644 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -118,7 +118,6 @@ class executor { // Initiate and Execute method this.responseData = await actionInstance.executeMethod(); const { responseString, responseOptions, packageName } = actionInstance.getResponseString(); - const { responseCode, responseMessage } = this.getResponse(responseString, responseOptions, packageName); // If encryption mode is enabled then encrypt the response data if (encryptionState) { @@ -126,21 +125,15 @@ class executor { this.responseData = encrypt(this.responseData); } - return { - responseCode, - responseMessage, - responseData: this.responseData - }; + const response = this.getResponse(responseString, responseOptions, packageName); + + + return response; } catch (e) { console.log("Exception caught", e); - const { responseCode, responseMessage } = this.getResponse(); + const response = this.getResponse(e === "NODE VERSION ERROR" ? e : ""); if (process.env.MODE == "DEV" && e.message) this.setDebugMessage(e.message); - - return { - responseCode, - responseMessage, - responseData: {} - }; + return response; } } From e28bb128ba90f3e11b9f23af1a8cb72d66b7fcb6 Mon Sep 17 00:00:00 2001 From: sujith-juego Date: Wed, 6 Sep 2023 09:43:21 +0530 Subject: [PATCH 4/4] Fixes on custom response. --- base/executor.class.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/base/executor.class.js b/base/executor.class.js index d2648d2..8c1587d 100644 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -228,7 +228,7 @@ class executor { Object.entries(RESP).forEach(array => { const [key,value] = array; if(typeof value === 'object'){ - RESP[key] = JSON.stringify(value); + RESP[key] = "{" + JSON.stringify(value) + "}"; } }); @@ -237,13 +237,13 @@ class executor { const resultTemplate = compiled(RESP); const matcherObj = { - '"{': '{', - '}"': '}', - '"[': '[', - ']"': ']' + '"{{': '{', + '}}"': '}', + '"{[': '[', + ']}"': ']' } - const replacedString =multiReplace(resultTemplate, matcherObj); + const replacedString = multiReplace(resultTemplate, matcherObj); return typeof CUSTOM_RESPONSE_TEMPLATE === 'string' ? replacedString : JSON.parse(replacedString); }catch(error){