diff --git a/js/controllers/profile.js b/js/controllers/profile.js index 92238910c..ff08185ee 100644 --- a/js/controllers/profile.js +++ b/js/controllers/profile.js @@ -4,6 +4,7 @@ angular.module('copayApp.controllers').controller('ProfileController', function( $scope.isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; $rootScope.title = 'Profile'; + $scope.hideAdv = true; $scope.downloadProfileBackup = function() { backupService.profileDownload($rootScope.iden); @@ -53,4 +54,17 @@ angular.module('copayApp.controllers').controller('ProfileController', function( }); }; + $scope.deleteProfile = function () { + identityService.deleteProfile(function (err, res) { + if (err) { + log.warn(err); + notification.error('Error', 'Could not delete profile'); + return; + } + $location.path('/'); + setTimeout(function () { + notification.error('Success', 'Profile successfully deleted'); + }, 1); + }); + }; }); diff --git a/js/models/Identity.js b/js/models/Identity.js index 23329ca77..5c2c9a2a1 100644 --- a/js/models/Identity.js +++ b/js/models/Identity.js @@ -307,6 +307,33 @@ Identity.prototype.store = function(opts, cb) { }); }; +/** + * @param {Object} opts + * @param {Function} cb + */ +Identity.prototype.remove = function(opts, cb) { + log.debug('Deleting profile'); + + var self = this; + opts = opts || {}; + + async.each(_.values(self.wallets), function(w, cb) { + w.close(); + self.storage.removeItem(Wallet.getStorageKey(w.getId()), function(err) { + if (err) return cb(err); + cb(); + }); + }, function (err) { + if (err) return cb(err); + + self.storage.removeItem(self.getId(), function(err) { + if (err) return cb(err); + self.emitAndKeepAlive('closed'); + return cb(); + }); + }); +}; + Identity.prototype._cleanUp = function() { // NOP }; diff --git a/js/services/identityService.js b/js/services/identityService.js index 6fb1cd0aa..94e6f1653 100644 --- a/js/services/identityService.js +++ b/js/services/identityService.js @@ -87,6 +87,10 @@ angular.module('copayApp.services') }); }; + root.deleteProfile = function (cb) { + $rootScope.iden.remove(null, cb); + }; + root.deleteWallet = function(w, cb) { $rootScope.iden.deleteWallet(w.id, cb); }; diff --git a/test/Identity.js b/test/Identity.js index 0e939f916..f46c72f0e 100644 --- a/test/Identity.js +++ b/test/Identity.js @@ -158,6 +158,76 @@ describe('Identity model', function() { }); }); + describe('#remove', function(done) { + it('should remove empty profile', function (done) { + var storage = sinon.stub(); + storage.setCredentials = sinon.stub(); + storage.removeItem = sinon.stub().yields(null); + + var opts = { + email: 'test@test.com', + password: '123', + network: { + testnet: { + url: 'https://test-insight.bitpay.com:443' + }, + livenet: { + url: 'https://insight.bitpay.com:443' + }, + }, + storage: storage, + }; + + var iden = new Identity(opts); + iden.remove(null, function (err, res) { + should.not.exist(err); + storage.removeItem.calledOnce.should.be.true; + storage.removeItem.getCall(0).args[0].should.equal(iden.getId()); + done(); + }); + }); + + it('should remove profile and wallets', function(done) { + var storage = sinon.stub(); + storage.setCredentials = sinon.stub(); + storage.removeItem = sinon.stub().yields(null); + + var opts = { + email: 'test@test.com', + password: '123', + network: { + testnet: { + url: 'https://test-insight.bitpay.com:443' + }, + livenet: { + url: 'https://insight.bitpay.com:443' + }, + }, + storage: storage, + }; + + var iden = new Identity(opts); + + _.each(_.range(3), function(i) { + var w = { + on: sinon.stub().yields(null), + getId: sinon.stub().returns('wallet' + i), + getName: sinon.stub().returns('wallet' + i), + close: sinon.stub(), + }; + iden.wallets[w.getId()] = w; + }); + + iden.remove(null, function(err, res) { + should.not.exist(err); + storage.removeItem.callCount.should.equal(4); + storage.removeItem.getCall(0).args[0].should.equal(Wallet.getStorageKey('wallet0')); + storage.removeItem.getCall(3).args[0].should.equal(iden.getId()); + done(); + }); + }); + }); + describe.skip('#storeWallet', function() { // TODO test storeWallet }); diff --git a/views/profile.html b/views/profile.html index a0d0a6160..85e07270a 100644 --- a/views/profile.html +++ b/views/profile.html @@ -37,6 +37,7 @@ +
@@ -94,4 +95,35 @@
+ +
+ +
+
+ + + Show + Hide + advanced options + + + +
+
+ +
+
+
+
+

+ Delete Profile +

+

Permanently delete this profile and all its wallets. WARNING: this action cannot be reversed.

+ Delete Profile + +
+
+
+