Generate andcopy passwords. Save password options

This commit is contained in:
Kyle Spearrin 2016-09-17 22:57:51 -04:00
parent 4105d2b5ad
commit 350d671c26
8 changed files with 145 additions and 28 deletions

View File

@ -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();

View File

@ -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) {

View File

@ -1,2 +1,2 @@
angular
.module('bit.tools', []);
.module('bit.tools', ['ngAnimate', 'ngclipboard', 'toastr']);

View File

@ -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'
});
}
};
});

View File

@ -9,15 +9,16 @@
</div>
<div class="content">
<div style="margin: 20px; font-size: 20px; text-align: center;">
<span id="generated-password">*&Houhdasdy87</span>
<span id="generated-password">{{password}}</span>
</div>
<div class="list" style="margin-top: 0;">
<div class="list-section" style="padding-top: 0;">
<div class="list-section-items">
<a class="list-section-item" href="#">
<a class="list-section-item text-primary" href="" ng-click="regenerate()">
Regenerate Password
</a>
<a class="list-section-item" href="#">
<a class="list-section-item text-primary" href="" ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e)" data-clipboard-target="#generated-password">
Copy Password
</a>
</div>
@ -32,19 +33,19 @@
</div>
<div class="list-section-item list-section-item-checkbox">
<label for="uppercase">A-Z</label>
<input id="uppercase" type="checkbox">
<input id="uppercase" type="checkbox" ng-model="options.uppercase" ng-change="saveOptions(options)">
</div>
<div class="list-section-item list-section-item-checkbox">
<label for="lowercase">a-z</label>
<input id="lowercase" type="checkbox">
<input id="lowercase" type="checkbox" ng-model="options.lowercase" ng-change="saveOptions(options)">
</div>
<div class="list-section-item list-section-item-checkbox">
<label for="numbers">0-9</label>
<input id="numbers" type="checkbox">
<input id="numbers" type="checkbox" ng-model="options.number" ng-change="saveOptions(options)">
</div>
<div class="list-section-item list-section-item-checkbox">
<label for="special">!@#$%^&*</label>
<input id="special" type="checkbox">
<input id="special" type="checkbox" ng-model="options.special" ng-change="saveOptions(options)">
</div>
</div>
</div>
@ -52,11 +53,11 @@
<div class="list-section-items">
<div class="list-section-item list-section-item-input">
<label for="min-numbers">Minimum Numbers</label>
<input id="min-numbers" type="number" min="0" max="5">
<input id="min-numbers" type="number" min="0" max="5" ng-model="options.minNumber" ng-change="saveOptions(options)">
</div>
<div class="list-section-item list-section-item-input">
<label for="min-special">Minimum Special</label>
<input id="min-special" type="number" min="0" max="5">
<input id="min-special" type="number" min="0" max="5" ng-model="options.minSpecial" ng-change="saveOptions(options)">
</div>
</div>
</div>
@ -64,7 +65,7 @@
<div class="list-section-items">
<div class="list-section-item list-section-item-checkbox">
<label for="ambiguous">Avoid Ambiguous Characters</label>
<input id="ambiguous" type="checkbox">
<input id="ambiguous" type="checkbox" ng-model="options.ambiguous" ng-change="saveOptions(options)">
</div>
</div>
</div>

View File

@ -200,6 +200,10 @@
position: relative;
z-index: 1;
&.text-primary {
color: @brand-primary !important;
}
&:not(.wrap) {
white-space: nowrap;
overflow: hidden;

View File

@ -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();

View File

@ -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;
};
};