From 255a7381b3cd7686d914abde248ea66e1f618e4f Mon Sep 17 00:00:00 2001 From: Daniel James Smith Date: Tue, 5 Sep 2023 21:48:34 +0200 Subject: [PATCH] [PM-3609] [Tech-Debt] Add types to password and username generator (#6090) * Create and use GeneratorOptions Selection between `password`and `username` * Use PasswordGeneratorOptions * Declare and use UsernameGeneratorOptions --- .../components/generator.component.ts | 17 +++++++++----- .../platform/abstractions/state.service.ts | 22 +++++++++++++------ .../src/platform/models/domain/account.ts | 13 +++++++---- .../src/platform/services/state.service.ts | 22 +++++++++++++------ .../src/tools/generator/generator-options.ts | 3 +++ .../src/tools/generator/password/index.ts | 1 + .../src/tools/generator/username/index.ts | 1 + .../username/username-generation-options.ts | 19 ++++++++++++++++ ...username-generation.service.abstraction.ts | 16 ++++++++------ .../username/username-generation.service.ts | 17 +++++++------- 10 files changed, 93 insertions(+), 38 deletions(-) create mode 100644 libs/common/src/tools/generator/generator-options.ts create mode 100644 libs/common/src/tools/generator/username/username-generation-options.ts diff --git a/libs/angular/src/tools/generator/components/generator.component.ts b/libs/angular/src/tools/generator/components/generator.component.ts index 9ef7318658..37904473ad 100644 --- a/libs/angular/src/tools/generator/components/generator.component.ts +++ b/libs/angular/src/tools/generator/components/generator.component.ts @@ -8,8 +8,15 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; -import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password"; -import { UsernameGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/username"; +import { GeneratorOptions } from "@bitwarden/common/tools/generator/generator-options"; +import { + PasswordGenerationServiceAbstraction, + PasswordGeneratorOptions, +} from "@bitwarden/common/tools/generator/password"; +import { + UsernameGenerationServiceAbstraction, + UsernameGeneratorOptions, +} from "@bitwarden/common/tools/generator/username"; @Directive() export class GeneratorComponent implements OnInit { @@ -24,8 +31,8 @@ export class GeneratorComponent implements OnInit { subaddressOptions: any[]; catchallOptions: any[]; forwardOptions: EmailForwarderOptions[]; - usernameOptions: any = {}; - passwordOptions: any = {}; + usernameOptions: UsernameGeneratorOptions = {}; + passwordOptions: PasswordGeneratorOptions = {}; username = "-"; password = "-"; showOptions = false; @@ -118,7 +125,7 @@ export class GeneratorComponent implements OnInit { } async typeChanged() { - await this.stateService.setGeneratorOptions({ type: this.type }); + await this.stateService.setGeneratorOptions({ type: this.type } as GeneratorOptions); if (this.regenerateWithoutButtonPress()) { await this.regenerate(); } diff --git a/libs/common/src/platform/abstractions/state.service.ts b/libs/common/src/platform/abstractions/state.service.ts index 82813718de..571dad6478 100644 --- a/libs/common/src/platform/abstractions/state.service.ts +++ b/libs/common/src/platform/abstractions/state.service.ts @@ -13,7 +13,9 @@ import { BiometricKey } from "../../auth/types/biometric-key"; import { KdfType, ThemeType, UriMatchType } from "../../enums"; import { EventData } from "../../models/data/event.data"; import { WindowState } from "../../models/domain/window-state"; -import { GeneratedPasswordHistory } from "../../tools/generator/password"; +import { GeneratorOptions } from "../../tools/generator/generator-options"; +import { GeneratedPasswordHistory, PasswordGeneratorOptions } from "../../tools/generator/password"; +import { UsernameGeneratorOptions } from "../../tools/generator/username"; import { SendData } from "../../tools/send/models/data/send.data"; import { SendView } from "../../tools/send/models/view/send.view"; import { CipherData } from "../../vault/models/data/cipher.data"; @@ -439,12 +441,18 @@ export abstract class StateService { value: { [id: string]: OrganizationData }, options?: StorageOptions ) => Promise; - getPasswordGenerationOptions: (options?: StorageOptions) => Promise; - setPasswordGenerationOptions: (value: any, options?: StorageOptions) => Promise; - getUsernameGenerationOptions: (options?: StorageOptions) => Promise; - setUsernameGenerationOptions: (value: any, options?: StorageOptions) => Promise; - getGeneratorOptions: (options?: StorageOptions) => Promise; - setGeneratorOptions: (value: any, options?: StorageOptions) => Promise; + getPasswordGenerationOptions: (options?: StorageOptions) => Promise; + setPasswordGenerationOptions: ( + value: PasswordGeneratorOptions, + options?: StorageOptions + ) => Promise; + getUsernameGenerationOptions: (options?: StorageOptions) => Promise; + setUsernameGenerationOptions: ( + value: UsernameGeneratorOptions, + options?: StorageOptions + ) => Promise; + getGeneratorOptions: (options?: StorageOptions) => Promise; + setGeneratorOptions: (value: GeneratorOptions, options?: StorageOptions) => Promise; /** * Gets the user's Pin, encrypted by the user key */ diff --git a/libs/common/src/platform/models/domain/account.ts b/libs/common/src/platform/models/domain/account.ts index 09dc6971dc..6d85d6501f 100644 --- a/libs/common/src/platform/models/domain/account.ts +++ b/libs/common/src/platform/models/domain/account.ts @@ -14,7 +14,12 @@ import { TrustedDeviceUserDecryptionOption } from "../../../auth/models/domain/u import { IdentityTokenResponse } from "../../../auth/models/response/identity-token.response"; import { KdfType, UriMatchType } from "../../../enums"; import { EventData } from "../../../models/data/event.data"; -import { GeneratedPasswordHistory } from "../../../tools/generator/password"; +import { GeneratorOptions } from "../../../tools/generator/generator-options"; +import { + GeneratedPasswordHistory, + PasswordGeneratorOptions, +} from "../../../tools/generator/password"; +import { UsernameGeneratorOptions } from "../../../tools/generator/username/username-generation-options"; import { SendData } from "../../../tools/send/models/data/send.data"; import { SendView } from "../../../tools/send/models/view/send.view"; import { DeepJsonify } from "../../../types/deep-jsonify"; @@ -235,9 +240,9 @@ export class AccountSettings { equivalentDomains?: any; minimizeOnCopyToClipboard?: boolean; neverDomains?: { [id: string]: any }; - passwordGenerationOptions?: any; - usernameGenerationOptions?: any; - generatorOptions?: any; + passwordGenerationOptions?: PasswordGeneratorOptions; + usernameGenerationOptions?: UsernameGeneratorOptions; + generatorOptions?: GeneratorOptions; pinKeyEncryptedUserKey?: EncryptedString; pinKeyEncryptedUserKeyEphemeral?: EncryptedString; protectedPin?: string; diff --git a/libs/common/src/platform/services/state.service.ts b/libs/common/src/platform/services/state.service.ts index 5fdf40e845..d0983448d6 100644 --- a/libs/common/src/platform/services/state.service.ts +++ b/libs/common/src/platform/services/state.service.ts @@ -22,7 +22,9 @@ import { VaultTimeoutAction } from "../../enums/vault-timeout-action.enum"; import { EventData } from "../../models/data/event.data"; import { WindowState } from "../../models/domain/window-state"; import { migrate } from "../../state-migrations"; -import { GeneratedPasswordHistory } from "../../tools/generator/password"; +import { GeneratorOptions } from "../../tools/generator/generator-options"; +import { GeneratedPasswordHistory, PasswordGeneratorOptions } from "../../tools/generator/password"; +import { UsernameGeneratorOptions } from "../../tools/generator/username"; import { SendData } from "../../tools/send/models/data/send.data"; import { SendView } from "../../tools/send/models/view/send.view"; import { CipherData } from "../../vault/models/data/cipher.data"; @@ -2367,13 +2369,16 @@ export class StateService< ); } - async getPasswordGenerationOptions(options?: StorageOptions): Promise { + async getPasswordGenerationOptions(options?: StorageOptions): Promise { return ( await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) )?.settings?.passwordGenerationOptions; } - async setPasswordGenerationOptions(value: any, options?: StorageOptions): Promise { + async setPasswordGenerationOptions( + value: PasswordGeneratorOptions, + options?: StorageOptions + ): Promise { const account = await this.getAccount( this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) ); @@ -2384,13 +2389,16 @@ export class StateService< ); } - async getUsernameGenerationOptions(options?: StorageOptions): Promise { + async getUsernameGenerationOptions(options?: StorageOptions): Promise { return ( await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) )?.settings?.usernameGenerationOptions; } - async setUsernameGenerationOptions(value: any, options?: StorageOptions): Promise { + async setUsernameGenerationOptions( + value: UsernameGeneratorOptions, + options?: StorageOptions + ): Promise { const account = await this.getAccount( this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) ); @@ -2401,13 +2409,13 @@ export class StateService< ); } - async getGeneratorOptions(options?: StorageOptions): Promise { + async getGeneratorOptions(options?: StorageOptions): Promise { return ( await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) )?.settings?.generatorOptions; } - async setGeneratorOptions(value: any, options?: StorageOptions): Promise { + async setGeneratorOptions(value: GeneratorOptions, options?: StorageOptions): Promise { const account = await this.getAccount( this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) ); diff --git a/libs/common/src/tools/generator/generator-options.ts b/libs/common/src/tools/generator/generator-options.ts new file mode 100644 index 0000000000..4f8eb293ab --- /dev/null +++ b/libs/common/src/tools/generator/generator-options.ts @@ -0,0 +1,3 @@ +export type GeneratorOptions = { + type?: "password" | "username"; +}; diff --git a/libs/common/src/tools/generator/password/index.ts b/libs/common/src/tools/generator/password/index.ts index 4dafe20d3a..bacc2c0c70 100644 --- a/libs/common/src/tools/generator/password/index.ts +++ b/libs/common/src/tools/generator/password/index.ts @@ -1,3 +1,4 @@ +export { PasswordGeneratorOptions } from "./password-generator-options"; export { PasswordGenerationServiceAbstraction } from "./password-generation.service.abstraction"; export { PasswordGenerationService } from "./password-generation.service"; export { GeneratedPasswordHistory } from "./generated-password-history"; diff --git a/libs/common/src/tools/generator/username/index.ts b/libs/common/src/tools/generator/username/index.ts index b4f73a29ed..c4197b4344 100644 --- a/libs/common/src/tools/generator/username/index.ts +++ b/libs/common/src/tools/generator/username/index.ts @@ -1,2 +1,3 @@ +export { UsernameGeneratorOptions } from "./username-generation-options"; export { UsernameGenerationServiceAbstraction } from "./username-generation.service.abstraction"; export { UsernameGenerationService } from "./username-generation.service"; diff --git a/libs/common/src/tools/generator/username/username-generation-options.ts b/libs/common/src/tools/generator/username/username-generation-options.ts new file mode 100644 index 0000000000..96b6e2ef1b --- /dev/null +++ b/libs/common/src/tools/generator/username/username-generation-options.ts @@ -0,0 +1,19 @@ +export type UsernameGeneratorOptions = { + type?: "word" | "subaddress" | "catchall" | "forwarded"; + wordCapitalize?: boolean; + wordIncludeNumber?: boolean; + subaddressType?: "random" | "website-name"; + subaddressEmail?: string; + catchallType?: "random" | "website-name"; + catchallDomain?: string; + website?: string; + forwardedService?: string; + forwardedAnonAddyApiToken?: string; + forwardedAnonAddyDomain?: string; + forwardedDuckDuckGoToken?: string; + forwardedFirefoxApiToken?: string; + forwardedFastmailApiToken?: string; + forwardedForwardEmailApiToken?: string; + forwardedForwardEmailDomain?: string; + forwardedSimpleLoginApiKey?: string; +}; diff --git a/libs/common/src/tools/generator/username/username-generation.service.abstraction.ts b/libs/common/src/tools/generator/username/username-generation.service.abstraction.ts index 52accf7d8c..05affef0e2 100644 --- a/libs/common/src/tools/generator/username/username-generation.service.abstraction.ts +++ b/libs/common/src/tools/generator/username/username-generation.service.abstraction.ts @@ -1,9 +1,11 @@ +import { UsernameGeneratorOptions } from "./username-generation-options"; + export abstract class UsernameGenerationServiceAbstraction { - generateUsername: (options: any) => Promise; - generateWord: (options: any) => Promise; - generateSubaddress: (options: any) => Promise; - generateCatchall: (options: any) => Promise; - generateForwarded: (options: any) => Promise; - getOptions: () => Promise; - saveOptions: (options: any) => Promise; + generateUsername: (options: UsernameGeneratorOptions) => Promise; + generateWord: (options: UsernameGeneratorOptions) => Promise; + generateSubaddress: (options: UsernameGeneratorOptions) => Promise; + generateCatchall: (options: UsernameGeneratorOptions) => Promise; + generateForwarded: (options: UsernameGeneratorOptions) => Promise; + getOptions: () => Promise; + saveOptions: (options: UsernameGeneratorOptions) => Promise; } diff --git a/libs/common/src/tools/generator/username/username-generation.service.ts b/libs/common/src/tools/generator/username/username-generation.service.ts index 3ff9884331..b1fed147db 100644 --- a/libs/common/src/tools/generator/username/username-generation.service.ts +++ b/libs/common/src/tools/generator/username/username-generation.service.ts @@ -13,9 +13,10 @@ import { ForwarderOptions, SimpleLoginForwarder, } from "./email-forwarders"; +import { UsernameGeneratorOptions } from "./username-generation-options"; import { UsernameGenerationServiceAbstraction } from "./username-generation.service.abstraction"; -const DefaultOptions = { +const DefaultOptions: UsernameGeneratorOptions = { type: "word", wordCapitalize: true, wordIncludeNumber: true, @@ -33,7 +34,7 @@ export class UsernameGenerationService implements UsernameGenerationServiceAbstr private apiService: ApiService ) {} - generateUsername(options: any): Promise { + generateUsername(options: UsernameGeneratorOptions): Promise { if (options.type === "catchall") { return this.generateCatchall(options); } else if (options.type === "subaddress") { @@ -45,7 +46,7 @@ export class UsernameGenerationService implements UsernameGenerationServiceAbstr } } - async generateWord(options: any): Promise { + async generateWord(options: UsernameGeneratorOptions): Promise { const o = Object.assign({}, DefaultOptions, options); if (o.wordCapitalize == null) { @@ -67,7 +68,7 @@ export class UsernameGenerationService implements UsernameGenerationServiceAbstr return word; } - async generateSubaddress(options: any): Promise { + async generateSubaddress(options: UsernameGeneratorOptions): Promise { const o = Object.assign({}, DefaultOptions, options); const subaddressEmail = o.subaddressEmail; @@ -94,7 +95,7 @@ export class UsernameGenerationService implements UsernameGenerationServiceAbstr return emailBeginning + "+" + subaddressString + "@" + emailEnding; } - async generateCatchall(options: any): Promise { + async generateCatchall(options: UsernameGeneratorOptions): Promise { const o = Object.assign({}, DefaultOptions, options); if (o.catchallDomain == null || o.catchallDomain === "") { @@ -113,7 +114,7 @@ export class UsernameGenerationService implements UsernameGenerationServiceAbstr return startString + "@" + o.catchallDomain; } - async generateForwarded(options: any): Promise { + async generateForwarded(options: UsernameGeneratorOptions): Promise { const o = Object.assign({}, DefaultOptions, options); if (o.forwardedService == null) { @@ -152,7 +153,7 @@ export class UsernameGenerationService implements UsernameGenerationServiceAbstr return forwarder.generate(this.apiService, forwarderOptions); } - async getOptions(): Promise { + async getOptions(): Promise { let options = await this.stateService.getUsernameGenerationOptions(); if (options == null) { options = Object.assign({}, DefaultOptions); @@ -163,7 +164,7 @@ export class UsernameGenerationService implements UsernameGenerationServiceAbstr return options; } - async saveOptions(options: any) { + async saveOptions(options: UsernameGeneratorOptions) { await this.stateService.setUsernameGenerationOptions(options); }