From 1855f7829dcc894b4e920c205f362ddbf8e16c86 Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Thu, 19 Nov 2015 11:11:41 +0100 Subject: [PATCH] Advanced setting: verboseApiLogsOnErrors. --- config.json | 10 +++++++++- src/api.js | 44 +++++++++++++++++++++++++++++++------------- src/index.js | 7 ++++--- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/config.json b/config.json index 70e9184ef..90bed6911 100644 --- a/config.json +++ b/config.json @@ -15,5 +15,13 @@ // Should users be created on first sign in? // // Necessary for external authentication providers. - "createUserOnFirstSignin": true + "createUserOnFirstSignin": true, + + // Whether API logs should contains the full request/response on + // errors. + // + // This is disabled by default for performance (lots of data) and + // security concerns (avoiding sensitive data in the logs) but can + // be turned for investigation by the administrator. + "verboseApiLogsOnErrors": false } diff --git a/src/api.js b/src/api.js index 9c614169e..e550e7947 100644 --- a/src/api.js +++ b/src/api.js @@ -80,6 +80,9 @@ function resolveParams (method, params) { const userId = user.get('id') + // Do not alter the original object. + params = { ...params } + const permissions = [] forEach(resolve, ([param, types, permission = 'administrate'], key) => { const id = params[param] @@ -161,8 +164,12 @@ methodSignature.description = 'returns the signature of an API method' // =================================================================== export default class Api { - constructor ({context} = {}) { + constructor ({ + context, + verboseLogsOnErrors + } = {}) { this._methods = createRawObject() + this._verboseLogsOnErrors = verboseLogsOnErrors this.context = context this.addMethods({ @@ -222,9 +229,9 @@ export default class Api { await checkPermission.call(context, method) checkParams(method, params) - await resolveParams.call(context, method, params) + const resolvedParams = await resolveParams.call(context, method, params) - let result = await method.call(context, params) + let result = await method.call(context, resolvedParams) // If nothing was returned, consider this operation a success // and return true. @@ -242,17 +249,28 @@ export default class Api { return result } catch (error) { - debug( - '%s | %s(...) [%s] =!> %s', - userName, - name, - ms(Date.now() - startTime), - error - ) + if (this._verboseLogsOnErrors) { + debug( + '%s | %s(%j) [%s] =!> %s', + userName, + name, + params, + ms(Date.now() - startTime), + error + ) - const stack = error && error.stack - if (stack) { - console.error(stack) + const stack = error && error.stack + if (stack) { + console.error(stack) + } + } else { + debug( + '%s | %s(...) [%s] =!> %s', + userName, + name, + ms(Date.now() - startTime), + error + ) } throw error diff --git a/src/index.js b/src/index.js index da285d6ee..e91a54c6a 100644 --- a/src/index.js +++ b/src/index.js @@ -383,13 +383,14 @@ const apiHelpers = { } } -const setUpApi = (webSocketServer, xo) => { +const setUpApi = (webSocketServer, xo, verboseLogsOnErrors) => { // FIXME: it can cause issues if there any property assignments in // XO methods called from the API. const context = { __proto__: xo, ...apiHelpers } const api = new Api({ - context + context, + verboseLogsOnErrors }) api.addMethods(apiMethods) @@ -611,7 +612,7 @@ export default async function main (args) { // Must be set up before the static files. const webSocketServer = setUpWebSocketServer(webServer) - const api = setUpApi(webSocketServer, xo) + const api = setUpApi(webSocketServer, xo, config.verboseApiLogsOnErrors) const scheduler = setUpScheduler(api, xo) setUpRemoteHandler(xo)