Merge pull request #627 from isocolsky/feat/new-pushnotifications
Refactor push notifications
This commit is contained in:
commit
ae532625d4
|
@ -55,7 +55,8 @@ var config = {
|
|||
defaultLanguage: 'en',
|
||||
defaultUnit: 'btc',
|
||||
subjectPrefix: '',
|
||||
pushServerUrl: 'http://localhost:8000',
|
||||
pushServerUrl: 'https://fcm.googleapis.com/fcm',
|
||||
authorizationKey: '',
|
||||
},
|
||||
fiatRateServiceOpts: {
|
||||
defaultProvider: 'BitPay',
|
||||
|
|
|
@ -672,9 +672,25 @@ ExpressApp.prototype.start = function(opts, cb) {
|
|||
});
|
||||
});
|
||||
|
||||
// DEPRECATED
|
||||
router.delete('/v1/pushnotifications/subscriptions/', function(req, res) {
|
||||
logDeprecated(req);
|
||||
getServerWithAuth(req, res, function(server) {
|
||||
server.pushNotificationsUnsubscribe(function(err, response) {
|
||||
server.pushNotificationsUnsubscribe({
|
||||
token: 'dummy'
|
||||
}, function(err, response) {
|
||||
if (err) return returnError(err, res, req);
|
||||
res.json(response);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
router.delete('/v2/pushnotifications/subscriptions/:token', function(req, res) {
|
||||
var opts = {
|
||||
token: req.params['token'],
|
||||
};
|
||||
getServerWithAuth(req, res, function(server) {
|
||||
server.pushNotificationsUnsubscribe(opts, function(err, response) {
|
||||
if (err) return returnError(err, res, req);
|
||||
res.json(response);
|
||||
});
|
||||
|
|
|
@ -9,5 +9,6 @@ Model.Preferences = require('./preferences');
|
|||
Model.Email = require('./email');
|
||||
Model.TxNote = require('./txnote');
|
||||
Model.Session = require('./session');
|
||||
Model.PushNotificationSub = require('./pushnotificationsub');
|
||||
|
||||
module.exports = Model;
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
'use strict';
|
||||
|
||||
function PushNotificationSub() {};
|
||||
|
||||
PushNotificationSub.create = function(opts) {
|
||||
opts = opts || {};
|
||||
|
||||
var x = new PushNotificationSub();
|
||||
|
||||
x.version = '1.0.0';
|
||||
x.createdOn = Math.floor(Date.now() / 1000);
|
||||
x.copayerId = opts.copayerId;
|
||||
x.token = opts.token;
|
||||
x.packageName = opts.packageName;
|
||||
x.platform = opts.platform;
|
||||
return x;
|
||||
};
|
||||
|
||||
PushNotificationSub.fromObj = function(obj) {
|
||||
var x = new PushNotificationSub();
|
||||
|
||||
x.version = obj.version;
|
||||
x.createdOn = obj.createdOn;
|
||||
x.copayerId = obj.copayerId;
|
||||
x.token = obj.token;
|
||||
x.packageName = obj.packageName;
|
||||
x.platform = obj.platform;
|
||||
return x;
|
||||
};
|
||||
|
||||
|
||||
module.exports = PushNotificationSub;
|
|
@ -60,6 +60,10 @@ PushNotificationsService.prototype.start = function(opts, cb) {
|
|||
self.defaultUnit = opts.pushNotificationsOpts.defaultUnit || 'btc';
|
||||
self.subjectPrefix = opts.pushNotificationsOpts.subjectPrefix || '';
|
||||
self.pushServerUrl = opts.pushNotificationsOpts.pushServerUrl;
|
||||
self.authorizationKey = opts.pushNotificationsOpts.authorizationKey;
|
||||
|
||||
if (!self.authorizationKey) return cb(new Error('Missing authorizationKey attribute in configuration.'))
|
||||
|
||||
async.parallel([
|
||||
|
||||
function(done) {
|
||||
|
@ -117,34 +121,40 @@ PushNotificationsService.prototype._sendPushNotifications = function(notificatio
|
|||
},
|
||||
function(contents, next) {
|
||||
async.map(recipientsList, function(recipient, next) {
|
||||
var opts = {};
|
||||
var content = contents[recipient.language];
|
||||
opts.users = [notification.walletId + '$' + recipient.copayerId];
|
||||
opts.android = {
|
||||
"data": {
|
||||
"title": content.plain.subject,
|
||||
"message": content.plain.body,
|
||||
"walletId": sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(notification.walletId)),
|
||||
"notId": Math.floor(Math.random() * 100000) + 1
|
||||
}
|
||||
};
|
||||
opts.ios = {
|
||||
"alert": {
|
||||
"title": content.plain.subject,
|
||||
"body": content.plain.body
|
||||
},
|
||||
"sound": "default",
|
||||
"payload": {
|
||||
"walletId": sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(notification.walletId))
|
||||
}
|
||||
};
|
||||
return next(err, opts);
|
||||
}, next);
|
||||
|
||||
self.storage.fetchPushNotificationSubs(recipient.copayerId, function(err, subs) {
|
||||
if (err) return next(err);
|
||||
|
||||
var notifications = _.map(subs, function(sub) {
|
||||
return {
|
||||
to: sub.token,
|
||||
priority: 'high',
|
||||
restricted_package_name: sub.packageName,
|
||||
notification: {
|
||||
title: content.plain.subject,
|
||||
body: content.plain.body,
|
||||
sound: "default",
|
||||
click_action: "FCM_PLUGIN_ACTIVITY",
|
||||
icon: "fcm_push_icon",
|
||||
},
|
||||
data: {
|
||||
walletId: sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(notification.walletId)),
|
||||
copayerId: sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(recipient.copayerId))
|
||||
},
|
||||
};
|
||||
});
|
||||
return next(err, notifications);
|
||||
});
|
||||
}, function(err, allNotifications) {
|
||||
if (err) return next(err);
|
||||
return next(null, _.flatten(allNotifications));
|
||||
});
|
||||
},
|
||||
function(optsList, next) {
|
||||
async.each(optsList,
|
||||
function(opts, next) {
|
||||
self._makeRequest(opts, function(err, response) {
|
||||
function(notifications, next) {
|
||||
async.each(notifications,
|
||||
function(notification, next) {
|
||||
self._makeRequest(notification, function(err, response) {
|
||||
if (err) log.error(err);
|
||||
if (response) {
|
||||
log.debug('Request status: ', response.statusCode);
|
||||
|
@ -360,10 +370,12 @@ PushNotificationsService.prototype._makeRequest = function(opts, cb) {
|
|||
url: self.pushServerUrl + '/send',
|
||||
method: 'POST',
|
||||
json: true,
|
||||
body: opts
|
||||
}, function(err, response) {
|
||||
return cb(err, response);
|
||||
});
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'key=' + self.authorizationKey,
|
||||
},
|
||||
body: opts,
|
||||
}, cb);
|
||||
};
|
||||
|
||||
module.exports = PushNotificationsService;
|
||||
|
|
|
@ -3055,36 +3055,39 @@ WalletService.prototype.getFiatRate = function(opts, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Subscribe this copayer to the Push Notifications service using the specified token.
|
||||
* @param {Object} opts
|
||||
* @param {string} opts.token - The token representing the app/device.
|
||||
* @param {string} [opts.packageName] - The restricted_package_name option associated with this token.
|
||||
* @param {string} [opts.platform] - The platform associated with this token.
|
||||
*/
|
||||
WalletService.prototype.pushNotificationsSubscribe = function(opts, cb) {
|
||||
if (!checkRequired(opts, ['token'], cb)) return;
|
||||
|
||||
var self = this;
|
||||
|
||||
opts.user = self.walletId + '$' + self.copayerId;
|
||||
|
||||
request({
|
||||
url: config.pushNotificationsOpts.pushServerUrl + '/subscribe',
|
||||
method: 'POST',
|
||||
json: true,
|
||||
body: opts
|
||||
}, function(err, response) {
|
||||
return cb(err, response);
|
||||
var sub = Model.PushNotificationSub.create({
|
||||
copayerId: self.copayerId,
|
||||
token: opts.token,
|
||||
packageName: opts.packageName,
|
||||
platform: opts.platform,
|
||||
});
|
||||
|
||||
self.storage.storePushNotificationSub(sub, cb);
|
||||
};
|
||||
|
||||
WalletService.prototype.pushNotificationsUnsubscribe = function(cb) {
|
||||
/**
|
||||
* Unsubscribe this copayer to the Push Notifications service using the specified token.
|
||||
* @param {Object} opts
|
||||
* @param {string} opts.token - The token representing the app/device.
|
||||
*/
|
||||
WalletService.prototype.pushNotificationsUnsubscribe = function(opts, cb) {
|
||||
if (!checkRequired(opts, ['token'], cb)) return;
|
||||
|
||||
var self = this;
|
||||
|
||||
request({
|
||||
url: config.pushNotificationsOpts.pushServerUrl + '/unsubscribe',
|
||||
method: 'POST',
|
||||
json: true,
|
||||
body: {
|
||||
user: self.walletId + '$' + self.copayerId
|
||||
}
|
||||
}, function(err, response) {
|
||||
return cb(err, response);
|
||||
});
|
||||
self.storage.removePushNotificationSub(self.copayerId, opts.token, cb);
|
||||
};
|
||||
|
||||
module.exports = WalletService;
|
||||
|
|
|
@ -24,6 +24,7 @@ var collections = {
|
|||
FIAT_RATES: 'fiat_rates',
|
||||
TX_NOTES: 'tx_notes',
|
||||
SESSIONS: 'sessions',
|
||||
PUSH_NOTIFICATION_SUBS: 'push_notification_subs',
|
||||
};
|
||||
|
||||
var Storage = function(opts) {
|
||||
|
@ -74,6 +75,9 @@ Storage.prototype._createIndexes = function() {
|
|||
walletId: 1,
|
||||
txid: 1,
|
||||
});
|
||||
this.db.collection(collections.PUSH_NOTIFICATION_SUBS).createIndex({
|
||||
copayerId: 1,
|
||||
});
|
||||
};
|
||||
|
||||
Storage.prototype.connect = function(opts, cb) {
|
||||
|
@ -890,6 +894,40 @@ Storage.prototype.storeSession = function(session, cb) {
|
|||
}, cb);
|
||||
};
|
||||
|
||||
Storage.prototype.fetchPushNotificationSubs = function(copayerId, cb) {
|
||||
this.db.collection(collections.PUSH_NOTIFICATION_SUBS).find({
|
||||
copayerId: copayerId,
|
||||
}).toArray(function(err, result) {
|
||||
if (err) return cb(err);
|
||||
|
||||
if (!result) return cb();
|
||||
|
||||
var tokens = _.map([].concat(result), function(r) {
|
||||
return Model.PushNotificationSub.fromObj(r);
|
||||
});
|
||||
return cb(null, tokens);
|
||||
});
|
||||
};
|
||||
|
||||
Storage.prototype.storePushNotificationSub = function(pushNotificationSub, cb) {
|
||||
this.db.collection(collections.PUSH_NOTIFICATION_SUBS).update({
|
||||
copayerId: pushNotificationSub.copayerId,
|
||||
token: pushNotificationSub.token,
|
||||
}, pushNotificationSub, {
|
||||
w: 1,
|
||||
upsert: true,
|
||||
}, cb);
|
||||
};
|
||||
|
||||
Storage.prototype.removePushNotificationSub = function(copayerId, token, cb) {
|
||||
this.db.collection(collections.PUSH_NOTIFICATION_SUBS).remove({
|
||||
copayerId: copayerId,
|
||||
token: token,
|
||||
}, {
|
||||
w: 1
|
||||
}, cb);
|
||||
};
|
||||
|
||||
Storage.prototype._dump = function(cb, fn) {
|
||||
fn = fn || console.log;
|
||||
cb = cb || function() {};
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}New copayer
|
||||
A new copayer just joined your wallet {{walletName}}.
|
||||
A new copayer just joined your wallet.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}New payment received
|
||||
A payment of {{amount}} has been received into your wallet {{walletName}}.
|
||||
A payment of {{amount}} has been received into your wallet.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Payment sent
|
||||
A Payment of {{amount}} has been sent from your wallet {{walletName}}.
|
||||
A Payment of {{amount}} has been sent from your wallet.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}New payment proposal
|
||||
A new payment proposal has been created in your wallet {{walletName}} by {{copayerName}}.
|
||||
A new payment proposal has been created in your wallet.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Payment proposal rejected
|
||||
A payment proposal in your wallet {{walletName}} has been rejected by {{rejectorsNames}}.
|
||||
A payment proposal in your wallet has been rejected.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Wallet complete
|
||||
Your wallet {{walletName}} is complete.
|
||||
Your wallet is complete.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Nuevo copayer
|
||||
Un nuevo copayer ha ingresado a su monedero {{walletName}}.
|
||||
Un nuevo copayer ha ingresado a su billetera.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Pago enviado
|
||||
Un pago de {{amount}} ha sido enviado de su monedero {{walletName}}.
|
||||
Un pago de {{amount}} ha sido enviado de su billetera.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Nueva propuesta de pago
|
||||
Una nueva propuesta de pago ha sido creada en su monedero {{walletName}} por {{copayerName}}.
|
||||
Una nueva propuesta de pago ha sido creada en su billetera.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Propuesta de pago rechazada
|
||||
Una propuesta de pago en su monedero {{walletName}} ha sido rechazada por {{rejectorsNames}}.
|
||||
Una propuesta de pago en su billetera ha sido rechazada.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Monedero completo
|
||||
Su monedero {{walletName}} está completo.
|
||||
{{subjectPrefix}}Billetera completa
|
||||
Su billetera está completa.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Nouveau copayer
|
||||
Un nouveau copayer vient de rejoindre votre portefeuille {{walletName}}.
|
||||
Un nouveau copayer vient de rejoindre votre portefeuille.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Nouveau paiement reçu
|
||||
Un paiement de {{amount}} a été reçu dans votre portefeuille {{walletName}}.
|
||||
Un paiement de {{amount}} a été reçu dans votre portefeuille.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Paiement envoyé
|
||||
Un paiement de {{amount}} a été envoyé de votre portefeuille {{walletName}}.
|
||||
Un paiement de {{amount}} a été envoyé de votre portefeuille.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Nouvelle proposition de paiement
|
||||
Une nouvelle proposition de paiement a été créée dans votre portefeuille {{walletName}} par {{copayerName}}.
|
||||
Une nouvelle proposition de paiement a été créée dans votre portefeuille.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Proposition de paiement rejetée
|
||||
Une proposition de paiement dans votre portefeuille {{walletName}} a été rejetée par {{rejectorsNames}}.
|
||||
Une proposition de paiement dans votre portefeuille a été rejetée.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
{{subjectPrefix}}Portefeuille terminé
|
||||
Votre portefeuille {{walletName}} est terminé.
|
||||
Votre portefeuille est terminé.
|
||||
|
|
|
@ -98,11 +98,8 @@ describe('Email notifications', function() {
|
|||
var one = emails[0];
|
||||
one.from.should.equal('bws@dummy.net');
|
||||
one.subject.should.contain('New payment proposal');
|
||||
one.text.should.contain(wallet.name);
|
||||
one.text.should.contain(wallet.copayers[0].name);
|
||||
should.exist(one.html);
|
||||
one.html.indexOf('<html>').should.equal(0);
|
||||
one.html.should.contain(wallet.name);
|
||||
server.storage.fetchUnsentEmails(function(err, unsent) {
|
||||
should.not.exist(err);
|
||||
unsent.should.be.empty;
|
||||
|
@ -202,7 +199,6 @@ describe('Email notifications', function() {
|
|||
var one = emails[0];
|
||||
one.from.should.equal('bws@dummy.net');
|
||||
one.subject.should.contain('Payment sent');
|
||||
one.text.should.contain(wallet.name);
|
||||
one.text.should.contain('800,000');
|
||||
should.exist(one.html);
|
||||
one.html.should.contain('https://insight.bitpay.com/tx/' + txp.txid);
|
||||
|
@ -258,9 +254,6 @@ describe('Email notifications', function() {
|
|||
var one = emails[0];
|
||||
one.from.should.equal('bws@dummy.net');
|
||||
one.subject.should.contain('Payment proposal rejected');
|
||||
one.text.should.contain(wallet.name);
|
||||
one.text.should.contain('copayer 2, copayer 3');
|
||||
one.text.should.not.contain('copayer 1');
|
||||
server.storage.fetchUnsentEmails(function(err, unsent) {
|
||||
should.not.exist(err);
|
||||
unsent.should.be.empty;
|
||||
|
@ -291,7 +284,6 @@ describe('Email notifications', function() {
|
|||
var one = emails[0];
|
||||
one.from.should.equal('bws@dummy.net');
|
||||
one.subject.should.contain('New payment received');
|
||||
one.text.should.contain(wallet.name);
|
||||
one.text.should.contain('123,000');
|
||||
server.storage.fetchUnsentEmails(function(err, unsent) {
|
||||
should.not.exist(err);
|
||||
|
@ -327,7 +319,6 @@ describe('Email notifications', function() {
|
|||
var one = emails[0];
|
||||
one.from.should.equal('bws@dummy.net');
|
||||
one.subject.should.contain('New payment received');
|
||||
one.text.should.contain(wallet.name);
|
||||
one.text.should.contain('123,000');
|
||||
server.storage.fetchUnsentEmails(function(err, unsent) {
|
||||
should.not.exist(err);
|
||||
|
@ -367,14 +358,12 @@ describe('Email notifications', function() {
|
|||
});
|
||||
spanish.from.should.equal('bws@dummy.net');
|
||||
spanish.subject.should.contain('Nuevo pago recibido');
|
||||
spanish.text.should.contain(wallet.name);
|
||||
spanish.text.should.contain('0.123 BTC');
|
||||
var english = _.find(emails, {
|
||||
to: 'copayer2@domain.com'
|
||||
});
|
||||
english.from.should.equal('bws@dummy.net');
|
||||
english.subject.should.contain('New payment received');
|
||||
english.text.should.contain(wallet.name);
|
||||
english.text.should.contain('123,000 bits');
|
||||
done();
|
||||
}, 100);
|
||||
|
|
|
@ -10,6 +10,8 @@ var log = require('npmlog');
|
|||
log.debug = log.verbose;
|
||||
log.level = 'info';
|
||||
|
||||
var sjcl = require('sjcl');
|
||||
|
||||
var WalletService = require('../../lib/server');
|
||||
var PushNotificationsService = require('../../lib/pushnotificationsservice');
|
||||
|
||||
|
@ -36,11 +38,24 @@ describe('Push notifications', function() {
|
|||
var i = 0;
|
||||
async.eachSeries(w.copayers, function(copayer, next) {
|
||||
helpers.getAuthServer(copayer.id, function(server) {
|
||||
server.savePreferences({
|
||||
email: 'copayer' + (++i) + '@domain.com',
|
||||
language: 'en',
|
||||
unit: 'bit',
|
||||
}, next);
|
||||
async.parallel([
|
||||
|
||||
function(done) {
|
||||
server.savePreferences({
|
||||
email: 'copayer' + (++i) + '@domain.com',
|
||||
language: 'en',
|
||||
unit: 'bit',
|
||||
}, done);
|
||||
},
|
||||
function(done) {
|
||||
server.pushNotificationsSubscribe({
|
||||
token: '1234',
|
||||
packageName: 'com.wallet',
|
||||
platform: 'Android',
|
||||
}, done);
|
||||
},
|
||||
], next);
|
||||
|
||||
});
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
|
@ -59,8 +74,8 @@ describe('Push notifications', function() {
|
|||
defaultLanguage: 'en',
|
||||
defaultUnit: 'btc',
|
||||
subjectPrefix: '',
|
||||
|
||||
pushServerUrl: 'http://localhost:8000/send',
|
||||
pushServerUrl: 'http://localhost:8000',
|
||||
authorizationKey: 'secret',
|
||||
},
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
|
@ -93,8 +108,8 @@ describe('Push notifications', function() {
|
|||
return c.args[0];
|
||||
});
|
||||
calls.length.should.equal(1);
|
||||
args[0].body.android.data.title.should.contain('New payment received');
|
||||
args[0].body.android.data.message.should.contain('123,000');
|
||||
args[0].body.notification.title.should.contain('New payment received');
|
||||
args[0].body.notification.body.should.contain('123,000');
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
|
@ -154,11 +169,24 @@ describe('Push notifications', function() {
|
|||
var i = 0;
|
||||
async.eachSeries(w.copayers, function(copayer, next) {
|
||||
helpers.getAuthServer(copayer.id, function(server) {
|
||||
server.savePreferences({
|
||||
email: 'copayer' + (++i) + '@domain.com',
|
||||
language: 'en',
|
||||
unit: 'bit',
|
||||
}, next);
|
||||
async.parallel([
|
||||
|
||||
function(done) {
|
||||
server.savePreferences({
|
||||
email: 'copayer' + (++i) + '@domain.com',
|
||||
language: 'en',
|
||||
unit: 'bit',
|
||||
}, done);
|
||||
},
|
||||
function(done) {
|
||||
server.pushNotificationsSubscribe({
|
||||
token: '1234',
|
||||
packageName: 'com.wallet',
|
||||
platform: 'Android',
|
||||
}, done);
|
||||
},
|
||||
], next);
|
||||
|
||||
});
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
|
@ -177,8 +205,8 @@ describe('Push notifications', function() {
|
|||
defaultLanguage: 'en',
|
||||
defaultUnit: 'btc',
|
||||
subjectPrefix: '',
|
||||
|
||||
pushServerUrl: 'http://localhost:8000/send',
|
||||
pushServerUrl: 'http://localhost:8000',
|
||||
authorizationKey: 'secret',
|
||||
},
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
|
@ -214,14 +242,14 @@ describe('Push notifications', function() {
|
|||
|
||||
calls.length.should.equal(3);
|
||||
|
||||
args[0].body.android.data.title.should.contain('Nuevo pago recibido');
|
||||
args[0].body.android.data.message.should.contain('0.123');
|
||||
args[0].body.notification.title.should.contain('Nuevo pago recibido');
|
||||
args[0].body.notification.body.should.contain('0.123');
|
||||
|
||||
args[1].body.android.data.title.should.contain('New payment received');
|
||||
args[1].body.android.data.message.should.contain('123,000');
|
||||
args[1].body.notification.title.should.contain('New payment received');
|
||||
args[1].body.notification.body.should.contain('123,000');
|
||||
|
||||
args[2].body.android.data.title.should.contain('New payment received');
|
||||
args[2].body.android.data.message.should.contain('123,000');
|
||||
args[2].body.notification.title.should.contain('New payment received');
|
||||
args[2].body.notification.body.should.contain('123,000');
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
|
@ -333,9 +361,7 @@ describe('Push notifications', function() {
|
|||
return c.args[0];
|
||||
});
|
||||
|
||||
args[0].body.android.data.title.should.contain('Payment proposal rejected');
|
||||
args[0].body.android.data.message.should.contain('copayer 2, copayer 3');
|
||||
args[0].body.android.data.message.should.not.contain('copayer 1');
|
||||
args[0].body.notification.title.should.contain('Payment proposal rejected');
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
|
@ -392,11 +418,11 @@ describe('Push notifications', function() {
|
|||
return c.args[0];
|
||||
});
|
||||
|
||||
args[0].body.android.data.title.should.contain('Payment sent');
|
||||
args[1].body.android.data.title.should.contain('Payment sent');
|
||||
args[0].body.notification.title.should.contain('Payment sent');
|
||||
args[1].body.notification.title.should.contain('Payment sent');
|
||||
|
||||
server.copayerId.should.not.equal((args[0].body.users[0]).split('$')[1]);
|
||||
server.copayerId.should.not.equal((args[1].body.users[0]).split('$')[1]);
|
||||
sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(server.copayerId)).should.not.equal(args[0].body.data.copayerId);
|
||||
sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(server.copayerId)).should.not.equal(args[1].body.data.copayerId);
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
|
@ -432,7 +458,8 @@ describe('Push notifications', function() {
|
|||
defaultLanguage: 'en',
|
||||
defaultUnit: 'btc',
|
||||
subjectPrefix: '',
|
||||
pushServerUrl: 'http://localhost:8000/send',
|
||||
pushServerUrl: 'http://localhost:8000',
|
||||
authorizationKey: 'secret',
|
||||
},
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
|
@ -452,44 +479,54 @@ describe('Push notifications', function() {
|
|||
customData: 'custom data ' + (i + 1),
|
||||
});
|
||||
|
||||
server.joinWallet(copayerOpts, next);
|
||||
server.joinWallet(copayerOpts, function(err, res) {
|
||||
if (err) return next(err);
|
||||
|
||||
helpers.getAuthServer(res.copayerId, function(server) {
|
||||
server.pushNotificationsSubscribe({
|
||||
token: 'token:' + copayerOpts.name,
|
||||
packageName: 'com.wallet',
|
||||
platform: 'Android',
|
||||
}, next);
|
||||
});
|
||||
});
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
setTimeout(function() {
|
||||
var calls = requestStub.getCalls();
|
||||
var args = _.map(calls, function(c) {
|
||||
return c.args[0];
|
||||
var args = _.filter(_.map(calls, function(call) {
|
||||
return call.args[0];
|
||||
}), function(arg) {
|
||||
return arg.body.notification.title == 'New copayer';
|
||||
});
|
||||
|
||||
var argu = _.compact(_.map(args, function(a) {
|
||||
if (a.body.android.data.title == 'New copayer')
|
||||
return a;
|
||||
}));
|
||||
|
||||
server.getWallet(null, function(err, w) {
|
||||
server.getWallet(null, function(err, wallet) {
|
||||
/*
|
||||
First call - copayer2 joined
|
||||
copayer2 should notify to copayer1
|
||||
copayer2 should NOT be notifyed
|
||||
*/
|
||||
w.copayers[0].id.should.contain((argu[0].body.users[0]).split('$')[1]);
|
||||
w.copayers[1].id.should.not.contain((argu[0].body.users[0]).split('$')[1]);
|
||||
var hashedCopayerIds = _.map(wallet.copayers, function(copayer) {
|
||||
return sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(copayer.id));
|
||||
});
|
||||
hashedCopayerIds[0].should.equal((args[0].body.data.copayerId));
|
||||
hashedCopayerIds[1].should.not.equal((args[0].body.data.copayerId));
|
||||
|
||||
/*
|
||||
Second call - copayer3 joined
|
||||
copayer3 should notify to copayer1
|
||||
*/
|
||||
w.copayers[0].id.should.contain((argu[1].body.users[0]).split('$')[1]);
|
||||
hashedCopayerIds[0].should.equal((args[1].body.data.copayerId));
|
||||
|
||||
/*
|
||||
Third call - copayer3 joined
|
||||
copayer3 should notify to copayer2
|
||||
*/
|
||||
w.copayers[1].id.should.contain((argu[2].body.users[0]).split('$')[1]);
|
||||
hashedCopayerIds[1].should.equal((args[2].body.data.copayerId));
|
||||
|
||||
// copayer3 should NOT notify any other copayer
|
||||
w.copayers[2].id.should.not.contain((argu[1].body.users[0]).split('$')[1]);
|
||||
w.copayers[2].id.should.not.contain((argu[2].body.users[0]).split('$')[1]);
|
||||
hashedCopayerIds[2].should.not.equal((args[1].body.data.copayerId));
|
||||
hashedCopayerIds[2].should.not.equal((args[2].body.data.copayerId));
|
||||
done();
|
||||
});
|
||||
}, 100);
|
||||
|
|
|
@ -7040,40 +7040,105 @@ describe('Wallet service', function() {
|
|||
});
|
||||
|
||||
it('should subscribe copayer to push notifications service', function(done) {
|
||||
request.yields();
|
||||
helpers.getAuthServer(wallet.copayers[0].id, function(server) {
|
||||
should.exist(server);
|
||||
server.pushNotificationsSubscribe({
|
||||
token: 'DEVICE_TOKEN'
|
||||
}, function(err, response) {
|
||||
token: 'DEVICE_TOKEN',
|
||||
packageName: 'com.wallet',
|
||||
platform: 'Android',
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
var calls = request.getCalls();
|
||||
calls.length.should.equal(1);
|
||||
var args = _.map(calls, function(c) {
|
||||
return c.args[0];
|
||||
server.storage.fetchPushNotificationSubs(wallet.copayers[0].id, function(err, subs) {
|
||||
should.not.exist(err);
|
||||
should.exist(subs);
|
||||
subs.length.should.equal(1);
|
||||
var s = subs[0];
|
||||
s.token.should.equal('DEVICE_TOKEN');
|
||||
s.packageName.should.equal('com.wallet');
|
||||
s.platform.should.equal('Android')
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should allow multiple subscriptions for the same copayer', function(done) {
|
||||
helpers.getAuthServer(wallet.copayers[0].id, function(server) {
|
||||
should.exist(server);
|
||||
server.pushNotificationsSubscribe({
|
||||
token: 'DEVICE_TOKEN',
|
||||
packageName: 'com.wallet',
|
||||
platform: 'Android',
|
||||
}, function(err) {
|
||||
server.pushNotificationsSubscribe({
|
||||
token: 'DEVICE_TOKEN2',
|
||||
packageName: 'com.my-other-wallet',
|
||||
platform: 'iOS',
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
server.storage.fetchPushNotificationSubs(wallet.copayers[0].id, function(err, subs) {
|
||||
should.not.exist(err);
|
||||
should.exist(subs);
|
||||
subs.length.should.equal(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
args[0].body.user.should.contain(wallet.copayers[0].id);
|
||||
args[0].body.user.should.contain(wallet.id);
|
||||
args[0].body.token.should.contain('DEVICE_TOKEN');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should unsubscribe copayer to push notifications service', function(done) {
|
||||
request.yields();
|
||||
helpers.getAuthServer(wallet.copayers[0].id, function(server) {
|
||||
should.exist(server);
|
||||
server.pushNotificationsUnsubscribe(function(err, response) {
|
||||
should.not.exist(err);
|
||||
var calls = request.getCalls();
|
||||
calls.length.should.equal(1);
|
||||
var args = _.map(calls, function(c) {
|
||||
return c.args[0];
|
||||
});
|
||||
async.series([
|
||||
|
||||
args[0].body.user.should.contain(wallet.copayers[0].id);
|
||||
args[0].body.user.should.contain(wallet.id);
|
||||
function(next) {
|
||||
server.pushNotificationsSubscribe({
|
||||
token: 'DEVICE_TOKEN',
|
||||
packageName: 'com.wallet',
|
||||
platform: 'Android',
|
||||
}, next);
|
||||
},
|
||||
function(next) {
|
||||
server.pushNotificationsSubscribe({
|
||||
token: 'DEVICE_TOKEN2',
|
||||
packageName: 'com.my-other-wallet',
|
||||
platform: 'iOS',
|
||||
}, next);
|
||||
},
|
||||
function(next) {
|
||||
server.pushNotificationsUnsubscribe({
|
||||
token: 'DEVICE_TOKEN2'
|
||||
}, next);
|
||||
},
|
||||
function(next) {
|
||||
server.storage.fetchPushNotificationSubs(wallet.copayers[0].id, function(err, subs) {
|
||||
should.not.exist(err);
|
||||
should.exist(subs);
|
||||
subs.length.should.equal(1);
|
||||
var s = subs[0];
|
||||
s.token.should.equal('DEVICE_TOKEN');
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
helpers.getAuthServer(wallet.copayers[1].id, function(server) {
|
||||
server.pushNotificationsUnsubscribe({
|
||||
token: 'DEVICE_TOKEN'
|
||||
}, next);
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
server.storage.fetchPushNotificationSubs(wallet.copayers[0].id, function(err, subs) {
|
||||
should.not.exist(err);
|
||||
should.exist(subs);
|
||||
subs.length.should.equal(1);
|
||||
var s = subs[0];
|
||||
s.token.should.equal('DEVICE_TOKEN');
|
||||
next();
|
||||
});
|
||||
},
|
||||
], function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue