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', () => { describe('ParsePushAdapter', () => {
it('can be initialized', (done) => { 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 // Make mock config
var pushConfig = { var pushConfig = {
android: { android: {
@@ -30,7 +22,7 @@ describe('ParsePushAdapter', () => {
] ]
}; };
parsePushAdapter.initialize(pushConfig); var parsePushAdapter = new ParsePushAdapter(pushConfig);
// Check ios // Check ios
var iosSenders = parsePushAdapter.senders['ios']; var iosSenders = parsePushAdapter.senders['ios'];
expect(iosSenders.length).toBe(2); expect(iosSenders.length).toBe(2);
@@ -53,7 +45,6 @@ describe('ParsePushAdapter', () => {
}); });
it('can throw on initializing with unsupported push type', (done) => { it('can throw on initializing with unsupported push type', (done) => {
var parsePushAdapter = new ParsePushAdapter();
// Make mock config // Make mock config
var pushConfig = { var pushConfig = {
win: { win: {
@@ -63,20 +54,19 @@ describe('ParsePushAdapter', () => {
}; };
expect(function() { expect(function() {
parsePushAdapter.initialize(pushConfig) new ParsePushAdapter(pushConfig);
}).toThrow(); }).toThrow();
done(); done();
}); });
it('can throw on initializing with invalid pushConfig', (done) => { it('can throw on initializing with invalid pushConfig', (done) => {
var parsePushAdapter = new ParsePushAdapter();
// Make mock config // Make mock config
var pushConfig = { var pushConfig = {
android: 123 android: 123
}; };
expect(function() { expect(function() {
parsePushAdapter.initialize(pushConfig) new ParsePushAdapter(pushConfig);
}).toThrow(); }).toThrow();
done(); 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) => { it('can check valid master key of request', (done) => {
// Make mock request // Make mock request
var request = { var request = {
@@ -13,7 +13,7 @@ describe('push', () => {
} }
expect(() => { expect(() => {
push.validateMasterKey(request); PushController.validateMasterKey(request);
}).not.toThrow(); }).not.toThrow();
done(); done();
}); });
@@ -30,7 +30,7 @@ describe('push', () => {
} }
expect(() => { expect(() => {
push.validateMasterKey(request); PushController.validateMasterKey(request);
}).toThrow(); }).toThrow();
done(); done();
}); });
@@ -43,7 +43,7 @@ describe('push', () => {
} }
} }
var where = push.getQueryCondition(request); var where = PushController.getQueryCondition(request);
expect(where).toEqual({ expect(where).toEqual({
'channels': { 'channels': {
'$in': ['Giants', 'Mets'] '$in': ['Giants', 'Mets']
@@ -62,7 +62,7 @@ describe('push', () => {
} }
} }
var where = push.getQueryCondition(request); var where = PushController.getQueryCondition(request);
expect(where).toEqual({ expect(where).toEqual({
'injuryReports': true 'injuryReports': true
}); });
@@ -77,7 +77,7 @@ describe('push', () => {
} }
expect(function() { expect(function() {
push.getQueryCondition(request); PushController.getQueryCondition(request);
}).toThrow(); }).toThrow();
done(); done();
}); });
@@ -96,7 +96,7 @@ describe('push', () => {
} }
expect(function() { expect(function() {
push.getQueryCondition(request); PushController.getQueryCondition(request);
}).toThrow(); }).toThrow();
done(); done();
}); });
@@ -108,7 +108,7 @@ describe('push', () => {
var validPushTypes = ['ios', 'android']; var validPushTypes = ['ios', 'android'];
expect(function(){ expect(function(){
push.validatePushType(where, validPushTypes); PushController.validatePushType(where, validPushTypes);
}).not.toThrow(); }).not.toThrow();
done(); done();
}); });
@@ -121,7 +121,7 @@ describe('push', () => {
var validPushTypes = ['ios', 'android']; var validPushTypes = ['ios', 'android'];
expect(function(){ expect(function(){
push.validatePushType(where, validPushTypes); PushController.validatePushType(where, validPushTypes);
}).not.toThrow(); }).not.toThrow();
done(); done();
}); });
@@ -136,7 +136,7 @@ describe('push', () => {
var validPushTypes = ['ios', 'android']; var validPushTypes = ['ios', 'android'];
expect(function(){ expect(function(){
push.validatePushType(where, validPushTypes); PushController.validatePushType(where, validPushTypes);
}).not.toThrow(); }).not.toThrow();
done(); done();
}); });
@@ -149,7 +149,7 @@ describe('push', () => {
var validPushTypes = ['ios', 'android']; var validPushTypes = ['ios', 'android'];
expect(function(){ expect(function(){
push.validatePushType(where, validPushTypes); PushController.validatePushType(where, validPushTypes);
}).toThrow(); }).toThrow();
done(); done();
}); });
@@ -162,7 +162,7 @@ describe('push', () => {
var validPushTypes = ['ios', 'android']; var validPushTypes = ['ios', 'android'];
expect(function(){ expect(function(){
push.validatePushType(where, validPushTypes); PushController.validatePushType(where, validPushTypes);
}).toThrow(); }).toThrow();
done(); done();
}); });
@@ -176,7 +176,7 @@ describe('push', () => {
} }
} }
var time = push.getExpirationTime(request); var time = PushController.getExpirationTime(request);
expect(time).toEqual(new Date(timeStr).valueOf()); expect(time).toEqual(new Date(timeStr).valueOf());
done(); done();
}); });
@@ -190,7 +190,7 @@ describe('push', () => {
} }
} }
var time = push.getExpirationTime(request); var time = PushController.getExpirationTime(request);
expect(time).toEqual(timeNumber * 1000); expect(time).toEqual(timeNumber * 1000);
done(); done();
}); });
@@ -204,7 +204,7 @@ describe('push', () => {
} }
expect(function(){ expect(function(){
push.getExpirationTime(request); PushController.getExpirationTime(request);
}).toThrow(); }).toThrow();
done(); done();
}); });

View File

@@ -7,16 +7,10 @@ const Parse = require('parse/node').Parse;
const GCM = require('../../GCM'); const GCM = require('../../GCM');
const APNS = require('../../APNS'); const APNS = require('../../APNS');
function ParsePushAdapter() { function ParsePushAdapter(pushConfig) {
this.validPushTypes = ['ios', 'android']; this.validPushTypes = ['ios', 'android'];
this.senders = {}; 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 // Initialize senders
for (let validPushType of this.validPushTypes) { for (let validPushType of this.validPushTypes) {
this.senders[validPushType] = []; this.senders[validPushType] = [];

View File

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

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, export class PushController {
PromiseRouter = require('./PromiseRouter'),
PushAdapter = require('./Adapters/Push/PushAdapter'),
rest = require('./rest');
function handlePushWithoutQueue(req) { constructor(pushAdapter) {
validateMasterKey(req); this._pushAdapter = pushAdapter;
var where = getQueryCondition(req); }
var pushAdapter = PushAdapter.getAdapter();
validatePushType(where, pushAdapter.getValidPushTypes()); handlePOST(req) {
// Replace the expiration_time with a valid Unix epoch milliseconds time if (!this._pushAdapter) {
req.body['expiration_time'] = getExpirationTime(req); throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
// TODO: If the req can pass the checking, we return immediately instead of waiting 'Push adapter is not availabe');
// 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); validateMasterKey(req);
}); var where = getQueryCondition(req);
return Parse.Promise.as({ var pushAdapter = this._pushAdapter;
response: { validatePushType(where, pushAdapter.getValidPushTypes());
'result': true // 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') { if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
module.exports.getQueryCondition = getQueryCondition; PushController.getQueryCondition = getQueryCondition;
module.exports.validateMasterKey = validateMasterKey; PushController.validateMasterKey = validateMasterKey;
module.exports.getExpirationTime = getExpirationTime; PushController.getExpirationTime = getExpirationTime;
module.exports.validatePushType = validatePushType; PushController.validatePushType = validatePushType;
} }
export default PushController;

View File

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