|
|
|
|
@@ -1,54 +1,17 @@
|
|
|
|
|
import { Parse } from 'parse/node';
|
|
|
|
|
import rest from '../rest';
|
|
|
|
|
import AdaptableController from './AdaptableController';
|
|
|
|
|
import { PushAdapter } from '../Adapters/Push/PushAdapter';
|
|
|
|
|
import deepcopy from 'deepcopy';
|
|
|
|
|
import RestQuery from '../RestQuery';
|
|
|
|
|
import RestWrite from '../RestWrite';
|
|
|
|
|
import { master } from '../Auth';
|
|
|
|
|
import { pushStatusHandler } from '../StatusHandler';
|
|
|
|
|
|
|
|
|
|
const UNSUPPORTED_BADGE_KEY = "unsupported";
|
|
|
|
|
|
|
|
|
|
export class PushController extends AdaptableController {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Check whether the deviceType parameter in qury condition is valid or not.
|
|
|
|
|
* @param {Object} where A query condition
|
|
|
|
|
* @param {Array} validPushTypes An array of valid push types(string)
|
|
|
|
|
*/
|
|
|
|
|
static validatePushType(where = {}, validPushTypes = []) {
|
|
|
|
|
var deviceTypeField = where.deviceType || {};
|
|
|
|
|
var deviceTypes = [];
|
|
|
|
|
if (typeof deviceTypeField === 'string') {
|
|
|
|
|
deviceTypes.push(deviceTypeField);
|
|
|
|
|
} else if (Array.isArray(deviceTypeField['$in'])) {
|
|
|
|
|
deviceTypes.concat(deviceTypeField['$in']);
|
|
|
|
|
}
|
|
|
|
|
for (var i = 0; i < deviceTypes.length; i++) {
|
|
|
|
|
var deviceType = deviceTypes[i];
|
|
|
|
|
if (validPushTypes.indexOf(deviceType) < 0) {
|
|
|
|
|
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
|
|
|
|
|
deviceType + ' is not supported push type.');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get pushIsAvailable() {
|
|
|
|
|
return !!this.adapter;
|
|
|
|
|
}
|
|
|
|
|
export class PushController {
|
|
|
|
|
|
|
|
|
|
sendPush(body = {}, where = {}, config, auth, onPushStatusSaved = () => {}) {
|
|
|
|
|
var pushAdapter = this.adapter;
|
|
|
|
|
if (!this.pushIsAvailable) {
|
|
|
|
|
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
|
|
|
|
|
'Push adapter is not available');
|
|
|
|
|
}
|
|
|
|
|
if (!this.options) {
|
|
|
|
|
if (!config.hasPushSupport) {
|
|
|
|
|
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
|
|
|
|
|
'Missing push configuration');
|
|
|
|
|
}
|
|
|
|
|
PushController.validatePushType(where, pushAdapter.getValidPushTypes());
|
|
|
|
|
// Replace the expiration_time with a valid Unix epoch milliseconds time
|
|
|
|
|
body['expiration_time'] = PushController.getExpirationTime(body);
|
|
|
|
|
// TODO: If the req can pass the checking, we return immediately instead of waiting
|
|
|
|
|
@@ -86,15 +49,7 @@ export class PushController extends AdaptableController {
|
|
|
|
|
onPushStatusSaved(pushStatus.objectId);
|
|
|
|
|
return badgeUpdate();
|
|
|
|
|
}).then(() => {
|
|
|
|
|
return rest.find(config, auth, '_Installation', where);
|
|
|
|
|
}).then((response) => {
|
|
|
|
|
if (!response.results) {
|
|
|
|
|
return Promise.reject({error: 'PushController: no results in query'})
|
|
|
|
|
}
|
|
|
|
|
pushStatus.setRunning(response.results);
|
|
|
|
|
return this.sendToAdapter(body, response.results, pushStatus, config);
|
|
|
|
|
}).then((results) => {
|
|
|
|
|
return pushStatus.complete(results);
|
|
|
|
|
return config.pushControllerQueue.enqueue(body, where, config, auth, pushStatus);
|
|
|
|
|
}).catch((err) => {
|
|
|
|
|
return pushStatus.fail(err).then(() => {
|
|
|
|
|
throw err;
|
|
|
|
|
@@ -102,34 +57,6 @@ export class PushController extends AdaptableController {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sendToAdapter(body, installations, pushStatus) {
|
|
|
|
|
if (body.data && body.data.badge && typeof body.data.badge == 'string' && body.data.badge.toLowerCase() == "increment") {
|
|
|
|
|
// Collect the badges to reduce the # of calls
|
|
|
|
|
const badgeInstallationsMap = installations.reduce((map, installation) => {
|
|
|
|
|
let badge = installation.badge;
|
|
|
|
|
if (installation.deviceType != "ios") {
|
|
|
|
|
badge = UNSUPPORTED_BADGE_KEY;
|
|
|
|
|
}
|
|
|
|
|
map[badge + ''] = map[badge + ''] || [];
|
|
|
|
|
map[badge + ''].push(installation);
|
|
|
|
|
return map;
|
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
|
|
// Map the on the badges count and return the send result
|
|
|
|
|
const promises = Object.keys(badgeInstallationsMap).map((badge) => {
|
|
|
|
|
const payload = deepcopy(body);
|
|
|
|
|
if (badge == UNSUPPORTED_BADGE_KEY) {
|
|
|
|
|
delete payload.data.badge;
|
|
|
|
|
} else {
|
|
|
|
|
payload.data.badge = parseInt(badge);
|
|
|
|
|
}
|
|
|
|
|
return this.adapter.send(payload, badgeInstallationsMap[badge], pushStatus.objectId);
|
|
|
|
|
});
|
|
|
|
|
return Promise.all(promises);
|
|
|
|
|
}
|
|
|
|
|
return this.adapter.send(body, installations, pushStatus.objectId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get expiration time from the request body.
|
|
|
|
|
* @param {Object} request A request object
|
|
|
|
|
@@ -157,10 +84,6 @@ export class PushController extends AdaptableController {
|
|
|
|
|
}
|
|
|
|
|
return expirationTime.valueOf();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expectedAdapterType() {
|
|
|
|
|
return PushAdapter;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default PushController;
|
|
|
|
|
|