1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 00:33:44 +00:00

[PM-13876] replace angular validation with html constraints validation (#11816)

* rough-in passphrase validation failure handling

* trigger valid change from settings

* fix `max` constraint enforcement

* add taps for generator validation monitoring/debugging

* HTML constraints validation rises like a phoenix

* remove min/max boundaries to fix chrome display issue

* bind settings components as view children of options components

* remove defunct `okSettings$`

* extend validationless generator to passwords

* extend validationless generator to catchall emails

* extend validationless generator to forwarder emails

* extend validationless generator to subaddress emails

* extend validationless generator to usernames

* fix observable cycle

* disable generate button when no algorithm is selected

* prevent duplicate algorithm emissions

* add constraints that assign email address defaults
This commit is contained in:
✨ Audrey ✨
2024-11-06 11:54:29 -05:00
committed by GitHub
parent a9595b4d14
commit 414bdde232
30 changed files with 552 additions and 218 deletions

View File

@@ -22,11 +22,11 @@ import { Option } from "@bitwarden/components/src/select/option";
import {
CredentialGeneratorService,
Generators,
PasswordAlgorithm,
GeneratedCredential,
CredentialAlgorithm,
isPasswordAlgorithm,
AlgorithmInfo,
isSameAlgorithm,
} from "@bitwarden/generator-core";
import { GeneratorHistoryService } from "@bitwarden/generator-history";
@@ -57,7 +57,7 @@ export class PasswordGeneratorComponent implements OnInit, OnDestroy {
@Input({ transform: coerceBooleanProperty }) disableMargin = false;
/** tracks the currently selected credential type */
protected credentialType$ = new BehaviorSubject<PasswordAlgorithm>(null);
protected credentialType$ = new BehaviorSubject<CredentialAlgorithm>(null);
/** Emits the last generated value. */
protected readonly value$ = new BehaviorSubject<string>("");
@@ -72,14 +72,14 @@ export class PasswordGeneratorComponent implements OnInit, OnDestroy {
* @param requestor a label used to trace generation request
* origin in the debugger.
*/
protected generate(requestor: string) {
protected async generate(requestor: string) {
this.generate$.next(requestor);
}
/** Tracks changes to the selected credential type
* @param type the new credential type
*/
protected onCredentialTypeChanged(type: PasswordAlgorithm) {
protected onCredentialTypeChanged(type: CredentialAlgorithm) {
// break subscription cycle
if (this.credentialType$.value !== type) {
this.zone.run(() => {
@@ -169,29 +169,34 @@ export class PasswordGeneratorComponent implements OnInit, OnDestroy {
preferences.next(preference);
});
// populate the form with the user's preferences to kick off interactivity
preferences.pipe(takeUntil(this.destroyed)).subscribe(({ password }) => {
// update navigation
this.onCredentialTypeChanged(password.algorithm);
// load algorithm metadata
const algorithm = this.generatorService.algorithm(password.algorithm);
// update subjects within the angular zone so that the
// template bindings refresh immediately
this.zone.run(() => {
this.algorithm$.next(algorithm);
});
});
// generate on load unless the generator prohibits it
this.algorithm$
// update active algorithm
preferences
.pipe(
distinctUntilChanged((prev, next) => prev.id === next.id),
filter((a) => !a.onlyOnRequest),
map(({ password }) => this.generatorService.algorithm(password.algorithm)),
distinctUntilChanged((prev, next) => isSameAlgorithm(prev?.id, next?.id)),
takeUntil(this.destroyed),
)
.subscribe(() => this.generate("autogenerate"));
.subscribe((algorithm) => {
// update navigation
this.onCredentialTypeChanged(algorithm.id);
// update subjects within the angular zone so that the
// template bindings refresh immediately
this.zone.run(() => {
this.algorithm$.next(algorithm);
});
});
// generate on load unless the generator prohibits it
this.algorithm$.pipe(takeUntil(this.destroyed)).subscribe((a) => {
this.zone.run(() => {
if (!a || a.onlyOnRequest) {
this.value$.next("-");
} else {
this.generate("autogenerate").catch((e: unknown) => this.logService.error(e));
}
});
});
}
private typeToGenerator$(type: CredentialAlgorithm) {