1
0
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:
Justin Baur
2022-10-18 13:03:09 -04:00
committed by GitHub
parent cf2d3f5382
commit 1d1986e5e3
19 changed files with 447 additions and 22 deletions

View File

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

View 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";
};

View File

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