diff --git a/apps/desktop/src/app/app-routing.module.ts b/apps/desktop/src/app/app-routing.module.ts index 5ea2f0bb1e3..536a6b95779 100644 --- a/apps/desktop/src/app/app-routing.module.ts +++ b/apps/desktop/src/app/app-routing.module.ts @@ -49,6 +49,7 @@ import { VaultIcons, } from "@bitwarden/vault"; +import { Fido2PlaceholderComponent } from "../app/components/fido2placeholder.component"; import { AccessibilityCookieComponent } from "../auth/accessibility-cookie.component"; import { maxAccountsGuardFn } from "../auth/guards/max-accounts.guard"; import { RemovePasswordComponent } from "../auth/remove-password.component"; diff --git a/apps/desktop/src/modal/passkeys/create/fido2-create.component.ts b/apps/desktop/src/modal/passkeys/create/fido2-create.component.ts index 365dd8a7ad5..0ac78e1c476 100644 --- a/apps/desktop/src/modal/passkeys/create/fido2-create.component.ts +++ b/apps/desktop/src/modal/passkeys/create/fido2-create.component.ts @@ -1,9 +1,10 @@ import { CommonModule } from "@angular/common"; import { Component, OnInit } from "@angular/core"; import { RouterModule, Router } from "@angular/router"; -import { BehaviorSubject, firstValueFrom, Observable } from "rxjs"; +import { BehaviorSubject, firstValueFrom, map, Observable } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; @@ -16,11 +17,8 @@ import { SectionComponent, TableModule, } from "@bitwarden/components"; -// import { SearchComponent } from "@bitwarden/components/src/search/search.component"; -import { BitwardenShield } from "../../../../../../libs/auth/src/angular/icons"; -import { BitIconButtonComponent } from "../../../../../../libs/components/src/icon-button/icon-button.component"; -import { SectionHeaderComponent } from "../../../../../../libs/components/src/section/section-header.component"; +// import { SearchComponent } from "@bitwarden/components/src/search/search.component"; import { DesktopFido2UserInterfaceService, DesktopFido2UserInterfaceSession, @@ -33,8 +31,6 @@ import { DesktopSettingsService } from "../../../platform/services/desktop-setti imports: [ CommonModule, RouterModule, - SectionHeaderComponent, - BitIconButtonComponent, TableModule, JslibModule, IconModule, @@ -51,11 +47,11 @@ export class Fido2CreateComponent implements OnInit { session?: DesktopFido2UserInterfaceSession = null; private ciphersSubject = new BehaviorSubject([]); ciphers$: Observable = this.ciphersSubject.asObservable(); - readonly Icons = { BitwardenShield }; constructor( private readonly desktopSettingsService: DesktopSettingsService, private readonly fido2UserInterfaceService: DesktopFido2UserInterfaceService, + private readonly accountService: AccountService, private readonly cipherService: CipherService, private readonly domainSettingsService: DomainSettingsService, private readonly router: Router, @@ -67,9 +63,12 @@ export class Fido2CreateComponent implements OnInit { const equivalentDomains = await firstValueFrom( this.domainSettingsService.getUrlEquivalentDomains(rpid), ); + const activeUserId = await firstValueFrom( + this.accountService.activeAccount$.pipe(map((a) => a?.id)), + ); this.cipherService - .getAllDecrypted() + .getAllDecrypted(activeUserId) .then((ciphers) => { const relevantCiphers = ciphers.filter((cipher) => { if (!cipher.login || !cipher.login.hasUris) { @@ -116,7 +115,7 @@ export class Fido2CreateComponent implements OnInit { // But if this route is somehow opened outside of session we want to make sure we clean up? await this.router.navigate(["/"]); await this.desktopSettingsService.setModalMode(false); - } catch (error) { + } catch { // TODO: Handle error appropriately } } diff --git a/apps/desktop/src/modal/passkeys/fido2-vault.component.ts b/apps/desktop/src/modal/passkeys/fido2-vault.component.ts index 7116aeda4e0..e59b56fb8fe 100644 --- a/apps/desktop/src/modal/passkeys/fido2-vault.component.ts +++ b/apps/desktop/src/modal/passkeys/fido2-vault.component.ts @@ -1,9 +1,10 @@ import { CommonModule } from "@angular/common"; -import { Component, OnInit } from "@angular/core"; +import { Component, OnInit, OnDestroy } from "@angular/core"; import { RouterModule, Router } from "@angular/router"; -import { BehaviorSubject, Observable } from "rxjs"; +import { firstValueFrom, map, BehaviorSubject, Observable } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { @@ -16,9 +17,6 @@ import { TableModule, } from "@bitwarden/components"; -import { BitwardenShield } from "../../../../../libs/auth/src/angular/icons"; -import { BitIconButtonComponent } from "../../../../../libs/components/src/icon-button/icon-button.component"; -import { SectionHeaderComponent } from "../../../../../libs/components/src/section/section-header.component"; import { DesktopFido2UserInterfaceService, DesktopFido2UserInterfaceSession, @@ -30,8 +28,6 @@ import { DesktopSettingsService } from "../../platform/services/desktop-settings imports: [ CommonModule, RouterModule, - SectionHeaderComponent, - BitIconButtonComponent, TableModule, JslibModule, IconModule, @@ -43,28 +39,33 @@ import { DesktopSettingsService } from "../../platform/services/desktop-settings ], templateUrl: "fido2-vault.component.html", }) -export class Fido2VaultComponent implements OnInit { +export class Fido2VaultComponent implements OnInit, OnDestroy { session?: DesktopFido2UserInterfaceSession = null; private ciphersSubject = new BehaviorSubject([]); ciphers$: Observable = this.ciphersSubject.asObservable(); private cipherIdsSubject = new BehaviorSubject([]); cipherIds$: Observable; - readonly Icons = { BitwardenShield }; constructor( private readonly desktopSettingsService: DesktopSettingsService, private readonly fido2UserInterfaceService: DesktopFido2UserInterfaceService, private readonly cipherService: CipherService, + private readonly accountService: AccountService, private readonly router: Router, ) {} async ngOnInit() { + const activeUserId = await firstValueFrom( + this.accountService.activeAccount$.pipe(map((a) => a?.id)), + ); + this.session = this.fido2UserInterfaceService.getCurrentSession(); this.cipherIds$ = this.session?.availableCipherIds$; + // eslint-disable-next-line rxjs-angular/prefer-takeuntil this.cipherIds$.subscribe((cipherIds) => { this.cipherService - .getAllDecryptedForIds(cipherIds || []) + .getAllDecryptedForIds(activeUserId, cipherIds || []) .then((ciphers) => { this.ciphersSubject.next(ciphers); }) diff --git a/libs/common/src/vault/abstractions/cipher.service.ts b/libs/common/src/vault/abstractions/cipher.service.ts index c0fdb4f7c1b..60954c5d0bf 100644 --- a/libs/common/src/vault/abstractions/cipher.service.ts +++ b/libs/common/src/vault/abstractions/cipher.service.ts @@ -56,8 +56,7 @@ export abstract class CipherService implements UserKeyRotationDataProvider; - getAllDecryptedForIds: (ids: string[]) => Promise; - getPasskeyCiphers: () => Promise; + getAllDecryptedForIds: (userId: UserId, ids: string[]) => Promise; abstract filterCiphersForUrl( ciphers: CipherView[], url: string, diff --git a/libs/common/src/vault/services/cipher.service.ts b/libs/common/src/vault/services/cipher.service.ts index 50cda97d16e..c8c17b59ac2 100644 --- a/libs/common/src/vault/services/cipher.service.ts +++ b/libs/common/src/vault/services/cipher.service.ts @@ -513,7 +513,7 @@ export class CipherService implements CipherServiceAbstraction { async getAllDecryptedForUrl( url: string, - userId: UserId, + userId?: UserId, includeOtherTypes?: CipherType[], defaultMatch: UriMatchStrategySetting = null, ): Promise { @@ -521,9 +521,11 @@ export class CipherService implements CipherServiceAbstraction { return await this.filterCiphersForUrl(ciphers, url, includeOtherTypes, defaultMatch); } - async getAllDecryptedForIds(ids: string[]): Promise { - const ciphers = await this.getAllDecrypted(); - return ciphers.filter((cipher) => ids.includes(cipher.id)); + async getAllDecryptedForIds(userId: UserId, ids: string[]): Promise { + if (userId) { + const ciphers = await this.getAllDecrypted(userId); + return ciphers.filter((cipher) => ids.includes(cipher.id)); + } } async filterCiphersForUrl( @@ -1751,15 +1753,6 @@ export class CipherService implements CipherServiceAbstraction { } } - async getPasskeyCiphers(): Promise { - let ciphers = await this.getAllDecrypted(); - if (!ciphers) { - return null; - } - ciphers = ciphers.filter((cipher) => cipher.login.fido2Credentials?.length); - return ciphers; - } - private async clearEncryptedCiphersState(userId: UserId) { await this.stateProvider.setUserState(ENCRYPTED_CIPHERS, {}, userId); }