1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-10 05:13:29 +00:00

fix(ChangePasswordComp): [Auth/PM-23913] Extension popout now closes after a password change (#15681)

This commit is contained in:
Jared Snider
2025-07-23 12:58:44 -04:00
committed by GitHub
parent 2040be68e3
commit e47e1f79d9
5 changed files with 96 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
import { MockProxy, mock } from "jest-mock-extended";
import { ChangePasswordService } from "@bitwarden/angular/auth/password-management/change-password";
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
import { KeyService } from "@bitwarden/key-management";
import { BrowserApi } from "../../../platform/browser/browser-api";
import BrowserPopupUtils from "../../../platform/browser/browser-popup-utils";
import { ExtensionChangePasswordService } from "./extension-change-password.service";
describe("ExtensionChangePasswordService", () => {
let keyService: MockProxy<KeyService>;
let masterPasswordApiService: MockProxy<MasterPasswordApiService>;
let masterPasswordService: MockProxy<InternalMasterPasswordServiceAbstraction>;
let window: MockProxy<Window>;
let changePasswordService: ChangePasswordService;
beforeEach(() => {
keyService = mock<KeyService>();
masterPasswordApiService = mock<MasterPasswordApiService>();
masterPasswordService = mock<InternalMasterPasswordServiceAbstraction>();
window = mock<Window>();
changePasswordService = new ExtensionChangePasswordService(
keyService,
masterPasswordApiService,
masterPasswordService,
window,
);
});
it("should instantiate the service", () => {
expect(changePasswordService).toBeDefined();
});
it("should close the browser extension popout", () => {
const closePopupSpy = jest.spyOn(BrowserApi, "closePopup");
const browserPopupUtilsInPopupSpy = jest
.spyOn(BrowserPopupUtils, "inPopout")
.mockReturnValue(true);
changePasswordService.closeBrowserExtensionPopout?.();
expect(closePopupSpy).toHaveBeenCalledWith(window);
expect(browserPopupUtilsInPopupSpy).toHaveBeenCalledWith(window);
});
});

View File

@@ -0,0 +1,29 @@
import {
DefaultChangePasswordService,
ChangePasswordService,
} from "@bitwarden/angular/auth/password-management/change-password";
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
import { KeyService } from "@bitwarden/key-management";
import { BrowserApi } from "../../../platform/browser/browser-api";
import BrowserPopupUtils from "../../../platform/browser/browser-popup-utils";
export class ExtensionChangePasswordService
extends DefaultChangePasswordService
implements ChangePasswordService
{
constructor(
protected keyService: KeyService,
protected masterPasswordApiService: MasterPasswordApiService,
protected masterPasswordService: InternalMasterPasswordServiceAbstraction,
private win: Window,
) {
super(keyService, masterPasswordApiService, masterPasswordService);
}
closeBrowserExtensionPopout(): void {
if (BrowserPopupUtils.inPopout(this.win)) {
BrowserApi.closePopup(this.win);
}
}
}

View File

@@ -5,6 +5,7 @@ import { merge, of, Subject } from "rxjs";
import { CollectionService } from "@bitwarden/admin-console/common";
import { DeviceManagementComponentServiceAbstraction } from "@bitwarden/angular/auth/device-management/device-management-component.service.abstraction";
import { ChangePasswordService } from "@bitwarden/angular/auth/password-management/change-password";
import { AngularThemingService } from "@bitwarden/angular/platform/services/theming/angular-theming.service";
import { SafeProvider, safeProvider } from "@bitwarden/angular/platform/utils/safe-provider";
import { ViewCacheService } from "@bitwarden/angular/platform/view-cache";
@@ -45,6 +46,7 @@ import {
AccountService as AccountServiceAbstraction,
} from "@bitwarden/common/auth/abstractions/account.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { MasterPasswordApiService } from "@bitwarden/common/auth/abstractions/master-password-api.service.abstraction";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import {
@@ -143,6 +145,7 @@ import {
import { AccountSwitcherService } from "../../auth/popup/account-switching/services/account-switcher.service";
import { ForegroundLockService } from "../../auth/popup/accounts/foreground-lock.service";
import { ExtensionChangePasswordService } from "../../auth/popup/change-password/extension-change-password.service";
import { ExtensionLoginComponentService } from "../../auth/popup/login/extension-login-component.service";
import { ExtensionSsoComponentService } from "../../auth/popup/login/extension-sso-component.service";
import { ExtensionLogoutService } from "../../auth/popup/logout/extension-logout.service";
@@ -664,6 +667,11 @@ const safeProviders: SafeProvider[] = [
useClass: DefaultSshImportPromptService,
deps: [DialogService, ToastService, PlatformUtilsService, I18nServiceAbstraction],
}),
safeProvider({
provide: ChangePasswordService,
useClass: ExtensionChangePasswordService,
deps: [KeyService, MasterPasswordApiService, InternalMasterPasswordServiceAbstraction, WINDOW],
}),
safeProvider({
provide: NotificationsService,
useClass: ForegroundNotificationsService,

View File

@@ -178,6 +178,9 @@ export class ChangePasswordComponent implements OnInit {
// TODO: PM-23515 eventually use the logout service instead of messaging service once it is available without circular dependencies
this.messagingService.send("logout");
// Close the popout if we are in a browser extension popout.
this.changePasswordService.closeBrowserExtensionPopout?.();
}
} catch (error) {
this.logService.error(error);

View File

@@ -59,4 +59,10 @@ export abstract class ChangePasswordService {
* - Currently only used on the web change password service.
*/
clearDeeplinkState?: () => Promise<void>;
/**
* Optional method that closes the browser extension popout if in a popout
* If not in a popout, does nothing.
*/
abstract closeBrowserExtensionPopout?(): void;
}