mirror of
https://github.com/bitwarden/browser
synced 2025-12-12 14:23:32 +00:00
Generate andcopy passwords. Save password options
This commit is contained in:
@@ -6,6 +6,7 @@ var siteService = new SiteService(cryptoService, userService, apiService);
|
|||||||
var folderService = new FolderService(cryptoService, userService, apiService);
|
var folderService = new FolderService(cryptoService, userService, apiService);
|
||||||
var syncService = new SyncService(siteService, folderService, userService, apiService);
|
var syncService = new SyncService(siteService, folderService, userService, apiService);
|
||||||
var autofillService = new AutofillService();
|
var autofillService = new AutofillService();
|
||||||
|
var passwordGenerationService = new PasswordGenerationService();
|
||||||
|
|
||||||
function buildContextMenu() {
|
function buildContextMenu() {
|
||||||
chrome.contextMenus.removeAll();
|
chrome.contextMenus.removeAll();
|
||||||
|
|||||||
@@ -89,7 +89,7 @@
|
|||||||
templateUrl: 'app/vault/views/vaultAddSite.html',
|
templateUrl: 'app/vault/views/vaultAddSite.html',
|
||||||
controller: 'vaultAddSiteController',
|
controller: 'vaultAddSiteController',
|
||||||
data: { authorize: true },
|
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', {
|
.state('editSite', {
|
||||||
url: '/edit-site?siteId',
|
url: '/edit-site?siteId',
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
templateUrl: 'app/tools/views/toolsPasswordGenerator.html',
|
templateUrl: 'app/tools/views/toolsPasswordGenerator.html',
|
||||||
controller: 'toolsPasswordGeneratorController',
|
controller: 'toolsPasswordGeneratorController',
|
||||||
data: { authorize: true },
|
data: { authorize: true },
|
||||||
params: { animation: null, fromAdd: false, fromEdit: null }
|
params: { animation: null, addState: null, editState: null }
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.run(function ($rootScope, userService, loginService, tokenService, $state) {
|
.run(function ($rootScope, userService, loginService, tokenService, $state) {
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
angular
|
angular
|
||||||
.module('bit.tools', []);
|
.module('bit.tools', ['ngAnimate', 'ngclipboard', 'toastr']);
|
||||||
|
|||||||
@@ -1,6 +1,63 @@
|
|||||||
angular
|
angular
|
||||||
.module('bit.tools')
|
.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();
|
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'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,15 +9,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div style="margin: 20px; font-size: 20px; text-align: center;">
|
<div style="margin: 20px; font-size: 20px; text-align: center;">
|
||||||
<span id="generated-password">*&Houhdasdy87</span>
|
<span id="generated-password">{{password}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="list" style="margin-top: 0;">
|
<div class="list" style="margin-top: 0;">
|
||||||
<div class="list-section" style="padding-top: 0;">
|
<div class="list-section" style="padding-top: 0;">
|
||||||
<div class="list-section-items">
|
<div class="list-section-items">
|
||||||
<a class="list-section-item" href="#">
|
<a class="list-section-item text-primary" href="" ng-click="regenerate()">
|
||||||
Regenerate Password
|
Regenerate Password
|
||||||
</a>
|
</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
|
Copy Password
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -32,19 +33,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="list-section-item list-section-item-checkbox">
|
<div class="list-section-item list-section-item-checkbox">
|
||||||
<label for="uppercase">A-Z</label>
|
<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>
|
||||||
<div class="list-section-item list-section-item-checkbox">
|
<div class="list-section-item list-section-item-checkbox">
|
||||||
<label for="lowercase">a-z</label>
|
<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>
|
||||||
<div class="list-section-item list-section-item-checkbox">
|
<div class="list-section-item list-section-item-checkbox">
|
||||||
<label for="numbers">0-9</label>
|
<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>
|
||||||
<div class="list-section-item list-section-item-checkbox">
|
<div class="list-section-item list-section-item-checkbox">
|
||||||
<label for="special">!@#$%^&*</label>
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -52,11 +53,11 @@
|
|||||||
<div class="list-section-items">
|
<div class="list-section-items">
|
||||||
<div class="list-section-item list-section-item-input">
|
<div class="list-section-item list-section-item-input">
|
||||||
<label for="min-numbers">Minimum Numbers</label>
|
<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>
|
||||||
<div class="list-section-item list-section-item-input">
|
<div class="list-section-item list-section-item-input">
|
||||||
<label for="min-special">Minimum Special</label>
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -64,7 +65,7 @@
|
|||||||
<div class="list-section-items">
|
<div class="list-section-items">
|
||||||
<div class="list-section-item list-section-item-checkbox">
|
<div class="list-section-item list-section-item-checkbox">
|
||||||
<label for="ambiguous">Avoid Ambiguous Characters</label>
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -200,6 +200,10 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
|
&.text-primary {
|
||||||
|
color: @brand-primary !important;
|
||||||
|
}
|
||||||
|
|
||||||
&:not(.wrap) {
|
&:not(.wrap) {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -24,6 +24,9 @@
|
|||||||
}
|
}
|
||||||
else if (checkbox.length > 0) {
|
else if (checkbox.length > 0) {
|
||||||
checkbox.prop('checked', !checkbox.is(':checked'));
|
checkbox.prop('checked', !checkbox.is(':checked'));
|
||||||
|
if (angular) {
|
||||||
|
angular.element(checkbox[0]).triggerHandler('click');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (select.length > 0) {
|
else if (select.length > 0) {
|
||||||
select.openSelect();
|
select.openSelect();
|
||||||
|
|||||||
@@ -1,24 +1,27 @@
|
|||||||
function PasswordGenerationService() {
|
function PasswordGenerationService() {
|
||||||
|
this.optionsCache = null;
|
||||||
|
|
||||||
initPasswordGenerationService();
|
initPasswordGenerationService();
|
||||||
};
|
};
|
||||||
|
|
||||||
function initPasswordGenerationService() {
|
function initPasswordGenerationService() {
|
||||||
PasswordGenerationService.prototype.generatePassword = function (options) {
|
var optionsKey = 'passwordGenerationOptions';
|
||||||
var defaults = {
|
var defaultOptions = {
|
||||||
length: 10,
|
length: 10,
|
||||||
ambiguous: false,
|
ambiguous: false,
|
||||||
number: true,
|
number: true,
|
||||||
minNumber: 1,
|
minNumber: 1,
|
||||||
uppercase: true,
|
uppercase: true,
|
||||||
minUppercase: 1,
|
minUppercase: 1,
|
||||||
lowercase: true,
|
lowercase: true,
|
||||||
minLowercase: 1,
|
minLowercase: 1,
|
||||||
special: false,
|
special: false,
|
||||||
minSpecial: 1
|
minSpecial: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PasswordGenerationService.prototype.generatePassword = function (options) {
|
||||||
// overload defaults with given options
|
// overload defaults with given options
|
||||||
var o = angular.extend({}, defaults, options);
|
var o = extend({}, defaultOptions, options);
|
||||||
|
|
||||||
// sanitize
|
// sanitize
|
||||||
if (o.uppercase && o.minUppercase < 0) o.minUppercase = 1;
|
if (o.uppercase && o.minUppercase < 0) o.minUppercase = 1;
|
||||||
@@ -99,4 +102,52 @@ function initPasswordGenerationService() {
|
|||||||
function randomInt(min, max) {
|
function randomInt(min, max) {
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
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;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user