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

chore(flag-removal): [Auth/PM20439] Remove flagging logic and flag (BrowserExtensionLoginApproval) (#16568)

This commit is contained in:
rr-bw
2025-09-29 13:29:56 -07:00
committed by GitHub
parent 0bfc5daa7c
commit 5f7e1f99bf
11 changed files with 64 additions and 127 deletions

View File

@@ -102,7 +102,7 @@
</bit-card>
</bit-section>
<bit-section *ngIf="extensionLoginApprovalFlagEnabled">
<bit-section>
<bit-section-header>
<h2 bitTypography="h6">{{ "manageDevices" | i18n }}</h2>
</bit-section-header>

View File

@@ -1,6 +1,7 @@
import { Component } from "@angular/core";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { By } from "@angular/platform-browser";
import { ActivatedRoute } from "@angular/router";
import { mock } from "jest-mock-extended";
import { firstValueFrom, of } from "rxjs";
@@ -19,7 +20,6 @@ import {
VaultTimeoutStringType,
VaultTimeoutAction,
} from "@bitwarden/common/key-management/vault-timeout";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.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";
@@ -67,6 +67,7 @@ describe("AccountSecurityComponent", () => {
providers: [
{ provide: AccountService, useValue: accountService },
{ provide: AccountSecurityComponent, useValue: mock<AccountSecurityComponent>() },
{ provide: ActivatedRoute, useValue: mock<ActivatedRoute>() },
{ provide: BiometricsService, useValue: mock<BiometricsService>() },
{ provide: BiometricStateService, useValue: biometricStateService },
{ provide: DialogService, useValue: dialogService },
@@ -88,7 +89,6 @@ describe("AccountSecurityComponent", () => {
{ provide: LogService, useValue: mock<LogService>() },
{ provide: OrganizationService, useValue: mock<OrganizationService>() },
{ provide: CollectionService, useValue: mock<CollectionService>() },
{ provide: ConfigService, useValue: mock<ConfigService>() },
{ provide: ValidationService, useValue: validationService },
],
})

View File

@@ -31,7 +31,6 @@ import { getFirstPolicy } from "@bitwarden/common/admin-console/services/policy/
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { getUserId } from "@bitwarden/common/auth/services/account.service";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { PinServiceAbstraction } from "@bitwarden/common/key-management/pin/pin.service.abstraction";
import {
VaultTimeout,
@@ -41,7 +40,6 @@ import {
VaultTimeoutSettingsService,
VaultTimeoutStringType,
} from "@bitwarden/common/key-management/vault-timeout";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.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";
@@ -115,7 +113,6 @@ export class AccountSecurityComponent implements OnInit, OnDestroy {
biometricUnavailabilityReason: string;
showChangeMasterPass = true;
pinEnabled$: Observable<boolean> = of(true);
extensionLoginApprovalFlagEnabled = false;
form = this.formBuilder.group({
vaultTimeout: [null as VaultTimeout | null],
@@ -157,7 +154,6 @@ export class AccountSecurityComponent implements OnInit, OnDestroy {
private biometricsService: BiometricsService,
private vaultNudgesService: NudgesService,
private validationService: ValidationService,
private configService: ConfigService,
private logService: LogService,
) {}
@@ -239,10 +235,6 @@ export class AccountSecurityComponent implements OnInit, OnDestroy {
};
this.form.patchValue(initialValues, { emitEvent: false });
this.extensionLoginApprovalFlagEnabled = await this.configService.getFeatureFlag(
FeatureFlag.PM14938_BrowserExtensionLoginApproval,
);
timer(0, 1000)
.pipe(
switchMap(async () => {

View File

@@ -14,7 +14,6 @@ import {
} from "@bitwarden/angular/auth/guards";
import { ChangePasswordComponent } from "@bitwarden/angular/auth/password-management/change-password";
import { SetInitialPasswordComponent } from "@bitwarden/angular/auth/password-management/set-initial-password/set-initial-password.component";
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
import {
DevicesIcon,
RegistrationUserAddIcon,
@@ -40,7 +39,6 @@ import {
TwoFactorAuthComponent,
TwoFactorAuthGuard,
} from "@bitwarden/auth/angular";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { AnonLayoutWrapperComponent, AnonLayoutWrapperData } from "@bitwarden/components";
import { LockComponent, ConfirmKeyConnectorDomainComponent } from "@bitwarden/key-management-ui";
@@ -262,7 +260,7 @@ const routes: Routes = [
{
path: "device-management",
component: ExtensionDeviceManagementComponent,
canActivate: [canAccessFeature(FeatureFlag.PM14938_BrowserExtensionLoginApproval), authGuard],
canActivate: [authGuard],
data: { elevation: 1 } satisfies RouteDataProperties,
},
{

View File

@@ -42,9 +42,7 @@ import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { PendingAuthRequestsStateService } from "@bitwarden/common/auth/services/auth-request-answering/pending-auth-requests.state";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { AnimationControlService } from "@bitwarden/common/platform/abstractions/animation-control.service";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.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";
@@ -82,7 +80,6 @@ export class AppComponent implements OnInit, OnDestroy {
private activeUserId: UserId;
private routerAnimations = false;
private processingPendingAuth = false;
private extensionLoginApprovalFeatureFlag = false;
private destroy$ = new Subject<void>();
@@ -118,7 +115,6 @@ export class AppComponent implements OnInit, OnDestroy {
private authRequestService: AuthRequestServiceAbstraction,
private pendingAuthRequestsState: PendingAuthRequestsStateService,
private authRequestAnsweringService: AuthRequestAnsweringServiceAbstraction,
private readonly configService: ConfigService,
) {
this.deviceTrustToastService.setupListeners$.pipe(takeUntilDestroyed()).subscribe();
@@ -127,10 +123,6 @@ export class AppComponent implements OnInit, OnDestroy {
}
async ngOnInit() {
this.extensionLoginApprovalFeatureFlag = await firstValueFrom(
this.configService.getFeatureFlag$(FeatureFlag.PM14938_BrowserExtensionLoginApproval),
);
initPopupClosedListener();
this.compactModeService.init();
@@ -140,24 +132,22 @@ export class AppComponent implements OnInit, OnDestroy {
this.activeUserId = account?.id;
});
if (this.extensionLoginApprovalFeatureFlag) {
// Trigger processing auth requests when the active user is in an unlocked state. Runs once when
// the popup is open.
this.accountService.activeAccount$
.pipe(
map((a) => a?.id), // Extract active userId
distinctUntilChanged(), // Only when userId actually changes
filter((userId) => userId != null), // Require a valid userId
switchMap((userId) => this.authService.authStatusFor$(userId).pipe(take(1))), // Get current auth status once for new user
filter((status) => status === AuthenticationStatus.Unlocked), // Only when the new user is Unlocked
tap(() => {
// Trigger processing when switching users while popup is open
void this.authRequestAnsweringService.processPendingAuthRequests();
}),
takeUntil(this.destroy$),
)
.subscribe();
}
// Trigger processing auth requests when the active user is in an unlocked state. Runs once when
// the popup is open.
this.accountService.activeAccount$
.pipe(
map((a) => a?.id), // Extract active userId
distinctUntilChanged(), // Only when userId actually changes
filter((userId) => userId != null), // Require a valid userId
switchMap((userId) => this.authService.authStatusFor$(userId).pipe(take(1))), // Get current auth status once for new user
filter((status) => status === AuthenticationStatus.Unlocked), // Only when the new user is Unlocked
tap(() => {
// Trigger processing when switching users while popup is open
void this.authRequestAnsweringService.processPendingAuthRequests();
}),
takeUntil(this.destroy$),
)
.subscribe();
this.authService.activeAccountStatus$
.pipe(
@@ -169,24 +159,22 @@ export class AppComponent implements OnInit, OnDestroy {
)
.subscribe();
if (this.extensionLoginApprovalFeatureFlag) {
// When the popup is already open and the active account transitions to Unlocked,
// process any pending auth requests for the active user. The above subscription does not handle
// this case.
this.authService.activeAccountStatus$
.pipe(
startWith(null as unknown as AuthenticationStatus), // Seed previous value to handle initial emission
pairwise(), // Compare previous and current statuses
filter(
([prev, curr]) =>
prev !== AuthenticationStatus.Unlocked && curr === AuthenticationStatus.Unlocked, // Fire on transitions into Unlocked (incl. initial)
),
takeUntil(this.destroy$),
)
.subscribe(() => {
void this.authRequestAnsweringService.processPendingAuthRequests();
});
}
// When the popup is already open and the active account transitions to Unlocked,
// process any pending auth requests for the active user. The above subscription does not handle
// this case.
this.authService.activeAccountStatus$
.pipe(
startWith(null as unknown as AuthenticationStatus), // Seed previous value to handle initial emission
pairwise(), // Compare previous and current statuses
filter(
([prev, curr]) =>
prev !== AuthenticationStatus.Unlocked && curr === AuthenticationStatus.Unlocked, // Fire on transitions into Unlocked (incl. initial)
),
takeUntil(this.destroy$),
)
.subscribe(() => {
void this.authRequestAnsweringService.processPendingAuthRequests();
});
this.ngZone.runOutsideAngular(() => {
window.onmousedown = () => this.recordActivity();
@@ -241,10 +229,7 @@ export class AppComponent implements OnInit, OnDestroy {
}
await this.router.navigate(["lock"]);
} else if (
msg.command === "openLoginApproval" &&
this.extensionLoginApprovalFeatureFlag
) {
} else if (msg.command === "openLoginApproval") {
if (this.processingPendingAuth) {
return;
}