diff --git a/src/Config.js b/src/Config.js index aeb25a6173..3b9188a483 100644 --- a/src/Config.js +++ b/src/Config.js @@ -24,8 +24,9 @@ function Config(applicationId, mount) { this.database = DatabaseAdapter.getDatabaseConnection(applicationId); this.filesController = cacheInfo.filesController; - + this.pushController = cacheInfo.pushController; this.oauth = cacheInfo.oauth; + this.mount = mount; } diff --git a/src/Controllers/FilesController.js b/src/Controllers/FilesController.js index 6fde54b766..f1238694aa 100644 --- a/src/Controllers/FilesController.js +++ b/src/Controllers/FilesController.js @@ -13,6 +13,13 @@ export class FilesController { this._filesAdapter = filesAdapter; } + static getHandler() { + return (req, res) => { + let config = new Config(req.params.appId); + return config.filesController.getHandler()(req, res); + } + } + getHandler() { return (req, res) => { let config = new Config(req.params.appId); @@ -30,6 +37,13 @@ export class FilesController { }; } + static createHandler() { + return (req, res, next) => { + let config = req.config; + return config.filesController.createHandler()(req, res, next); + } + } + createHandler() { return (req, res, next) => { if (!req.body || !req.body.length) { @@ -50,6 +64,7 @@ export class FilesController { return; } + const filesController = req.config.filesController; // If a content-type is included, we'll add an extension so we can // return the same content-type. let extension = ''; @@ -60,9 +75,9 @@ export class FilesController { } let filename = randomHexString(32) + '_' + req.params.filename + extension; - this._filesAdapter.createFile(req.config, filename, req.body).then(() => { + filesController._filesAdapter.createFile(req.config, filename, req.body).then(() => { res.status(201); - var location = this._filesAdapter.getFileLocation(req.config, filename); + var location = filesController._filesAdapter.getFileLocation(req.config, filename); res.set('Location', location); res.json({ url: location, name: filename }); }).catch((error) => { @@ -72,6 +87,13 @@ export class FilesController { }; } + static deleteHandler() { + return (req, res, next) => { + let config = req.config; + return config.filesController.deleteHandler()(req, res, next); + } + } + deleteHandler() { return (req, res, next) => { this._filesAdapter.deleteFile(req.config, req.params.filename).then(() => { @@ -114,9 +136,9 @@ export class FilesController { } } - getExpressRouter() { + static getExpressRouter() { let router = express.Router(); - router.get('/files/:appId/:filename', this.getHandler()); + router.get('/files/:appId/:filename', FilesController.getHandler()); router.post('/files', function(req, res, next) { next(new Parse.Error(Parse.Error.INVALID_FILE_NAME, @@ -127,14 +149,14 @@ export class FilesController { Middlewares.allowCrossDomain, BodyParser.raw({type: '*/*', limit: '20mb'}), Middlewares.handleParseHeaders, - this.createHandler() + FilesController.createHandler() ); router.delete('/files/:filename', Middlewares.allowCrossDomain, Middlewares.handleParseHeaders, Middlewares.enforceMasterKeyAccess, - this.deleteHandler() + FilesController.deleteHandler() ); return router; diff --git a/src/Controllers/PushController.js b/src/Controllers/PushController.js index 9f9252dcc8..e87e6f764c 100644 --- a/src/Controllers/PushController.js +++ b/src/Controllers/PushController.js @@ -31,11 +31,11 @@ export class PushController { } }); } - - getExpressRouter() { + + static getExpressRouter() { var router = new PromiseRouter(); router.route('POST','/push', (req) => { - return this.handlePOST(req); + return req.config.pushController.handlePOST(req); }); return router; } diff --git a/src/PromiseRouter.js b/src/PromiseRouter.js index 03514e7818..498e7d4920 100644 --- a/src/PromiseRouter.js +++ b/src/PromiseRouter.js @@ -5,7 +5,7 @@ // themselves use our routing information, without disturbing express // components that external developers may be modifying. -function PromiseRouter() { +export default class PromiseRouter { // Each entry should be an object with: // path: the path to route, in express format // method: the HTTP method that this route handles. @@ -15,73 +15,102 @@ function PromiseRouter() { // status: optional. the http status code. defaults to 200 // response: a json object with the content of the response // location: optional. a location header - this.routes = []; -} - -// Global flag. Set this to true to log every request and response. -PromiseRouter.verbose = process.env.VERBOSE || false; - -// Merge the routes into this one -PromiseRouter.prototype.merge = function(router) { - for (var route of router.routes) { - this.routes.push(route); - } -}; - -PromiseRouter.prototype.route = function(method, path, handler) { - switch(method) { - case 'POST': - case 'GET': - case 'PUT': - case 'DELETE': - break; - default: - throw 'cannot route method: ' + method; + constructor() { + this.routes = []; + this.mountRoutes(); } + + // Leave the opportunity to + // subclasses to mount their routes by overriding + mountRoutes() {} + + // Merge the routes into this one + merge(router) { + for (var route of router.routes) { + this.routes.push(route); + } + }; + + route(method, path, handler) { + switch(method) { + case 'POST': + case 'GET': + case 'PUT': + case 'DELETE': + break; + default: + throw 'cannot route method: ' + method; + } - this.routes.push({ - path: path, - method: method, - handler: handler - }); -}; + this.routes.push({ + path: path, + method: method, + handler: handler + }); + }; + + // Returns an object with: + // handler: the handler that should deal with this request + // params: any :-params that got parsed from the path + // Returns undefined if there is no match. + match(method, path) { + for (var route of this.routes) { + if (route.method != method) { + continue; + } -// Returns an object with: -// handler: the handler that should deal with this request -// params: any :-params that got parsed from the path -// Returns undefined if there is no match. -PromiseRouter.prototype.match = function(method, path) { - for (var route of this.routes) { - if (route.method != method) { - continue; - } + // NOTE: we can only route the specific wildcards :className and + // :objectId, and in that order. + // This is pretty hacky but I don't want to rebuild the entire + // express route matcher. Maybe there's a way to reuse its logic. + var pattern = '^' + route.path + '$'; - // NOTE: we can only route the specific wildcards :className and - // :objectId, and in that order. - // This is pretty hacky but I don't want to rebuild the entire - // express route matcher. Maybe there's a way to reuse its logic. - var pattern = '^' + route.path + '$'; + pattern = pattern.replace(':className', + '(_?[A-Za-z][A-Za-z_0-9]*)'); + pattern = pattern.replace(':objectId', + '([A-Za-z0-9]+)'); + var re = new RegExp(pattern); + var m = path.match(re); + if (!m) { + continue; + } + var params = {}; + if (m[1]) { + params.className = m[1]; + } + if (m[2]) { + params.objectId = m[2]; + } - pattern = pattern.replace(':className', - '(_?[A-Za-z][A-Za-z_0-9]*)'); - pattern = pattern.replace(':objectId', - '([A-Za-z0-9]+)'); - var re = new RegExp(pattern); - var m = path.match(re); - if (!m) { - continue; + return {params: params, handler: route.handler}; } - var params = {}; - if (m[1]) { - params.className = m[1]; - } - if (m[2]) { - params.objectId = m[2]; + }; + + // Mount the routes on this router onto an express app (or express router) + mountOnto(expressApp) { + for (var route of this.routes) { + switch(route.method) { + case 'POST': + expressApp.post(route.path, makeExpressHandler(route.handler)); + break; + case 'GET': + expressApp.get(route.path, makeExpressHandler(route.handler)); + break; + case 'PUT': + expressApp.put(route.path, makeExpressHandler(route.handler)); + break; + case 'DELETE': + expressApp.delete(route.path, makeExpressHandler(route.handler)); + break; + default: + throw 'unexpected code branch'; + } } + }; +} - return {params: params, handler: route.handler}; - } -}; +// Global flag. Set this to true to log every request and response. +PromiseRouter.verbose = process.env.VERBOSE || false; // A helper function to make an express handler out of a a promise // handler. @@ -122,27 +151,3 @@ function makeExpressHandler(promiseHandler) { } } } - -// Mount the routes on this router onto an express app (or express router) -PromiseRouter.prototype.mountOnto = function(expressApp) { - for (var route of this.routes) { - switch(route.method) { - case 'POST': - expressApp.post(route.path, makeExpressHandler(route.handler)); - break; - case 'GET': - expressApp.get(route.path, makeExpressHandler(route.handler)); - break; - case 'PUT': - expressApp.put(route.path, makeExpressHandler(route.handler)); - break; - case 'DELETE': - expressApp.delete(route.path, makeExpressHandler(route.handler)); - break; - default: - throw 'unexpected code branch'; - } - } -}; - -module.exports = PromiseRouter; diff --git a/src/Routers/AnalyticsRouter.js b/src/Routers/AnalyticsRouter.js new file mode 100644 index 0000000000..9e26e5f980 --- /dev/null +++ b/src/Routers/AnalyticsRouter.js @@ -0,0 +1,20 @@ +// AnalyticsRouter.js + +var Parse = require('parse/node').Parse; + +import PromiseRouter from '../PromiseRouter'; + +// Returns a promise that resolves to an empty object response +function ignoreAndSucceed(req) { + return Promise.resolve({ + response: {} + }); +} + + +export class AnalyticsRouter extends PromiseRouter { + mountRoutes() { + this.route('POST','/events/AppOpened', ignoreAndSucceed); + this.route('POST','/events/:eventName', ignoreAndSucceed); + } +} diff --git a/src/Routers/ClassesRouter.js b/src/Routers/ClassesRouter.js index 9b5b20d745..dfb3d9774b 100644 --- a/src/Routers/ClassesRouter.js +++ b/src/Routers/ClassesRouter.js @@ -4,8 +4,8 @@ import rest from '../rest'; import url from 'url'; -export class ClassesRouter { - // Returns a promise that resolves to a {response} object. +export class ClassesRouter extends PromiseRouter { + handleFind(req) { let body = Object.assign(req.body, req.query); let options = {}; @@ -97,15 +97,13 @@ export class ClassesRouter { return {response: {}}; }); } - - getExpressRouter() { - var router = new PromiseRouter(); - router.route('GET', '/classes/:className', (req) => { return this.handleFind(req); }); - router.route('GET', '/classes/:className/:objectId', (req) => { return this.handleGet(req); }); - router.route('POST', '/classes/:className', (req) => { return this.handleCreate(req); }); - router.route('PUT', '/classes/:className/:objectId', (req) => { return this.handleUpdate(req); }); - router.route('DELETE', '/classes/:className/:objectId', (req) => { return this.handleDelete(req); }); - return router; + + mountRoutes() { + this.route('GET', '/classes/:className', (req) => { return this.handleFind(req); }); + this.route('GET', '/classes/:className/:objectId', (req) => { return this.handleGet(req); }); + this.route('POST', '/classes/:className', (req) => { return this.handleCreate(req); }); + this.route('PUT', '/classes/:className/:objectId', (req) => { return this.handleUpdate(req); }); + this.route('DELETE', '/classes/:className/:objectId', (req) => { return this.handleDelete(req); }); } } diff --git a/src/Routers/FunctionsRouter.js b/src/Routers/FunctionsRouter.js new file mode 100644 index 0000000000..76190682bc --- /dev/null +++ b/src/Routers/FunctionsRouter.js @@ -0,0 +1,55 @@ +// functions.js + +var express = require('express'), + Parse = require('parse/node').Parse; + +import PromiseRouter from '../PromiseRouter'; + +export class FunctionsRouter extends PromiseRouter { + + mountRoutes() { + this.route('POST', '/functions/:functionName', FunctionsRouter.handleCloudFunction); + } + + static createResponseObject(resolve, reject) { + return { + success: function(result) { + resolve({ + response: { + result: Parse._encode(result) + } + }); + }, + error: function(error) { + reject(new Parse.Error(Parse.Error.SCRIPT_FAILED, error)); + } + } + } + + static handleCloudFunction(req) { + if (Parse.Cloud.Functions[req.params.functionName]) { + + var request = { + params: Object.assign({}, req.body, req.query), + master: req.auth && req.auth.isMaster, + user: req.auth && req.auth.user, + installationId: req.info.installationId + }; + + if (Parse.Cloud.Validators[req.params.functionName]) { + var result = Parse.Cloud.Validators[req.params.functionName](request); + if (!result) { + throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Validation failed.'); + } + } + + return new Promise(function (resolve, reject) { + var response = FunctionsRouter.createResponseObject(resolve, reject); + Parse.Cloud.Functions[req.params.functionName](request, response); + }); + } else { + throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Invalid function.'); + } + } +} + diff --git a/src/validate_purchase.js b/src/Routers/IAPValidationRouter.js similarity index 64% rename from src/validate_purchase.js rename to src/Routers/IAPValidationRouter.js index dfcf5c0f56..831915b797 100644 --- a/src/validate_purchase.js +++ b/src/Routers/IAPValidationRouter.js @@ -1,8 +1,9 @@ -var PromiseRouter = require("./PromiseRouter"); +import PromiseRouter from '../PromiseRouter'; var request = require("request"); -var rest = require("./rest"); -var Auth = require("./Auth"); +var rest = require("../rest"); +var Auth = require("../Auth"); +// TODO move validation logic in IAPValidationController const IAP_SANDBOX_URL = "https://sandbox.itunes.apple.com/verifyReceipt"; const IAP_PRODUCTION_URL = "https://buy.itunes.apple.com/verifyReceipt"; @@ -57,34 +58,39 @@ function getFileForProductIdentifier(productIdentifier, req) { }); } -function handleRequest(req) { - let receipt = req.body.receipt; - const productIdentifier = req.body.productIdentifier; - - if (!receipt || ! productIdentifier) { - // TODO: Error, malformed request - throw new Parse.Error(Parse.Error.INVALID_JSON, "missing receipt or productIdentifier"); - } - - // Transform the object if there - // otherwise assume it's in Base64 already - if (typeof receipt == "object") { - if (receipt["__type"] == "Bytes") { - receipt = receipt.base64; + + +export class IAPValidationRouter extends PromiseRouter { + + handleRequest(req) { + let receipt = req.body.receipt; + const productIdentifier = req.body.productIdentifier; + + if (!receipt || ! productIdentifier) { + // TODO: Error, malformed request + throw new Parse.Error(Parse.Error.INVALID_JSON, "missing receipt or productIdentifier"); + } + + // Transform the object if there + // otherwise assume it's in Base64 already + if (typeof receipt == "object") { + if (receipt["__type"] == "Bytes") { + receipt = receipt.base64; + } + } + + if (process.env.NODE_ENV == "test" && req.body.bypassAppStoreValidation) { + return getFileForProductIdentifier(productIdentifier, req); } + + return validateWithAppStore(IAP_PRODUCTION_URL, receipt).then( () => { + return getFileForProductIdentifier(productIdentifier, req); + }, (error) => { + return Promise.resolve({response: appStoreError(error.status) }); + }); } - if (process.env.NODE_ENV == "test" && req.body.bypassAppStoreValidation) { - return getFileForProductIdentifier(productIdentifier, req); + mountRoutes() { + this.route("POST","/validate_purchase", this.handleRequest); } - - return validateWithAppStore(IAP_PRODUCTION_URL, receipt).then( () => { - return getFileForProductIdentifier(productIdentifier, req); - }, (error) => { - return Promise.resolve({response: appStoreError(error.status) }); - }); } - -var router = new PromiseRouter(); -router.route("POST","/validate_purchase", handleRequest); -module.exports = router; diff --git a/src/Routers/InstallationsRouter.js b/src/Routers/InstallationsRouter.js index fca703e9a1..9c21f005bf 100644 --- a/src/Routers/InstallationsRouter.js +++ b/src/Routers/InstallationsRouter.js @@ -50,14 +50,12 @@ export class InstallationsRouter extends ClassesRouter { return super.handleDelete(req); } - getExpressRouter() { - let router = new PromiseRouter(); - router.route('GET','/installations', req => { return this.handleFind(req); }); - router.route('GET','/installations/:objectId', req => { return this.handleGet(req); }); - router.route('POST','/installations', req => { return this.handleCreate(req); }); - router.route('PUT','/installations/:objectId', req => { return this.handleUpdate(req); }); - router.route('DELETE','/installations/:objectId', req => { return this.handleDelete(req); }); - return router; + mountRoutes() { + this.route('GET','/installations', req => { return this.handleFind(req); }); + this.route('GET','/installations/:objectId', req => { return this.handleGet(req); }); + this.route('POST','/installations', req => { return this.handleCreate(req); }); + this.route('PUT','/installations/:objectId', req => { return this.handleUpdate(req); }); + this.route('DELETE','/installations/:objectId', req => { return this.handleDelete(req); }); } } diff --git a/src/Routers/RolesRouter.js b/src/Routers/RolesRouter.js index b20a91ee86..c9b4f999c5 100644 --- a/src/Routers/RolesRouter.js +++ b/src/Routers/RolesRouter.js @@ -29,14 +29,12 @@ export class RolesRouter extends ClassesRouter { return super.handleDelete(req); } - getExpressRouter() { - let router = new PromiseRouter(); - router.route('GET','/roles', req => { return this.handleFind(req); }); - router.route('GET','/roles/:objectId', req => { return this.handleGet(req); }); - router.route('POST','/roles', req => { return this.handleCreate(req); }); - router.route('PUT','/roles/:objectId', req => { return this.handleUpdate(req); }); - router.route('DELETE','/roles/:objectId', req => { return this.handleDelete(req); }); - return router; + mountRoutes() { + this.route('GET','/roles', req => { return this.handleFind(req); }); + this.route('GET','/roles/:objectId', req => { return this.handleGet(req); }); + this.route('POST','/roles', req => { return this.handleCreate(req); }); + this.route('PUT','/roles/:objectId', req => { return this.handleUpdate(req); }); + this.route('DELETE','/roles/:objectId', req => { return this.handleDelete(req); }); } } diff --git a/src/schemas.js b/src/Routers/SchemasRouter.js similarity index 92% rename from src/schemas.js rename to src/Routers/SchemasRouter.js index 9fb191c82a..d738815869 100644 --- a/src/schemas.js +++ b/src/Routers/SchemasRouter.js @@ -2,11 +2,11 @@ var express = require('express'), Parse = require('parse/node').Parse, - PromiseRouter = require('./PromiseRouter'), - Schema = require('./Schema'); + Schema = require('../Schema'); -var router = new PromiseRouter(); +import PromiseRouter from '../PromiseRouter'; +// TODO: refactor in a SchemaController at one point... function masterKeyRequiredResponse() { return Promise.resolve({ status: 401, @@ -257,21 +257,23 @@ function deleteSchema(req) { } }); })) - .catch(error => { + .catch( (error) => { if (error.message == 'ns not found') { // If they try to delete a non-existant class, thats fine, just let them. return Promise.resolve({ response: {} }); - } else { - return Promise.reject(error); - } + } + + return Promise.reject(error); }); } -router.route('GET', '/schemas', getAllSchemas); -router.route('GET', '/schemas/:className', getOneSchema); -router.route('POST', '/schemas', createSchema); -router.route('POST', '/schemas/:className', createSchema); -router.route('PUT', '/schemas/:className', modifySchema); -router.route('DELETE', '/schemas/:className', deleteSchema); - -module.exports = router; +export class SchemasRouter extends PromiseRouter { + mountRoutes() { + this.route('GET', '/schemas', getAllSchemas); + this.route('GET', '/schemas/:className', getOneSchema); + this.route('POST', '/schemas', createSchema); + this.route('POST', '/schemas/:className', createSchema); + this.route('PUT', '/schemas/:className', modifySchema); + this.route('DELETE', '/schemas/:className', deleteSchema); + } +} diff --git a/src/Routers/SessionsRouter.js b/src/Routers/SessionsRouter.js index ecffd80ac7..1a8d8cbfb9 100644 --- a/src/Routers/SessionsRouter.js +++ b/src/Routers/SessionsRouter.js @@ -48,15 +48,13 @@ export class SessionsRouter extends ClassesRouter { }); } - getExpressRouter() { - let router = new PromiseRouter(); - router.route('GET','/sessions/me', req => { return this.handleMe(req); }); - router.route('GET', '/sessions', req => { return this.handleFind(req); }); - router.route('GET', '/sessions/:objectId', req => { return this.handleGet(req); }); - router.route('POST', '/sessions', req => { return this.handleCreate(req); }); - router.route('PUT', '/sessions/:objectId', req => { return this.handleUpdate(req); }); - router.route('DELETE', '/sessions/:objectId', req => { return this.handleDelete(req); }); - return router; + mountRoutes() { + this.route('GET','/sessions/me', req => { return this.handleMe(req); }); + this.route('GET', '/sessions', req => { return this.handleFind(req); }); + this.route('GET', '/sessions/:objectId', req => { return this.handleGet(req); }); + this.route('POST', '/sessions', req => { return this.handleCreate(req); }); + this.route('PUT', '/sessions/:objectId', req => { return this.handleUpdate(req); }); + this.route('DELETE', '/sessions/:objectId', req => { return this.handleDelete(req); }); } } diff --git a/src/Routers/UsersRouter.js b/src/Routers/UsersRouter.js index 946dfe54c8..29d33ed2ff 100644 --- a/src/Routers/UsersRouter.js +++ b/src/Routers/UsersRouter.js @@ -138,20 +138,18 @@ export class UsersRouter extends ClassesRouter { return Promise.resolve(success); } - getExpressRouter() { - let router = new PromiseRouter(); - router.route('GET', '/users', req => { return this.handleFind(req); }); - router.route('POST', '/users', req => { return this.handleCreate(req); }); - router.route('GET', '/users/me', req => { return this.handleMe(req); }); - router.route('GET', '/users/:objectId', req => { return this.handleGet(req); }); - router.route('PUT', '/users/:objectId', req => { return this.handleUpdate(req); }); - router.route('DELETE', '/users/:objectId', req => { return this.handleDelete(req); }); - router.route('GET', '/login', req => { return this.handleLogIn(req); }); - router.route('POST', '/logout', req => { return this.handleLogOut(req); }); - router.route('POST', '/requestPasswordReset', () => { + mountRoutes() { + this.route('GET', '/users', req => { return this.handleFind(req); }); + this.route('POST', '/users', req => { return this.handleCreate(req); }); + this.route('GET', '/users/me', req => { return this.handleMe(req); }); + this.route('GET', '/users/:objectId', req => { return this.handleGet(req); }); + this.route('PUT', '/users/:objectId', req => { return this.handleUpdate(req); }); + this.route('DELETE', '/users/:objectId', req => { return this.handleDelete(req); }); + this.route('GET', '/login', req => { return this.handleLogIn(req); }); + this.route('POST', '/logout', req => { return this.handleLogOut(req); }); + this.route('POST', '/requestPasswordReset', () => { throw new Parse.Error(Parse.Error.COMMAND_UNAVAILABLE, 'This path is not implemented yet.'); }); - return router; } } diff --git a/src/analytics.js b/src/analytics.js deleted file mode 100644 index 7294837f6a..0000000000 --- a/src/analytics.js +++ /dev/null @@ -1,20 +0,0 @@ -// analytics.js - -var Parse = require('parse/node').Parse, - PromiseRouter = require('./PromiseRouter'), - rest = require('./rest'); - -var router = new PromiseRouter(); - - -// Returns a promise that resolves to an empty object response -function ignoreAndSucceed(req) { - return Promise.resolve({ - response: {} - }); -} - -router.route('POST','/events/AppOpened', ignoreAndSucceed); -router.route('POST','/events/:eventName', ignoreAndSucceed); - -module.exports = router; \ No newline at end of file diff --git a/src/functions.js b/src/functions.js deleted file mode 100644 index 8e88aa0358..0000000000 --- a/src/functions.js +++ /dev/null @@ -1,54 +0,0 @@ -// functions.js - -var express = require('express'), - Parse = require('parse/node').Parse, - PromiseRouter = require('./PromiseRouter'), - rest = require('./rest'); - -var router = new PromiseRouter(); - -function handleCloudFunction(req) { - if (Parse.Cloud.Functions[req.params.functionName]) { - - var request = { - params: Object.assign({}, req.body, req.query), - master: req.auth && req.auth.isMaster, - user: req.auth && req.auth.user, - installationId: req.info.installationId - }; - - if (Parse.Cloud.Validators[req.params.functionName]) { - var result = Parse.Cloud.Validators[req.params.functionName](request); - if (!result) { - throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Validation failed.'); - } - } - - return new Promise(function (resolve, reject) { - var response = createResponseObject(resolve, reject); - Parse.Cloud.Functions[req.params.functionName](request, response); - }); - } else { - throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Invalid function.'); - } -} - -function createResponseObject(resolve, reject) { - return { - success: function(result) { - resolve({ - response: { - result: Parse._encode(result) - } - }); - }, - error: function(error) { - reject(new Parse.Error(Parse.Error.SCRIPT_FAILED, error)); - } - } -} - -router.route('POST', '/functions/:functionName', handleCloudFunction); - - -module.exports = router; diff --git a/src/global_config.js b/src/global_config.js index 3dd1b5432e..0c005e4dc6 100644 --- a/src/global_config.js +++ b/src/global_config.js @@ -1,8 +1,8 @@ // global_config.js -var Parse = require('parse/node').Parse, - PromiseRouter = require('./PromiseRouter'); +var Parse = require('parse/node').Parse; +import PromiseRouter from './PromiseRouter'; var router = new PromiseRouter(); function getGlobalConfig(req) { diff --git a/src/index.js b/src/index.js index 4b43e2eef1..de63f9bb06 100644 --- a/src/index.js +++ b/src/index.js @@ -8,9 +8,9 @@ var batch = require('./batch'), middlewares = require('./middlewares'), multer = require('multer'), Parse = require('parse/node').Parse, - PromiseRouter = require('./PromiseRouter'), httpRequest = require('./httpRequest'); - + +import PromiseRouter from './PromiseRouter'; import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter'; import { S3Adapter } from './Adapters/Files/S3Adapter'; import { FilesController } from './Controllers/FilesController'; @@ -23,6 +23,11 @@ import { InstallationsRouter } from './Routers/InstallationsRouter'; import { UsersRouter } from './Routers/UsersRouter'; import { SessionsRouter } from './Routers/SessionsRouter'; import { RolesRouter } from './Routers/RolesRouter'; +import { AnalyticsRouter } from './Routers/AnalyticsRouter'; +import { FunctionsRouter } from './Routers/FunctionsRouter'; +import { SchemasRouter } from './Routers/SchemasRouter'; +import { IAPValidationRouter } from './Routers/IAPValidationRouter'; + import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter'; import { LoggerController } from './Controllers/LoggerController'; @@ -106,7 +111,7 @@ function ParseServer({ } let filesController = new FilesController(filesAdapter); - + cache.apps[appId] = { masterKey: masterKey, collectionPrefix: collectionPrefix, @@ -119,7 +124,7 @@ function ParseServer({ filesController: filesController, enableAnonymousUsers: enableAnonymousUsers, oauth: oauth, - }; +}; // To maintain compatibility. TODO: Remove in v2.1 if (process.env.FACEBOOK_APP_ID) { @@ -135,7 +140,7 @@ function ParseServer({ var api = express(); // File handling needs to be before default middlewares are applied - api.use('/', filesController.getExpressRouter()); + api.use('/', FilesController.getExpressRouter()); // TODO: separate this from the regular ParseServer object if (process.env.TESTING == 1) { @@ -148,18 +153,19 @@ function ParseServer({ api.use(middlewares.handleParseHeaders); let routers = [ - new ClassesRouter().getExpressRouter(), - new UsersRouter().getExpressRouter(), - new SessionsRouter().getExpressRouter(), - new RolesRouter().getExpressRouter(), - require('./analytics'), - new InstallationsRouter().getExpressRouter(), - require('./functions'), - require('./schemas'), - new PushController(pushAdapter).getExpressRouter(), + new ClassesRouter(), + new UsersRouter(), + new SessionsRouter(), + new RolesRouter(), + new AnalyticsRouter(), + new InstallationsRouter(), + new FunctionsRouter(), + new SchemasRouter(), + PushController.getExpressRouter(), new LoggerController(loggerAdapter).getExpressRouter(), - require('./validate_purchase') + new IAPValidationRouter() ]; + if (process.env.PARSE_EXPERIMENTAL_CONFIG_ENABLED || process.env.TESTING) { routers.push(require('./global_config')); }