123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.flatten = flatten;
- exports.jobStatusHandler = jobStatusHandler;
- exports.pushStatusHandler = pushStatusHandler;
- var _cryptoUtils = require("./cryptoUtils");
- var _KeyPromiseQueue = require("./KeyPromiseQueue");
- var _logger = require("./logger");
- var _rest = _interopRequireDefault(require("./rest"));
- var _Auth = _interopRequireDefault(require("./Auth"));
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
- function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
- function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
- const PUSH_STATUS_COLLECTION = '_PushStatus';
- const JOB_STATUS_COLLECTION = '_JobStatus';
- const pushPromiseQueue = new _KeyPromiseQueue.KeyPromiseQueue();
- const jobPromiseQueue = new _KeyPromiseQueue.KeyPromiseQueue();
- const incrementOp = function (object = {}, key, amount = 1) {
- if (!object[key]) {
- object[key] = {
- __op: 'Increment',
- amount: amount
- };
- } else {
- object[key].amount += amount;
- }
- return object[key];
- };
- function flatten(array) {
- var flattened = [];
- for (var i = 0; i < array.length; i++) {
- if (Array.isArray(array[i])) {
- flattened = flattened.concat(flatten(array[i]));
- } else {
- flattened.push(array[i]);
- }
- }
- return flattened;
- }
- function statusHandler(className, database) {
- function create(object) {
- return database.create(className, object).then(() => {
- return Promise.resolve(object);
- });
- }
- function update(where, object) {
- return jobPromiseQueue.enqueue(where.objectId, () => database.update(className, where, object));
- }
- return Object.freeze({
- create,
- update
- });
- }
- function restStatusHandler(className, config) {
- const auth = _Auth.default.master(config);
- function create(object) {
- return _rest.default.create(config, auth, className, object).then(({
- response
- }) => {
- return _objectSpread(_objectSpread({}, object), response);
- });
- }
- function update(where, object) {
- return pushPromiseQueue.enqueue(where.objectId, () => _rest.default.update(config, auth, className, {
- objectId: where.objectId
- }, object).then(({
- response
- }) => {
- return _objectSpread(_objectSpread({}, object), response);
- }));
- }
- return Object.freeze({
- create,
- update
- });
- }
- function jobStatusHandler(config) {
- let jobStatus;
- const objectId = (0, _cryptoUtils.newObjectId)(config.objectIdSize);
- const database = config.database;
- const handler = statusHandler(JOB_STATUS_COLLECTION, database);
- const setRunning = function (jobName, params) {
- const now = new Date();
- jobStatus = {
- objectId,
- jobName,
- params,
- status: 'running',
- source: 'api',
- createdAt: now,
-
- ACL: {}
- };
- return handler.create(jobStatus);
- };
- const setMessage = function (message) {
- if (!message || typeof message !== 'string') {
- return Promise.resolve();
- }
- return handler.update({
- objectId
- }, {
- message
- });
- };
- const setSucceeded = function (message) {
- return setFinalStatus('succeeded', message);
- };
- const setFailed = function (message) {
- return setFinalStatus('failed', message);
- };
- const setFinalStatus = function (status, message = undefined) {
- const finishedAt = new Date();
- const update = {
- status,
- finishedAt
- };
- if (message && typeof message === 'string') {
- update.message = message;
- }
- if (message instanceof Error && typeof message.message === 'string') {
- update.message = message.message;
- }
- return handler.update({
- objectId
- }, update);
- };
- return Object.freeze({
- setRunning,
- setSucceeded,
- setMessage,
- setFailed
- });
- }
- function pushStatusHandler(config, existingObjectId) {
- let pushStatus;
- const database = config.database;
- const handler = restStatusHandler(PUSH_STATUS_COLLECTION, config);
- let objectId = existingObjectId;
- const setInitial = function (body = {}, where, options = {
- source: 'rest'
- }) {
- const now = new Date();
- let pushTime = now.toISOString();
- let status = 'pending';
- if (Object.prototype.hasOwnProperty.call(body, 'push_time')) {
- if (config.hasPushScheduledSupport) {
- pushTime = body.push_time;
- status = 'scheduled';
- } else {
- _logger.logger.warn('Trying to schedule a push while server is not configured.');
- _logger.logger.warn('Push will be sent immediately');
- }
- }
- const data = body.data || {};
- const payloadString = JSON.stringify(data);
- let pushHash;
- if (typeof data.alert === 'string') {
- pushHash = (0, _cryptoUtils.md5Hash)(data.alert);
- } else if (typeof data.alert === 'object') {
- pushHash = (0, _cryptoUtils.md5Hash)(JSON.stringify(data.alert));
- } else {
- pushHash = 'd41d8cd98f00b204e9800998ecf8427e';
- }
- const object = {
- pushTime,
- query: JSON.stringify(where),
- payload: payloadString,
- source: options.source,
- title: options.title,
- expiry: body.expiration_time,
- expiration_interval: body.expiration_interval,
- status: status,
- numSent: 0,
- pushHash,
-
- ACL: {}
- };
- return handler.create(object).then(result => {
- objectId = result.objectId;
- pushStatus = {
- objectId
- };
- return Promise.resolve(pushStatus);
- });
- };
- const setRunning = function (batches) {
- _logger.logger.verbose(`_PushStatus ${objectId}: sending push to installations with %d batches`, batches);
- return handler.update({
- status: 'pending',
- objectId: objectId
- }, {
- status: 'running',
- count: batches
- });
- };
- const trackSent = function (results, UTCOffset, cleanupInstallations = process.env.PARSE_SERVER_CLEANUP_INVALID_INSTALLATIONS) {
- const update = {
- numSent: 0,
- numFailed: 0
- };
- const devicesToRemove = [];
- if (Array.isArray(results)) {
- results = flatten(results);
- results.reduce((memo, result) => {
-
- if (!result || !result.device || !result.device.deviceType) {
- return memo;
- }
- const deviceType = result.device.deviceType;
- const key = result.transmitted ? `sentPerType.${deviceType}` : `failedPerType.${deviceType}`;
- memo[key] = incrementOp(memo, key);
- if (typeof UTCOffset !== 'undefined') {
- const offsetKey = result.transmitted ? `sentPerUTCOffset.${UTCOffset}` : `failedPerUTCOffset.${UTCOffset}`;
- memo[offsetKey] = incrementOp(memo, offsetKey);
- }
- if (result.transmitted) {
- memo.numSent++;
- } else {
- if (result && result.response && result.response.error && result.device && result.device.deviceToken) {
- const token = result.device.deviceToken;
- const error = result.response.error;
-
-
- if (error === 'NotRegistered' || error === 'InvalidRegistration') {
- devicesToRemove.push(token);
- }
-
-
-
- if ((error === null || error === void 0 ? void 0 : error.code) === 'messaging/registration-token-not-registered' || (error === null || error === void 0 ? void 0 : error.code) === 'messaging/invalid-registration-token' || (error === null || error === void 0 ? void 0 : error.code) === 'messaging/invalid-argument' && (error === null || error === void 0 ? void 0 : error.message) === 'The registration token is not a valid FCM registration token') {
- devicesToRemove.push(token);
- }
-
-
- if (error === 'Unregistered' || error === 'BadDeviceToken') {
- devicesToRemove.push(token);
- }
- }
- memo.numFailed++;
- }
- return memo;
- }, update);
- }
- _logger.logger.verbose(`_PushStatus ${objectId}: sent push! %d success, %d failures`, update.numSent, update.numFailed);
- _logger.logger.verbose(`_PushStatus ${objectId}: needs cleanup`, {
- devicesToRemove
- });
- ['numSent', 'numFailed'].forEach(key => {
- if (update[key] > 0) {
- update[key] = {
- __op: 'Increment',
- amount: update[key]
- };
- } else {
- delete update[key];
- }
- });
- if (devicesToRemove.length > 0 && cleanupInstallations) {
- _logger.logger.info(`Removing device tokens on ${devicesToRemove.length} _Installations`);
- database.update('_Installation', {
- deviceToken: {
- $in: devicesToRemove
- }
- }, {
- deviceToken: {
- __op: 'Delete'
- }
- }, {
- acl: undefined,
- many: true
- });
- }
- incrementOp(update, 'count', -1);
- update.status = 'running';
- return handler.update({
- objectId
- }, update).then(res => {
- if (res && res.count === 0) {
- return this.complete();
- }
- });
- };
- const complete = function () {
- return handler.update({
- objectId
- }, {
- status: 'succeeded',
- count: {
- __op: 'Delete'
- }
- });
- };
- const fail = function (err) {
- if (typeof err === 'string') {
- err = {
- message: err
- };
- }
- const update = {
- errorMessage: err,
- status: 'failed'
- };
- return handler.update({
- objectId
- }, update);
- };
- const rval = {
- setInitial,
- setRunning,
- trackSent,
- complete,
- fail
- };
-
- Object.defineProperty(rval, 'objectId', {
- get: () => objectId
- });
- return Object.freeze(rval);
- }
|