From 350d671c2646a4a99564fa25aaf5b81fb315bdff Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Sat, 17 Sep 2016 22:57:51 -0400 Subject: [PATCH] Generate andcopy passwords. Save password options --- src/background.js | 1 + src/popup/app/config.js | 4 +- src/popup/app/tools/toolsModule.js | 2 +- .../tools/toolsPasswordGeneratorController.js | 59 +++++++++++++- .../tools/views/toolsPasswordGenerator.html | 21 ++--- src/popup/less/components.less | 4 + src/popup/scripts/popup.js | 3 + src/services/passwordGenerationService.js | 79 +++++++++++++++---- 8 files changed, 145 insertions(+), 28 deletions(-) diff --git a/src/background.js b/src/background.js index 05164b545f..bb4c7a44a5 100644 --- a/src/background.js +++ b/src/background.js @@ -6,6 +6,7 @@ var siteService = new SiteService(cryptoService, userService, apiService); var folderService = new FolderService(cryptoService, userService, apiService); var syncService = new SyncService(siteService, folderService, userService, apiService); var autofillService = new AutofillService(); +var passwordGenerationService = new PasswordGenerationService(); function buildContextMenu() { chrome.contextMenus.removeAll(); diff --git a/src/popup/app/config.js b/src/popup/app/config.js index d7dfe4f5d4..ad28d712d5 100644 --- a/src/popup/app/config.js +++ b/src/popup/app/config.js @@ -89,7 +89,7 @@ templateUrl: 'app/vault/views/vaultAddSite.html', controller: 'vaultAddSiteController', data: { authorize: true }, - params: { animation: null, returnScrollY: 0, returnSearchText: null, name: null, uri: null } + params: { animation: null, returnScrollY: 0, returnSearchText: null, name: null, uri: null, site: null } }) .state('editSite', { url: '/edit-site?siteId', @@ -104,7 +104,7 @@ templateUrl: 'app/tools/views/toolsPasswordGenerator.html', controller: 'toolsPasswordGeneratorController', data: { authorize: true }, - params: { animation: null, fromAdd: false, fromEdit: null } + params: { animation: null, addState: null, editState: null } }); }) .run(function ($rootScope, userService, loginService, tokenService, $state) { diff --git a/src/popup/app/tools/toolsModule.js b/src/popup/app/tools/toolsModule.js index 510df97574..8b592b4357 100644 --- a/src/popup/app/tools/toolsModule.js +++ b/src/popup/app/tools/toolsModule.js @@ -1,2 +1,2 @@ angular - .module('bit.tools', []); + .module('bit.tools', ['ngAnimate', 'ngclipboard', 'toastr']); diff --git a/src/popup/app/tools/toolsPasswordGeneratorController.js b/src/popup/app/tools/toolsPasswordGeneratorController.js index 6f618f3c03..1d110f6904 100644 --- a/src/popup/app/tools/toolsPasswordGeneratorController.js +++ b/src/popup/app/tools/toolsPasswordGeneratorController.js @@ -1,6 +1,63 @@ angular .module('bit.tools') - .controller('toolsPasswordGeneratorController', function ($scope, $state, $stateParams) { + .controller('toolsPasswordGeneratorController', function ($scope, $state, $stateParams, passwordGenerationService, toastr, $q) { + var addState = $stateParams.addState, + editState = $stateParams.editState; + popupUtils.initListSectionItemListeners(); + $scope.password = '-'; + + $q.when(passwordGenerationService.getOptions()).then(function (options) { + $scope.options = options; + $scope.regenerate(); + }); + + $scope.regenerate = function () { + $scope.password = passwordGenerationService.generatePassword($scope.options); + }; + + $scope.saveOptions = function (options) { + if (!options.uppercase && !options.lowercase && !options.number && !options.special) { + options.lowercase = $scope.options.lowercase = true; + } + if (!options.minNumber) { + options.minNumber = $scope.options.minNumber = 0; + } + if (!options.minSpecial) { + options.minSpecial = $scope.options.minSpecial = 0; + } + + passwordGenerationService.saveOptions(options); + $scope.regenerate(); + }; + + $scope.clipboardError = function (e, password) { + toastr.info('Your web browser does not support easy clipboard copying. Copy it manually instead.'); + }; + + $scope.clipboardSuccess = function (e) { + e.clearSelection(); + toastr.info('Password copied!'); + }; + + $scope.close = function () { + if (addState) { + $state.go('addSite', { + animation: 'out-slide-down', + site: addState + }); + } + else if (editState) { + $state.go('editSite', { + animation: 'out-slide-down', + siteId: editState + }); + } + else { + $state.go('tabs.tools', { + animation: 'out-slide-down' + }); + } + }; }); diff --git a/src/popup/app/tools/views/toolsPasswordGenerator.html b/src/popup/app/tools/views/toolsPasswordGenerator.html index 8c99571154..603bd3c7ab 100644 --- a/src/popup/app/tools/views/toolsPasswordGenerator.html +++ b/src/popup/app/tools/views/toolsPasswordGenerator.html @@ -9,15 +9,16 @@
- *&Houhdasdy87 + {{password}}
- +
- +
- +
- +
@@ -52,11 +53,11 @@
- +
- +
@@ -64,7 +65,7 @@
- +
diff --git a/src/popup/less/components.less b/src/popup/less/components.less index 553c50aef7..fbcf565f71 100644 --- a/src/popup/less/components.less +++ b/src/popup/less/components.less @@ -200,6 +200,10 @@ position: relative; z-index: 1; + &.text-primary { + color: @brand-primary !important; + } + &:not(.wrap) { white-space: nowrap; overflow: hidden; diff --git a/src/popup/scripts/popup.js b/src/popup/scripts/popup.js index b22303e5b1..2b31276dbd 100644 --- a/src/popup/scripts/popup.js +++ b/src/popup/scripts/popup.js @@ -24,6 +24,9 @@ } else if (checkbox.length > 0) { checkbox.prop('checked', !checkbox.is(':checked')); + if (angular) { + angular.element(checkbox[0]).triggerHandler('click'); + } } else if (select.length > 0) { select.openSelect(); diff --git a/src/services/passwordGenerationService.js b/src/services/passwordGenerationService.js index b90f43cd80..bb74535b17 100644 --- a/src/services/passwordGenerationService.js +++ b/src/services/passwordGenerationService.js @@ -1,24 +1,27 @@ function PasswordGenerationService() { + this.optionsCache = null; + initPasswordGenerationService(); }; function initPasswordGenerationService() { - PasswordGenerationService.prototype.generatePassword = function (options) { - var defaults = { - length: 10, - ambiguous: false, - number: true, - minNumber: 1, - uppercase: true, - minUppercase: 1, - lowercase: true, - minLowercase: 1, - special: false, - minSpecial: 1 - }; + var optionsKey = 'passwordGenerationOptions'; + var defaultOptions = { + length: 10, + ambiguous: false, + number: true, + minNumber: 1, + uppercase: true, + minUppercase: 1, + lowercase: true, + minLowercase: 1, + special: false, + minSpecial: 1 + }; + PasswordGenerationService.prototype.generatePassword = function (options) { // overload defaults with given options - var o = angular.extend({}, defaults, options); + var o = extend({}, defaultOptions, options); // sanitize if (o.uppercase && o.minUppercase < 0) o.minUppercase = 1; @@ -99,4 +102,52 @@ function initPasswordGenerationService() { function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } + + function extend() { + for (var i = 1; i < arguments.length; i++) { + for (var key in arguments[i]) { + if (arguments[i].hasOwnProperty(key)) { + arguments[0][key] = arguments[i][key]; + } + } + } + + return arguments[0]; + } + + PasswordGenerationService.prototype.getOptions = function () { + var deferred = Q.defer(); + var self = this; + + if (self.optionsCache) { + deferred.resolve(self.optionsCache); + return deferred.promise; + } + + chrome.storage.local.get(optionsKey, function (obj) { + var options = obj[optionsKey]; + if (!options) { + options = defaultOptions; + } + + self.optionsCache = options; + deferred.resolve(self.optionsCache); + }); + + return deferred.promise; + }; + + PasswordGenerationService.prototype.saveOptions = function (options) { + var deferred = Q.defer(); + var self = this; + + var obj = {}; + obj[optionsKey] = options; + chrome.storage.local.set(obj, function () { + self.optionsCache = options; + deferred.resolve(); + }); + + return deferred.promise; + }; };