Merge pull request #501 from flovilmart/app-agnostic-controllers
Refactors PushController and FilesController to support multiple apps
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,74 +15,103 @@ 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 = [];
|
||||
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
|
||||
});
|
||||
};
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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];
|
||||
}
|
||||
|
||||
return {params: params, handler: route.handler};
|
||||
}
|
||||
};
|
||||
|
||||
// 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';
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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.
|
||||
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 + '$';
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
return {params: params, handler: route.handler};
|
||||
}
|
||||
};
|
||||
|
||||
// A helper function to make an express handler out of a a promise
|
||||
// handler.
|
||||
// Express handlers should never throw; if a promise handler throws we
|
||||
@@ -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;
|
||||
|
||||
20
src/Routers/AnalyticsRouter.js
Normal file
20
src/Routers/AnalyticsRouter.js
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
55
src/Routers/FunctionsRouter.js
Normal file
55
src/Routers/FunctionsRouter.js
Normal file
@@ -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.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
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) });
|
||||
});
|
||||
}
|
||||
|
||||
var router = new PromiseRouter();
|
||||
router.route("POST","/validate_purchase", handleRequest);
|
||||
module.exports = router;
|
||||
|
||||
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) });
|
||||
});
|
||||
}
|
||||
|
||||
mountRoutes() {
|
||||
this.route("POST","/validate_purchase", this.handleRequest);
|
||||
}
|
||||
}
|
||||
@@ -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); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
|
||||
36
src/index.js
36
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'));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user