mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
feat(user-decryption-options) [PM-26413]: Remove ActiveUserState from UserDecryptionOptionsService (#16894)
* feat(user-decryption-options) [PM-26413]: Update UserDecryptionOptionsService and tests to use UserId-only APIs. * feat(user-decryption-options) [PM-26413]: Update InternalUserDecryptionOptionsService call sites to use UserId-only API. * feat(user-decryption-options) [PM-26413] Update userDecryptionOptions$ call sites to use the UserId-only API. * feat(user-decryption-options) [PM-26413]: Update additional call sites. * feat(user-decryption-options) [PM-26413]: Update dependencies and an additional call site. * feat(user-verification-service) [PM-26413]: Replace where allowed by unrestricted imports invocation of UserVerificationService.hasMasterPassword (deprecated) with UserDecryptionOptions.hasMasterPasswordById$. Additional work to complete as tech debt tracked in PM-27009. * feat(user-decryption-options) [PM-26413]: Update for non-null strict adherence. * feat(user-decryption-options) [PM-26413]: Update type safety and defensive returns. * chore(user-decryption-options) [PM-26413]: Comment cleanup. * feat(user-decryption-options) [PM-26413]: Update tests. * feat(user-decryption-options) [PM-26413]: Standardize null-checking on active account id for new API consumption. * feat(vault-timeout-settings-service) [PM-26413]: Add test cases to illustrate null active account from AccountService. * fix(fido2-user-verification-service-spec) [PM-26413]: Update test harness to use FakeAccountService. * fix(downstream-components) [PM-26413]: Prefer use of the getUserId operator in all authenticated contexts for user id provided to UserDecryptionOptionsService. --------- Co-authored-by: bnagawiecki <107435978+bnagawiecki@users.noreply.github.com>
This commit is contained in:
@@ -123,7 +123,9 @@ describe("WebSetInitialPasswordService", () => {
|
||||
|
||||
userDecryptionOptions = new UserDecryptionOptions({ hasMasterPassword: true });
|
||||
userDecryptionOptionsSubject = new BehaviorSubject(userDecryptionOptions);
|
||||
userDecryptionOptionsService.userDecryptionOptions$ = userDecryptionOptionsSubject;
|
||||
userDecryptionOptionsService.userDecryptionOptionsById$.mockReturnValue(
|
||||
userDecryptionOptionsSubject,
|
||||
);
|
||||
|
||||
setPasswordRequest = new SetPasswordRequest(
|
||||
credentials.newServerMasterKeyHash,
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { Component, OnInit, OnDestroy } from "@angular/core";
|
||||
import { firstValueFrom, from, lastValueFrom, map, Observable, Subject, takeUntil } from "rxjs";
|
||||
import { firstValueFrom, lastValueFrom, map, Observable, Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { UserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { HeaderModule } from "../../../layouts/header/header.module";
|
||||
@@ -42,8 +41,7 @@ export class AccountComponent implements OnInit, OnDestroy {
|
||||
constructor(
|
||||
private accountService: AccountService,
|
||||
private dialogService: DialogService,
|
||||
private userVerificationService: UserVerificationService,
|
||||
private configService: ConfigService,
|
||||
private userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
||||
private organizationService: OrganizationService,
|
||||
) {}
|
||||
|
||||
@@ -56,7 +54,7 @@ export class AccountComponent implements OnInit, OnDestroy {
|
||||
map((organizations) => organizations.some((o) => o.userIsManagedByOrganization === true)),
|
||||
);
|
||||
|
||||
const hasMasterPassword$ = from(this.userVerificationService.hasMasterPassword());
|
||||
const hasMasterPassword$ = this.userDecryptionOptionsService.hasMasterPasswordById$(userId);
|
||||
|
||||
this.showChangeEmail$ = hasMasterPassword$;
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import { firstValueFrom } from "rxjs";
|
||||
import { ChangePasswordComponent } from "@bitwarden/angular/auth/password-management/change-password";
|
||||
import { InputPasswordFlow } from "@bitwarden/auth/angular";
|
||||
import { UserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { CalloutModule } from "@bitwarden/components";
|
||||
import { I18nPipe } from "@bitwarden/ui-common";
|
||||
|
||||
@@ -24,12 +26,15 @@ export class PasswordSettingsComponent implements OnInit {
|
||||
constructor(
|
||||
private router: Router,
|
||||
private userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
|
||||
const userHasMasterPassword = await firstValueFrom(
|
||||
this.userDecryptionOptionsService.hasMasterPassword$,
|
||||
this.userDecryptionOptionsService.hasMasterPasswordById$(userId),
|
||||
);
|
||||
|
||||
if (!userHasMasterPassword) {
|
||||
await this.router.navigate(["/settings/security/two-factor"]);
|
||||
return;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
|
||||
import { UserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { ChangeKdfModule } from "../../../key-management/change-kdf/change-kdf.module";
|
||||
@@ -23,20 +22,28 @@ export class SecurityKeysComponent implements OnInit {
|
||||
showChangeKdf = true;
|
||||
|
||||
constructor(
|
||||
private userVerificationService: UserVerificationService,
|
||||
private userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
||||
private accountService: AccountService,
|
||||
private apiService: ApiService,
|
||||
private dialogService: DialogService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.showChangeKdf = await this.userVerificationService.hasMasterPassword();
|
||||
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
|
||||
this.showChangeKdf = await firstValueFrom(
|
||||
this.userDecryptionOptionsService.hasMasterPasswordById$(userId),
|
||||
);
|
||||
}
|
||||
|
||||
async viewUserApiKey() {
|
||||
const entityId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
|
||||
if (!entityId) {
|
||||
throw new Error("Active account not found");
|
||||
}
|
||||
|
||||
await ApiKeyComponent.open(this.dialogService, {
|
||||
data: {
|
||||
keyType: "user",
|
||||
@@ -55,6 +62,11 @@ export class SecurityKeysComponent implements OnInit {
|
||||
const entityId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
|
||||
if (!entityId) {
|
||||
throw new Error("Active account not found");
|
||||
}
|
||||
|
||||
await ApiKeyComponent.open(this.dialogService, {
|
||||
data: {
|
||||
keyType: "user",
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { Observable } from "rxjs";
|
||||
import { firstValueFrom, Observable } from "rxjs";
|
||||
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { UserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
|
||||
@@ -20,7 +22,8 @@ export class SecurityComponent implements OnInit {
|
||||
consolidatedSessionTimeoutComponent$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
private userVerificationService: UserVerificationService,
|
||||
private userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
||||
private accountService: AccountService,
|
||||
private configService: ConfigService,
|
||||
) {
|
||||
this.consolidatedSessionTimeoutComponent$ = this.configService.getFeatureFlag$(
|
||||
@@ -29,6 +32,9 @@ export class SecurityComponent implements OnInit {
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.showChangePassword = await this.userVerificationService.hasMasterPassword();
|
||||
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
|
||||
this.showChangePassword = userId
|
||||
? await firstValueFrom(this.userDecryptionOptionsService.hasMasterPasswordById$(userId))
|
||||
: false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,10 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy {
|
||||
combineLatest([
|
||||
this.organization$,
|
||||
resetPasswordPolicies$,
|
||||
this.userDecryptionOptionsService.userDecryptionOptions$,
|
||||
this.accountService.activeAccount$.pipe(
|
||||
getUserId,
|
||||
switchMap((userId) => this.userDecryptionOptionsService.userDecryptionOptionsById$(userId)),
|
||||
),
|
||||
managingOrg$,
|
||||
])
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
|
||||
Reference in New Issue
Block a user