From 7e1b6740cd4278b94a9a684c0b9dcb1102d97951 Mon Sep 17 00:00:00 2001 From: Allistair Vilakazi Date: Mon, 10 Aug 2020 17:43:36 +0200 Subject: [PATCH 1/6] feat: initial settings middleware implementation (without db lookup) --- src/middlewares/middleware.js | 27 +++++--- src/middlewares/settings.js | 79 ++++++++++++++++++++++ src/routes/googleLogin.js | 3 +- src/services/adminAuth.js | 4 +- src/utils/mocks/settings.js | 120 ++++++++++++++++++++++++++++++++++ src/utils/settingsHandler.js | 60 +++++++++++++---- 6 files changed, 270 insertions(+), 23 deletions(-) create mode 100644 src/middlewares/settings.js create mode 100644 src/utils/mocks/settings.js diff --git a/src/middlewares/middleware.js b/src/middlewares/middleware.js index 058e869d..22f3cf86 100644 --- a/src/middlewares/middleware.js +++ b/src/middlewares/middleware.js @@ -61,29 +61,38 @@ const googleAuthProvider = (req, res, next) => const authProvider = (providerType) => { return async (req, res, next) => { - const admin = await Admin.findById(req.admin.id).populate("settings"); - const { successCallbackUrl, failureCallbackUrl } = admin.settings; + // Temporary check during experimentation to check whether or not the settingsMiddleware + // is enabled. If its enabled then we don't have to use our backup settings + // stored in our database. + if (!req.settings) { + console.log(`No settings from settingsMiddleware: ${req.settings}`); + admin = await Admin.findById(req.admin.id).populate("settings"); + req.settings = admin.settings; + } else { + console.log(`Received settings from settingsMiddleware: ${req.settings}`); + } let provider; let providerEnabled = false; const callbacksAvailable = - successCallbackUrl !== null && failureCallbackUrl !== null; + req.settings.successCallbackUrl !== null && + req.settings.failureCallbackUrl !== null; switch (providerType) { case TWITTER_PROVIDER: - provider = admin.settings.twitterAuthProvider; + provider = req.settings.settings.twitterAuthProvider; providerEnabled = provider && provider.key; break; case FACEBOOK_PROVIDER: - provider = admin.settings.facebookAuthProvider; + provider = req.settings.facebookAuthProvider; providerEnabled = provider && provider.appID; break; case GITHUB_PROVIDER: - provider = admin.settings.githubAuthProvider; + provider = req.settings.githubAuthProvider; providerEnabled = provider && provider.clientID; break; case GOOGLE_PROVIDER: - provider = admin.settings.googleAuthProvider; + provider = req.settings.googleAuthProvider; providerEnabled = provider && provider.clientID; break; @@ -95,8 +104,8 @@ const authProvider = (providerType) => { if (providerEnabled && callbacksAvailable) { req.provider = provider; - req.successCallbackUrl = successCallbackUrl; - req.failureCallbackUrl = failureCallbackUrl; + req.successCallbackUrl = req.settings.successCallbackUrl; + req.failureCallbackUrl = req.settings.failureCallbackUrl; next(); } else { diff --git a/src/middlewares/settings.js b/src/middlewares/settings.js new file mode 100644 index 00000000..2c431333 --- /dev/null +++ b/src/middlewares/settings.js @@ -0,0 +1,79 @@ +require("dotenv").config(); +const CustomResponse = require("../utils/response"); +const settingsHandler = require("../utils/settingsHandler"); +const getMockSettings = require("../utils/mocks/settings"); +const log = require("debug")("log"); + +//get settings from external DB or endpoint +//function might be modified to accomodate both sources +const getSettings = async (apiKey) => { + //fool linter + log(apiKey); + + //mock the request for now with mocksettings + //settings need to come from source + //validate the settings by matching against predefined schema + const settings = settingsHandler.parseSettings(getMockSettings(), true); + return settings; +}; + +const settingsMiddleware = async (req, res, next) => { + /* In multi-tenant app, projectID is retreived from API key in a custom HTTP header + ** For now we stick with multi-tenant and we will customize this to cater for ** + ** single tenancy architecture in time where projectIDs are irrelevant ** + ** In retrospect, expiry of API keys should be from MicroAPI, ** + ** so making a request for settings with an invalid API key will be rejected ** + */ + try { + // we are calling our custom HTTP header X-MicroAPI-ProjectKey + const apiKey = req.headers["x-microapi-projectkey"]; + if (!apiKey) { + res + .status(401) + .json( + CustomResponse( + "UnauthorizedError", + { statusCode: 401, message: "No API key found" }, + false + ) + ); + } + + // get settings from parent DB/source + const settings = await getSettings(apiKey); + if (settings.errors) { + res + .status(400) + .json( + CustomResponse( + "BadRequestError", + { statusCode: 400, message: settings.errors[0].message }, + false + ) + ); + } + + console.log(settings); + + //attach setting to request body + req.settings = settings; + // req.projectId = projectId; + + //pass to next middleware + next(); + } catch (error) { + console.log(error); + res.status(500).json( + CustomResponse( + "InternalServerError", + { + statusCode: 500, + message: "Something went wrong, please try again later", + }, + false + ) + ); + } +}; + +module.exports = settingsMiddleware; diff --git a/src/routes/googleLogin.js b/src/routes/googleLogin.js index 8f621fa2..74349ee7 100644 --- a/src/routes/googleLogin.js +++ b/src/routes/googleLogin.js @@ -3,6 +3,7 @@ const passport = require("passport"); const url = require("url"); const { google } = require("googleapis"); const CustomResponse = require("../utils/response"); +const settingsMiddleware = require("../middlewares/settings"); const createGoogleStrategy = require("../config/passport/googleStrategy"); const { authorizeUser, @@ -13,7 +14,7 @@ const route = express.Router(); // The credentials of all who are currently undergoing Google's authentication flow. const activeCredentials = {}; -route.get("/", authorizeUser, googleAuthProvider, async (req, res) => { +route.get("/", settingsMiddleware, authorizeUser, googleAuthProvider, async (req, res) => { try { const oauth2Client = new google.auth.OAuth2( req.provider.clientID, diff --git a/src/services/adminAuth.js b/src/services/adminAuth.js index 71a38341..81711771 100644 --- a/src/services/adminAuth.js +++ b/src/services/adminAuth.js @@ -5,7 +5,7 @@ const Settings = require("../models/settings"); const { CustomError } = require("../utils/CustomError"); const RandomString = require("randomstring"); const { sendForgotPasswordMail } = require("../EmailFactory/index"); -const { settingsSchema } = require("../utils/settingsHandler"); +const settingsHandler = require("../utils/settingsHandler"); class AdminService { async register(body) { @@ -82,7 +82,7 @@ class AdminService { // New API KEY for admin const message = "Settings retrieved successfully"; return { - data: settingsSchema, + data: settingsHandler.settingsSchema, message: message, }; } diff --git a/src/utils/mocks/settings.js b/src/utils/mocks/settings.js new file mode 100644 index 00000000..0eb2e377 --- /dev/null +++ b/src/utils/mocks/settings.js @@ -0,0 +1,120 @@ +const getMockSettings = () => [ + { + setting_name: "Email Verification Callback", + setting_type: "String", + setting_key: "emailVerifyCallback", + setting_required: true, + setting_value: "/emailCallback", + }, + { + setting_name: "Password Reset Callback", + setting_type: "String", + setting_key: "passwordResetCallback", + setting_required: true, + setting_value: "/passwordResetCallback", + }, + { + setting_name: "Login Success Callback", + setting_type: "String", + setting_key: "successCallback", + setting_required: true, + setting_value: "successCallback", + }, + { + setting_name: "MongoDB URI", + setting_type: "String", + setting_key: "mongoDbUri", + setting_required: true, + setting_value: "dbUriString", + }, + { + setting_name: "Facebook Credentials", + setting_type: "Array", + setting_key: "facebookAuthProvider", + setting_required: false, + setting_value: [ + { + setting_name: "Facebook Application ID", + setting_type: "String", + setting_key: "appID", + setting_value: null, + setting_required: true, + }, + { + setting_name: "Facebook Application Secret", + setting_type: "String", + setting_key: "appSecret", + setting_value: null, + setting_required: true, + }, + ], + }, + { + setting_name: "Twitter Credentials", + setting_type: "Array", + setting_key: "twitterAuthProvider", + setting_required: false, + setting_value: [ + { + setting_name: "Twitter Consumer Key", + setting_type: "String", + setting_key: "key", + setting_value: null, + setting_required: true, + }, + { + setting_name: "Twitter Consumer Secret", + setting_type: "String", + setting_key: "secret", + setting_value: null, + setting_required: true, + }, + ], + }, + { + setting_name: "Github Credentials", + setting_type: "Array", + setting_key: "githubAuthProvider", + setting_required: false, + setting_value: [ + { + setting_name: "Github Client ID", + setting_type: "String", + setting_key: "clientID", + setting_value: null, + setting_required: true, + }, + { + setting_name: "Github Client Secret", + setting_type: "String", + setting_key: "clientSecret", + setting_value: null, + setting_required: true, + }, + ], + }, + { + setting_name: "Google Credentials", + setting_type: "Array", + setting_key: "googleAuthProvider", + setting_required: false, + setting_value: [ + { + setting_name: "Google Client ID", + setting_type: "String", + setting_key: "clientID", + setting_value: null, + setting_required: true, + }, + { + setting_name: "Google Client Secret", + setting_type: "String", + setting_key: "clientSecret", + setting_value: null, + setting_required: true, + }, + ], + }, +]; + +module.exports = getMockSettings; diff --git a/src/utils/settingsHandler.js b/src/utils/settingsHandler.js index cc91c73b..393a2792 100644 --- a/src/utils/settingsHandler.js +++ b/src/utils/settingsHandler.js @@ -1,4 +1,4 @@ -exports.settingsSchema = [ +const settingsSchema = [ { setting_name: "Email Verification Callback", setting_type: "String", @@ -47,13 +47,6 @@ exports.settingsSchema = [ setting_value: null, setting_required: true, }, - { - setting_name: "Login Success Callback", - setting_type: "String", - setting_key: "successCallback", - setting_required: false, - setting_value: null, - }, ], }, { @@ -124,14 +117,59 @@ exports.settingsSchema = [ }, ]; -exports.parseSettings = (data) => { - return data.reduce((acc, item) => { +const parseSettings = ( + data, + validate = false, + errors = [], + isRecursion = false, + parentKey = "" +) => { + const settings = data.reduce((acc, item) => { if (item["setting_type"] == "Array") { - const newTemp = parseSettings(item.setting_value); + const newTemp = parseSettings( + item.setting_value, + item["setting_required"] && validate, //only validate if parent is required + errors, + true, + item["setting_key"] + ); return { ...acc, [item["setting_key"]]: newTemp }; } const temp = acc; temp[item.setting_key] = item.setting_value; + + //do validation here + if (validate) { + if (item["setting_required"] && !item["setting_value"]) { + errors.push( + `RequiredError: ${parentKey ? parentKey + "." : ""}${ + item["setting_key"] + } is a required setting` + ); + } else if ( + item["setting_type"].toLowerCase() !== + (typeof item["setting_value"]).toLowerCase() + ) { + errors.push( + `TypeError: ${parentKey ? parentKey + "." : ""}${ + item["setting_key"] + } should be a/an ${item["setting_type"]}` + ); + } + } + return { ...acc, ...temp }; }, {}); + + //Don't attach errors in recursion + if (validate && !isRecursion && errors.length) { + settings.errors = errors; + } + + return settings; +}; + +module.exports = { + settingsSchema, + parseSettings, }; From 6b8609b1ef721b9cac23cdef5969efd037028c24 Mon Sep 17 00:00:00 2001 From: Allistair Vilakazi Date: Mon, 10 Aug 2020 18:12:22 +0200 Subject: [PATCH 2/6] WIP: add initial setup for db querying --- package-lock.json | 16 ++++++++++++ package.json | 1 + src/middlewares/settings.js | 51 +++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/package-lock.json b/package-lock.json index a26618af..da3ad1b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8434,6 +8434,17 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "requires": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + } + }, "nan": { "version": "2.14.1", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", @@ -10548,6 +10559,11 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, + "sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" + }, "sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", diff --git a/package.json b/package.json index 33737358..5415ee76 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "mongoose": "^5.9.19", "mongoose-findorcreate": "^3.0.0", "mongoose-mongodb-errors": "0.0.2", + "mysql": "^2.18.1", "passport": "^0.4.1", "passport-facebook": "^3.0.0", "passport-github": "^1.1.0", diff --git a/src/middlewares/settings.js b/src/middlewares/settings.js index 2c431333..f7d0d7c4 100644 --- a/src/middlewares/settings.js +++ b/src/middlewares/settings.js @@ -1,15 +1,66 @@ require("dotenv").config(); +const mysql = require("mysql"); const CustomResponse = require("../utils/response"); const settingsHandler = require("../utils/settingsHandler"); const getMockSettings = require("../utils/mocks/settings"); const log = require("debug")("log"); +const dbConfig = { + host: "lucid.blog", + user: "root", + password: "123456", + database: "microapi", + port: 5321, +}; + //get settings from external DB or endpoint //function might be modified to accomodate both sources const getSettings = async (apiKey) => { //fool linter log(apiKey); + let connection; + + function handleDisconnect() { + // Recreate the connection, since the old one cannot be reused. + connection = mysql.createConnection(dbConfig); + + connection.connect((err) => { + // The server is either down or restarting (takes a while sometimes). + if (err) { + console.log("error when connecting to db:", err); + // We introduce a delay before attempting to reconnect, to avoid a hot loop, + // and to allow our node script to process asynchronous requests in the meantime. + setTimeout(handleDisconnect, 2000); + } + }); + + connection.on("error", (err) => { + console.log("db error", err); + if (err.code === "PROTOCOL_CONNECTION_LOST") { + // Connection to the MySQL server is usually lost due to either server restart, or a + // connnection idle timeout (the wait_timeout server variable configures this) + handleDisconnect(); + } else { + throw err; + } + }); + } + + handleDisconnect(); + + // Query the database for the project belonging to the project + connection.query("SELECT * FROM user_dashboard_project", (err, results) => { + if (err) { + if (err.code === "PROTOCOL_CONNECTION_LOST") { + handleDisconnect(); + } + console.log("Query error: ", err); + return; + } + console.log(results); + }); + //mock the request for now with mocksettings //settings need to come from source //validate the settings by matching against predefined schema From e2c6cb9cb9021ec6439c23d6ccc9fee7f10f9bf6 Mon Sep 17 00:00:00 2001 From: Allistair Vilakazi Date: Mon, 10 Aug 2020 18:15:10 +0200 Subject: [PATCH 3/6] fix: update connection tries --- src/middlewares/settings.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/middlewares/settings.js b/src/middlewares/settings.js index f7d0d7c4..b5bf0e8c 100644 --- a/src/middlewares/settings.js +++ b/src/middlewares/settings.js @@ -13,6 +13,8 @@ const dbConfig = { port: 5321, }; +const MAX_CONNECTION_TRIES = 5; + //get settings from external DB or endpoint //function might be modified to accomodate both sources const getSettings = async (apiKey) => { @@ -20,8 +22,10 @@ const getSettings = async (apiKey) => { log(apiKey); let connection; + let connectionTries = 0; function handleDisconnect() { + connectionTries += 1; // Recreate the connection, since the old one cannot be reused. connection = mysql.createConnection(dbConfig); @@ -37,7 +41,10 @@ const getSettings = async (apiKey) => { connection.on("error", (err) => { console.log("db error", err); - if (err.code === "PROTOCOL_CONNECTION_LOST") { + if ( + err.code === "PROTOCOL_CONNECTION_LOST" && + connectionTries <= MAX_CONNECTION_TRIES + ) { // Connection to the MySQL server is usually lost due to either server restart, or a // connnection idle timeout (the wait_timeout server variable configures this) handleDisconnect(); @@ -52,7 +59,10 @@ const getSettings = async (apiKey) => { // Query the database for the project belonging to the project connection.query("SELECT * FROM user_dashboard_project", (err, results) => { if (err) { - if (err.code === "PROTOCOL_CONNECTION_LOST") { + if ( + err.code === "PROTOCOL_CONNECTION_LOST" && + connectionTries <= MAX_CONNECTION_TRIES + ) { handleDisconnect(); } console.log("Query error: ", err); From 5cc347dda54ee478dce4fba392bdf090bf9fc886 Mon Sep 17 00:00:00 2001 From: Allistair Vilakazi Date: Mon, 10 Aug 2020 18:41:05 +0200 Subject: [PATCH 4/6] WIP --- src/middlewares/settings.js | 42 ++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/middlewares/settings.js b/src/middlewares/settings.js index b5bf0e8c..58653e0e 100644 --- a/src/middlewares/settings.js +++ b/src/middlewares/settings.js @@ -24,6 +24,24 @@ const getSettings = async (apiKey) => { let connection; let connectionTries = 0; + let outsideResolve; + let outsideReject; + const promise = new Promise((resolve, reject) => { + outsideResolve = resolve; + outsideReject = reject; + }); + + function getConnectionErrorResponse(err) { + let message; + + if (connectionTries === MAX_CONNECTION_TRIES) { + message = "Maximum connection tries reached"; + } else { + message = err.message; + } + return { errors: [{ message }] }; + } + function handleDisconnect() { connectionTries += 1; // Recreate the connection, since the old one cannot be reused. @@ -31,11 +49,14 @@ const getSettings = async (apiKey) => { connection.connect((err) => { // The server is either down or restarting (takes a while sometimes). - if (err) { + if (err && connectionTries <= MAX_CONNECTION_TRIES) { console.log("error when connecting to db:", err); // We introduce a delay before attempting to reconnect, to avoid a hot loop, // and to allow our node script to process asynchronous requests in the meantime. setTimeout(handleDisconnect, 2000); + } else { + const errorResponse = getConnectionErrorResponse(err); + outsideReject(errorResponse); } }); @@ -49,7 +70,8 @@ const getSettings = async (apiKey) => { // connnection idle timeout (the wait_timeout server variable configures this) handleDisconnect(); } else { - throw err; + const errorResponse = getConnectionErrorResponse(err); + outsideReject(errorResponse); } }); } @@ -66,16 +88,20 @@ const getSettings = async (apiKey) => { handleDisconnect(); } console.log("Query error: ", err); - return; + const errorResponse = getConnectionErrorResponse(err); + outsideReject(errorResponse); } + console.log(results); + //mock the request for now with mocksettings + //settings need to come from source + //validate the settings by matching against predefined schema + // const settings = settingsHandler.parseSettings(getMockSettings(), true); + + outsideResolve(results); }); - //mock the request for now with mocksettings - //settings need to come from source - //validate the settings by matching against predefined schema - const settings = settingsHandler.parseSettings(getMockSettings(), true); - return settings; + return promise; }; const settingsMiddleware = async (req, res, next) => { From 2a0bfa997ae21965fda32eda9dc867ed78514ad7 Mon Sep 17 00:00:00 2001 From: Allistair Vilakazi Date: Tue, 11 Aug 2020 11:50:50 +0200 Subject: [PATCH 5/6] feat: update configuration --- src/middlewares/settings.js | 102 +++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 47 deletions(-) diff --git a/src/middlewares/settings.js b/src/middlewares/settings.js index 58653e0e..c47da802 100644 --- a/src/middlewares/settings.js +++ b/src/middlewares/settings.js @@ -6,11 +6,11 @@ const getMockSettings = require("../utils/mocks/settings"); const log = require("debug")("log"); const dbConfig = { - host: "lucid.blog", - user: "root", - password: "123456", - database: "microapi", - port: 5321, + host: process.env.MICROAPI_DB_HOST, + user: process.env.MICROAPI_DB_USER, + password: process.env.MICROAPI_DB_PASSWORD, + database: process.env.MICROAPI_DB_DATABASE, + port: process.env.MICROAPI_DB_PORT, }; const MAX_CONNECTION_TRIES = 5; @@ -37,7 +37,8 @@ const getSettings = async (apiKey) => { if (connectionTries === MAX_CONNECTION_TRIES) { message = "Maximum connection tries reached"; } else { - message = err.message; + console.log(err); + message = err; } return { errors: [{ message }] }; } @@ -49,58 +50,65 @@ const getSettings = async (apiKey) => { connection.connect((err) => { // The server is either down or restarting (takes a while sometimes). - if (err && connectionTries <= MAX_CONNECTION_TRIES) { - console.log("error when connecting to db:", err); - // We introduce a delay before attempting to reconnect, to avoid a hot loop, - // and to allow our node script to process asynchronous requests in the meantime. - setTimeout(handleDisconnect, 2000); + if (err) { + if (connectionTries <= MAX_CONNECTION_TRIES) { + console.log("error when connecting to db:", err.message); + // We introduce a delay before attempting to reconnect, to avoid a hot loop, + // and to allow our node script to process asynchronous requests in the meantime. + setTimeout(handleDisconnect, 2000); + } else { + const errorResponse = getConnectionErrorResponse(err); + outsideReject(errorResponse); + } } else { - const errorResponse = getConnectionErrorResponse(err); - outsideReject(errorResponse); + // Query the database for the project belonging to the project + connection.query( + "SELECT * FROM user_dashboard_project", + (err, results) => { + if (err) { + if ( + err.code === "PROTOCOL_CONNECTION_LOST" || + connectionTries <= MAX_CONNECTION_TRIES + ) { + handleDisconnect(); + } + console.log("Query error: ", err); + const errorResponse = getConnectionErrorResponse(err); + outsideReject(errorResponse); + } + + console.log(results); + //mock the request for now with mocksettings + //settings need to come from source + //validate the settings by matching against predefined schema + // const settings = settingsHandler.parseSettings(getMockSettings(), true); + + outsideResolve(results); + } + ); } }); connection.on("error", (err) => { - console.log("db error", err); - if ( - err.code === "PROTOCOL_CONNECTION_LOST" && - connectionTries <= MAX_CONNECTION_TRIES - ) { - // Connection to the MySQL server is usually lost due to either server restart, or a - // connnection idle timeout (the wait_timeout server variable configures this) - handleDisconnect(); - } else { - const errorResponse = getConnectionErrorResponse(err); - outsideReject(errorResponse); + if (err) { + console.log("db error", err); + if ( + err.code === "PROTOCOL_CONNECTION_LOST" || + connectionTries <= MAX_CONNECTION_TRIES + ) { + // Connection to the MySQL server is usually lost due to either server restart, or a + // connnection idle timeout (the wait_timeout server variable configures this) + handleDisconnect(); + } else { + const errorResponse = getConnectionErrorResponse(err); + outsideReject(errorResponse); + } } }); } handleDisconnect(); - // Query the database for the project belonging to the project - connection.query("SELECT * FROM user_dashboard_project", (err, results) => { - if (err) { - if ( - err.code === "PROTOCOL_CONNECTION_LOST" && - connectionTries <= MAX_CONNECTION_TRIES - ) { - handleDisconnect(); - } - console.log("Query error: ", err); - const errorResponse = getConnectionErrorResponse(err); - outsideReject(errorResponse); - } - - console.log(results); - //mock the request for now with mocksettings - //settings need to come from source - //validate the settings by matching against predefined schema - // const settings = settingsHandler.parseSettings(getMockSettings(), true); - - outsideResolve(results); - }); - return promise; }; From 8b5242afcb9177c91f9e39de89a7516c6d930007 Mon Sep 17 00:00:00 2001 From: Allistair Vilakazi Date: Tue, 11 Aug 2020 21:36:29 +0200 Subject: [PATCH 6/6] feat: make project key optional --- src/middlewares/settings.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/middlewares/settings.js b/src/middlewares/settings.js index c47da802..d70576ce 100644 --- a/src/middlewares/settings.js +++ b/src/middlewares/settings.js @@ -123,15 +123,17 @@ const settingsMiddleware = async (req, res, next) => { // we are calling our custom HTTP header X-MicroAPI-ProjectKey const apiKey = req.headers["x-microapi-projectkey"]; if (!apiKey) { - res - .status(401) - .json( - CustomResponse( - "UnauthorizedError", - { statusCode: 401, message: "No API key found" }, - false - ) - ); + // Temporarily optional as this is an experimental feature. + next(); + // res + // .status(401) + // .json( + // CustomResponse( + // "UnauthorizedError", + // { statusCode: 401, message: "No API key found" }, + // false + // ) + // ); } // get settings from parent DB/source