From 3c464e9579298f1618e45fb59217670786cbcbd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Tue, 23 Jan 2018 16:45:29 -0300 Subject: [PATCH 1/5] Encrypt wallet at create --- src/js/controllers/onboarding/tour.js | 55 +++++++++++++++++--------- www/views/modals/password-warning.html | 12 ++++++ 2 files changed, 48 insertions(+), 19 deletions(-) create mode 100644 www/views/modals/password-warning.html diff --git a/src/js/controllers/onboarding/tour.js b/src/js/controllers/onboarding/tour.js index 5781ec22a7b..c821c3bcbcd 100644 --- a/src/js/controllers/onboarding/tour.js +++ b/src/js/controllers/onboarding/tour.js @@ -1,6 +1,6 @@ 'use strict'; angular.module('copayApp.controllers').controller('tourController', - function($scope, $state, $log, $timeout, $filter, ongoingProcess, profileService, rateService, popupService, gettextCatalog) { + function ($scope, $state, $log, $timeout, $filter, ongoingProcess, profileService, rateService, popupService, gettextCatalog) { $scope.data = { index: 0 @@ -13,44 +13,44 @@ angular.module('copayApp.controllers').controller('tourController', spaceBetween: 100 } - $scope.$on("$ionicSlides.sliderInitialized", function(event, data) { + $scope.$on("$ionicSlides.sliderInitialized", function (event, data) { $scope.slider = data.slider; }); - $scope.$on("$ionicSlides.slideChangeStart", function(event, data) { + $scope.$on("$ionicSlides.slideChangeStart", function (event, data) { $scope.data.index = data.slider.activeIndex; }); - $scope.$on("$ionicSlides.slideChangeEnd", function(event, data) {}); + $scope.$on("$ionicSlides.slideChangeEnd", function (event, data) { }); - $scope.$on("$ionicView.enter", function(event, data) { - rateService.whenAvailable(function() { + $scope.$on("$ionicView.enter", function (event, data) { + rateService.whenAvailable(function () { var localCurrency = 'USD'; var btcAmount = 1; var rate = rateService.toFiat(btcAmount * 1e8, localCurrency, 'btc'); $scope.localCurrencySymbol = '$'; $scope.localCurrencyPerBtc = $filter('formatFiatAmount')(parseFloat(rate.toFixed(2), 10)); - $timeout(function() { + $timeout(function () { $scope.$apply(); }) }); }); var retryCount = 0; - $scope.createDefaultWallet = function() { + $scope.createDefaultWallet = function () { ongoingProcess.set('creatingWallet', true); - $timeout(function() { - profileService.createDefaultWallet(function(err, walletClient) { + $timeout(function () { + profileService.createDefaultWallet(function (err, walletClient) { if (err) { $log.warn(err); - return $timeout(function() { + return $timeout(function () { $log.warn('Retrying to create default wallet.....:' + ++retryCount); if (retryCount > 3) { ongoingProcess.set('creatingWallet', false); popupService.showAlert( gettextCatalog.getString('Cannot Create Wallet'), err, - function() { + function () { retryCount = 0; return $scope.createDefaultWallet(); }, gettextCatalog.getString('Retry')); @@ -67,21 +67,38 @@ angular.module('copayApp.controllers').controller('tourController', walletId: walletId }); - /* - $state.go('onboarding.backupRequest', { - walletId: walletId - }); - */ + /* + $state.go('onboarding.backupRequest', { + walletId: walletId + }); + */ }); }, 300); }; - $scope.goBack = function() { + /* + $ionicModal.fromTemplateUrl('views/modals/password-warning.html', { + scope: $scope + }).then(function(modal) { + $scope.passwordWarningModal = modal; + $scope.passwordWarningModal.show(); + }); + /* + /* + $scope.close = function() { + $scope.passwordWarningModal.hide(); + }; + $scope.encrypt = function() { + + } + */ + + $scope.goBack = function () { if ($scope.data.index != 0) $scope.slider.slidePrev(); else $state.go('onboarding.welcome'); } - $scope.slideNext = function() { + $scope.slideNext = function () { if ($scope.data.index != 2) $scope.slider.slideNext(); else $state.go('onboarding.welcome'); } diff --git a/www/views/modals/password-warning.html b/www/views/modals/password-warning.html new file mode 100644 index 00000000000..c55e17c2e15 --- /dev/null +++ b/www/views/modals/password-warning.html @@ -0,0 +1,12 @@ + \ No newline at end of file From 133c6cab443834021031346eae7e2ca149af8b74 Mon Sep 17 00:00:00 2001 From: Gabriel Masclef Date: Tue, 23 Jan 2018 17:30:15 -0300 Subject: [PATCH 2/5] Feat: Remove spending password from create personal/shared wallet --- src/js/controllers/create.js | 46 ++++----------- www/views/tab-create-personal.html | 82 ++++---------------------- www/views/tab-create-shared.html | 93 +++++------------------------- 3 files changed, 34 insertions(+), 187 deletions(-) diff --git a/src/js/controllers/create.js b/src/js/controllers/create.js index 658c604bba5..d7eff0ad4d5 100644 --- a/src/js/controllers/create.js +++ b/src/js/controllers/create.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('createController', - function($scope, $rootScope, $timeout, $log, lodash, $state, $ionicScrollDelegate, $ionicHistory, profileService, configService, gettextCatalog, ledger, trezor, intelTEE, derivationPathHelper, ongoingProcess, walletService, storageService, popupService, appConfigService, pushNotificationsService) { + function ($scope, $rootScope, $timeout, $log, lodash, $state, $ionicScrollDelegate, $ionicHistory, profileService, configService, gettextCatalog, ledger, trezor, intelTEE, derivationPathHelper, ongoingProcess, walletService, storageService, popupService, appConfigService, pushNotificationsService) { /* For compressed keys, m*73 + n*34 <= 496 */ var COPAYER_PAIR_LIMITS = { @@ -19,7 +19,7 @@ angular.module('copayApp.controllers').controller('createController', 12: 1, }; - $scope.$on("$ionicView.beforeEnter", function(event, data) { + $scope.$on("$ionicView.beforeEnter", function (event, data) { $scope.formData = {}; var defaults = configService.getDefaults(); var config = configService.getSync(); @@ -32,41 +32,17 @@ angular.module('copayApp.controllers').controller('createController', $scope.setTotalCopayers(tc); updateRCSelect(tc); - resetPasswordFields(); }); - $scope.showAdvChange = function() { + $scope.showAdvChange = function () { $scope.showAdv = !$scope.showAdv; - $scope.encrypt = null; $scope.resizeView(); }; - $scope.checkPassword = function(pw1, pw2) { - if (pw1 && pw1.length > 0) { - if (pw2 && pw2.length > 0) { - if (pw1 == pw2) $scope.result = 'correct'; - else { - $scope.formData.passwordSaved = null; - $scope.result = 'incorrect'; - } - } else - $scope.result = null; - } else - $scope.result = null; - }; - - $scope.resizeView = function() { - $timeout(function() { + $scope.resizeView = function () { + $timeout(function () { $ionicScrollDelegate.resize(); }, 10); - resetPasswordFields(); - }; - - function resetPasswordFields() { - $scope.formData.passphrase = $scope.formData.createPassphrase = $scope.formData.passwordSaved = $scope.formData.repeatPassword = $scope.result = null; - $timeout(function() { - $scope.$apply(); - }); }; function updateRCSelect(n) { @@ -123,13 +99,13 @@ angular.module('copayApp.controllers').controller('createController', $scope.seedOptions = seedOptions; }; - $scope.setTotalCopayers = function(tc) { + $scope.setTotalCopayers = function (tc) { $scope.formData.totalCopayers = tc; updateRCSelect(tc); updateSeedSourceSelect(tc); }; - $scope.create = function() { + $scope.create = function () { var opts = { name: $scope.formData.walletName, @@ -207,7 +183,7 @@ angular.module('copayApp.controllers').controller('createController', return; } - src.getInfoForNewWallet(opts.n > 1, account, opts.networkName, function(err, lopts) { + src.getInfoForNewWallet(opts.n > 1, account, opts.networkName, function (err, lopts) { ongoingProcess.set('connecting ' + $scope.formData.seedSource.id, false); if (err) { popupService.showAlert(gettextCatalog.getString('Error'), err); @@ -223,8 +199,8 @@ angular.module('copayApp.controllers').controller('createController', function _create(opts) { ongoingProcess.set('creatingWallet', true); - $timeout(function() { - profileService.createWallet(opts, function(err, client) { + $timeout(function () { + profileService.createWallet(opts, function (err, client) { ongoingProcess.set('creatingWallet', false); if (err) { $log.warn(err); @@ -246,7 +222,7 @@ angular.module('copayApp.controllers').controller('createController', disableAnimate: true }); $state.go('tabs.home'); - $timeout(function() { + $timeout(function () { $state.transitionTo('tabs.copayers', { walletId: client.credentials.walletId }); diff --git a/www/views/tab-create-personal.html b/www/views/tab-create-personal.html index a9239241e0b..4a7bf10b838 100644 --- a/www/views/tab-create-personal.html +++ b/www/views/tab-create-personal.html @@ -10,13 +10,8 @@
@@ -48,70 +43,12 @@ -
- - Add a password - -
- Add an optional password to secure the recovery phrase - The recovery phrase could require a password to be imported -
-
- -
- - - -
-
- - - -
- -
- This password cannot be recovered. If the password is lost, there is no way you could recover your funds. -
- - - I have written it down - - @@ -123,13 +60,14 @@ For audit purposes -
- + + + + - - + \ No newline at end of file diff --git a/www/views/tab-create-shared.html b/www/views/tab-create-shared.html index 8567718b226..6f7a75ec9f6 100644 --- a/www/views/tab-create-shared.html +++ b/www/views/tab-create-shared.html @@ -10,23 +10,14 @@
@@ -44,8 +35,7 @@
Required number of signatures
- @@ -77,70 +67,12 @@ -
- - Add a password - -
- Add an optional password to secure the recovery phrase - The recovery phrase could require a password to be imported -
-
- -
- - - -
-
- - - -
- -
- This password cannot be recovered. If the password is lost, there is no way you could recover your funds. -
- - - I have written it down - - @@ -152,13 +84,14 @@ For audit purposes -
- + + + + - - + \ No newline at end of file From d9cafcd69ae37a6ae2149e942e0bd81fb42beb09 Mon Sep 17 00:00:00 2001 From: Gabriel Masclef Date: Tue, 23 Jan 2018 18:02:06 -0300 Subject: [PATCH 3/5] password removed from join wallet --- src/js/controllers/join.js | 45 ++++------------- www/views/join.html | 101 +++++-------------------------------- 2 files changed, 25 insertions(+), 121 deletions(-) diff --git a/src/js/controllers/join.js b/src/js/controllers/join.js index 661170e7a6e..afb19653d16 100644 --- a/src/js/controllers/join.js +++ b/src/js/controllers/join.js @@ -1,9 +1,9 @@ 'use strict'; angular.module('copayApp.controllers').controller('joinController', - function($scope, $rootScope, $timeout, $state, $ionicHistory, $ionicScrollDelegate, profileService, configService, storageService, applicationService, gettextCatalog, lodash, ledger, trezor, intelTEE, derivationPathHelper, ongoingProcess, walletService, $log, $stateParams, popupService, appConfigService) { + function ($scope, $rootScope, $timeout, $state, $ionicHistory, $ionicScrollDelegate, profileService, configService, storageService, applicationService, gettextCatalog, lodash, ledger, trezor, intelTEE, derivationPathHelper, ongoingProcess, walletService, $log, $stateParams, popupService, appConfigService) { - $scope.$on("$ionicView.beforeEnter", function(event, data) { + $scope.$on("$ionicView.beforeEnter", function (event, data) { var defaults = configService.getDefaults(); var config = configService.getSync(); $scope.formData = {}; @@ -12,45 +12,22 @@ angular.module('copayApp.controllers').controller('joinController', $scope.formData.account = 1; $scope.formData.secret = null; $scope.formData.coin = data.stateParams.coin; - resetPasswordFields(); updateSeedSourceSelect(); }); - $scope.showAdvChange = function() { + $scope.showAdvChange = function () { $scope.showAdv = !$scope.showAdv; $scope.encrypt = null; $scope.resizeView(); }; - $scope.checkPassword = function(pw1, pw2) { - if (pw1 && pw1.length > 0) { - if (pw2 && pw2.length > 0) { - if (pw1 == pw2) $scope.result = 'correct'; - else { - $scope.formData.passwordSaved = null; - $scope.result = 'incorrect'; - } - } else - $scope.result = null; - } else - $scope.result = null; - }; - - $scope.resizeView = function() { - $timeout(function() { + $scope.resizeView = function () { + $timeout(function () { $ionicScrollDelegate.resize(); }, 10); - resetPasswordFields(); - }; - - function resetPasswordFields() { - $scope.formData.passphrase = $scope.formData.createPassphrase = $scope.formData.passwordSaved = $scope.formData.repeatPassword = $scope.result = null; - $timeout(function() { - $scope.$apply(); - }); }; - $scope.onQrCodeScannedJoin = function(data) { + $scope.onQrCodeScannedJoin = function (data) { $scope.formData.secret = data; $scope.$apply(); }; @@ -100,7 +77,7 @@ angular.module('copayApp.controllers').controller('joinController', } }; - $scope.join = function() { + $scope.join = function () { var opts = { secret: $scope.formData.secret, @@ -175,7 +152,7 @@ angular.module('copayApp.controllers').controller('joinController', } // TODO: cannot currently join an intelTEE testnet wallet (need to detect from the secret) - src.getInfoForNewWallet(true, account, 'livenet', function(err, lopts) { + src.getInfoForNewWallet(true, account, 'livenet', function (err, lopts) { ongoingProcess.set('connecting' + $scope.formData.seedSource.id, false); if (err) { popupService.showAlert(gettextCatalog.getString('Error'), err); @@ -192,8 +169,8 @@ angular.module('copayApp.controllers').controller('joinController', function _join(opts) { ongoingProcess.set('joiningWallet', true); - $timeout(function() { - profileService.joinWallet(opts, function(err, client) { + $timeout(function () { + profileService.joinWallet(opts, function (err, client) { ongoingProcess.set('joiningWallet', false); if (err) { popupService.showAlert(gettextCatalog.getString('Error'), err); @@ -208,7 +185,7 @@ angular.module('copayApp.controllers').controller('joinController', disableAnimate: true }); $state.go('tabs.home'); - $timeout(function() { + $timeout(function () { $state.transitionTo('tabs.copayers', { walletId: client.credentials.walletId }); diff --git a/www/views/join.html b/www/views/join.html index 75b2dbf4e52..d8803140aab 100644 --- a/www/views/join.html +++ b/www/views/join.html @@ -14,11 +14,7 @@
@@ -28,12 +24,8 @@
- +
@@ -60,98 +52,33 @@
Wallet Key
- -
- + + + + - - + \ No newline at end of file From 0064370917f82f0a853da200fb344a0c1de3dbb9 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Tue, 23 Jan 2018 18:05:49 -0300 Subject: [PATCH 4/5] Adds warning modal for encrypt wallet --- src/js/services/onGoingProcess.js | 13 ++++ src/js/services/profileService.js | 106 ++++++++++++++++++++++-------- 2 files changed, 92 insertions(+), 27 deletions(-) diff --git a/src/js/services/onGoingProcess.js b/src/js/services/onGoingProcess.js index fe395350868..8623d69b866 100644 --- a/src/js/services/onGoingProcess.js +++ b/src/js/services/onGoingProcess.js @@ -6,6 +6,7 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti var isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP; var ongoingProcess = {}; + var pausedOngoingProcess = {}; var processNames = { 'broadcastingTx': gettext('Broadcasting transaction'), @@ -63,6 +64,18 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti return ongoingProcess[processName]; }; + root.pause = function() { + pausedOngoingProcess = ongoingProcess; + root.clear(); + } + + root.resume = function() { + lodash.forEach(pausedOngoingProcess, function(v, k) { + root.set(k, v); + }); + pausedOngoingProcess = {}; + } + root.set = function(processName, isOn, customHandler) { $log.debug('ongoingProcess', processName, isOn); root[processName] = isOn; diff --git a/src/js/services/profileService.js b/src/js/services/profileService.js index af6f43582d1..98c23a2f2dc 100644 --- a/src/js/services/profileService.js +++ b/src/js/services/profileService.js @@ -1,6 +1,6 @@ 'use strict'; angular.module('copayApp.services') - .factory('profileService', function profileServiceFactory($rootScope, $timeout, $filter, $log, $state, sjcl, lodash, storageService, bwcService, configService, gettextCatalog, bwcError, uxLanguage, platformInfo, txFormatService, appConfigService) { + .factory('profileService', function profileServiceFactory($rootScope, $timeout, $filter, $log, $state, sjcl, lodash, storageService, bwcService, configService, gettextCatalog, bwcError, uxLanguage, platformInfo, txFormatService, appConfigService, popupService, ongoingProcess) { var isChromeApp = platformInfo.isChromeApp; @@ -505,45 +505,97 @@ angular.module('copayApp.services') }); } + // An alert dialog + var askPassword = function(name, title, cb) { + var opts = { + inputType: 'password', + forceHTMLPrompt: true, + class: 'text-warn' + }; + popupService.showPrompt(title, name, opts, function(res) { + if (!res) return cb(); + if (res) return cb(res) + }); + }; + + var showWarningNoEncrypt = function(cb) { + var title = gettextCatalog.getString('Are you sure?'); + var msg = gettextCatalog.getString('Your wallet keys will be stored in plan text in this device, if an other app access the store it will be able to access your Bitcoin'); + var yes = gettextCatalog.getString('Yes'); + var no = gettextCatalog.getString('No'); + popupService.showConfirm(title, msg, yes, no, function(res) { + return cb(res); + }); + }; + + var encryptWallet = function(wallet, cb) { + + var title = gettextCatalog.getString('Please enter a password to encrypt your wallet keys on this device storage'); + var warnMsg = gettextCatalog.getString('Your wallet key will be encrypted. The Spending Password cannot be recovered. Be sure to write it down.'); + askPassword(warnMsg, title, function(password) { + if (!password) { + showWarningNoEncrypt(function(res) { + if (res) return cb() + return encryptWallet(wallet, cb); + }); + } else { + title = gettextCatalog.getString('Confirm your new spending password'); + askPassword(warnMsg, title, function(password2) { + if (!password2 || password != password2) + return encryptWallet(wallet, cb); + + wallet.encryptPrivateKey(password); + return cb(); + }); + } + }); + }; + // Adds and bind a new client to the profile var addAndBindWalletClient = function(client, opts, cb) { if (!client || !client.credentials) return cb(gettextCatalog.getString('Could not access wallet')); - var walletId = client.credentials.walletId + // Encrypt wallet + ongoingProcess.pause(); + encryptWallet(client, function() { + ongoingProcess.resume(); - if (!root.profile.addWallet(JSON.parse(client.export()))) - return cb(gettextCatalog.getString("Wallet already in {{appName}}", { - appName: appConfigService.nameCase - })); + var walletId = client.credentials.walletId + if (!root.profile.addWallet(JSON.parse(client.export()))) + return cb(gettextCatalog.getString("Wallet already in {{appName}}", { + appName: appConfigService.nameCase + })); - var skipKeyValidation = shouldSkipValidation(walletId); - if (!skipKeyValidation) - root.runValidation(client); - root.bindWalletClient(client); + var skipKeyValidation = shouldSkipValidation(walletId); + if (!skipKeyValidation) + root.runValidation(client); - var saveBwsUrl = function(cb) { - var defaults = configService.getDefaults(); - var bwsFor = {}; - bwsFor[walletId] = opts.bwsurl || defaults.bws.url; + root.bindWalletClient(client); - // Dont save the default - if (bwsFor[walletId] == defaults.bws.url) - return cb(); + var saveBwsUrl = function(cb) { + var defaults = configService.getDefaults(); + var bwsFor = {}; + bwsFor[walletId] = opts.bwsurl || defaults.bws.url; - configService.set({ - bwsFor: bwsFor, - }, function(err) { - if (err) $log.warn(err); - return cb(); - }); - }; + // Dont save the default + if (bwsFor[walletId] == defaults.bws.url) + return cb(); - saveBwsUrl(function() { - storageService.storeProfile(root.profile, function(err) { - return cb(err, client); + configService.set({ + bwsFor: bwsFor, + }, function(err) { + if (err) $log.warn(err); + return cb(); + }); + }; + + saveBwsUrl(function() { + storageService.storeProfile(root.profile, function(err) { + return cb(err, client); + }); }); }); }; From e3edbad4339e85d00c49f5d533c7efd97798e3fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Tue, 23 Jan 2018 18:09:20 -0300 Subject: [PATCH 5/5] Remove unused file --- src/js/controllers/onboarding/tour.js | 17 ----------------- www/views/modals/password-warning.html | 12 ------------ 2 files changed, 29 deletions(-) delete mode 100644 www/views/modals/password-warning.html diff --git a/src/js/controllers/onboarding/tour.js b/src/js/controllers/onboarding/tour.js index c821c3bcbcd..9e65d174243 100644 --- a/src/js/controllers/onboarding/tour.js +++ b/src/js/controllers/onboarding/tour.js @@ -76,23 +76,6 @@ angular.module('copayApp.controllers').controller('tourController', }, 300); }; - /* - $ionicModal.fromTemplateUrl('views/modals/password-warning.html', { - scope: $scope - }).then(function(modal) { - $scope.passwordWarningModal = modal; - $scope.passwordWarningModal.show(); - }); - /* - /* - $scope.close = function() { - $scope.passwordWarningModal.hide(); - }; - $scope.encrypt = function() { - - } - */ - $scope.goBack = function () { if ($scope.data.index != 0) $scope.slider.slidePrev(); else $state.go('onboarding.welcome'); diff --git a/www/views/modals/password-warning.html b/www/views/modals/password-warning.html deleted file mode 100644 index c55e17c2e15..00000000000 --- a/www/views/modals/password-warning.html +++ /dev/null @@ -1,12 +0,0 @@ - \ No newline at end of file