Merge pull request #903 from ParsePlatform/nlutsenko.push
Cleanup PushController/PushRouter, remove raw mongo collection access.
This commit is contained in:
@@ -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) => {
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,24 +37,12 @@ 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;
|
||||||
if (!pushAdapter) {
|
if (!pushAdapter) {
|
||||||
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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static handlePOST(req) {
|
||||||
* 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) {
|
|
||||||
// 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;
|
||||||
|
|||||||
Reference in New Issue
Block a user