From 43f24ee35e1b4e4d4a530305ee749bdcd9bb530e Mon Sep 17 00:00:00 2001 From: Andy Phillipson Date: Mon, 14 Nov 2016 16:24:52 -0500 Subject: [PATCH] Abstract bitpayCardCredentials to appIdentity. Improve alert text on card removal. --- src/js/controllers/bitpayCardIntro.js | 6 +- src/js/controllers/preferencesBitpayCard.js | 4 +- src/js/services/appIdentityService.js | 34 +++++++++++ src/js/services/bitpayCardService.js | 66 ++++++--------------- src/js/services/storageService.js | 37 +++++++++--- 5 files changed, 87 insertions(+), 60 deletions(-) create mode 100644 src/js/services/appIdentityService.js diff --git a/src/js/controllers/bitpayCardIntro.js b/src/js/controllers/bitpayCardIntro.js index 63e5b7904..f2abecdf0 100644 --- a/src/js/controllers/bitpayCardIntro.js +++ b/src/js/controllers/bitpayCardIntro.js @@ -1,5 +1,5 @@ 'use strict'; -angular.module('copayApp.controllers').controller('bitpayCardIntroController', function($scope, $log, $state, $ionicHistory, storageService, externalLinkService, bitpayCardService, gettextCatalog, popupService) { +angular.module('copayApp.controllers').controller('bitpayCardIntroController', function($scope, $log, $state, $ionicHistory, storageService, externalLinkService, bitpayCardService, gettextCatalog, popupService, appIdentityService) { var checkOtp = function(obj, cb) { if (obj.otp) { @@ -56,9 +56,9 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', f }); }); } else { - bitpayCardService.getCredentials(function(err, credentials) { + appIdentityService.getIdentity(bitpayCardService.getEnvironment(), function(err, appIdentity) { if (err) popupService.showAlert(null, err); - else $log.info('BitPay Debit Card Credentials: Ok.'); + else $log.info('App identity: Ok.'); }); } }); diff --git a/src/js/controllers/preferencesBitpayCard.js b/src/js/controllers/preferencesBitpayCard.js index 3b7e0ac54..9813ad3a3 100644 --- a/src/js/controllers/preferencesBitpayCard.js +++ b/src/js/controllers/preferencesBitpayCard.js @@ -4,7 +4,9 @@ angular.module('copayApp.controllers').controller('preferencesBitpayCardControll function($scope, $state, $timeout, $ionicHistory, bitpayCardService, popupService, gettextCatalog) { $scope.remove = function(card) { - var msg = gettextCatalog.getString('Are you sure you would like to remove your BitPay Card account from this device?'); + var msg = gettextCatalog.getString('Are you sure you would like to remove your BitPay Card account ({{lastFourDigits}}) from this device?', { + lastFourDigits: card.lastFourDigits + }); popupService.showConfirm(null, msg, null, null, function(res) { if (res) remove(card); }); diff --git a/src/js/services/appIdentityService.js b/src/js/services/appIdentityService.js new file mode 100644 index 000000000..6df3f136d --- /dev/null +++ b/src/js/services/appIdentityService.js @@ -0,0 +1,34 @@ +'use strict'; + +angular.module('copayApp.services').factory('appIdentityService', function($log, lodash, storageService, bitauthService) { + var root = {}; + + root.getIdentity = function(network, cb) { + var pubkey, sin, isNew; + storageService.getAppIdentity(network, function(err, data) { + if (err) return cb(err); + if (lodash.isString(data)) { + data = JSON.parse(data); + } + var appIdentity = data || {}; + if (lodash.isEmpty(appIdentity) || (appIdentity && !appIdentity.priv)) { + isNew = true; + appIdentity = bitauthService.generateSin(); + } + try { + pubkey = bitauthService.getPublicKeyFromPrivateKey(appIdentity.priv); + sin = bitauthService.getSinFromPublicKey(pubkey); + if (isNew) + storageService.setAppIdentity(network, JSON.stringify(appIdentity), function(err) {}); + } + catch (e) { + $log.error(e); + return cb(e); + }; + return cb(null, appIdentity); + }); + }; + + return root; + +}); \ No newline at end of file diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index bd671c02d..4ae042f6c 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -1,36 +1,10 @@ 'use strict'; -angular.module('copayApp.services').factory('bitpayCardService', function($http, $log, lodash, storageService, bitauthService, platformInfo, moment) { +angular.module('copayApp.services').factory('bitpayCardService', function($http, $log, lodash, storageService, bitauthService, platformInfo, moment, appIdentityService) { var root = {}; var BITPAY_CARD_NETWORK = 'livenet'; var BITPAY_CARD_API_URL = BITPAY_CARD_NETWORK == 'livenet' ? 'https://bitpay.com' : 'https://test.bitpay.com'; - var _getCredentials = function(cb) { - var pubkey, sin, isNew; - storageService.getBitpayCardCredentials(BITPAY_CARD_NETWORK, function(err, data) { - if (err) return cb(err); - if (lodash.isString(data)) { - data = JSON.parse(data); - } - var credentials = data || {}; - if (lodash.isEmpty(credentials) || (credentials && !credentials.priv)) { - isNew = true; - credentials = bitauthService.generateSin(); - } - try { - pubkey = bitauthService.getPublicKeyFromPrivateKey(credentials.priv); - sin = bitauthService.getSinFromPublicKey(pubkey); - if (isNew) - storageService.setBitpayCardCredentials(BITPAY_CARD_NETWORK, JSON.stringify(credentials), function(err) {}); - } - catch (e) { - $log.error(e); - return cb(e); - }; - return cb(null, credentials); - }); - }; - var _setError = function(msg, e) { $log.error(msg); var error = e.data ? e.data.error : msg; @@ -47,25 +21,25 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }; }; - var _post = function(endpoint, json, credentials) { + var _post = function(endpoint, json, appIdentity) { var dataToSign = BITPAY_CARD_API_URL + endpoint + JSON.stringify(json); - var signedData = bitauthService.sign(dataToSign, credentials.priv); + var signedData = bitauthService.sign(dataToSign, appIdentity.priv); return { method: 'POST', url: BITPAY_CARD_API_URL + endpoint, headers: { 'content-type': 'application/json', - 'x-identity': credentials.pub, + 'x-identity': appIdentity.pub, 'x-signature': signedData }, data: json }; }; - var _postAuth = function(endpoint, json, credentials) { - json['params'].signature = bitauthService.sign(JSON.stringify(json.params), credentials.priv); - json['params'].pubkey = credentials.pub; + var _postAuth = function(endpoint, json, appIdentity) { + json['params'].signature = bitauthService.sign(JSON.stringify(json.params), appIdentity.priv); + json['params'].pubkey = appIdentity.pub; json['params'] = JSON.stringify(json.params); var ret = { @@ -81,12 +55,12 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, return ret; }; - var _afterBitAuthSuccess = function(token, obj, credentials, cb) { + var _afterBitAuthSuccess = function(token, obj, appIdentity, cb) { var json = { method: 'getDebitCards' }; // Get Debit Cards - $http(_post('/api/v2/' + token, json, credentials)).then(function(data) { + $http(_post('/api/v2/' + token, json, appIdentity)).then(function(data) { if (data && data.data.error) return cb(data.data.error); $log.info('BitPay Get Debit Cards: SUCCESS'); return cb(data.data.error, {token: token, cards: data.data.data, email: obj.email}); @@ -129,12 +103,6 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, return BITPAY_CARD_NETWORK; }; - root.getCredentials = function(cb) { - _getCredentials(function(err, credentials) { - return cb(err, credentials); - }); - }; - root.bitAuthPair = function(obj, cb) { var deviceName = 'Unknow device'; if (platformInfo.isNW) { @@ -151,12 +119,12 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, code: obj.otp } }; - _getCredentials(function(err, credentials) { + appIdentityService.getIdentity(root.getEnvironment(), function(err, appIdentity) { if (err) return cb(err); - $http(_postAuth('/api/v2/', json, credentials)).then(function(data) { + $http(_postAuth('/api/v2/', json, appIdentity)).then(function(data) { if (data && data.data.error) return cb(data.data.error); $log.info('BitPay Card BitAuth Create Token: SUCCESS'); - _afterBitAuthSuccess(data.data.data, obj, credentials, cb); + _afterBitAuthSuccess(data.data.data, obj, appIdentity, cb); }, function(data) { return cb(_setError('BitPay Card Error Create Token: BitAuth', data)); }); @@ -170,14 +138,14 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, method: 'getInvoiceHistory', params: JSON.stringify(params) }; - _getCredentials(function(err, credentials) { + appIdentityService.getIdentity(root.getEnvironment(), function(err, appIdentity) { if (err) return cb(err); root.getBitpayDebitCards(function(err, data) { if (err) return cb(err); var card = lodash.find(data, {id : cardId}); if (!card) return cb(_setError('Not card found')); // Get invoices - $http(_post('/api/v2/' + card.token, json, credentials)).then(function(data) { + $http(_post('/api/v2/' + card.token, json, appIdentity)).then(function(data) { $log.info('BitPay Get Invoices: SUCCESS'); invoices = data.data.data || []; if (lodash.isEmpty(invoices)) $log.info('No invoices'); @@ -186,7 +154,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, params: JSON.stringify(params) }; // Get transactions list - $http(_post('/api/v2/' + card.token, json, credentials)).then(function(data) { + $http(_post('/api/v2/' + card.token, json, appIdentity)).then(function(data) { $log.info('BitPay Get Transactions: SUCCESS'); transactions = data.data.data || {}; transactions['txs'] = _processTransactions(invoices, transactions.transactionList); @@ -207,13 +175,13 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, method: 'generateTopUpInvoice', params: JSON.stringify(params) }; - _getCredentials(function(err, credentials) { + appIdentityService.getIdentity(root.getEnvironment(), function(err, appIdentity) { if (err) return cb(err); root.getBitpayDebitCards(function(err, data) { if (err) return cb(err); var card = lodash.find(data, {id : cardId}); if (!card) return cb(_setError('Not card found')); - $http(_post('/api/v2/' + card.token, json, credentials)).then(function(data) { + $http(_post('/api/v2/' + card.token, json, appIdentity)).then(function(data) { $log.info('BitPay TopUp: SUCCESS'); if(data.data.error) { return cb(data.data.error); diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index 17586f609..340b25eb5 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -95,7 +95,8 @@ angular.module('copayApp.services') // Upgraders are executed in numerical order per the '##_' object key prefix. // var _upgraders = { - '00_bitpayDebitCards' : _upgrade_bitpayDebitCards // 2016-11: Upgrade bitpayDebitCards-x to bitpayAccounts-x + '00_bitpayDebitCards' : _upgrade_bitpayDebitCards, // 2016-11: Upgrade bitpayDebitCards-x to bitpayAccounts-x + '01_bitpayCardCredentials' : _upgrade_bitpayCardCredentials // 2016-11: Upgrade bitpayCardCredentials-x to appIdentity-x }; function _upgrade_bitpayDebitCards(key, network, cb) { @@ -119,6 +120,28 @@ angular.module('copayApp.services') } }); }; + + function _upgrade_bitpayCardCredentials(key, network, cb) { + key += '-' + network; + storage.get(key, function(err, data) { + if (err) return cb(err); + if (data != null) { + // Needs upgrade + if (lodash.isString(data)) { + data = JSON.parse(data); + } + data = data || {}; + root.setAppIdentity(network, data, function(err) { + if (err) return cb(err); + storage.remove(key, function() { + cb(null, 'replaced with \'appIdentity\''); + }); + }); + } else { + cb(); + } + }); + }; // //////////////////////////////////////////////////////////////////////////// @@ -488,16 +511,16 @@ angular.module('copayApp.services') }); }; - root.setBitpayCardCredentials = function(network, data, cb) { - storage.set('bitpayCardCredentials-' + network, data, cb); + root.setAppIdentity = function(network, data, cb) { + storage.set('appIdentity-' + network, data, cb); }; - root.getBitpayCardCredentials = function(network, cb) { - storage.get('bitpayCardCredentials-' + network, cb); + root.getAppIdentity = function(network, cb) { + storage.get('appIdentity-' + network, cb); }; - root.removeBitpayCardCredentials = function(network, cb) { - storage.remove('bitpayCardCredentials-' + network, cb); + root.removeAppIdentity = function(network, cb) { + storage.remove('appIdentity-' + network, cb); }; root.removeAllWalletData = function(walletId, cb) {