Make push follow controller and adapter style

This commit is contained in:
wangmengyan95
2016-02-10 12:03:02 -08:00
parent 6afaeb808b
commit 06b1ee2362
6 changed files with 90 additions and 95 deletions

View File

@@ -2,14 +2,6 @@ var ParsePushAdapter = require('../src/Adapters/Push/ParsePushAdapter');
describe('ParsePushAdapter', () => {
it('can be initialized', (done) => {
var parsePushAdapter = new ParsePushAdapter();
expect(parsePushAdapter.validPushTypes).toEqual(['ios', 'android']);
done();
});
it('can initialize', (done) => {
var parsePushAdapter = new ParsePushAdapter();
// Make mock config
var pushConfig = {
android: {
@@ -30,7 +22,7 @@ describe('ParsePushAdapter', () => {
]
};
parsePushAdapter.initialize(pushConfig);
var parsePushAdapter = new ParsePushAdapter(pushConfig);
// Check ios
var iosSenders = parsePushAdapter.senders['ios'];
expect(iosSenders.length).toBe(2);
@@ -53,7 +45,6 @@ describe('ParsePushAdapter', () => {
});
it('can throw on initializing with unsupported push type', (done) => {
var parsePushAdapter = new ParsePushAdapter();
// Make mock config
var pushConfig = {
win: {
@@ -63,20 +54,19 @@ describe('ParsePushAdapter', () => {
};
expect(function() {
parsePushAdapter.initialize(pushConfig)
new ParsePushAdapter(pushConfig);
}).toThrow();
done();
});
it('can throw on initializing with invalid pushConfig', (done) => {
var parsePushAdapter = new ParsePushAdapter();
// Make mock config
var pushConfig = {
android: 123
};
expect(function() {
parsePushAdapter.initialize(pushConfig)
new ParsePushAdapter(pushConfig);
}).toThrow();
done();
});

View File

@@ -1,6 +1,6 @@
var push = require('../src/push');
var PushController = require('../src/Controllers/PushController').PushController;
describe('push', () => {
describe('PushController', () => {
it('can check valid master key of request', (done) => {
// Make mock request
var request = {
@@ -13,7 +13,7 @@ describe('push', () => {
}
expect(() => {
push.validateMasterKey(request);
PushController.validateMasterKey(request);
}).not.toThrow();
done();
});
@@ -30,7 +30,7 @@ describe('push', () => {
}
expect(() => {
push.validateMasterKey(request);
PushController.validateMasterKey(request);
}).toThrow();
done();
});
@@ -43,7 +43,7 @@ describe('push', () => {
}
}
var where = push.getQueryCondition(request);
var where = PushController.getQueryCondition(request);
expect(where).toEqual({
'channels': {
'$in': ['Giants', 'Mets']
@@ -62,7 +62,7 @@ describe('push', () => {
}
}
var where = push.getQueryCondition(request);
var where = PushController.getQueryCondition(request);
expect(where).toEqual({
'injuryReports': true
});
@@ -77,7 +77,7 @@ describe('push', () => {
}
expect(function() {
push.getQueryCondition(request);
PushController.getQueryCondition(request);
}).toThrow();
done();
});
@@ -96,7 +96,7 @@ describe('push', () => {
}
expect(function() {
push.getQueryCondition(request);
PushController.getQueryCondition(request);
}).toThrow();
done();
});
@@ -108,7 +108,7 @@ describe('push', () => {
var validPushTypes = ['ios', 'android'];
expect(function(){
push.validatePushType(where, validPushTypes);
PushController.validatePushType(where, validPushTypes);
}).not.toThrow();
done();
});
@@ -121,7 +121,7 @@ describe('push', () => {
var validPushTypes = ['ios', 'android'];
expect(function(){
push.validatePushType(where, validPushTypes);
PushController.validatePushType(where, validPushTypes);
}).not.toThrow();
done();
});
@@ -136,7 +136,7 @@ describe('push', () => {
var validPushTypes = ['ios', 'android'];
expect(function(){
push.validatePushType(where, validPushTypes);
PushController.validatePushType(where, validPushTypes);
}).not.toThrow();
done();
});
@@ -149,7 +149,7 @@ describe('push', () => {
var validPushTypes = ['ios', 'android'];
expect(function(){
push.validatePushType(where, validPushTypes);
PushController.validatePushType(where, validPushTypes);
}).toThrow();
done();
});
@@ -162,7 +162,7 @@ describe('push', () => {
var validPushTypes = ['ios', 'android'];
expect(function(){
push.validatePushType(where, validPushTypes);
PushController.validatePushType(where, validPushTypes);
}).toThrow();
done();
});
@@ -176,7 +176,7 @@ describe('push', () => {
}
}
var time = push.getExpirationTime(request);
var time = PushController.getExpirationTime(request);
expect(time).toEqual(new Date(timeStr).valueOf());
done();
});
@@ -190,7 +190,7 @@ describe('push', () => {
}
}
var time = push.getExpirationTime(request);
var time = PushController.getExpirationTime(request);
expect(time).toEqual(timeNumber * 1000);
done();
});
@@ -204,7 +204,7 @@ describe('push', () => {
}
expect(function(){
push.getExpirationTime(request);
PushController.getExpirationTime(request);
}).toThrow();
done();
});

View File

@@ -7,16 +7,10 @@ const Parse = require('parse/node').Parse;
const GCM = require('../../GCM');
const APNS = require('../../APNS');
function ParsePushAdapter() {
this.validPushTypes = ['ios', 'android'];
this.senders = {};
}
function ParsePushAdapter(pushConfig) {
this.validPushTypes = ['ios', 'android'];
this.senders = {};
/**
* Register push senders
* @param {Object} pushConfig The push configuration which is given when parse server is initialized
*/
ParsePushAdapter.prototype.initialize = function(pushConfig) {
// Initialize senders
for (let validPushType of this.validPushTypes) {
this.senders[validPushType] = [];

View File

@@ -3,27 +3,15 @@
// Allows you to change the push notification mechanism.
//
// Adapter classes must implement the following functions:
// * initialize(pushConfig)
// * getPushSenders(parseConfig)
// * getValidPushTypes(parseConfig)
// * getValidPushTypes()
// * send(devices, installations)
//
// Default is ParsePushAdapter, which uses GCM for
// android push and APNS for ios push.
export class PushAdapter {
send(devices, installations) { }
var ParsePushAdapter = require('./ParsePushAdapter');
var adapter = new ParsePushAdapter();
function setAdapter(pushAdapter) {
adapter = pushAdapter;
getValidPushTypes() { }
}
function getAdapter() {
return adapter;
}
module.exports = {
getAdapter: getAdapter,
setAdapter: setAdapter
};
export default PushAdapter;

View File

@@ -1,27 +1,44 @@
// push.js
import { Parse } from 'parse/node';
import PromiseRouter from '../PromiseRouter';
import rest from '../rest';
var Parse = require('parse/node').Parse,
PromiseRouter = require('./PromiseRouter'),
PushAdapter = require('./Adapters/Push/PushAdapter'),
rest = require('./rest');
export class PushController {
function handlePushWithoutQueue(req) {
validateMasterKey(req);
var where = getQueryCondition(req);
var pushAdapter = PushAdapter.getAdapter();
validatePushType(where, pushAdapter.getValidPushTypes());
// Replace the expiration_time with a valid Unix epoch milliseconds time
req.body['expiration_time'] = getExpirationTime(req);
// TODO: If the req can pass the checking, we return immediately instead of waiting
// pushes to be sent. We probably change this behaviour in the future.
rest.find(req.config, req.auth, '_Installation', where).then(function(response) {
return pushAdapter.send(req.body, response.results);
});
return Parse.Promise.as({
response: {
'result': true
}
});
constructor(pushAdapter) {
this._pushAdapter = pushAdapter;
}
handlePOST(req) {
if (!this._pushAdapter) {
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
'Push adapter is not availabe');
}
validateMasterKey(req);
var where = getQueryCondition(req);
var pushAdapter = this._pushAdapter;
validatePushType(where, pushAdapter.getValidPushTypes());
// Replace the expiration_time with a valid Unix epoch milliseconds time
req.body['expiration_time'] = getExpirationTime(req);
// TODO: If the req can pass the checking, we return immediately instead of waiting
// pushes to be sent. We probably change this behaviour in the future.
rest.find(req.config, req.auth, '_Installation', where).then(function(response) {
return pushAdapter.send(req.body, response.results);
});
return Parse.Promise.as({
response: {
'result': true
}
});
}
getExpressRouter() {
var router = new PromiseRouter();
router.route('POST','/push', (req) => {
return this.handlePOST(req);
});
return router;
}
}
/**
@@ -116,16 +133,11 @@ function validateMasterKey(req) {
}
}
var router = new PromiseRouter();
router.route('POST','/push', handlePushWithoutQueue);
module.exports = {
router: router,
}
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
module.exports.getQueryCondition = getQueryCondition;
module.exports.validateMasterKey = validateMasterKey;
module.exports.getExpirationTime = getExpirationTime;
module.exports.validatePushType = validatePushType;
PushController.getQueryCondition = getQueryCondition;
PushController.validateMasterKey = validateMasterKey;
PushController.getExpirationTime = getExpirationTime;
PushController.validatePushType = validatePushType;
}
export default PushController;

View File

@@ -5,7 +5,6 @@ var batch = require('./batch'),
cache = require('./cache'),
DatabaseAdapter = require('./DatabaseAdapter'),
express = require('express'),
PushAdapter = require('./Adapters/Push/PushAdapter'),
middlewares = require('./middlewares'),
multer = require('multer'),
Parse = require('parse/node').Parse,
@@ -14,9 +13,12 @@ var batch = require('./batch'),
import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter';
import { S3Adapter } from './Adapters/Files/S3Adapter';
import { FilesController } from './Controllers/FilesController';
import ParsePushAdapter from './Adapters/Push/ParsePushAdapter';
import { PushController } from './Controllers/PushController';
// Mutate the Parse object to add the Cloud Code handlers
addParseCloud();
@@ -42,6 +44,8 @@ addParseCloud();
// "dotNetKey": optional key from Parse dashboard
// "restAPIKey": optional key from Parse dashboard
// "javascriptKey": optional key from Parse dashboard
// "push": optional key from configure push
function ParseServer(args) {
if (!args.appId || !args.masterKey) {
throw 'You must provide an appId and masterKey!';
@@ -51,8 +55,18 @@ function ParseServer(args) {
DatabaseAdapter.setAdapter(args.databaseAdapter);
}
// Make files adapter
let filesAdapter = args.filesAdapter || new GridStoreAdapter();
// Make push adapter
let pushConfig = args.push;
let pushAdapter;
if (pushConfig && pushConfig.adapter) {
pushAdapter = pushConfig.adapter;
} else if (pushConfig) {
pushAdapter = new ParsePushAdapter(pushConfig)
}
if (args.databaseURI) {
DatabaseAdapter.setAppDatabaseURI(args.appId, args.databaseURI);
}
@@ -87,10 +101,6 @@ function ParseServer(args) {
cache.apps[args.appId]['facebookAppIds'].push(process.env.FACEBOOK_APP_ID);
}
// Register push senders
var pushConfig = args.push;
PushAdapter.getAdapter().initialize(pushConfig);
// Initialize the node client SDK automatically
Parse.initialize(args.appId, args.javascriptKey || '', args.masterKey);
if(args.serverURL) {
@@ -122,13 +132,14 @@ function ParseServer(args) {
router.merge(require('./sessions'));
router.merge(require('./roles'));
router.merge(require('./analytics'));
router.merge(require('./push').router);
router.merge(require('./installations'));
router.merge(require('./functions'));
router.merge(require('./schemas'));
if (process.env.PARSE_EXPERIMENTAL_CONFIG_ENABLED || process.env.TESTING) {
router.merge(require('./global_config'));
}
let pushController = new PushController(pushAdapter);
router.merge(pushController.getExpressRouter());
batch.mountOnto(router);