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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user