Adds jobs endpoint protected by masterKey (#2560)

* Adds jobs endpoint protected by masterKey

* Adds connection timeout for 15 minutes in jobs

* Refactors pushStatusHandler into StatusHandler

* Adds reporting of _JobStatus

* Only accept strings as messages

* Adds test for masterKey basic auth

* Adds CloudCodeRouter for cloud_code endpoint of job status, enable Jobs feature on dashboard

* xit racing test
This commit is contained in:
Florent Vilmart
2016-08-30 07:19:21 -04:00
committed by GitHub
parent 4b2a780e03
commit 10ace495d8
12 changed files with 414 additions and 56 deletions

View File

@@ -5,6 +5,8 @@ var express = require('express'),
triggers = require('../triggers');
import PromiseRouter from '../PromiseRouter';
import { promiseEnforceMasterKeyAccess } from '../middlewares';
import { jobStatusHandler } from '../StatusHandler';
import _ from 'lodash';
import { logger } from '../logger';
@@ -32,9 +34,51 @@ 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 createResponseObject(resolve, reject) {
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({
@@ -49,15 +93,17 @@ export class FunctionsRouter extends PromiseRouter {
code = Parse.Error.SCRIPT_FAILED;
}
reject(new Parse.Error(code, message));
}
},
message: message
}
}
static handleCloudFunction(req) {
var applicationId = req.config.applicationId;
var theFunction = triggers.getFunction(req.params.functionName, applicationId);
var theValidator = triggers.getValidator(req.params.functionName, applicationId);
if (theFunction) {
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 = {
@@ -67,7 +113,7 @@ export class FunctionsRouter extends PromiseRouter {
installationId: req.info.installationId,
log: req.config.loggerController,
headers: req.headers,
functionName: req.params.functionName
functionName
};
if (theValidator && typeof theValidator === "function") {
@@ -83,9 +129,9 @@ export class FunctionsRouter extends PromiseRouter {
var response = FunctionsRouter.createResponseObject((result) => {
try {
const cleanResult = logger.truncateLogMessage(JSON.stringify(result.response.result));
logger.info(`Ran cloud function ${req.params.functionName} for user ${userString} `
logger.info(`Ran cloud function ${functionName} for user ${userString} `
+ `with:\n Input: ${cleanInput }\n Result: ${cleanResult }`, {
functionName: req.params.functionName,
functionName,
params,
user: userString,
});
@@ -95,10 +141,10 @@ export class FunctionsRouter extends PromiseRouter {
}
}, (error) => {
try {
logger.error(`Failed running cloud function ${req.params.functionName} for `
logger.error(`Failed running cloud function ${functionName} for `
+ `user ${userString} with:\n Input: ${cleanInput}\n Error: `
+ JSON.stringify(error), {
functionName: req.params.functionName,
functionName,
error,
params,
user: userString