From 90af629024155c678056cde1f2717e85675e179a Mon Sep 17 00:00:00 2001 From: jng Date: Mon, 8 Sep 2025 15:14:05 -0400 Subject: [PATCH] added another route guard so when user clears all at risk items they are directed back to the vault page --- apps/browser/src/popup/app-routing.module.ts | 7 +++- .../popup/guards/at-risk-passwords.guard.ts | 42 ++++++++++++++++++- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/apps/browser/src/popup/app-routing.module.ts b/apps/browser/src/popup/app-routing.module.ts index 8d190e4555c..7562bf696a4 100644 --- a/apps/browser/src/popup/app-routing.module.ts +++ b/apps/browser/src/popup/app-routing.module.ts @@ -74,7 +74,10 @@ import { IntroCarouselComponent } from "../vault/popup/components/vault-v2/intro import { PasswordHistoryV2Component } from "../vault/popup/components/vault-v2/vault-password-history-v2/vault-password-history-v2.component"; import { VaultV2Component } from "../vault/popup/components/vault-v2/vault-v2.component"; import { ViewV2Component } from "../vault/popup/components/vault-v2/view-v2/view-v2.component"; -import { canAccessAtRiskPasswords } from "../vault/popup/guards/at-risk-passwords.guard"; +import { + canAccessAtRiskPasswords, + hasAtRiskPasswords, +} from "../vault/popup/guards/at-risk-passwords.guard"; import { clearVaultStateGuard } from "../vault/popup/guards/clear-vault-state.guard"; import { IntroCarouselGuard } from "../vault/popup/guards/intro-carousel.guard"; import { AppearanceV2Component } from "../vault/popup/settings/appearance-v2.component"; @@ -660,7 +663,7 @@ const routes: Routes = [ { path: "at-risk-passwords", component: AtRiskPasswordsComponent, - canActivate: [authGuard, canAccessAtRiskPasswords], + canActivate: [authGuard, canAccessAtRiskPasswords, hasAtRiskPasswords], }, { path: "account-switcher", diff --git a/apps/browser/src/vault/popup/guards/at-risk-passwords.guard.ts b/apps/browser/src/vault/popup/guards/at-risk-passwords.guard.ts index fc302dd6c36..2eee36c9bde 100644 --- a/apps/browser/src/vault/popup/guards/at-risk-passwords.guard.ts +++ b/apps/browser/src/vault/popup/guards/at-risk-passwords.guard.ts @@ -1,10 +1,11 @@ import { inject } from "@angular/core"; import { CanActivateFn, Router } from "@angular/router"; -import { map, switchMap } from "rxjs"; +import { combineLatest, map, switchMap } from "rxjs"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { TaskService } from "@bitwarden/common/vault/tasks"; +import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; +import { SecurityTaskType, TaskService } from "@bitwarden/common/vault/tasks"; import { filterOutNullish } from "@bitwarden/common/vault/utils/observable-utilities"; import { ToastService } from "@bitwarden/components"; @@ -32,3 +33,40 @@ export const canAccessAtRiskPasswords: CanActivateFn = () => { }), ); }; + +export const hasAtRiskPasswords: CanActivateFn = () => { + const accountService = inject(AccountService); + const taskService = inject(TaskService); + const cipherService = inject(CipherService); + const router = inject(Router); + + return accountService.activeAccount$.pipe( + filterOutNullish(), + switchMap((user) => + combineLatest([ + taskService.pendingTasks$(user.id), + cipherService.cipherViews$(user.id).pipe( + filterOutNullish(), + map((ciphers) => Object.fromEntries(ciphers.map((c) => [c.id, c]))), + ), + ]).pipe( + map(([tasks, ciphers]) => { + const atRiskCiphers = tasks + .filter( + (t) => + t.type === SecurityTaskType.UpdateAtRiskCredential && + t.cipherId != null && + ciphers[t.cipherId] != null && + !ciphers[t.cipherId].isDeleted, + ) + .map((t) => ciphers[t.cipherId!]); + + if (atRiskCiphers.length === 0) { + return router.createUrlTree(["/tabs/vault"]); + } + return true; + }), + ), + ), + ); +};