mirror of
https://github.com/bitwarden/browser
synced 2025-12-14 07:13:32 +00:00
[PS-817] Add Generate Password Shortcut to MV3 (#3575)
* Add generate command * Add JSDoc * Minor improvements * Remove unneeded comment * Make some properties optional * Remove main.background.ts changes * One more * Lint * Make all but length optional * Address PR feedback * Move generate command code to command * Address PR feedback * Use new alarm scheme * Let feature handle state keys Moves to a feature folder and creates clipboard-module level state handler functions. StateService is being paired down to storage routing, so we are handling storage specifics in-module. Co-authored-by: Justin Baur <justindbaur@users.noreply.github.com> Co-authored-by: Daniel Smith <djsmith85@users.noreply.github.com> * Missed some changes Co-authored-by: Matt Gibson <mgibson@bitwarden.com> Co-authored-by: Justin Baur <justindbaur@users.noreply.github.com> Co-authored-by: Daniel Smith <djsmith85@users.noreply.github.com>
This commit is contained in:
@@ -1,20 +1,24 @@
|
||||
import * as zxcvbn from "zxcvbn";
|
||||
|
||||
import { GeneratedPasswordHistory } from "../models/domain/generated-password-history";
|
||||
import { PasswordGeneratorOptions } from "../models/domain/password-generator-options";
|
||||
import { PasswordGeneratorPolicyOptions } from "../models/domain/password-generator-policy-options";
|
||||
|
||||
export abstract class PasswordGenerationService {
|
||||
generatePassword: (options: any) => Promise<string>;
|
||||
generatePassphrase: (options: any) => Promise<string>;
|
||||
getOptions: () => Promise<[any, PasswordGeneratorPolicyOptions]>;
|
||||
generatePassword: (options: PasswordGeneratorOptions) => Promise<string>;
|
||||
generatePassphrase: (options: PasswordGeneratorOptions) => Promise<string>;
|
||||
getOptions: () => Promise<[PasswordGeneratorOptions, PasswordGeneratorPolicyOptions]>;
|
||||
enforcePasswordGeneratorPoliciesOnOptions: (
|
||||
options: any
|
||||
) => Promise<[any, PasswordGeneratorPolicyOptions]>;
|
||||
options: PasswordGeneratorOptions
|
||||
) => Promise<[PasswordGeneratorOptions, PasswordGeneratorPolicyOptions]>;
|
||||
getPasswordGeneratorPolicyOptions: () => Promise<PasswordGeneratorPolicyOptions>;
|
||||
saveOptions: (options: any) => Promise<any>;
|
||||
saveOptions: (options: PasswordGeneratorOptions) => Promise<void>;
|
||||
getHistory: () => Promise<GeneratedPasswordHistory[]>;
|
||||
addHistory: (password: string) => Promise<any>;
|
||||
clear: (userId?: string) => Promise<any>;
|
||||
addHistory: (password: string) => Promise<void>;
|
||||
clear: (userId?: string) => Promise<void>;
|
||||
passwordStrength: (password: string, userInputs?: string[]) => zxcvbn.ZXCVBNResult;
|
||||
normalizeOptions: (options: any, enforcedPolicyOptions: PasswordGeneratorPolicyOptions) => void;
|
||||
normalizeOptions: (
|
||||
options: PasswordGeneratorOptions,
|
||||
enforcedPolicyOptions: PasswordGeneratorPolicyOptions
|
||||
) => void;
|
||||
}
|
||||
|
||||
17
libs/common/src/models/domain/password-generator-options.ts
Normal file
17
libs/common/src/models/domain/password-generator-options.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export type PasswordGeneratorOptions = {
|
||||
length?: number;
|
||||
ambiguous?: boolean;
|
||||
uppercase?: boolean;
|
||||
minUppercase?: number;
|
||||
lowercase?: boolean;
|
||||
minLowercase?: number;
|
||||
number?: boolean;
|
||||
minNumber?: number;
|
||||
special?: boolean;
|
||||
minSpecial?: number;
|
||||
numWords?: number;
|
||||
wordSeparator?: string;
|
||||
capitalize?: boolean;
|
||||
includeNumber?: boolean;
|
||||
type?: "password" | "passphrase";
|
||||
};
|
||||
@@ -9,10 +9,11 @@ import { PolicyType } from "../enums/policyType";
|
||||
import { EFFLongWordList } from "../misc/wordlist";
|
||||
import { EncString } from "../models/domain/enc-string";
|
||||
import { GeneratedPasswordHistory } from "../models/domain/generated-password-history";
|
||||
import { PasswordGeneratorOptions } from "../models/domain/password-generator-options";
|
||||
import { PasswordGeneratorPolicyOptions } from "../models/domain/password-generator-policy-options";
|
||||
import { Policy } from "../models/domain/policy";
|
||||
|
||||
const DefaultOptions = {
|
||||
const DefaultOptions: PasswordGeneratorOptions = {
|
||||
length: 14,
|
||||
ambiguous: false,
|
||||
number: true,
|
||||
@@ -39,7 +40,7 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
|
||||
private stateService: StateService
|
||||
) {}
|
||||
|
||||
async generatePassword(options: any): Promise<string> {
|
||||
async generatePassword(options: PasswordGeneratorOptions): Promise<string> {
|
||||
// overload defaults with given options
|
||||
const o = Object.assign({}, DefaultOptions, options);
|
||||
|
||||
@@ -145,7 +146,7 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
|
||||
return password;
|
||||
}
|
||||
|
||||
async generatePassphrase(options: any): Promise<string> {
|
||||
async generatePassphrase(options: PasswordGeneratorOptions): Promise<string> {
|
||||
const o = Object.assign({}, DefaultOptions, options);
|
||||
|
||||
if (o.numWords == null || o.numWords <= 2) {
|
||||
@@ -178,7 +179,7 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
|
||||
return wordList.join(o.wordSeparator);
|
||||
}
|
||||
|
||||
async getOptions(): Promise<[any, PasswordGeneratorPolicyOptions]> {
|
||||
async getOptions(): Promise<[PasswordGeneratorOptions, PasswordGeneratorPolicyOptions]> {
|
||||
let options = await this.stateService.getPasswordGenerationOptions();
|
||||
if (options == null) {
|
||||
options = Object.assign({}, DefaultOptions);
|
||||
@@ -192,8 +193,8 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
|
||||
}
|
||||
|
||||
async enforcePasswordGeneratorPoliciesOnOptions(
|
||||
options: any
|
||||
): Promise<[any, PasswordGeneratorPolicyOptions]> {
|
||||
options: PasswordGeneratorOptions
|
||||
): Promise<[PasswordGeneratorOptions, PasswordGeneratorPolicyOptions]> {
|
||||
let enforcedPolicyOptions = await this.getPasswordGeneratorPolicyOptions();
|
||||
if (enforcedPolicyOptions != null) {
|
||||
if (options.length < enforcedPolicyOptions.minLength) {
|
||||
@@ -340,7 +341,7 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
|
||||
return enforcedOptions;
|
||||
}
|
||||
|
||||
async saveOptions(options: any) {
|
||||
async saveOptions(options: PasswordGeneratorOptions) {
|
||||
await this.stateService.setPasswordGenerationOptions(options);
|
||||
}
|
||||
|
||||
@@ -363,7 +364,7 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
|
||||
: new Array<GeneratedPasswordHistory>();
|
||||
}
|
||||
|
||||
async addHistory(password: string): Promise<any> {
|
||||
async addHistory(password: string): Promise<void> {
|
||||
// Cannot add new history if no key is available
|
||||
const hasKey = await this.cryptoService.hasKey();
|
||||
if (!hasKey) {
|
||||
@@ -389,7 +390,7 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
|
||||
return await this.stateService.setEncryptedPasswordGenerationHistory(newHistory);
|
||||
}
|
||||
|
||||
async clear(userId?: string): Promise<any> {
|
||||
async clear(userId?: string): Promise<void> {
|
||||
await this.stateService.setEncryptedPasswordGenerationHistory(null, { userId: userId });
|
||||
await this.stateService.setDecryptedPasswordGenerationHistory(null, { userId: userId });
|
||||
}
|
||||
@@ -408,7 +409,10 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr
|
||||
return result;
|
||||
}
|
||||
|
||||
normalizeOptions(options: any, enforcedPolicyOptions: PasswordGeneratorPolicyOptions) {
|
||||
normalizeOptions(
|
||||
options: PasswordGeneratorOptions,
|
||||
enforcedPolicyOptions: PasswordGeneratorPolicyOptions
|
||||
) {
|
||||
options.minLowercase = 0;
|
||||
options.minUppercase = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user