1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-12 06:13:38 +00:00

[PM-22371] remove end user activation flag (#16067)

This commit is contained in:
Jason Ng
2025-08-22 12:56:16 -04:00
committed by GitHub
parent 4676a122da
commit 6e9da95230
6 changed files with 2 additions and 68 deletions

View File

@@ -6,8 +6,6 @@ import { BehaviorSubject } from "rxjs";
import { BrowserExtensionIcon } from "@bitwarden/assets/svg"; import { BrowserExtensionIcon } from "@bitwarden/assets/svg";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { DeviceType } from "@bitwarden/common/enums"; import { DeviceType } from "@bitwarden/common/enums";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
@@ -22,7 +20,6 @@ describe("SetupExtensionComponent", () => {
let fixture: ComponentFixture<SetupExtensionComponent>; let fixture: ComponentFixture<SetupExtensionComponent>;
let component: SetupExtensionComponent; let component: SetupExtensionComponent;
const getFeatureFlag = jest.fn().mockResolvedValue(false);
const navigate = jest.fn().mockResolvedValue(true); const navigate = jest.fn().mockResolvedValue(true);
const openExtension = jest.fn().mockResolvedValue(true); const openExtension = jest.fn().mockResolvedValue(true);
const update = jest.fn().mockResolvedValue(true); const update = jest.fn().mockResolvedValue(true);
@@ -34,14 +31,12 @@ describe("SetupExtensionComponent", () => {
openExtension.mockClear(); openExtension.mockClear();
update.mockClear(); update.mockClear();
setAnonLayoutWrapperData.mockClear(); setAnonLayoutWrapperData.mockClear();
getFeatureFlag.mockClear().mockResolvedValue(true);
window.matchMedia = jest.fn().mockReturnValue(false); window.matchMedia = jest.fn().mockReturnValue(false);
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [SetupExtensionComponent, RouterModule.forRoot([])], imports: [SetupExtensionComponent, RouterModule.forRoot([])],
providers: [ providers: [
{ provide: I18nService, useValue: { t: (key: string) => key } }, { provide: I18nService, useValue: { t: (key: string) => key } },
{ provide: ConfigService, useValue: { getFeatureFlag } },
{ provide: WebBrowserInteractionService, useValue: { extensionInstalled$, openExtension } }, { provide: WebBrowserInteractionService, useValue: { extensionInstalled$, openExtension } },
{ provide: PlatformUtilsService, useValue: { getDevice: () => DeviceType.UnknownBrowser } }, { provide: PlatformUtilsService, useValue: { getDevice: () => DeviceType.UnknownBrowser } },
{ provide: AnonLayoutWrapperDataService, useValue: { setAnonLayoutWrapperData } }, { provide: AnonLayoutWrapperDataService, useValue: { setAnonLayoutWrapperData } },
@@ -74,19 +69,8 @@ describe("SetupExtensionComponent", () => {
}); });
describe("initialization", () => { describe("initialization", () => {
it("redirects to the vault if the feature flag is disabled", async () => {
Utils.isMobileBrowser = false;
getFeatureFlag.mockResolvedValue(false);
navigate.mockClear();
await component.ngOnInit();
expect(navigate).toHaveBeenCalledWith(["/vault"]);
});
it("redirects to the vault if the user is on a mobile browser", async () => { it("redirects to the vault if the user is on a mobile browser", async () => {
Utils.isMobileBrowser = true; Utils.isMobileBrowser = true;
getFeatureFlag.mockResolvedValue(true);
navigate.mockClear(); navigate.mockClear();
await component.ngOnInit(); await component.ngOnInit();
@@ -96,12 +80,10 @@ describe("SetupExtensionComponent", () => {
it("does not redirect the user", async () => { it("does not redirect the user", async () => {
Utils.isMobileBrowser = false; Utils.isMobileBrowser = false;
getFeatureFlag.mockResolvedValue(true);
navigate.mockClear(); navigate.mockClear();
await component.ngOnInit(); await component.ngOnInit();
expect(getFeatureFlag).toHaveBeenCalledWith(FeatureFlag.PM19315EndUserActivationMvp);
expect(navigate).not.toHaveBeenCalled(); expect(navigate).not.toHaveBeenCalled();
}); });
}); });

View File

@@ -8,8 +8,6 @@ import { JslibModule } from "@bitwarden/angular/jslib.module";
import { BrowserExtensionIcon, Party } from "@bitwarden/assets/svg"; import { BrowserExtensionIcon, Party } from "@bitwarden/assets/svg";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { getUserId } from "@bitwarden/common/auth/services/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";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { StateProvider } from "@bitwarden/common/platform/state"; import { StateProvider } from "@bitwarden/common/platform/state";
@@ -59,7 +57,6 @@ type SetupExtensionState = UnionOfValues<typeof SetupExtensionState>;
}) })
export class SetupExtensionComponent implements OnInit, OnDestroy { export class SetupExtensionComponent implements OnInit, OnDestroy {
private webBrowserExtensionInteractionService = inject(WebBrowserInteractionService); private webBrowserExtensionInteractionService = inject(WebBrowserInteractionService);
private configService = inject(ConfigService);
private router = inject(Router); private router = inject(Router);
private destroyRef = inject(DestroyRef); private destroyRef = inject(DestroyRef);
private platformUtilsService = inject(PlatformUtilsService); private platformUtilsService = inject(PlatformUtilsService);
@@ -134,12 +131,9 @@ export class SetupExtensionComponent implements OnInit, OnDestroy {
/** Conditionally redirects the user to the vault upon landing on the page. */ /** Conditionally redirects the user to the vault upon landing on the page. */
async conditionallyRedirectUser() { async conditionallyRedirectUser() {
const isFeatureEnabled = await this.configService.getFeatureFlag(
FeatureFlag.PM19315EndUserActivationMvp,
);
const isMobile = Utils.isMobileBrowser; const isMobile = Utils.isMobileBrowser;
if (!isFeatureEnabled || isMobile) { if (isMobile) {
await this.dismissExtensionPage(); await this.dismissExtensionPage();
await this.router.navigate(["/vault"]); await this.router.navigate(["/vault"]);
} }

View File

@@ -4,8 +4,6 @@ import { BehaviorSubject } from "rxjs";
import { VaultProfileService } from "@bitwarden/angular/vault/services/vault-profile.service"; import { VaultProfileService } from "@bitwarden/angular/vault/services/vault-profile.service";
import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { StateProvider } from "@bitwarden/common/platform/state"; import { StateProvider } from "@bitwarden/common/platform/state";
@@ -27,26 +25,17 @@ describe("setupExtensionRedirectGuard", () => {
const extensionInstalled$ = new BehaviorSubject<boolean>(false); const extensionInstalled$ = new BehaviorSubject<boolean>(false);
const state$ = new BehaviorSubject<boolean>(false); const state$ = new BehaviorSubject<boolean>(false);
const createUrlTree = jest.fn(); const createUrlTree = jest.fn();
const getFeatureFlag = jest.fn().mockImplementation((key) => {
if (key === FeatureFlag.PM19315EndUserActivationMvp) {
return Promise.resolve(true);
}
return Promise.resolve(false);
});
const getProfileCreationDate = jest.fn().mockResolvedValue(seventeenDaysAgo); const getProfileCreationDate = jest.fn().mockResolvedValue(seventeenDaysAgo);
beforeEach(() => { beforeEach(() => {
Utils.isMobileBrowser = false; Utils.isMobileBrowser = false;
getFeatureFlag.mockClear();
getProfileCreationDate.mockClear(); getProfileCreationDate.mockClear();
createUrlTree.mockClear(); createUrlTree.mockClear();
TestBed.configureTestingModule({ TestBed.configureTestingModule({
providers: [ providers: [
{ provide: Router, useValue: { createUrlTree } }, { provide: Router, useValue: { createUrlTree } },
{ provide: ConfigService, useValue: { getFeatureFlag } },
{ provide: AccountService, useValue: { activeAccount$ } }, { provide: AccountService, useValue: { activeAccount$ } },
{ provide: StateProvider, useValue: { getUser: () => ({ state$ }) } }, { provide: StateProvider, useValue: { getUser: () => ({ state$ }) } },
{ provide: WebBrowserInteractionService, useValue: { extensionInstalled$ } }, { provide: WebBrowserInteractionService, useValue: { extensionInstalled$ } },
@@ -81,12 +70,6 @@ describe("setupExtensionRedirectGuard", () => {
expect(await setupExtensionGuard()).toBe(true); expect(await setupExtensionGuard()).toBe(true);
}); });
it("returns `true` when the feature flag is disabled", async () => {
getFeatureFlag.mockResolvedValueOnce(false);
expect(await setupExtensionGuard()).toBe(true);
});
it("returns `true` when the user is on a mobile device", async () => { it("returns `true` when the user is on a mobile device", async () => {
Utils.isMobileBrowser = true; Utils.isMobileBrowser = true;

View File

@@ -4,8 +4,6 @@ import { firstValueFrom, map } from "rxjs";
import { VaultProfileService } from "@bitwarden/angular/vault/services/vault-profile.service"; import { VaultProfileService } from "@bitwarden/angular/vault/services/vault-profile.service";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { import {
SETUP_EXTENSION_DISMISSED_DISK, SETUP_EXTENSION_DISMISSED_DISK,
@@ -26,7 +24,6 @@ export const SETUP_EXTENSION_DISMISSED = new UserKeyDefinition<boolean>(
export const setupExtensionRedirectGuard: CanActivateFn = async () => { export const setupExtensionRedirectGuard: CanActivateFn = async () => {
const router = inject(Router); const router = inject(Router);
const configService = inject(ConfigService);
const accountService = inject(AccountService); const accountService = inject(AccountService);
const vaultProfileService = inject(VaultProfileService); const vaultProfileService = inject(VaultProfileService);
const stateProvider = inject(StateProvider); const stateProvider = inject(StateProvider);
@@ -34,13 +31,9 @@ export const setupExtensionRedirectGuard: CanActivateFn = async () => {
const isMobile = Utils.isMobileBrowser; const isMobile = Utils.isMobileBrowser;
const endUserFeatureEnabled = await configService.getFeatureFlag(
FeatureFlag.PM19315EndUserActivationMvp,
);
// The extension page isn't applicable for mobile users, do not redirect them. // The extension page isn't applicable for mobile users, do not redirect them.
// Include before any other checks to avoid unnecessary processing. // Include before any other checks to avoid unnecessary processing.
if (!endUserFeatureEnabled || isMobile) { if (isMobile) {
return true; return true;
} }

View File

@@ -10,9 +10,7 @@ import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/mod
import { AccountApiService } from "@bitwarden/common/auth/abstractions/account-api.service"; import { AccountApiService } from "@bitwarden/common/auth/abstractions/account-api.service";
import { RegisterVerificationEmailClickedRequest } from "@bitwarden/common/auth/models/request/registration/register-verification-email-clicked.request"; import { RegisterVerificationEmailClickedRequest } from "@bitwarden/common/auth/models/request/registration/register-verification-email-clicked.request";
import { HttpStatusCode } from "@bitwarden/common/enums"; import { HttpStatusCode } from "@bitwarden/common/enums";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service"; import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
@@ -79,7 +77,6 @@ export class RegistrationFinishComponent implements OnInit, OnDestroy {
private logService: LogService, private logService: LogService,
private anonLayoutWrapperDataService: AnonLayoutWrapperDataService, private anonLayoutWrapperDataService: AnonLayoutWrapperDataService,
private loginSuccessHandlerService: LoginSuccessHandlerService, private loginSuccessHandlerService: LoginSuccessHandlerService,
private configService: ConfigService,
) {} ) {}
async ngOnInit() { async ngOnInit() {
@@ -189,19 +186,6 @@ export class RegistrationFinishComponent implements OnInit, OnDestroy {
return; return;
} }
const endUserActivationFlagEnabled = await this.configService.getFeatureFlag(
FeatureFlag.PM19315EndUserActivationMvp,
);
if (!endUserActivationFlagEnabled) {
// Only show the toast when the end user activation feature flag is _not_ enabled
this.toastService.showToast({
variant: "success",
title: null,
message: this.i18nService.t("youHaveBeenLoggedIn"),
});
}
await this.loginSuccessHandlerService.run(authenticationResult.userId); await this.loginSuccessHandlerService.run(authenticationResult.userId);
await this.router.navigate(["/vault"]); await this.router.navigate(["/vault"]);

View File

@@ -50,7 +50,6 @@ export enum FeatureFlag {
PM22136_SdkCipherEncryption = "pm-22136-sdk-cipher-encryption", PM22136_SdkCipherEncryption = "pm-22136-sdk-cipher-encryption",
CipherKeyEncryption = "cipher-key-encryption", CipherKeyEncryption = "cipher-key-encryption",
RemoveCardItemTypePolicy = "pm-16442-remove-card-item-type-policy", RemoveCardItemTypePolicy = "pm-16442-remove-card-item-type-policy",
PM19315EndUserActivationMvp = "pm-19315-end-user-activation-mvp",
/* Platform */ /* Platform */
IpcChannelFramework = "ipc-channel-framework", IpcChannelFramework = "ipc-channel-framework",
@@ -92,7 +91,6 @@ export const DefaultFeatureFlagValue = {
[FeatureFlag.PM19941MigrateCipherDomainToSdk]: FALSE, [FeatureFlag.PM19941MigrateCipherDomainToSdk]: FALSE,
[FeatureFlag.RemoveCardItemTypePolicy]: FALSE, [FeatureFlag.RemoveCardItemTypePolicy]: FALSE,
[FeatureFlag.PM22134SdkCipherListView]: FALSE, [FeatureFlag.PM22134SdkCipherListView]: FALSE,
[FeatureFlag.PM19315EndUserActivationMvp]: FALSE,
[FeatureFlag.PM22136_SdkCipherEncryption]: FALSE, [FeatureFlag.PM22136_SdkCipherEncryption]: FALSE,
/* Auth */ /* Auth */