Stores the _PushStatus when sending push, set pending, and running states

This commit is contained in:
Florent Vilmart
2016-03-12 14:32:39 -05:00
parent 308fe1498a
commit 4d401d9daa
5 changed files with 104 additions and 28 deletions

View File

@@ -105,9 +105,9 @@ describe('PushController', () => {
}).toThrow();
done();
});
it('properly increment badges', (done) => {
var payload = {data:{
alert: "Hello World!",
badge: "Increment",
@@ -122,7 +122,7 @@ describe('PushController', () => {
installation.set("deviceType", "ios");
installations.push(installation);
}
while(installations.length != 15) {
var installation = new Parse.Object("_Installation");
installation.set("installationId", "installation_"+installations.length);
@@ -130,7 +130,7 @@ describe('PushController', () => {
installation.set("deviceType", "android");
installations.push(installation);
}
var pushAdapter = {
send: function(body, installations) {
var badge = body.data.badge;
@@ -151,14 +151,14 @@ describe('PushController', () => {
return ["ios", "android"];
}
}
var config = new Config(Parse.applicationId);
var auth = {
isMaster: true
}
var pushController = new PushController(pushAdapter, Parse.applicationId);
Parse.Object.saveAll(installations).then((installations) => {
Parse.Object.saveAll(installations).then((installations) => {
return pushController.sendPush(payload, {}, config, auth);
}).then((result) => {
done();
@@ -167,11 +167,11 @@ describe('PushController', () => {
fail("should not fail");
done();
});
});
it('properly set badges to 1', (done) => {
var payload = {data: {
alert: "Hello World!",
badge: 1,
@@ -186,7 +186,7 @@ describe('PushController', () => {
installation.set("deviceType", "ios");
installations.push(installation);
}
var pushAdapter = {
send: function(body, installations) {
var badge = body.data.badge;
@@ -203,14 +203,14 @@ describe('PushController', () => {
return ["ios"];
}
}
var config = new Config(Parse.applicationId);
var auth = {
isMaster: true
}
var pushController = new PushController(pushAdapter, Parse.applicationId);
Parse.Object.saveAll(installations).then((installations) => {
Parse.Object.saveAll(installations).then((installations) => {
return pushController.sendPush(payload, {}, config, auth);
}).then((result) => {
done();
@@ -219,15 +219,56 @@ describe('PushController', () => {
fail("should not fail");
done();
});
});
it('properly creates _PushStatus', (done) => {
var payload = {data: {
alert: "Hello World!",
badge: 1,
}}
var pushAdapter = {
send: function(body, installations) {
var badge = body.data.badge;
return Promise.resolve({
body: body,
installations: installations
})
},
getValidPushTypes: function() {
return ["ios"];
}
}
var config = new Config(Parse.applicationId);
var auth = {
isMaster: true
}
var pushController = new PushController(pushAdapter, Parse.applicationId);
pushController.sendPush(payload, {}, config, auth).then((result) => {
let query = new Parse.Query('_PushStatus');
return query.find({useMasterKey: true});
}).then((results) => {
expect(results.length).toBe(1);
let result = results[0];
expect(result.get('source')).toEqual('rest');
expect(result.get('query')).toEqual(JSON.stringify({}));
expect(result.get('payload')).toEqual(payload.data);
expect(result.get('status')).toEqual("running");
done();
});
});
it('should support full RESTQuery for increment', (done) => {
var payload = {data: {
alert: "Hello World!",
badge: 'Increment',
}}
var pushAdapter = {
send: function(body, installations) {
return Promise.resolve();
@@ -236,12 +277,12 @@ describe('PushController', () => {
return ["ios"];
}
}
var config = new Config(Parse.applicationId);
var auth = {
isMaster: true
}
let where = {
'deviceToken': {
'$inQuery': {

View File

@@ -4,13 +4,13 @@
//
// Adapter classes must implement the following functions:
// * getValidPushTypes()
// * send(devices, installations)
// * send(devices, installations, pushStatus)
//
// Default is ParsePushAdapter, which uses GCM for
// android push and APNS for ios push.
export class PushAdapter {
send(devices, installations) { }
send(devices, installations, pushStatus) { }
/**
* Get an array of valid push types.

View File

@@ -4,8 +4,10 @@ import rest from '../rest';
import AdaptableController from './AdaptableController';
import { PushAdapter } from '../Adapters/Push/PushAdapter';
import deepcopy from 'deepcopy';
import { md5Hash } from '../cryptoUtils';
import features from '../features';
import RestQuery from '../RestQuery';
import RestWrite from '../RestWrite';
const FEATURE_NAME = 'push';
const UNSUPPORTED_BADGE_KEY = "unsupported";
@@ -65,7 +67,7 @@ export class PushController extends AdaptableController {
}
let updateWhere = deepcopy(where);
badgeUpdate = () => {
badgeUpdate = () => {
let badgeQuery = new RestQuery(config, auth, '_Installation', updateWhere);
return badgeQuery.buildRestWhere().then(() => {
let restWhere = deepcopy(badgeQuery.restWhere);
@@ -81,8 +83,13 @@ export class PushController extends AdaptableController {
})
}
}
return badgeUpdate().then(() => {
let pushStatus;
return Promise.resolve().then(() => {
return this.saveInitialPushStatus(body, where, config);
}).then((res) => {
pushStatus = res.response;
return badgeUpdate();
}).then(() => {
return rest.find(config, auth, '_Installation', where);
}).then((response) => {
if (body.data && body.data.badge && body.data.badge == "Increment") {
@@ -105,14 +112,38 @@ export class PushController extends AdaptableController {
} else {
payload.data.badge = parseInt(badge);
}
return pushAdapter.send(payload, badgeInstallationsMap[badge]);
return pushAdapter.send(payload, badgeInstallationsMap[badge], pushStatus);
});
return Promise.all(promises);
}
return pushAdapter.send(body, response.results);
return pushAdapter.send(body, response.results, pushStatus);
}).then(() => {
return this.updatePushStatus({status: "running"}, pushStatus, config);
});
}
saveInitialPushStatus(body, where, config, options = {source: 'rest'}) {
let pushStatus = {
pushTime: (new Date()).toISOString(),
query: JSON.stringify(where),
payload: body.data,
source: options.source,
title: options.title,
expiry: body.expiration_time,
status: "pending",
numSent: 0,
pushHash: md5Hash(JSON.stringify(body.data)),
ACL: new Parse.ACL() // lockdown!
}
let restWrite = new RestWrite(config, {isMaster: true},'_PushStatus',null, pushStatus);
return restWrite.execute();
}
updatePushStatus(update, pushStatus, config) {
let restWrite = new RestWrite(config, {isMaster: true}, '_PushStatus', {objectId: pushStatus.objectId, "status": "pending"}, update);
return restWrite.execute();
}
/**
* Get expiration time from the request body.
* @param {Object} request A request object

View File

@@ -71,7 +71,7 @@ var defaultColumns = {
},
_PushStatus: {
"pushTime": {type:'String'},
"source": {type:'String'}, // rest or web
"source": {type:'String'}, // rest or webui
"query": {type:'String'}, // the stringified JSON query
"payload": {type:'Object'}, // the JSON payload,
"title": {type:'String'},

View File

@@ -1,6 +1,6 @@
/* @flow */
import { randomBytes } from 'crypto';
import { randomBytes, createHash } from 'crypto';
// Returns a new random hex string of the given even size.
export function randomHexString(size: number): string {
@@ -44,3 +44,7 @@ export function newObjectId(): string {
export function newToken(): string {
return randomHexString(32);
}
export function md5Hash(string: string): string {
return createHash('md5').update(string).digest('hex');
}