From 83b885bc415e6e3bc7e67db6efc5f04f6f70db6e Mon Sep 17 00:00:00 2001 From: Sam Tolmay Date: Fri, 29 Oct 2021 13:28:12 +0200 Subject: [PATCH] feat: Use logger in request api call. --- .../src/routes/request/authorizeRequest.js | 8 ++- .../src/routes/request/checkConnectionRead.js | 37 ++++++++++++ .../src/routes/request/evaluateOperators.js | 10 ++-- ...adConnection.js => getConnectionConfig.js} | 15 +++-- .../routes/request/getConnectionHandler.js | 35 ++++++++++++ .../routes/request/getConnectionPackage.js | 38 ------------- .../{loadRequest.js => getRequestConfig.js} | 8 ++- .../src/routes/request/getRequestHandler.js | 33 +++++++++++ packages/api/src/routes/request/request.js | 57 ++++++++++--------- 9 files changed, 159 insertions(+), 82 deletions(-) create mode 100644 packages/api/src/routes/request/checkConnectionRead.js rename packages/api/src/routes/request/{loadConnection.js => getConnectionConfig.js} (64%) create mode 100644 packages/api/src/routes/request/getConnectionHandler.js delete mode 100644 packages/api/src/routes/request/getConnectionPackage.js rename packages/api/src/routes/request/{loadRequest.js => getRequestConfig.js} (73%) create mode 100644 packages/api/src/routes/request/getRequestHandler.js diff --git a/packages/api/src/routes/request/authorizeRequest.js b/packages/api/src/routes/request/authorizeRequest.js index 5581402be..5ed7dbeb2 100644 --- a/packages/api/src/routes/request/authorizeRequest.js +++ b/packages/api/src/routes/request/authorizeRequest.js @@ -16,11 +16,13 @@ import { ConfigurationError } from '../../context/errors'; -function authorizeRequest({ authorize }, { request }) { - if (!authorize(request)) { +function authorizeRequest({ authorize, logger }, { requestConfig }) { + if (!authorize(requestConfig)) { + logger.warn({ authorized: false }, 'Unauthorized Request'); // Throw does not exist error to avoid leaking information that request exists to unauthorized users - throw new ConfigurationError(`Request "${request.requestId}" does not exist.`); + throw new ConfigurationError(`Request "${requestConfig.requestId}" does not exist.`); } + logger.debug({ authorized: true }, 'Authorize Request'); } export default authorizeRequest; diff --git a/packages/api/src/routes/request/checkConnectionRead.js b/packages/api/src/routes/request/checkConnectionRead.js new file mode 100644 index 000000000..339b53191 --- /dev/null +++ b/packages/api/src/routes/request/checkConnectionRead.js @@ -0,0 +1,37 @@ +/* + Copyright 2020-2021 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +import { ConfigurationError } from '../../context/errors'; + +function checkConnectionRead( + { logger }, + { connectionConfig, connectionProperties, requestConfig, requestHandler } +) { + if (requestHandler.checkRead && connectionProperties.read === false) { + const err = new ConfigurationError( + `Connection "${connectionConfig.connectionId}" does not allow reads.` + ); + logger.debug( + { + params: { connectionId: connectionConfig.connectionId, requestId: requestConfig.requestId }, + err, + }, + err.message + ); + throw err; + } +} + +export default checkConnectionRead; diff --git a/packages/api/src/routes/request/evaluateOperators.js b/packages/api/src/routes/request/evaluateOperators.js index da7bb7195..88e4f338d 100644 --- a/packages/api/src/routes/request/evaluateOperators.js +++ b/packages/api/src/routes/request/evaluateOperators.js @@ -18,7 +18,7 @@ import { NodeParser } from '@lowdefy/operators'; import { RequestError } from '../../context/errors'; -async function evaluateOperators({ secrets, user }, { connection, payload, request }) { +async function evaluateOperators({ secrets, user }, { connectionConfig, payload, requestConfig }) { const operatorsParser = new NodeParser({ payload, secrets, @@ -26,16 +26,16 @@ async function evaluateOperators({ secrets, user }, { connection, payload, reque }); await operatorsParser.init(); const { output: connectionProperties, errors: connectionErrors } = operatorsParser.parse({ - input: connection.properties || {}, - location: connection.connectionId, + input: connectionConfig.properties || {}, + location: connectionConfig.connectionId, }); if (connectionErrors.length > 0) { throw new RequestError(connectionErrors[0]); } const { output: requestProperties, errors: requestErrors } = operatorsParser.parse({ - input: request.properties || {}, - location: request.requestId, + input: requestConfig.properties || {}, + location: requestConfig.requestId, }); if (requestErrors.length > 0) { throw new RequestError(requestErrors[0]); diff --git a/packages/api/src/routes/request/loadConnection.js b/packages/api/src/routes/request/getConnectionConfig.js similarity index 64% rename from packages/api/src/routes/request/loadConnection.js rename to packages/api/src/routes/request/getConnectionConfig.js index a89a582e7..aefedbc2e 100644 --- a/packages/api/src/routes/request/loadConnection.js +++ b/packages/api/src/routes/request/getConnectionConfig.js @@ -16,19 +16,24 @@ import { ConfigurationError } from '../../context/errors'; -async function loadConnection({ readConfigFile }, { request }) { - const { connectionId, requestId } = request; +async function getConnectionConfig({ logger, readConfigFile }, { requestConfig }) { + const { connectionId, requestId } = requestConfig; + let err; if (!connectionId) { - throw new ConfigurationError(`Request "${requestId}" does not specify a connection.`); + err = new ConfigurationError(`Request "${requestId}" does not specify a connection.`); + logger.debug({ params: { requestId }, err }, err.message); + throw err; } const connection = await readConfigFile(`connections/${connectionId}.json`); if (!connection) { - throw new ConfigurationError(`Connection "${connectionId}" does not exist.`); + err = new ConfigurationError(`Connection "${connectionId}" does not exist.`); + logger.debug({ params: { requestId }, err }, err.message); + throw err; } return connection; } -export default loadConnection; +export default getConnectionConfig; diff --git a/packages/api/src/routes/request/getConnectionHandler.js b/packages/api/src/routes/request/getConnectionHandler.js new file mode 100644 index 000000000..c86100cd3 --- /dev/null +++ b/packages/api/src/routes/request/getConnectionHandler.js @@ -0,0 +1,35 @@ +/* + Copyright 2020-2021 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +import { ConfigurationError } from '../../context/errors'; + +function getConnectionHandler({ connections, logger }, { connectionConfig }) { + const connectionHandler = connections[connectionConfig.type]; + + if (!connectionHandler) { + const err = new ConfigurationError( + `Connection type "${connectionConfig.type}" can not be found.` + ); + logger.debug( + { params: { id: connectionConfig.connectionId, type: connectionConfig.type }, err }, + err.message + ); + throw err; + } + + return null; +} + +export default getConnectionHandler; diff --git a/packages/api/src/routes/request/getConnectionPackage.js b/packages/api/src/routes/request/getConnectionPackage.js deleted file mode 100644 index c3bd80950..000000000 --- a/packages/api/src/routes/request/getConnectionPackage.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright 2020-2021 Lowdefy, Inc - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -import { ConfigurationError } from '../../context/errors'; - -async function getConnectionPackage({ connectionTypes, logger }, { connection, request }) { - // const connectionTypeDefinition = connectionTypes[connection.type]; - // if (!connectionTypeDefinition) { - // throw new ConfigurationError( - // `Request "${request.requestId}" has undefined connection type "${connection.type}".` - // ); - // } - - // const connectionPackage = await import(connectionTypeDefinition.package); - - // logger.info(connectionPackage); - - // if (!connectionPackage) { - // throw new ConfigurationError( - // `Connection package "${connectionTypeDefinition.package}" could not be imported.` - // ); - // } - return null; -} - -export default getConnectionPackage; diff --git a/packages/api/src/routes/request/loadRequest.js b/packages/api/src/routes/request/getRequestConfig.js similarity index 73% rename from packages/api/src/routes/request/loadRequest.js rename to packages/api/src/routes/request/getRequestConfig.js index fe165cc99..70300f8cc 100644 --- a/packages/api/src/routes/request/loadRequest.js +++ b/packages/api/src/routes/request/getRequestConfig.js @@ -16,12 +16,14 @@ import { ConfigurationError } from '../../context/errors'; -async function loadRequest({ readConfigFile }, { pageId, requestId }) { +async function getRequestConfig({ logger, readConfigFile }, { pageId, requestId }) { const request = await readConfigFile(`pages/${pageId}/requests/${requestId}.json`); if (!request) { - throw new ConfigurationError(`Request "${requestId}" does not exist.`); + const err = new ConfigurationError(`Request "${requestId}" does not exist.`); + logger.debug({ params: { pageId, requestId }, err }, err.message); + throw err; } return request; } -export default loadRequest; +export default getRequestConfig; diff --git a/packages/api/src/routes/request/getRequestHandler.js b/packages/api/src/routes/request/getRequestHandler.js new file mode 100644 index 000000000..f48fabde3 --- /dev/null +++ b/packages/api/src/routes/request/getRequestHandler.js @@ -0,0 +1,33 @@ +/* + Copyright 2020-2021 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +import { ConfigurationError } from '../../context/errors'; + +function getRequestHandler({ logger }, { connectionHandler, requestConfig }) { + const requestHandler = connectionHandler.requests[requestConfig.type]; + + if (!requestHandler) { + const err = new ConfigurationError(`Request type "${requestConfig.type}" can not be found.`); + logger.debug( + { params: { id: requestConfig.requestId, type: requestConfig.type }, err }, + err.message + ); + throw err; + } + + return null; +} + +export default getRequestHandler; diff --git a/packages/api/src/routes/request/request.js b/packages/api/src/routes/request/request.js index 00a106783..96e94c59e 100644 --- a/packages/api/src/routes/request/request.js +++ b/packages/api/src/routes/request/request.js @@ -17,39 +17,40 @@ import { serializer } from '@lowdefy/helpers'; import authorizeRequest from './authorizeRequest'; -// import evaluateOperators from './evaluateOperators'; -// import getConnectionPackage from './getConnectionPackage'; -// import getRequestDefinition from './getRequestDefinition'; -import loadConnection from './loadConnection'; -import loadRequest from './loadRequest'; +import checkConnectionRead from './checkConnectionRead'; +import checkConnectionWrite from './checkConnectionWrite'; +import evaluateOperators from './evaluateOperators'; +import getConnectionConfig from './getConnectionConfig'; +import getConnectionHandler from './getConnectionHandler'; +import getRequestConfig from './getRequestConfig'; +import getRequestHandler from './getRequestHandler'; async function request(context, { pageId, payload, requestId }) { - const request = await loadRequest(context, { pageId, requestId }); + const { logger } = context; + logger.debug({ route: 'request', params: { pageId, payload, requestId } }, 'Started request'); + const requestConfig = await getRequestConfig(context, { pageId, requestId }); + const connectionConfig = await getConnectionConfig(context, { pageId, requestId }); + authorizeRequest(context, { requestConfig }); - authorizeRequest(context, { request }); + const connectionHandler = getConnectionHandler(context, { connectionConfig }); + const requestHandler = getRequestHandler(context, { connectionHandler, requestConfig }); - const connection = await loadConnection(context, { request }); + const { connectionProperties, requestProperties } = await evaluateOperators(context, { + connectionConfig, + payload: serializer.deserialize(payload), + requestConfig, + }); - // Get definitions early to throw and avoid evaluating operators if request/connection type is invalid - // const connectionPackage = await getConnectionPackage(context, { connection, request }); - // const requestDefinition = getRequestDefinition(context, { connectionDefinition, request }); - - // const { connectionProperties, requestProperties } = await evaluateOperators(context, { - // connection, - // payload: serializer.deserialize(payload), - // request, - // }); - - // this.checkConnectionRead({ - // connectionId: request.connectionId, - // connectionProperties, - // checkRead: requestDefinition.checkRead, - // }); - // this.checkConnectionWrite({ - // connectionId: request.connectionId, - // connectionProperties, - // checkWrite: requestDefinition.checkWrite, - // }); + checkConnectionRead({ + connectionId: request.connectionId, + connectionProperties, + checkRead: requestHandler.checkRead, + }); + checkConnectionWrite({ + connectionId: request.connectionId, + connectionProperties, + checkWrite: requestHandler.checkWrite, + }); // try { // validate({ schema: connectionDefinition.schema, data: connectionProperties });