From c71f6c637ff64379b091e76600fb0d1f13f90cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Fri, 15 Jan 2016 12:02:16 -0300 Subject: [PATCH 1/5] push notifications service subscribe, unsubscribe and tests --- config.js | 2 +- lib/expressapp.js | 26 +++++++++++++++++ lib/pushnotificationsservice.js | 2 +- lib/server.js | 48 +++++++++++++++++++++++++++++--- test/integration/helpers.js | 5 ++-- test/integration/server.js | 49 ++++++++++++++++++++++++++++++++- 6 files changed, 123 insertions(+), 9 deletions(-) diff --git a/config.js b/config.js index 4ba24b7..5bffbd0 100644 --- a/config.js +++ b/config.js @@ -50,7 +50,7 @@ var config = { defaultLanguage: 'en', defaultUnit: 'btc', subjectPrefix: '', - pushServerUrl: 'http://localhost:8000/send', + pushServerUrl: 'http://localhost:8000', }, fiatRateServiceOpts: { defaultProvider: 'BitPay', diff --git a/lib/expressapp.js b/lib/expressapp.js index c197374..e627ee0 100644 --- a/lib/expressapp.js +++ b/lib/expressapp.js @@ -518,6 +518,32 @@ ExpressApp.prototype.start = function(opts, cb) { }); }); + router.post('/v1/pushnotifications/subscriptions/', function(req, res) { + getServerWithAuth(req, res, function(server) { + server.pushNotificationsSubscribe(req.body, function(err, response) { + if (err) return returnError(err, res, req); + res.json(response); + }); + }); + }); + + router.delete('/v1/pushnotifications/subscriptions/', function(req, res) { + getServerWithAuth(req, res, function(server) { + server.pushNotificationsUnsubscribe(null, function(err, response) { + if (err) return returnError(err, res, req); + res.json(response); + }); + }); + }); + + router.delete('/v1/pushnotifications/subscriptions/:opts/', function(req, res) { + getServerWithAuth(req, res, function(server) { + server.pushNotificationsUnsubscribe(req.params['opts'], function(err, response) { + if (err) return returnError(err, res, req); + res.json(response); + }); + }); + }); this.app.use(opts.basePath || '/bws/api', router); diff --git a/lib/pushnotificationsservice.js b/lib/pushnotificationsservice.js index 8d8b81c..641cc92 100644 --- a/lib/pushnotificationsservice.js +++ b/lib/pushnotificationsservice.js @@ -341,7 +341,7 @@ PushNotificationsService.prototype._makeRequest = function(opts, cb) { var self = this; self.request({ - url: self.pushServerUrl, + url: self.pushServerUrl + '/send', method: 'POST', json: true, body: opts diff --git a/lib/server.js b/lib/server.js index fed64fe..a60589a 100644 --- a/lib/server.js +++ b/lib/server.js @@ -3,6 +3,8 @@ var _ = require('lodash'); var $ = require('preconditions').singleton(); var async = require('async'); var log = require('npmlog'); +var config = require('../config'); + log.debug = log.verbose; log.disableColor(); var EmailValidator = require('email-validator'); @@ -24,6 +26,8 @@ var MessageBroker = require('./messagebroker'); var BlockchainExplorer = require('./blockchainexplorer'); var FiatRateService = require('./fiatrateservice'); +var request = require('request'); + var Model = require('./model'); var Wallet = Model.Wallet; @@ -80,6 +84,8 @@ WalletService.initialize = function(opts, cb) { lock = opts.lock || new Lock(opts.lockOpts); blockchainExplorer = opts.blockchainExplorer; blockchainExplorerOpts = opts.blockchainExplorerOpts; + if (opts.request) + request = opts.request; function initStorage(cb) { if (opts.storage) { @@ -644,8 +650,8 @@ WalletService.prototype.joinWallet = function(opts, cb) { } if (_.find(wallet.copayers, { - xPubKey: opts.xPubKey - })) return cb(Errors.COPAYER_IN_WALLET); + xPubKey: opts.xPubKey + })) return cb(Errors.COPAYER_IN_WALLET); if (wallet.copayers.length == wallet.n) return cb(Errors.WALLET_FULL); @@ -738,8 +744,8 @@ WalletService.prototype._canCreateAddress = function(ignoreMaxGap, cb) { isChange: true }), Defaults.MAX_MAIN_ADDRESS_GAP); if (latestAddresses.length < Defaults.MAX_MAIN_ADDRESS_GAP || _.any(latestAddresses, { - hasActivity: true - })) return cb(null, true); + hasActivity: true + })) return cb(null, true); var bc = self._getBlockchainExplorer(latestAddresses[0].network); var activityFound = false; @@ -2421,6 +2427,40 @@ WalletService.prototype.getFiatRate = function(opts, cb) { }); }; +WalletService.prototype.pushNotificationsSubscribe = function(opts, cb) { + 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); + }); +}; + +WalletService.prototype.pushNotificationsUnsubscribe = function(opts, cb) { + var self = this; + + if (opts) opts = { + token: opts + }; + else opts = { + user: self.walletId + '$' + self.copayerId + }; + + request({ + url: config.pushNotificationsOpts.pushServerUrl + '/unsubscribe', + method: 'POST', + json: true, + body: opts + }, function(err, response) { + return cb(err, response); + }); +}; module.exports = WalletService; module.exports.ClientError = ClientError; diff --git a/test/integration/helpers.js b/test/integration/helpers.js index a89cb4d..99b43b9 100644 --- a/test/integration/helpers.js +++ b/test/integration/helpers.js @@ -60,7 +60,8 @@ helpers.beforeEach = function(cb) { blockchainExplorer = sinon.stub(); var opts = { storage: storage, - blockchainExplorer: blockchainExplorer + blockchainExplorer: blockchainExplorer, + request: sinon.stub() }; WalletService.initialize(opts, function() { return cb(opts); @@ -101,7 +102,7 @@ helpers.getAuthServer = function(copayerId, cb) { clientVersion: helpers.CLIENT_VERSION, }, function(err, server) { verifyStub.restore(); - if (err || !server) throw new Error('Could not login as copayerId ' + copayerId); + if (err || !server) throw new Error('Could not login as copayerId ' + copayerId + ' err: ' + err); return cb(server); }); }; diff --git a/test/integration/server.js b/test/integration/server.js index fa4c7b5..924c9e0 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -23,7 +23,7 @@ var WalletService = require('../../lib/server'); var TestData = require('../testdata'); var helpers = require('./helpers'); -var storage, blockchainExplorer; +var storage, blockchainExplorer, request; describe('Wallet service', function() { @@ -34,6 +34,7 @@ describe('Wallet service', function() { helpers.beforeEach(function(res) { storage = res.storage; blockchainExplorer = res.blockchainExplorer; + request = res.request; done(); }); }); @@ -5451,4 +5452,50 @@ describe('Wallet service', function() { }); }); }); + + describe('Subscribe/unsubscribe', function() { + var server, wallet; + beforeEach(function(done) { + helpers.createAndJoinWallet(2, 3, function(s, w) { + server = s; + wallet = w; + done(); + }); + }); + + 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({}, 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]; + }); + args[0].body.user.should.contain(wallet.copayers[0].id); + 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]; + }); + args[0].body.user.should.contain(wallet.copayers[0].id); + done(); + }); + }); + }); + }); + }); From 88d292aaceaa2813dd4f9d8c378be395c65d4c50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Fri, 15 Jan 2016 12:37:11 -0300 Subject: [PATCH 2/5] test fixed --- test/integration/server.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/test/integration/server.js b/test/integration/server.js index 924c9e0..242478b 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -5484,18 +5484,37 @@ describe('Wallet service', function() { request.yields(); helpers.getAuthServer(wallet.copayers[0].id, function(server) { should.exist(server); - server.pushNotificationsUnsubscribe({}, function(err, response) { + server.pushNotificationsUnsubscribe(null, 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]; }); + args[0].body.user.should.contain(wallet.copayers[0].id); done(); }); }); }); + + it('should unsubscribe all wallets from device to push notifications service', function(done) { + request.yields(); + helpers.getAuthServer(wallet.copayers[0].id, function(server) { + should.exist(server); + server.pushNotificationsUnsubscribe('TOKEN_DEVICE', 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]; + }); + + args[0].body.token.should.contain('TOKEN_DEVICE'); + done(); + }); + }); + }); }); }); From bd7bcbab450576ae996039b28655a140860394e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Fri, 15 Jan 2016 17:16:10 -0300 Subject: [PATCH 3/5] push notifications unsubscribe method refactor --- lib/expressapp.js | 13 ++----------- lib/server.js | 15 +++++---------- test/integration/server.js | 30 +++++++++--------------------- 3 files changed, 16 insertions(+), 42 deletions(-) diff --git a/lib/expressapp.js b/lib/expressapp.js index e627ee0..af850fb 100644 --- a/lib/expressapp.js +++ b/lib/expressapp.js @@ -527,18 +527,9 @@ ExpressApp.prototype.start = function(opts, cb) { }); }); - router.delete('/v1/pushnotifications/subscriptions/', function(req, res) { + router.delete('/v1/pushnotifications/subscriptions/:token/', function(req, res) { getServerWithAuth(req, res, function(server) { - server.pushNotificationsUnsubscribe(null, function(err, response) { - if (err) return returnError(err, res, req); - res.json(response); - }); - }); - }); - - router.delete('/v1/pushnotifications/subscriptions/:opts/', function(req, res) { - getServerWithAuth(req, res, function(server) { - server.pushNotificationsUnsubscribe(req.params['opts'], function(err, response) { + server.pushNotificationsUnsubscribe(req.params['token'], function(err, response) { if (err) return returnError(err, res, req); res.json(response); }); diff --git a/lib/server.js b/lib/server.js index a60589a..07e5338 100644 --- a/lib/server.js +++ b/lib/server.js @@ -2430,7 +2430,7 @@ WalletService.prototype.getFiatRate = function(opts, cb) { WalletService.prototype.pushNotificationsSubscribe = function(opts, cb) { var self = this; - opts.user = self.walletId + '$' + self.copayerId; + opts.user = self.walletId + '$' + self.copayerId + '$' + opts.token; request({ url: config.pushNotificationsOpts.pushServerUrl + '/subscribe', @@ -2442,21 +2442,16 @@ WalletService.prototype.pushNotificationsSubscribe = function(opts, cb) { }); }; -WalletService.prototype.pushNotificationsUnsubscribe = function(opts, cb) { +WalletService.prototype.pushNotificationsUnsubscribe = function(token, cb) { var self = this; - if (opts) opts = { - token: opts - }; - else opts = { - user: self.walletId + '$' + self.copayerId - }; - request({ url: config.pushNotificationsOpts.pushServerUrl + '/unsubscribe', method: 'POST', json: true, - body: opts + body: { + user: self.walletId + '$' + self.copayerId + '$' + token + } }, function(err, response) { return cb(err, response); }); diff --git a/test/integration/server.js b/test/integration/server.js index 242478b..75dddd7 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -5453,7 +5453,7 @@ describe('Wallet service', function() { }); }); - describe('Subscribe/unsubscribe', function() { + describe.only('Subscribe/unsubscribe', function() { var server, wallet; beforeEach(function(done) { helpers.createAndJoinWallet(2, 3, function(s, w) { @@ -5467,7 +5467,9 @@ describe('Wallet service', function() { request.yields(); helpers.getAuthServer(wallet.copayers[0].id, function(server) { should.exist(server); - server.pushNotificationsSubscribe({}, function(err, response) { + server.pushNotificationsSubscribe({ + token: 'DEVICE_TOKEN' + }, function(err, response) { should.not.exist(err); var calls = request.getCalls(); calls.length.should.equal(1); @@ -5475,6 +5477,8 @@ describe('Wallet service', function() { return c.args[0]; }); args[0].body.user.should.contain(wallet.copayers[0].id); + args[0].body.user.should.contain(wallet.id); + args[0].body.user.should.contain('DEVICE_TOKEN'); done(); }); }); @@ -5484,7 +5488,7 @@ describe('Wallet service', function() { request.yields(); helpers.getAuthServer(wallet.copayers[0].id, function(server) { should.exist(server); - server.pushNotificationsUnsubscribe(null, function(err, response) { + server.pushNotificationsUnsubscribe('DEVICE_TOKEN', function(err, response) { should.not.exist(err); var calls = request.getCalls(); calls.length.should.equal(1); @@ -5493,24 +5497,8 @@ describe('Wallet service', function() { }); args[0].body.user.should.contain(wallet.copayers[0].id); - done(); - }); - }); - }); - - it('should unsubscribe all wallets from device to push notifications service', function(done) { - request.yields(); - helpers.getAuthServer(wallet.copayers[0].id, function(server) { - should.exist(server); - server.pushNotificationsUnsubscribe('TOKEN_DEVICE', 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]; - }); - - args[0].body.token.should.contain('TOKEN_DEVICE'); + args[0].body.user.should.contain(wallet.id); + args[0].body.user.should.contain('DEVICE_TOKEN'); done(); }); }); From 365c638cd02159cda68389af5db0cf13b9e133b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Fri, 15 Jan 2016 17:23:00 -0300 Subject: [PATCH 4/5] remove only in test --- test/integration/server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/server.js b/test/integration/server.js index 75dddd7..ff62e38 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -5453,7 +5453,7 @@ describe('Wallet service', function() { }); }); - describe.only('Subscribe/unsubscribe', function() { + describe('Subscribe/unsubscribe', function() { var server, wallet; beforeEach(function(done) { helpers.createAndJoinWallet(2, 3, function(s, w) { From bcd840c7fc56ea87666107beee6d8ac30324bacc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Mon, 18 Jan 2016 10:26:37 -0300 Subject: [PATCH 5/5] check token in opts --- lib/server.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/server.js b/lib/server.js index 07e5338..fbb0dc7 100644 --- a/lib/server.js +++ b/lib/server.js @@ -2428,6 +2428,9 @@ WalletService.prototype.getFiatRate = function(opts, cb) { }; WalletService.prototype.pushNotificationsSubscribe = function(opts, cb) { + if (!Utils.checkRequired(opts, ['token'])) + return cb(new ClientError('Required argument missing')); + var self = this; opts.user = self.walletId + '$' + self.copayerId + '$' + opts.token;