Merge pull request #903 from ParsePlatform/nlutsenko.push

Cleanup PushController/PushRouter, remove raw mongo collection access.
This commit is contained in:
Florent Vilmart
2016-03-07 20:42:21 -05:00
7 changed files with 32 additions and 123 deletions

View File

@@ -5,11 +5,11 @@ var Parse = require('parse/node').Parse;
let Config = require('../src/Config'); let Config = require('../src/Config');
describe('a GlobalConfig', () => { describe('a GlobalConfig', () => {
beforeEach(function (done) { beforeEach(done => {
let config = new Config('test'); let config = new Config('test');
config.database.adaptiveCollection('_GlobalConfig') config.database.adaptiveCollection('_GlobalConfig')
.then(coll => coll.upsertOne({ '_id': 1 }, { $set: { params: { companies: ['US', 'DK'] } } })) .then(coll => coll.upsertOne({ '_id': 1 }, { $set: { params: { companies: ['US', 'DK'] } } }))
.then(done()); .then(() => { done(); });
}); });
it('can be retrieved', (done) => { it('can be retrieved', (done) => {

View File

@@ -3,31 +3,6 @@ var PushController = require('../src/Controllers/PushController').PushController
var Config = require('../src/Config'); var Config = require('../src/Config');
describe('PushController', () => { describe('PushController', () => {
it('can check valid master key of request', (done) => {
// Make mock request
var auth = {
isMaster: true
}
expect(() => {
PushController.validateMasterKey(auth);
}).not.toThrow();
done();
});
it('can check invalid master key of request', (done) => {
// Make mock request
var auth = {
isMaster: false
}
expect(() => {
PushController.validateMasterKey(auth);
}).toThrow();
done();
});
it('can validate device type when no device type is set', (done) => { it('can validate device type when no device type is set', (done) => {
// Make query condition // Make query condition
var where = { var where = {

View File

@@ -2,40 +2,6 @@ var PushRouter = require('../src/Routers/PushRouter').PushRouter;
var request = require('request'); var request = require('request');
describe('PushRouter', () => { describe('PushRouter', () => {
it('can check valid master key of request', (done) => {
// Make mock request
var request = {
info: {
masterKey: 'masterKey'
},
config: {
masterKey: 'masterKey'
}
}
expect(() => {
PushRouter.validateMasterKey(request);
}).not.toThrow();
done();
});
it('can check invalid master key of request', (done) => {
// Make mock request
var request = {
info: {
masterKey: 'masterKey'
},
config: {
masterKey: 'masterKeyAgain'
}
}
expect(() => {
PushRouter.validateMasterKey(request);
}).toThrow();
done();
});
it('can get query condition when channels is set', (done) => { it('can get query condition when channels is set', (done) => {
// Make mock request // Make mock request
var request = { var request = {

View File

@@ -64,6 +64,10 @@ export default class MongoCollection {
return this._mongoCollection.update(query, update, { upsert: true }); return this._mongoCollection.update(query, update, { upsert: true });
} }
updateMany(query, update) {
return this._mongoCollection.updateMany(query, update);
}
// Atomically find and delete an object based on query. // Atomically find and delete an object based on query.
// The result is the promise with an object that was in the database before deleting. // The result is the promise with an object that was in the database before deleting.
// Postgres Note: Translates directly to `DELETE * FROM ... RETURNING *`, which will return data after delete is done. // Postgres Note: Translates directly to `DELETE * FROM ... RETURNING *`, which will return data after delete is done.

View File

@@ -35,7 +35,7 @@ DatabaseController.prototype.collection = function(className) {
throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME, throw new Parse.Error(Parse.Error.INVALID_CLASS_NAME,
'invalid className: ' + className); 'invalid className: ' + className);
} }
return this.rawCollection(className); return this.adapter.collection(this.collectionPrefix + className);
}; };
DatabaseController.prototype.adaptiveCollection = function(className) { DatabaseController.prototype.adaptiveCollection = function(className) {
@@ -46,10 +46,6 @@ DatabaseController.prototype.collectionExists = function(className) {
return this.adapter.collectionExists(this.collectionPrefix + className); return this.adapter.collectionExists(this.collectionPrefix + className);
}; };
DatabaseController.prototype.rawCollection = function(className) {
return this.adapter.collection(this.collectionPrefix + className);
};
DatabaseController.prototype.dropCollection = function(className) { DatabaseController.prototype.dropCollection = function(className) {
return this.adapter.dropCollection(this.collectionPrefix + className); return this.adapter.dropCollection(this.collectionPrefix + className);
}; };

View File

@@ -36,17 +36,6 @@ export class PushController extends AdaptableController {
} }
} }
} }
/**
* Check whether the api call has master key or not.
* @param {Object} request A request object
*/
static validateMasterKey(auth = {}) {
if (!auth.isMaster) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
'Master key is invalid, you should only use master key to send push');
}
}
sendPush(body = {}, where = {}, config, auth) { sendPush(body = {}, where = {}, config, auth) {
var pushAdapter = this.adapter; var pushAdapter = this.adapter;
@@ -54,7 +43,6 @@ export class PushController extends AdaptableController {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED, throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
'Push adapter is not available'); 'Push adapter is not available');
} }
PushController.validateMasterKey(auth);
PushController.validatePushType(where, pushAdapter.getValidPushTypes()); PushController.validatePushType(where, pushAdapter.getValidPushTypes());
// Replace the expiration_time with a valid Unix epoch milliseconds time // Replace the expiration_time with a valid Unix epoch milliseconds time
body['expiration_time'] = PushController.getExpirationTime(body); body['expiration_time'] = PushController.getExpirationTime(body);
@@ -63,23 +51,19 @@ export class PushController extends AdaptableController {
let badgeUpdate = Promise.resolve(); let badgeUpdate = Promise.resolve();
if (body.badge) { if (body.badge) {
var op = {}; let op = {};
if (body.badge == "Increment") { if (body.badge == "Increment") {
op = {'$inc': {'badge': 1}} op = { $inc: { badge: 1 } }
} else if (Number(body.badge)) { } else if (Number(body.badge)) {
op = {'$set': {'badge': body.badge } } op = { $set: { badge: body.badge } }
} else { } else {
throw "Invalid value for badge, expected number or 'Increment'"; throw "Invalid value for badge, expected number or 'Increment'";
} }
let updateWhere = deepcopy(where); let updateWhere = deepcopy(where);
updateWhere.deviceType = 'ios'; // Only on iOS!
// Only on iOS! badgeUpdate = config.database.adaptiveCollection("_Installation")
updateWhere.deviceType = 'ios'; .then(coll => coll.updateMany(updateWhere, op));
// TODO: @nlutsenko replace with better thing
badgeUpdate = config.database.rawCollection("_Installation").then((coll) => {
return coll.update(updateWhere, op, { multi: true });
});
} }
return badgeUpdate.then(() => { return badgeUpdate.then(() => {
@@ -144,6 +128,6 @@ export class PushController extends AdaptableController {
expectedAdapterType() { expectedAdapterType() {
return PushAdapter; return PushAdapter;
} }
}; }
export default PushController; export default PushController;

View File

@@ -1,57 +1,42 @@
import PushController from '../Controllers/PushController'
import PromiseRouter from '../PromiseRouter'; import PromiseRouter from '../PromiseRouter';
import * as middleware from "../middlewares";
import { Parse } from "parse/node";
export class PushRouter extends PromiseRouter { export class PushRouter extends PromiseRouter {
mountRoutes() { mountRoutes() {
this.route("POST", "/push", req => { return this.handlePOST(req); }); this.route("POST", "/push", middleware.promiseEnforceMasterKeyAccess, PushRouter.handlePOST);
}
/**
* Check whether the api call has master key or not.
* @param {Object} request A request object
*/
static validateMasterKey(req) {
if (req.info.masterKey !== req.config.masterKey) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
'Master key is invalid, you should only use master key to send push');
}
} }
handlePOST(req) { static handlePOST(req) {
// TODO: move to middlewares when support for Promise middlewares
PushRouter.validateMasterKey(req);
const pushController = req.config.pushController; const pushController = req.config.pushController;
if (!pushController) { if (!pushController) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED, throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED, 'Push controller is not set');
'Push controller is not set');
} }
var where = PushRouter.getQueryCondition(req); let where = PushRouter.getQueryCondition(req);
pushController.sendPush(req.body, where, req.config, req.auth); pushController.sendPush(req.body, where, req.config, req.auth);
return Promise.resolve({ return Promise.resolve({
response: { response: {
'result': true 'result': true
} }
}); });
} }
/** /**
* Get query condition from the request body. * Get query condition from the request body.
* @param {Object} request A request object * @param {Object} req A request object
* @returns {Object} The query condition, the where field in a query api call * @returns {Object} The query condition, the where field in a query api call
*/ */
static getQueryCondition(req) { static getQueryCondition(req) {
var body = req.body || {}; let body = req.body || {};
var hasWhere = typeof body.where !== 'undefined'; let hasWhere = typeof body.where !== 'undefined';
var hasChannels = typeof body.channels !== 'undefined'; let hasChannels = typeof body.channels !== 'undefined';
var where; let where;
if (hasWhere && hasChannels) { if (hasWhere && hasChannels) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED, throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
'Channels and query can not be set at the same time.'); 'Channels and query can not be set at the same time.');
} else if (hasWhere) { } else if (hasWhere) {
where = body.where; where = body.where;
} else if (hasChannels) { } else if (hasChannels) {
@@ -62,11 +47,10 @@ export class PushRouter extends PromiseRouter {
} }
} else { } else {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED, throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
'Channels and query should be set at least one.'); 'Channels and query should be set at least one.');
} }
return where; return where;
} }
} }
export default PushRouter; export default PushRouter;