From 84b179f53a5b4fa38d70a50c4f597f8d942c89e8 Mon Sep 17 00:00:00 2001
From: Alec Rippberger <127791530+alec-livefront@users.noreply.github.com>
Date: Tue, 1 Apr 2025 18:46:40 -0500
Subject: [PATCH 1/6] refactor(auth): [PM-9698] remove deprecated SSO
components
Removes v1 SSO components in favor of new implementation as well as related orphaned styles/translations.
Refs: PM-9698
---
.../src/auth/popup/sso-v1.component.html | 0
.../src/auth/popup/sso-v1.component.ts | 105 ----------
apps/browser/src/popup/app.module.ts | 2 -
apps/desktop/src/app/app.module.ts | 2 -
apps/desktop/src/auth/sso-v1.component.html | 9 -
apps/desktop/src/auth/sso-v1.component.ts | 83 --------
apps/desktop/src/scss/pages.scss | 13 --
apps/web/src/app/auth/sso-v1.component.html | 22 ---
apps/web/src/app/auth/sso-v1.component.ts | 186 ------------------
.../src/app/shared/loose-components.module.ts | 3 -
10 files changed, 425 deletions(-)
delete mode 100644 apps/browser/src/auth/popup/sso-v1.component.html
delete mode 100644 apps/browser/src/auth/popup/sso-v1.component.ts
delete mode 100644 apps/desktop/src/auth/sso-v1.component.html
delete mode 100644 apps/desktop/src/auth/sso-v1.component.ts
delete mode 100644 apps/web/src/app/auth/sso-v1.component.html
delete mode 100644 apps/web/src/app/auth/sso-v1.component.ts
diff --git a/apps/browser/src/auth/popup/sso-v1.component.html b/apps/browser/src/auth/popup/sso-v1.component.html
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/apps/browser/src/auth/popup/sso-v1.component.ts b/apps/browser/src/auth/popup/sso-v1.component.ts
deleted file mode 100644
index f56fe697e70..00000000000
--- a/apps/browser/src/auth/popup/sso-v1.component.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-import { Component, Inject } from "@angular/core";
-import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
-import { ActivatedRoute, Router } from "@angular/router";
-
-import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component";
-import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
-import {
- LoginStrategyServiceAbstraction,
- UserDecryptionOptionsServiceAbstraction,
-} from "@bitwarden/auth/common";
-import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
-import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
-import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
-import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
-import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
-import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
-import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
-import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
-import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
-import { ToastService } from "@bitwarden/components";
-import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
-
-import { BrowserApi } from "../../platform/browser/browser-api";
-
-@Component({
- selector: "app-sso",
- templateUrl: "sso-v1.component.html",
-})
-export class SsoComponentV1 extends BaseSsoComponent {
- constructor(
- ssoLoginService: SsoLoginServiceAbstraction,
- loginStrategyService: LoginStrategyServiceAbstraction,
- router: Router,
- i18nService: I18nService,
- route: ActivatedRoute,
- stateService: StateService,
- platformUtilsService: PlatformUtilsService,
- apiService: ApiService,
- cryptoFunctionService: CryptoFunctionService,
- passwordGenerationService: PasswordGenerationServiceAbstraction,
- syncService: SyncService,
- environmentService: EnvironmentService,
- logService: LogService,
- userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
- configService: ConfigService,
- masterPasswordService: InternalMasterPasswordServiceAbstraction,
- accountService: AccountService,
- private authService: AuthService,
- @Inject(WINDOW) private win: Window,
- toastService: ToastService,
- ) {
- super(
- ssoLoginService,
- loginStrategyService,
- router,
- i18nService,
- route,
- stateService,
- platformUtilsService,
- apiService,
- cryptoFunctionService,
- environmentService,
- passwordGenerationService,
- logService,
- userDecryptionOptionsService,
- configService,
- masterPasswordService,
- accountService,
- toastService,
- );
-
- environmentService.environment$.pipe(takeUntilDestroyed()).subscribe((env) => {
- this.redirectUri = env.getWebVaultUrl() + "/sso-connector.html";
- });
- this.clientId = "browser";
-
- this.onSuccessfulLogin = async () => {
- // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- syncService.fullSync(true);
-
- // If the vault is unlocked then this will clear keys from memory, which we don't want to do
- if ((await this.authService.getAuthStatus()) !== AuthenticationStatus.Unlocked) {
- BrowserApi.reloadOpenWindows();
- }
-
- this.win.close();
- };
-
- this.onSuccessfulLoginTde = async () => {
- // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- syncService.fullSync(true);
- };
-
- this.onSuccessfulLoginTdeNavigate = async () => {
- this.win.close();
- };
- }
-}
diff --git a/apps/browser/src/popup/app.module.ts b/apps/browser/src/popup/app.module.ts
index b2542679e06..71e310ad335 100644
--- a/apps/browser/src/popup/app.module.ts
+++ b/apps/browser/src/popup/app.module.ts
@@ -24,7 +24,6 @@ import { RemovePasswordComponent } from "../auth/popup/remove-password.component
import { SetPasswordComponent } from "../auth/popup/set-password.component";
import { AccountSecurityComponent } from "../auth/popup/settings/account-security.component";
import { VaultTimeoutInputComponent } from "../auth/popup/settings/vault-timeout-input.component";
-import { SsoComponentV1 } from "../auth/popup/sso-v1.component";
import { UpdateTempPasswordComponent } from "../auth/popup/update-temp-password.component";
import { AutofillComponent } from "../autofill/popup/settings/autofill.component";
import { NotificationsSettingsComponent } from "../autofill/popup/settings/notifications.component";
@@ -89,7 +88,6 @@ import "../platform/popup/locales";
ColorPasswordPipe,
ColorPasswordCountPipe,
SetPasswordComponent,
- SsoComponentV1,
TabsV2Component,
UpdateTempPasswordComponent,
UserVerificationComponent,
diff --git a/apps/desktop/src/app/app.module.ts b/apps/desktop/src/app/app.module.ts
index b717afe4a41..fdc25ed642e 100644
--- a/apps/desktop/src/app/app.module.ts
+++ b/apps/desktop/src/app/app.module.ts
@@ -15,7 +15,6 @@ import { DeleteAccountComponent } from "../auth/delete-account.component";
import { LoginModule } from "../auth/login/login.module";
import { RemovePasswordComponent } from "../auth/remove-password.component";
import { SetPasswordComponent } from "../auth/set-password.component";
-import { SsoComponentV1 } from "../auth/sso-v1.component";
import { UpdateTempPasswordComponent } from "../auth/update-temp-password.component";
import { SshAgentService } from "../autofill/services/ssh-agent.service";
import { PremiumComponent } from "../billing/app/accounts/premium.component";
@@ -76,7 +75,6 @@ import { SharedModule } from "./shared/shared.module";
SetPasswordComponent,
SettingsComponent,
ShareComponent,
- SsoComponentV1,
UpdateTempPasswordComponent,
VaultComponent,
VaultTimeoutInputComponent,
diff --git a/apps/desktop/src/auth/sso-v1.component.html b/apps/desktop/src/auth/sso-v1.component.html
deleted file mode 100644
index cb5bba9dc66..00000000000
--- a/apps/desktop/src/auth/sso-v1.component.html
+++ /dev/null
@@ -1,9 +0,0 @@
-
diff --git a/apps/desktop/src/auth/sso-v1.component.ts b/apps/desktop/src/auth/sso-v1.component.ts
deleted file mode 100644
index 1bb6d8362a1..00000000000
--- a/apps/desktop/src/auth/sso-v1.component.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import { Component } from "@angular/core";
-import { ActivatedRoute, Router } from "@angular/router";
-
-import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component";
-import {
- LoginStrategyServiceAbstraction,
- UserDecryptionOptionsServiceAbstraction,
-} from "@bitwarden/auth/common";
-import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
-import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
-import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
-import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
-import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
-import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
-import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
-import { ToastService } from "@bitwarden/components";
-import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
-
-@Component({
- selector: "app-sso",
- templateUrl: "sso-v1.component.html",
-})
-export class SsoComponentV1 extends BaseSsoComponent {
- constructor(
- ssoLoginService: SsoLoginServiceAbstraction,
- loginStrategyService: LoginStrategyServiceAbstraction,
- router: Router,
- i18nService: I18nService,
- syncService: SyncService,
- route: ActivatedRoute,
- stateService: StateService,
- platformUtilsService: PlatformUtilsService,
- apiService: ApiService,
- cryptoFunctionService: CryptoFunctionService,
- environmentService: EnvironmentService,
- passwordGenerationService: PasswordGenerationServiceAbstraction,
- logService: LogService,
- userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
- configService: ConfigService,
- masterPasswordService: InternalMasterPasswordServiceAbstraction,
- accountService: AccountService,
- toastService: ToastService,
- ) {
- super(
- ssoLoginService,
- loginStrategyService,
- router,
- i18nService,
- route,
- stateService,
- platformUtilsService,
- apiService,
- cryptoFunctionService,
- environmentService,
- passwordGenerationService,
- logService,
- userDecryptionOptionsService,
- configService,
- masterPasswordService,
- accountService,
- toastService,
- );
- this.onSuccessfulLogin = async () => {
- // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- syncService.fullSync(true);
- };
-
- this.onSuccessfulLoginTde = async () => {
- // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- syncService.fullSync(true);
- };
-
- this.redirectUri = "bitwarden://sso-callback";
- this.clientId = "desktop";
- }
-}
diff --git a/apps/desktop/src/scss/pages.scss b/apps/desktop/src/scss/pages.scss
index ecb36aae662..155ffaf0ad1 100644
--- a/apps/desktop/src/scss/pages.scss
+++ b/apps/desktop/src/scss/pages.scss
@@ -1,7 +1,6 @@
@import "variables.scss";
#lock-page,
-#sso-page,
#set-password-page,
#remove-password-page {
display: flex;
@@ -106,18 +105,6 @@
}
}
-#sso-page {
- .content {
- width: 325px;
-
- .box {
- margin-top: 30px;
- margin-bottom: 30px;
- text-align: center;
- }
- }
-}
-
#set-password-page,
#remove-password-page {
.content {
diff --git a/apps/web/src/app/auth/sso-v1.component.html b/apps/web/src/app/auth/sso-v1.component.html
deleted file mode 100644
index 59abc92e872..00000000000
--- a/apps/web/src/app/auth/sso-v1.component.html
+++ /dev/null
@@ -1,22 +0,0 @@
-
diff --git a/apps/web/src/app/auth/sso-v1.component.ts b/apps/web/src/app/auth/sso-v1.component.ts
deleted file mode 100644
index d664f5b890b..00000000000
--- a/apps/web/src/app/auth/sso-v1.component.ts
+++ /dev/null
@@ -1,186 +0,0 @@
-// FIXME: Update this file to be type safe and remove this and next line
-// @ts-strict-ignore
-import { Component, OnInit } from "@angular/core";
-import { FormControl, FormGroup, Validators } from "@angular/forms";
-import { ActivatedRoute, Router } from "@angular/router";
-import { firstValueFrom } from "rxjs";
-import { first } from "rxjs/operators";
-
-import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component";
-import {
- LoginStrategyServiceAbstraction,
- UserDecryptionOptionsServiceAbstraction,
-} from "@bitwarden/auth/common";
-import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { OrgDomainApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization-domain/org-domain-api.service.abstraction";
-import { OrganizationDomainSsoDetailsResponse } from "@bitwarden/common/admin-console/abstractions/organization-domain/responses/organization-domain-sso-details.response";
-import { VerifiedOrganizationDomainSsoDetailsResponse } from "@bitwarden/common/admin-console/abstractions/organization-domain/responses/verified-organization-domain-sso-details.response";
-import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
-import { HttpStatusCode } from "@bitwarden/common/enums";
-import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
-import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
-import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
-import { ListResponse } from "@bitwarden/common/models/response/list.response";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
-import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
-import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
-import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
-import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
-import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
-import { ToastService } from "@bitwarden/components";
-import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
-
-@Component({
- selector: "app-sso",
- templateUrl: "sso-v1.component.html",
-})
-export class SsoComponentV1 extends BaseSsoComponent implements OnInit {
- protected formGroup = new FormGroup({
- identifier: new FormControl(null, [Validators.required]),
- });
-
- get identifierFormControl() {
- return this.formGroup.controls.identifier;
- }
-
- constructor(
- ssoLoginService: SsoLoginServiceAbstraction,
- loginStrategyService: LoginStrategyServiceAbstraction,
- router: Router,
- i18nService: I18nService,
- route: ActivatedRoute,
- stateService: StateService,
- platformUtilsService: PlatformUtilsService,
- apiService: ApiService,
- cryptoFunctionService: CryptoFunctionService,
- environmentService: EnvironmentService,
- passwordGenerationService: PasswordGenerationServiceAbstraction,
- logService: LogService,
- private orgDomainApiService: OrgDomainApiServiceAbstraction,
- private validationService: ValidationService,
- userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
- configService: ConfigService,
- masterPasswordService: InternalMasterPasswordServiceAbstraction,
- accountService: AccountService,
- toastService: ToastService,
- ) {
- super(
- ssoLoginService,
- loginStrategyService,
- router,
- i18nService,
- route,
- stateService,
- platformUtilsService,
- apiService,
- cryptoFunctionService,
- environmentService,
- passwordGenerationService,
- logService,
- userDecryptionOptionsService,
- configService,
- masterPasswordService,
- accountService,
- toastService,
- );
- this.redirectUri = window.location.origin + "/sso-connector.html";
- this.clientId = "web";
- }
-
- async ngOnInit() {
- // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- super.ngOnInit();
-
- // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
- this.route.queryParams.pipe(first()).subscribe(async (qParams) => {
- if (qParams.identifier != null) {
- // SSO Org Identifier in query params takes precedence over claimed domains
- this.identifierFormControl.setValue(qParams.identifier);
- this.loggingIn = true;
- await this.submit();
- } else {
- // Note: this flow is written for web but both browser and desktop
- // redirect here on SSO button click.
-
- // Check if email matches any claimed domains
- if (qParams.email) {
- // show loading spinner
- this.loggingIn = true;
- try {
- if (await this.configService.getFeatureFlag(FeatureFlag.VerifiedSsoDomainEndpoint)) {
- const response: ListResponse =
- await this.orgDomainApiService.getVerifiedOrgDomainsByEmail(qParams.email);
-
- if (response.data.length > 0) {
- this.identifierFormControl.setValue(response.data[0].organizationIdentifier);
- await this.submit();
- return;
- }
- } else {
- const response: OrganizationDomainSsoDetailsResponse =
- await this.orgDomainApiService.getClaimedOrgDomainByEmail(qParams.email);
-
- if (response?.ssoAvailable && response?.verifiedDate) {
- this.identifierFormControl.setValue(response.organizationIdentifier);
- await this.submit();
- return;
- }
- }
- } catch (error) {
- this.handleGetClaimedDomainByEmailError(error);
- }
-
- this.loggingIn = false;
- }
-
- // Fallback to state svc if domain is unclaimed
- const storedIdentifier = await this.ssoLoginService.getOrganizationSsoIdentifier();
- if (storedIdentifier != null) {
- this.identifierFormControl.setValue(storedIdentifier);
- }
- }
- });
- }
-
- private handleGetClaimedDomainByEmailError(error: any): void {
- if (error instanceof ErrorResponse) {
- const errorResponse: ErrorResponse = error as ErrorResponse;
- switch (errorResponse.statusCode) {
- case HttpStatusCode.NotFound:
- //this is a valid case for a domain not found
- return;
-
- default:
- this.validationService.showError(errorResponse);
- break;
- }
- }
- }
-
- submit = async () => {
- if (this.formGroup.invalid) {
- return;
- }
-
- const autoSubmit = (await firstValueFrom(this.route.queryParams)).identifier != null;
-
- this.identifier = this.identifierFormControl.value;
- await this.ssoLoginService.setOrganizationSsoIdentifier(this.identifier);
- if (this.clientId === "browser") {
- document.cookie = `ssoHandOffMessage=${this.i18nService.t("ssoHandOff")};SameSite=strict`;
- }
- try {
- await Object.getPrototypeOf(this).submit.call(this);
- } catch (error) {
- if (autoSubmit) {
- await this.router.navigate(["/login"]);
- } else {
- this.validationService.showError(error);
- }
- }
- };
-}
diff --git a/apps/web/src/app/shared/loose-components.module.ts b/apps/web/src/app/shared/loose-components.module.ts
index 70dbf63f1f8..41347c3f082 100644
--- a/apps/web/src/app/shared/loose-components.module.ts
+++ b/apps/web/src/app/shared/loose-components.module.ts
@@ -42,7 +42,6 @@ import { TwoFactorSetupYubiKeyComponent } from "../auth/settings/two-factor/two-
import { TwoFactorSetupComponent } from "../auth/settings/two-factor/two-factor-setup.component";
import { TwoFactorVerifyComponent } from "../auth/settings/two-factor/two-factor-verify.component";
import { UserVerificationModule } from "../auth/shared/components/user-verification";
-import { SsoComponentV1 } from "../auth/sso-v1.component";
import { UpdatePasswordComponent } from "../auth/update-password.component";
import { UpdateTempPasswordComponent } from "../auth/update-temp-password.component";
import { VerifyEmailTokenComponent } from "../auth/verify-email-token.component";
@@ -146,7 +145,6 @@ import { SharedModule } from "./shared.module";
SetPasswordComponent,
SponsoredFamiliesComponent,
SponsoringOrgRowComponent,
- SsoComponentV1,
TwoFactorSetupAuthenticatorComponent,
TwoFactorSetupDuoComponent,
TwoFactorSetupEmailComponent,
@@ -206,7 +204,6 @@ import { SharedModule } from "./shared.module";
SetPasswordComponent,
SponsoredFamiliesComponent,
SponsoringOrgRowComponent,
- SsoComponentV1,
TwoFactorSetupAuthenticatorComponent,
TwoFactorSetupDuoComponent,
TwoFactorSetupEmailComponent,
From afcb656d128d8f301eea090cee9de83fe95b55d9 Mon Sep 17 00:00:00 2001
From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com>
Date: Tue, 1 Apr 2025 16:48:41 -0700
Subject: [PATCH 2/6] [PM-17747] - remove emergency access attachments dialog.
fix 404 (#13854)
* remove emergency access attachments dialog. fix 404
* fix types
* fix type issue
---
.../emergency-access-attachments.component.ts | 66 -------------------
.../view/emergency-access-view.component.html | 22 -------
.../view/emergency-access-view.component.ts | 50 ++++----------
.../view/emergency-view-dialog.component.html | 2 +-
.../view/emergency-view-dialog.component.ts | 6 ++
.../src/app/shared/loose-components.module.ts | 3 -
libs/common/src/types/guid.ts | 1 +
.../attachments-v2-view.component.html | 1 +
.../attachments-v2-view.component.ts | 5 +-
.../cipher-view/cipher-view.component.html | 3 +-
.../src/cipher-view/cipher-view.component.ts | 5 +-
.../download-attachment.component.ts | 6 +-
12 files changed, 37 insertions(+), 133 deletions(-)
delete mode 100644 apps/web/src/app/auth/settings/emergency-access/attachments/emergency-access-attachments.component.ts
diff --git a/apps/web/src/app/auth/settings/emergency-access/attachments/emergency-access-attachments.component.ts b/apps/web/src/app/auth/settings/emergency-access/attachments/emergency-access-attachments.component.ts
deleted file mode 100644
index 73191e1539e..00000000000
--- a/apps/web/src/app/auth/settings/emergency-access/attachments/emergency-access-attachments.component.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import { Component } from "@angular/core";
-
-import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/angular/vault/components/attachments.component";
-import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
-import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
-import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
-import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
-import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
-import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
-import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
-import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view";
-import { DialogService, ToastService } from "@bitwarden/components";
-import { KeyService } from "@bitwarden/key-management";
-
-@Component({
- selector: "emergency-access-attachments",
- templateUrl: "../../../../vault/individual-vault/attachments.component.html",
-})
-export class EmergencyAccessAttachmentsComponent extends BaseAttachmentsComponent {
- viewOnly = true;
- canAccessAttachments = true;
-
- constructor(
- cipherService: CipherService,
- i18nService: I18nService,
- keyService: KeyService,
- encryptService: EncryptService,
- stateService: StateService,
- platformUtilsService: PlatformUtilsService,
- apiService: ApiService,
- logService: LogService,
- fileDownloadService: FileDownloadService,
- dialogService: DialogService,
- billingAccountProfileStateService: BillingAccountProfileStateService,
- accountService: AccountService,
- toastService: ToastService,
- ) {
- super(
- cipherService,
- i18nService,
- keyService,
- encryptService,
- platformUtilsService,
- apiService,
- window,
- logService,
- stateService,
- fileDownloadService,
- dialogService,
- billingAccountProfileStateService,
- accountService,
- toastService,
- );
- }
-
- protected async init() {
- // Do nothing since cipher is already decoded
- }
-
- protected showFixOldAttachments(attachment: AttachmentView) {
- return false;
- }
-}
diff --git a/apps/web/src/app/auth/settings/emergency-access/view/emergency-access-view.component.html b/apps/web/src/app/auth/settings/emergency-access/view/emergency-access-view.component.html
index a936e3a427d..87e2643c178 100644
--- a/apps/web/src/app/auth/settings/emergency-access/view/emergency-access-view.component.html
+++ b/apps/web/src/app/auth/settings/emergency-access/view/emergency-access-view.component.html
@@ -38,28 +38,6 @@
{{ currentCipher.subTitle }}
-
-
-
-
-
-
-
- |
diff --git a/apps/web/src/app/auth/settings/emergency-access/view/emergency-access-view.component.ts b/apps/web/src/app/auth/settings/emergency-access/view/emergency-access-view.component.ts
index 1e3d0cf705f..bf7ca29da9b 100644
--- a/apps/web/src/app/auth/settings/emergency-access/view/emergency-access-view.component.ts
+++ b/apps/web/src/app/auth/settings/emergency-access/view/emergency-access-view.component.ts
@@ -1,15 +1,13 @@
-// FIXME: Update this file to be type safe and remove this and next line
-// @ts-strict-ignore
import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
+import { firstValueFrom } from "rxjs";
-import { ModalService } from "@bitwarden/angular/services/modal.service";
+import { EmergencyAccessId } from "@bitwarden/common/types/guid";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { DialogService } from "@bitwarden/components";
import { CipherFormConfigService, DefaultCipherFormConfigService } from "@bitwarden/vault";
import { EmergencyAccessService } from "../../../emergency-access";
-import { EmergencyAccessAttachmentsComponent } from "../attachments/emergency-access-attachments.component";
import { EmergencyViewDialogComponent } from "./emergency-view-dialog.component";
@@ -20,56 +18,34 @@ import { EmergencyViewDialogComponent } from "./emergency-view-dialog.component"
})
export class EmergencyAccessViewComponent implements OnInit {
@ViewChild("attachments", { read: ViewContainerRef, static: true })
- attachmentsModalRef: ViewContainerRef;
-
- id: string;
+ id: EmergencyAccessId | null = null;
ciphers: CipherView[] = [];
loaded = false;
constructor(
- private modalService: ModalService,
private router: Router,
private route: ActivatedRoute,
private emergencyAccessService: EmergencyAccessService,
private dialogService: DialogService,
) {}
- ngOnInit() {
- // eslint-disable-next-line rxjs-angular/prefer-takeuntil
- this.route.params.subscribe((qParams) => {
- if (qParams.id == null) {
- return this.router.navigate(["settings/emergency-access"]);
- }
+ async ngOnInit() {
+ const qParams = await firstValueFrom(this.route.params);
+ if (qParams.id == null) {
+ await this.router.navigate(["settings/emergency-access"]);
+ return;
+ }
- this.id = qParams.id;
-
- // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- this.load();
- });
+ this.id = qParams.id;
+ this.ciphers = await this.emergencyAccessService.getViewOnlyCiphers(qParams.id);
+ this.loaded = true;
}
async selectCipher(cipher: CipherView) {
EmergencyViewDialogComponent.open(this.dialogService, {
cipher,
+ emergencyAccessId: this.id!,
});
return;
}
-
- async load() {
- this.ciphers = await this.emergencyAccessService.getViewOnlyCiphers(this.id);
- this.loaded = true;
- }
-
- // FIXME PM-17747: This will also need to be replaced with the new AttachmentViewDialog
- async viewAttachments(cipher: CipherView) {
- await this.modalService.openViewRef(
- EmergencyAccessAttachmentsComponent,
- this.attachmentsModalRef,
- (comp) => {
- comp.cipher = cipher;
- comp.emergencyAccessId = this.id;
- },
- );
- }
}
diff --git a/apps/web/src/app/auth/settings/emergency-access/view/emergency-view-dialog.component.html b/apps/web/src/app/auth/settings/emergency-access/view/emergency-view-dialog.component.html
index be38e1d9505..b3d8e48260a 100644
--- a/apps/web/src/app/auth/settings/emergency-access/view/emergency-view-dialog.component.html
+++ b/apps/web/src/app/auth/settings/emergency-access/view/emergency-view-dialog.component.html
@@ -3,7 +3,7 @@
{{ title }}
diff --git a/libs/vault/src/cipher-view/attachments/attachments-v2-view.component.ts b/libs/vault/src/cipher-view/attachments/attachments-v2-view.component.ts
index 0c2ca35cbbc..8e4a1ac952c 100644
--- a/libs/vault/src/cipher-view/attachments/attachments-v2-view.component.ts
+++ b/libs/vault/src/cipher-view/attachments/attachments-v2-view.component.ts
@@ -9,7 +9,7 @@ import { JslibModule } from "@bitwarden/angular/jslib.module";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions";
import { StateProvider } from "@bitwarden/common/platform/state";
-import { OrganizationId } from "@bitwarden/common/types/guid";
+import { EmergencyAccessId, OrganizationId } from "@bitwarden/common/types/guid";
import { OrgKey } from "@bitwarden/common/types/key";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import {
@@ -41,6 +41,9 @@ import { DownloadAttachmentComponent } from "../../components/download-attachmen
export class AttachmentsV2ViewComponent {
@Input() cipher: CipherView;
+ // Required for fetching attachment data when viewed from cipher via emergency access
+ @Input() emergencyAccessId?: EmergencyAccessId;
+
canAccessPremium: boolean;
orgKey: OrgKey;
diff --git a/libs/vault/src/cipher-view/cipher-view.component.html b/libs/vault/src/cipher-view/cipher-view.component.html
index b2e747aa2fe..c441c921c39 100644
--- a/libs/vault/src/cipher-view/cipher-view.component.html
+++ b/libs/vault/src/cipher-view/cipher-view.component.html
@@ -76,7 +76,8 @@
-
+
+
diff --git a/libs/vault/src/cipher-view/cipher-view.component.ts b/libs/vault/src/cipher-view/cipher-view.component.ts
index 657c0d11527..48b70271e43 100644
--- a/libs/vault/src/cipher-view/cipher-view.component.ts
+++ b/libs/vault/src/cipher-view/cipher-view.component.ts
@@ -15,7 +15,7 @@ import { isCardExpired } from "@bitwarden/common/autofill/utils";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { CipherId, CollectionId, UserId } from "@bitwarden/common/types/guid";
+import { CipherId, CollectionId, EmergencyAccessId, UserId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
@@ -61,6 +61,9 @@ import { ViewIdentitySectionsComponent } from "./view-identity-sections/view-ide
export class CipherViewComponent implements OnChanges, OnDestroy {
@Input({ required: true }) cipher: CipherView | null = null;
+ // Required for fetching attachment data when viewed from cipher via emergency access
+ @Input() emergencyAccessId?: EmergencyAccessId;
+
activeUserId$ = getUserId(this.accountService.activeAccount$);
/**
diff --git a/libs/vault/src/components/download-attachment/download-attachment.component.ts b/libs/vault/src/components/download-attachment/download-attachment.component.ts
index 1445ca557cf..812051775f8 100644
--- a/libs/vault/src/components/download-attachment/download-attachment.component.ts
+++ b/libs/vault/src/components/download-attachment/download-attachment.component.ts
@@ -13,7 +13,7 @@ import { FileDownloadService } from "@bitwarden/common/platform/abstractions/fil
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer";
import { StateProvider } from "@bitwarden/common/platform/state";
-import { OrganizationId } from "@bitwarden/common/types/guid";
+import { EmergencyAccessId, OrganizationId } from "@bitwarden/common/types/guid";
import { OrgKey } from "@bitwarden/common/types/key";
import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
@@ -36,6 +36,9 @@ export class DownloadAttachmentComponent {
// When in view mode, we will want to check for the master password reprompt
@Input() checkPwReprompt?: boolean = false;
+ // Required for fetching attachment data when viewed from cipher via emergency access
+ @Input() emergencyAccessId?: EmergencyAccessId;
+
/** The organization key if the cipher is associated with one */
private orgKey: OrgKey | null = null;
@@ -68,6 +71,7 @@ export class DownloadAttachmentComponent {
const attachmentDownloadResponse = await this.apiService.getAttachmentData(
this.cipher.id,
this.attachment.id,
+ this.emergencyAccessId,
);
url = attachmentDownloadResponse.url;
} catch (e) {
From d0606922ce6394f8dcc1473e681be29af2c89cb6 Mon Sep 17 00:00:00 2001
From: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com>
Date: Wed, 2 Apr 2025 09:23:18 +0100
Subject: [PATCH 3/6] make the mode dark mode compatible (#14073)
---
.../admin-console/organizations/manage/events.component.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/web/src/app/admin-console/organizations/manage/events.component.html b/apps/web/src/app/admin-console/organizations/manage/events.component.html
index adadec5075a..80d22467123 100644
--- a/apps/web/src/app/admin-console/organizations/manage/events.component.html
+++ b/apps/web/src/app/admin-console/organizations/manage/events.component.html
@@ -111,10 +111,10 @@
From f13bc2766b37ddc9c8f7d4c80bf9c981e4662c5c Mon Sep 17 00:00:00 2001
From: Daniel James Smith <2670567+djsmith85@users.noreply.github.com>
Date: Wed, 2 Apr 2025 15:28:40 +0200
Subject: [PATCH 4/6] Set selected format to json, when the zip format option
is removed (#14092)
Co-authored-by: Daniel James Smith
---
.../vault-export-ui/src/components/export.component.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/libs/tools/export/vault-export/vault-export-ui/src/components/export.component.ts b/libs/tools/export/vault-export/vault-export-ui/src/components/export.component.ts
index c8efe093762..69f77c6ca32 100644
--- a/libs/tools/export/vault-export/vault-export-ui/src/components/export.component.ts
+++ b/libs/tools/export/vault-export/vault-export-ui/src/components/export.component.ts
@@ -234,6 +234,7 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit {
this.organizationId = value !== "myVault" ? value : undefined;
this.formatOptions = this.formatOptions.filter((option) => option.value !== "zip");
+ this.exportForm.get("format").setValue("json");
if (value === "myVault" && isExportAttachmentsEnabled) {
this.formatOptions.push({ name: ".zip (with attachments)", value: "zip" });
}
From 9080a5a024219e810119fe99968e02f8b73b7710 Mon Sep 17 00:00:00 2001
From: Daniel Riera
Date: Wed, 2 Apr 2025 09:30:47 -0400
Subject: [PATCH 5/6] PM-19378 remove v1 notification bar path (#13973)
* PM-19378
- Remove NotificationBarAddLoginImproments flag
- Remove divergent paths in various files
- Fix tests to reflect new singular path
* PM-19378
- Remove applyRedesign from relevant files
- Update styling to reflect changes
* remove notification-bar
* edit styling for to accodmmodate v3 in iframe
---
.../overlay-notifications.background.spec.ts | 31 -
.../overlay-notifications.background.ts | 42 +-
.../src/autofill/content/notification-bar.ts | 1082 -----------------
.../abstractions/notification-bar.ts | 1 -
.../src/autofill/notification/bar.html | 2 +-
.../src/autofill/notification/bar.scss | 272 ++---
apps/browser/src/autofill/notification/bar.ts | 4 -
.../overlay-notifications-content.service.ts | 19 +-
.../services/autofill.service.spec.ts | 25 +-
.../src/autofill/services/autofill.service.ts | 16 +-
.../browser/src/background/main.background.ts | 1 -
apps/browser/webpack.config.js | 1 -
libs/common/src/enums/feature-flag.enum.ts | 2 -
13 files changed, 147 insertions(+), 1351 deletions(-)
delete mode 100644 apps/browser/src/autofill/content/notification-bar.ts
diff --git a/apps/browser/src/autofill/background/overlay-notifications.background.spec.ts b/apps/browser/src/autofill/background/overlay-notifications.background.spec.ts
index 57930496978..a51757dabea 100644
--- a/apps/browser/src/autofill/background/overlay-notifications.background.spec.ts
+++ b/apps/browser/src/autofill/background/overlay-notifications.background.spec.ts
@@ -1,8 +1,6 @@
import { mock, MockProxy } from "jest-mock-extended";
-import { BehaviorSubject } from "rxjs";
import { CLEAR_NOTIFICATION_LOGIN_DATA_DURATION } from "@bitwarden/common/autofill/constants";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { ServerConfig } from "@bitwarden/common/platform/abstractions/config/server-config";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { EnvironmentServerConfigData } from "@bitwarden/common/platform/models/data/server-config.data";
@@ -25,8 +23,6 @@ import { OverlayNotificationsBackground } from "./overlay-notifications.backgrou
describe("OverlayNotificationsBackground", () => {
let logService: MockProxy;
- let getFeatureFlagMock$: BehaviorSubject;
- let configService: MockProxy;
let notificationBackground: NotificationBackground;
let getEnableChangedPasswordPromptSpy: jest.SpyInstance;
let getEnableAddedLoginPromptSpy: jest.SpyInstance;
@@ -35,10 +31,6 @@ describe("OverlayNotificationsBackground", () => {
beforeEach(async () => {
jest.useFakeTimers();
logService = mock();
- getFeatureFlagMock$ = new BehaviorSubject(true);
- configService = mock({
- getFeatureFlag$: jest.fn().mockReturnValue(getFeatureFlagMock$),
- });
notificationBackground = mock();
getEnableChangedPasswordPromptSpy = jest
.spyOn(notificationBackground, "getEnableChangedPasswordPrompt")
@@ -48,10 +40,8 @@ describe("OverlayNotificationsBackground", () => {
.mockResolvedValue(true);
overlayNotificationsBackground = new OverlayNotificationsBackground(
logService,
- configService,
notificationBackground,
);
- configService.getFeatureFlag.mockResolvedValue(true);
await overlayNotificationsBackground.init();
});
@@ -60,27 +50,6 @@ describe("OverlayNotificationsBackground", () => {
jest.clearAllTimers();
});
- describe("feature flag behavior", () => {
- let runtimeRemoveListenerSpy: jest.SpyInstance;
-
- beforeEach(() => {
- runtimeRemoveListenerSpy = jest.spyOn(chrome.runtime.onMessage, "removeListener");
- });
-
- it("removes the extension listeners if the current flag value is set to `false`", () => {
- getFeatureFlagMock$.next(false);
-
- expect(runtimeRemoveListenerSpy).toHaveBeenCalled();
- });
-
- it("ignores the feature flag change if the previous flag value is equal to the current flag value", () => {
- getFeatureFlagMock$.next(false);
- getFeatureFlagMock$.next(false);
-
- expect(runtimeRemoveListenerSpy).toHaveBeenCalledTimes(1);
- });
- });
-
describe("setting up the form submission listeners", () => {
let fields: MockProxy[];
let details: MockProxy;
diff --git a/apps/browser/src/autofill/background/overlay-notifications.background.ts b/apps/browser/src/autofill/background/overlay-notifications.background.ts
index ce30dd462b3..5c85ce132d7 100644
--- a/apps/browser/src/autofill/background/overlay-notifications.background.ts
+++ b/apps/browser/src/autofill/background/overlay-notifications.background.ts
@@ -1,11 +1,8 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
-import { startWith, Subject, Subscription, switchMap, timer } from "rxjs";
-import { pairwise } from "rxjs/operators";
+import { Subject, switchMap, timer } from "rxjs";
import { CLEAR_NOTIFICATION_LOGIN_DATA_DURATION } from "@bitwarden/common/autofill/constants";
-import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { BrowserApi } from "../../platform/browser/browser-api";
@@ -26,7 +23,6 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg
private websiteOriginsWithFields: WebsiteOriginsWithFields = new Map();
private activeFormSubmissionRequests: ActiveFormSubmissionRequests = new Set();
private modifyLoginCipherFormData: ModifyLoginCipherFormDataForTab = new Map();
- private featureFlagState$: Subscription;
private clearLoginCipherFormDataSubject: Subject = new Subject();
private notificationFallbackTimeout: number | NodeJS.Timeout | null;
private readonly formSubmissionRequestMethods: Set = new Set(["POST", "PUT", "PATCH"]);
@@ -38,7 +34,6 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg
constructor(
private logService: LogService,
- private configService: ConfigService,
private notificationBackground: NotificationBackground,
) {}
@@ -46,35 +41,13 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg
* Initialize the overlay notifications background service.
*/
async init() {
- this.featureFlagState$ = this.configService
- .getFeatureFlag$(FeatureFlag.NotificationBarAddLoginImprovements)
- .pipe(startWith(undefined), pairwise())
- .subscribe(([prev, current]) => this.handleInitFeatureFlagChange(prev, current));
+ this.setupExtensionListeners();
+
this.clearLoginCipherFormDataSubject
.pipe(switchMap(() => timer(CLEAR_NOTIFICATION_LOGIN_DATA_DURATION)))
.subscribe(() => this.modifyLoginCipherFormData.clear());
}
- /**
- * Handles enabling/disabling the extension listeners that trigger the
- * overlay notifications based on the feature flag state.
- *
- * @param previousValue - The previous value of the feature flag
- * @param currentValue - The current value of the feature flag
- */
- private handleInitFeatureFlagChange = (previousValue: boolean, currentValue: boolean) => {
- if (previousValue === currentValue) {
- return;
- }
-
- if (currentValue) {
- this.setupExtensionListeners();
- return;
- }
-
- this.removeExtensionListeners();
- };
-
/**
* Handles the response from the content script with the page details. Triggers an initialization
* of the add login or change password notification if the conditions are met.
@@ -520,15 +493,6 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg
chrome.tabs.onUpdated.addListener(this.handleTabUpdated);
}
- /**
- * Removes the listeners for the extension messages and the tab events.
- */
- private removeExtensionListeners() {
- BrowserApi.removeListener(chrome.runtime.onMessage, this.handleExtensionMessage);
- chrome.tabs.onRemoved.removeListener(this.handleTabRemoved);
- chrome.tabs.onUpdated.removeListener(this.handleTabUpdated);
- }
-
/**
* Handles messages that are sent to the extension background.
*
diff --git a/apps/browser/src/autofill/content/notification-bar.ts b/apps/browser/src/autofill/content/notification-bar.ts
deleted file mode 100644
index bf3d562a0ef..00000000000
--- a/apps/browser/src/autofill/content/notification-bar.ts
+++ /dev/null
@@ -1,1082 +0,0 @@
-// FIXME: Update this file to be type safe and remove this and next line
-// @ts-strict-ignore
-import { ServerConfig } from "@bitwarden/common/platform/abstractions/config/server-config";
-
-import {
- AddLoginMessageData,
- ChangePasswordMessageData,
-} from "../background/abstractions/notification.background";
-import AutofillField from "../models/autofill-field";
-import { WatchedForm } from "../models/watched-form";
-import { NotificationBarIframeInitData } from "../notification/abstractions/notification-bar";
-import { NotificationTypeData } from "../overlay/notifications/abstractions/overlay-notifications-content.service";
-import { FormData } from "../services/abstractions/autofill.service";
-import { sendExtensionMessage, setupExtensionDisconnectAction } from "../utils";
-
-interface HTMLElementWithFormOpId extends HTMLElement {
- formOpId: string;
-}
-
-/**
- * @fileoverview This file contains the code for the Bitwarden Notification Bar content script.
- * The notification bar is used to notify logged in users that they can
- * save a new login, change a existing password on a password change screen,
- * or update an existing login after detecting a different password on login.
- *
- * Note: content scripts are reloaded on non-SPA page change.
- */
-
-/*
- * Run content script when the DOM is fully loaded
- *
- * The DOMContentLoaded event fires when the HTML document has been completely parsed,
- * and all deferred scripts (