Files
kami-parse-server/src/Routers/FunctionsRouter.js
Florent Vilmart ad707457be Obfuscate password name value pairs in log strings (#2755)
* Unit test to catch password in logs.

* Add clean to logger controller to "look for" password strings in log messages.
2016-09-20 21:45:24 -04:00

168 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// FunctionsRouter.js
var express = require('express'),
Parse = require('parse/node').Parse,
triggers = require('../triggers');
import PromiseRouter from '../PromiseRouter';
import { promiseEnforceMasterKeyAccess } from '../middlewares';
import { jobStatusHandler } from '../StatusHandler';
import _ from 'lodash';
import { logger } from '../logger';
function parseObject(obj) {
if (Array.isArray(obj)) {
return obj.map((item) => {
return parseObject(item);
});
} else if (obj && obj.__type == 'Date') {
return Object.assign(new Date(obj.iso), obj);
} else if (obj && obj.__type == 'File') {
return Parse.File.fromJSON(obj);
} else if (obj && typeof obj === 'object') {
return parseParams(obj);
} else {
return obj;
}
}
function parseParams(params) {
return _.mapValues(params, parseObject);
}
export class FunctionsRouter extends PromiseRouter {
mountRoutes() {
this.route('POST', '/functions/:functionName', FunctionsRouter.handleCloudFunction);
this.route('POST', '/jobs/:jobName', promiseEnforceMasterKeyAccess, function(req) {
return FunctionsRouter.handleCloudJob(req);
});
this.route('POST', '/jobs', promiseEnforceMasterKeyAccess, function(req) {
return FunctionsRouter.handleCloudJob(req);
});
}
static handleCloudJob(req) {
const jobName = req.params.jobName || req.body.jobName;
const applicationId = req.config.applicationId;
const jobHandler = jobStatusHandler(req.config);
const jobFunction = triggers.getJob(jobName, applicationId);
if (!jobFunction) {
throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Invalid job.');
}
let params = Object.assign({}, req.body, req.query);
params = parseParams(params);
const request = {
params: params,
log: req.config.loggerController,
headers: req.headers,
jobName
};
const status = {
success: jobHandler.setSucceeded.bind(jobHandler),
error: jobHandler.setFailed.bind(jobHandler),
message: jobHandler.setMessage.bind(jobHandler)
}
return jobHandler.setRunning(jobName, params).then((jobStatus) => {
request.jobId = jobStatus.objectId
// run the function async
process.nextTick(() => {
jobFunction(request, status);
});
return {
headers: {
'X-Parse-Job-Status-Id': jobStatus.objectId
},
response: {}
}
});
}
static createResponseObject(resolve, reject, message) {
return {
success: function(result) {
resolve({
response: {
result: Parse._encode(result)
}
});
},
error: function(code, message) {
if (!message) {
message = code;
code = Parse.Error.SCRIPT_FAILED;
}
reject(new Parse.Error(code, message));
},
message: message
}
}
static handleCloudFunction(req) {
const functionName = req.params.functionName;
const applicationId = req.config.applicationId;
const theFunction = triggers.getFunction(functionName, applicationId);
const theValidator = triggers.getValidator(req.params.functionName, applicationId);
if (theFunction) {
let params = Object.assign({}, req.body, req.query);
params = parseParams(params);
var request = {
params: params,
master: req.auth && req.auth.isMaster,
user: req.auth && req.auth.user,
installationId: req.info.installationId,
log: req.config.loggerController,
headers: req.headers,
functionName
};
if (theValidator && typeof theValidator === "function") {
var result = theValidator(request);
if (!result) {
throw new Parse.Error(Parse.Error.VALIDATION_ERROR, 'Validation failed.');
}
}
return new Promise(function (resolve, reject) {
const userString = (req.auth && req.auth.user) ? req.auth.user.id : undefined;
const cleanInput = logger.cleanAndTruncateLogMessage(JSON.stringify(params));
var response = FunctionsRouter.createResponseObject((result) => {
try {
const cleanResult = logger.cleanAndTruncateLogMessage(JSON.stringify(result.response.result));
logger.info(`Ran cloud function ${functionName} for user ${userString} `
+ `with:\n Input: ${cleanInput }\n Result: ${cleanResult }`, {
functionName,
params,
user: userString,
});
resolve(result);
} catch (e) {
reject(e);
}
}, (error) => {
try {
logger.error(`Failed running cloud function ${functionName} for `
+ `user ${userString} with:\n Input: ${cleanInput}\n Error: `
+ JSON.stringify(error), {
functionName,
error,
params,
user: userString
});
reject(error);
} catch (e) {
reject(e);
}
});
// Force the keys before the function calls.
Parse.applicationId = req.config.applicationId;
Parse.javascriptKey = req.config.javascriptKey;
Parse.masterKey = req.config.masterKey;
theFunction(request, response);
});
} else {
throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Invalid function.');
}
}
}