mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 01:03:35 +00:00
[PM-16792] [PM-16822] Encapsulate encryptor and state provision within UserStateSubject (#13195)
This commit is contained in:
@@ -1,12 +1,25 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { BehaviorSubject, distinctUntilChanged, firstValueFrom, map, switchMap } from "rxjs";
|
||||
import { Component, Input, OnChanges, SimpleChanges, OnInit, OnDestroy } from "@angular/core";
|
||||
import {
|
||||
BehaviorSubject,
|
||||
ReplaySubject,
|
||||
Subject,
|
||||
firstValueFrom,
|
||||
map,
|
||||
switchMap,
|
||||
takeUntil,
|
||||
} from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import {
|
||||
SemanticLogger,
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
} from "@bitwarden/common/tools/log";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { ButtonModule, DialogModule, DialogService } from "@bitwarden/components";
|
||||
import { GeneratorHistoryService } from "@bitwarden/generator-history";
|
||||
@@ -26,28 +39,66 @@ import { EmptyCredentialHistoryComponent } from "./empty-credential-history.comp
|
||||
EmptyCredentialHistoryComponent,
|
||||
],
|
||||
})
|
||||
export class CredentialGeneratorHistoryDialogComponent {
|
||||
export class CredentialGeneratorHistoryDialogComponent implements OnChanges, OnInit, OnDestroy {
|
||||
private readonly destroyed = new Subject<void>();
|
||||
protected readonly hasHistory$ = new BehaviorSubject<boolean>(false);
|
||||
protected readonly userId$ = new BehaviorSubject<UserId>(null);
|
||||
|
||||
constructor(
|
||||
private accountService: AccountService,
|
||||
private history: GeneratorHistoryService,
|
||||
private dialogService: DialogService,
|
||||
) {
|
||||
this.accountService.activeAccount$
|
||||
.pipe(
|
||||
takeUntilDestroyed(),
|
||||
map(({ id }) => id),
|
||||
distinctUntilChanged(),
|
||||
)
|
||||
.subscribe(this.userId$);
|
||||
private logService: LogService,
|
||||
) {}
|
||||
|
||||
this.userId$
|
||||
@Input()
|
||||
account: Account | null;
|
||||
|
||||
protected account$ = new ReplaySubject<Account>(1);
|
||||
|
||||
/** Send structured debug logs from the credential generator component
|
||||
* to the debugger console.
|
||||
*
|
||||
* @warning this may reveal sensitive information in plaintext.
|
||||
*/
|
||||
@Input()
|
||||
debug: boolean = false;
|
||||
|
||||
// this `log` initializer is overridden in `ngOnInit`
|
||||
private log: SemanticLogger = disabledSemanticLoggerProvider({});
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
const account = changes?.account;
|
||||
if (account?.previousValue?.id !== account?.currentValue?.id) {
|
||||
this.log.debug(
|
||||
{
|
||||
previousUserId: account?.previousValue?.id as UserId,
|
||||
currentUserId: account?.currentValue?.id as UserId,
|
||||
},
|
||||
"account input change detected",
|
||||
);
|
||||
this.account$.next(account.currentValue ?? this.account);
|
||||
}
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.log = ifEnabledSemanticLoggerProvider(this.debug, this.logService, {
|
||||
type: "CredentialGeneratorComponent",
|
||||
});
|
||||
|
||||
if (!this.account) {
|
||||
this.account = await firstValueFrom(this.accountService.activeAccount$);
|
||||
this.log.info(
|
||||
{ userId: this.account.id },
|
||||
"account not specified; using active account settings",
|
||||
);
|
||||
this.account$.next(this.account);
|
||||
}
|
||||
|
||||
this.account$
|
||||
.pipe(
|
||||
takeUntilDestroyed(),
|
||||
switchMap((id) => id && this.history.credentials$(id)),
|
||||
switchMap((account) => account.id && this.history.credentials$(account.id)),
|
||||
map((credentials) => credentials.length > 0),
|
||||
takeUntil(this.destroyed),
|
||||
)
|
||||
.subscribe(this.hasHistory$);
|
||||
}
|
||||
@@ -63,7 +114,14 @@ export class CredentialGeneratorHistoryDialogComponent {
|
||||
});
|
||||
|
||||
if (confirmed) {
|
||||
await this.history.clear(await firstValueFrom(this.userId$));
|
||||
await this.history.clear((await firstValueFrom(this.account$)).id);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroyed.next();
|
||||
this.destroyed.complete();
|
||||
|
||||
this.log.debug("component destroyed");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user