Skip to content

Commit

Permalink
extend validationless generator to catchall emails
Browse files Browse the repository at this point in the history
  • Loading branch information
audreyality committed Nov 1, 2024
1 parent 9b79bdb commit 1942a92
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<form class="box" [formGroup]="settings" class="tw-container">
<bit-form-field>
<bit-label>{{ "domainName" | i18n }}</bit-label>
<input bitInput formControlName="catchallDomain" type="text" />
<input bitInput formControlName="catchallDomain" type="text" (change)="(catchallDomain)" />
</bit-form-field>
</form>
45 changes: 40 additions & 5 deletions libs/tools/generator/components/src/catchall-settings.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { BehaviorSubject, skip, Subject, takeUntil } from "rxjs";
import { BehaviorSubject, map, skip, Subject, takeUntil, withLatestFrom } from "rxjs";

import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { UserId } from "@bitwarden/common/types/guid";
Expand All @@ -12,6 +12,11 @@ import {

import { completeOnAccountSwitch } from "./util";

/** Splits an email into a username, subaddress, and domain named group.
* Subaddress is optional.
*/
export const DOMAIN_PARSER = new RegExp("[^@]+@(?<domain>.+)");

/** Options group for catchall emails */
@Component({
selector: "tools-catchall-settings",
Expand Down Expand Up @@ -53,14 +58,43 @@ export class CatchallSettingsComponent implements OnInit, OnDestroy {
const singleUserId$ = this.singleUserId$();
const settings = await this.generatorService.settings(Generators.catchall, { singleUserId$ });

settings.pipe(takeUntil(this.destroyed$)).subscribe((s) => {
this.settings.patchValue(s, { emitEvent: false });
});
settings
.pipe(
withLatestFrom(this.accountService.activeAccount$),
map(([settings, activeAccount]) => {
// if the subaddress isn't specified, copy it from
// the user's settings
if ((settings.catchallDomain ?? "").trim().length < 1) {
const parsed = DOMAIN_PARSER.exec(activeAccount.email);
if (parsed) {
settings.catchallDomain = parsed.groups.domain;
}
}

return settings;
}),
takeUntil(this.destroyed$),
)
.subscribe((s) => {
this.settings.patchValue(s, { emitEvent: false });
});

// the first emission is the current value; subsequent emissions are updates
settings.pipe(skip(1), takeUntil(this.destroyed$)).subscribe(this.onUpdated);

this.settings.valueChanges.pipe(takeUntil(this.destroyed$)).subscribe(settings);
// now that outputs are set up, connect inputs
this.saveSettings
.pipe(
withLatestFrom(this.settings.valueChanges),
map(([, settings]) => settings),
takeUntil(this.destroyed$),
)
.subscribe(settings);
}

private saveSettings = new Subject<string>();
save(site: string = "component api call") {
this.saveSettings.next(site);
}

private singleUserId$() {
Expand All @@ -78,6 +112,7 @@ export class CatchallSettingsComponent implements OnInit, OnDestroy {

private readonly destroyed$ = new Subject<void>();
ngOnDestroy(): void {
this.destroyed$.next();
this.destroyed$.complete();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,10 @@ export class CredentialGeneratorComponent implements OnInit, OnDestroy {
await this.passwordComponent.save("credential generator");
}

if (this.catchallComponent) {
await this.catchallComponent.save("credential generator");
}

this.generate$.next(requestor);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,15 @@ export class PasswordGeneratorComponent implements OnInit, OnDestroy {
});

// generate on load unless the generator prohibits it
this.algorithm$
.pipe(
distinctUntilChanged((prev, next) => prev.id === next.id),
filter((a) => !a.onlyOnRequest),
takeUntil(this.destroyed),
)
.subscribe(() => this.generate("autogenerate"));
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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class SubaddressSettingsComponent implements OnInit, OnDestroy {
map(([settings, activeAccount]) => {
// if the subaddress isn't specified, copy it from
// the user's settings
if ((settings.subaddressEmail ?? "").length < 1) {
if ((settings.subaddressEmail ?? "").trim().length < 1) {
settings.subaddressEmail = activeAccount.email;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ export class UsernameGeneratorComponent implements OnInit, OnDestroy {
if (!a || a.onlyOnRequest) {
this.value$.next("-");
} else {
this.generate("autogenerate");
this.generate("autogenerate").catch((e: unknown) => this.logService.error(e));
}
});
});
Expand Down Expand Up @@ -440,7 +440,11 @@ export class UsernameGeneratorComponent 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) {
if (this.catchallComponent) {
await this.catchallComponent.save("credential generator");
}

this.generate$.next(requestor);
}

Expand All @@ -455,6 +459,7 @@ export class UsernameGeneratorComponent implements OnInit, OnDestroy {

private readonly destroyed = new Subject<void>();
ngOnDestroy() {
this.destroyed.next();
this.destroyed.complete();

// finalize subjects
Expand Down

0 comments on commit 1942a92

Please sign in to comment.