1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-05 18:13:26 +00:00

[PM-14613] Remove account deprovisioning feature flag (#14353)

This commit is contained in:
Thomas Rittson
2025-05-07 11:23:18 +10:00
committed by GitHub
parent 744c1b1b49
commit df40954b61
27 changed files with 153 additions and 519 deletions

View File

@@ -50,11 +50,15 @@ export abstract class BaseMembersComponent<UserView extends UserViewTypes> {
}
get showBulkConfirmUsers(): boolean {
return this.dataSource.acceptedUserCount > 0;
return this.dataSource
.getCheckedUsers()
.every((member) => member.status == this.userStatusType.Accepted);
}
get showBulkReinviteUsers(): boolean {
return this.dataSource.invitedUserCount > 0;
return this.dataSource
.getCheckedUsers()
.every((member) => member.status == this.userStatusType.Invited);
}
abstract userType: typeof OrganizationUserType | typeof ProviderUserType;

View File

@@ -115,7 +115,7 @@
*ngIf="canAccessExport$ | async"
></bit-nav-item>
<bit-nav-item
[text]="domainVerificationNavigationTextKey | i18n"
[text]="'claimedDomains' | i18n"
route="settings/domain-verification"
*ngIf="organization?.canManageDomainVerification"
></bit-nav-item>

View File

@@ -55,7 +55,6 @@ export class OrganizationLayoutComponent implements OnInit {
protected readonly logo = AdminConsoleLogo;
protected orgFilter = (org: Organization) => canAccessOrgAdmin(org);
protected domainVerificationNavigationTextKey: string;
protected integrationPageEnabled$: Observable<boolean>;
@@ -146,12 +145,6 @@ export class OrganizationLayoutComponent implements OnInit {
this.integrationPageEnabled$ = this.organization$.pipe(map((org) => org.canAccessIntegrations));
this.domainVerificationNavigationTextKey = (await this.configService.getFeatureFlag(
FeatureFlag.AccountDeprovisioning,
))
? "claimedDomains"
: "domainVerification";
this.canShowPoliciesTab$ = this.organization$.pipe(
switchMap((organization) =>
this.organizationBillingService

View File

@@ -1,12 +1,9 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Component, Inject } from "@angular/core";
import { firstValueFrom } from "rxjs";
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/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 { DIALOG_DATA, DialogConfig, DialogService } from "@bitwarden/components";
@@ -35,7 +32,6 @@ export class BulkDeleteDialogComponent {
@Inject(DIALOG_DATA) protected dialogParams: BulkDeleteDialogParams,
protected i18nService: I18nService,
private organizationUserApiService: OrganizationUserApiService,
private configService: ConfigService,
private deleteManagedMemberWarningService: DeleteManagedMemberWarningService,
) {
this.organizationId = dialogParams.organizationId;
@@ -43,11 +39,7 @@ export class BulkDeleteDialogComponent {
}
async submit() {
if (
await firstValueFrom(this.configService.getFeatureFlag$(FeatureFlag.AccountDeprovisioning))
) {
await this.deleteManagedMemberWarningService.acknowledgeWarning(this.organizationId);
}
await this.deleteManagedMemberWarningService.acknowledgeWarning(this.organizationId);
try {
this.loading = true;

View File

@@ -1,12 +1,6 @@
<bit-dialog
dialogSize="large"
*ngIf="{ enabled: accountDeprovisioningEnabled$ | async } as accountDeprovisioning"
>
<bit-dialog dialogSize="large">
<ng-container bitDialogTitle>
<span *ngIf="accountDeprovisioning.enabled; else nonMemberTitle">{{ bulkMemberTitle }}</span>
<ng-template #nonMemberTitle>
{{ bulkTitle }}
</ng-template>
<span>{{ bulkTitle }}</span>
</ng-container>
<div bitDialogContent>
@@ -20,7 +14,7 @@
<bit-callout
type="danger"
*ngIf="nonCompliantMembers && accountDeprovisioning.enabled"
*ngIf="nonCompliantMembers"
title="{{ 'nonCompliantMembersTitle' | i18n }}"
>
{{ "nonCompliantMembersError" | i18n }}
@@ -50,7 +44,7 @@
<bit-table>
<ng-container header>
<tr>
<th bitCell>{{ (accountDeprovisioning.enabled ? "member" : "user") | i18n }}</th>
<th bitCell>{{ "member" | i18n }}</th>
<th bitCell class="tw-w-1/2" *ngIf="this.showNoMasterPasswordWarning">
{{ "details" | i18n }}
</th>
@@ -82,7 +76,7 @@
<ng-container header>
<tr>
<th bitCell class="tw-w-1/2">
{{ (accountDeprovisioning.enabled ? "member" : "user") | i18n }}
{{ "member" | i18n }}
</th>
<th bitCell class="tw-w-1/2">{{ "status" | i18n }}</th>
</tr>
@@ -113,7 +107,7 @@
[bitAction]="submit"
buttonType="primary"
>
{{ accountDeprovisioning.enabled ? bulkMemberTitle : bulkTitle }}
{{ bulkTitle }}
</button>
<button type="button" bitButton buttonType="secondary" bitDialogClose>
{{ "close" | i18n }}

View File

@@ -1,12 +1,9 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Component, Inject } from "@angular/core";
import { Observable } from "rxjs";
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/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 { DIALOG_DATA, DialogService } from "@bitwarden/components";
@@ -34,12 +31,10 @@ export class BulkRestoreRevokeComponent {
error: string;
showNoMasterPasswordWarning = false;
nonCompliantMembers: boolean = false;
accountDeprovisioningEnabled$: Observable<boolean>;
constructor(
protected i18nService: I18nService,
private organizationUserApiService: OrganizationUserApiService,
private configService: ConfigService,
@Inject(DIALOG_DATA) protected data: BulkRestoreDialogParams,
) {
this.isRevoking = data.isRevoking;
@@ -48,17 +43,9 @@ export class BulkRestoreRevokeComponent {
this.showNoMasterPasswordWarning = this.users.some(
(u) => u.status > OrganizationUserStatusType.Invited && u.hasMasterPassword === false,
);
this.accountDeprovisioningEnabled$ = this.configService.getFeatureFlag$(
FeatureFlag.AccountDeprovisioning,
);
}
get bulkTitle() {
const titleKey = this.isRevoking ? "revokeUsers" : "restoreUsers";
return this.i18nService.t(titleKey);
}
get bulkMemberTitle() {
const titleKey = this.isRevoking ? "revokeMembers" : "restoreMembers";
return this.i18nService.t(titleKey);
}

View File

@@ -275,11 +275,7 @@
{{ "revoke" | i18n }}
</button>
<button
*ngIf="
this.editMode &&
(!(accountDeprovisioningEnabled$ | async) ||
!(editParams$ | async)?.managedByOrganization)
"
*ngIf="this.editMode && !(editParams$ | async)?.managedByOrganization"
type="button"
buttonType="danger"
bitButton
@@ -290,11 +286,7 @@
{{ "remove" | i18n }}
</button>
<button
*ngIf="
this.editMode &&
(accountDeprovisioningEnabled$ | async) &&
(editParams$ | async)?.managedByOrganization
"
*ngIf="this.editMode && (editParams$ | async)?.managedByOrganization"
type="button"
buttonType="danger"
bitButton

View File

@@ -152,10 +152,6 @@ export class MemberDialogComponent implements OnDestroy {
manageResetPassword: false,
});
protected accountDeprovisioningEnabled$: Observable<boolean> = this.configService.getFeatureFlag$(
FeatureFlag.AccountDeprovisioning,
);
protected isExternalIdVisible$ = this.configService
.getFeatureFlag$(FeatureFlag.SsoExternalIdVisibility)
.pipe(
@@ -667,11 +663,9 @@ export class MemberDialogComponent implements OnDestroy {
const showWarningDialog = combineLatest([
this.organization$,
this.deleteManagedMemberWarningService.warningAcknowledged(this.params.organizationId),
this.accountDeprovisioningEnabled$,
]).pipe(
map(
([organization, acknowledged, featureFlagEnabled]) =>
featureFlagEnabled &&
([organization, acknowledged]) =>
organization.canManageUsers &&
organization.productTierType === ProductTierType.Enterprise &&
!acknowledged,
@@ -714,9 +708,8 @@ export class MemberDialogComponent implements OnDestroy {
message: this.i18nService.t("organizationUserDeleted", this.params.name),
});
if (await firstValueFrom(this.accountDeprovisioningEnabled$)) {
await this.deleteManagedMemberWarningService.acknowledgeWarning(this.params.organizationId);
}
await this.deleteManagedMemberWarningService.acknowledgeWarning(this.params.organizationId);
this.close(MemberDialogResult.Deleted);
};

View File

@@ -345,7 +345,7 @@
{{ "revokeAccess" | i18n }}
</button>
<button
*ngIf="!accountDeprovisioningEnabled || !u.managedByOrganization"
*ngIf="!u.managedByOrganization"
type="button"
bitMenuItem
(click)="remove(u)"
@@ -355,7 +355,7 @@
</span>
</button>
<button
*ngIf="accountDeprovisioningEnabled && u.managedByOrganization"
*ngIf="u.managedByOrganization"
type="button"
bitMenuItem
(click)="deleteUser(u)"

View File

@@ -1,6 +1,6 @@
// 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 { Component, ViewChild, ViewContainerRef } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { ActivatedRoute, Router } from "@angular/router";
import {
@@ -46,9 +46,7 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
import { getUserId } from "@bitwarden/common/auth/services/account.service";
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
import { isNotSelfUpgradable, ProductTierType } from "@bitwarden/common/billing/enums";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.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 { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
@@ -91,7 +89,7 @@ class MembersTableDataSource extends PeopleTableDataSource<OrganizationUserView>
@Component({
templateUrl: "members.component.html",
})
export class MembersComponent extends BaseMembersComponent<OrganizationUserView> implements OnInit {
export class MembersComponent extends BaseMembersComponent<OrganizationUserView> {
@ViewChild("resetPasswordTemplate", { read: ViewContainerRef, static: true })
resetPasswordModalRef: ViewContainerRef;
@@ -104,7 +102,6 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
status: OrganizationUserStatusType = null;
orgResetPasswordPolicyEnabled = false;
orgIsOnSecretsManagerStandalone = false;
accountDeprovisioningEnabled = false;
protected canUseSecretsManager$: Observable<boolean>;
@@ -139,7 +136,6 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
private groupService: GroupApiService,
private collectionService: CollectionService,
private billingApiService: BillingApiServiceAbstraction,
private configService: ConfigService,
protected deleteManagedMemberWarningService: DeleteManagedMemberWarningService,
) {
super(
@@ -237,12 +233,6 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
.subscribe();
}
async ngOnInit() {
this.accountDeprovisioningEnabled = await this.configService.getFeatureFlag(
FeatureFlag.AccountDeprovisioning,
);
}
async getUsers(): Promise<OrganizationUserView[]> {
let groupsPromise: Promise<Map<string, string>>;
let collectionsPromise: Promise<Map<string, string>>;
@@ -591,20 +581,18 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
}
async bulkDelete() {
if (this.accountDeprovisioningEnabled) {
const warningAcknowledged = await firstValueFrom(
this.deleteManagedMemberWarningService.warningAcknowledged(this.organization.id),
);
const warningAcknowledged = await firstValueFrom(
this.deleteManagedMemberWarningService.warningAcknowledged(this.organization.id),
);
if (
!warningAcknowledged &&
this.organization.canManageUsers &&
this.organization.productTierType === ProductTierType.Enterprise
) {
const acknowledged = await this.deleteManagedMemberWarningService.showWarning();
if (!acknowledged) {
return;
}
if (
!warningAcknowledged &&
this.organization.canManageUsers &&
this.organization.productTierType === ProductTierType.Enterprise
) {
const acknowledged = await this.deleteManagedMemberWarningService.showWarning();
if (!acknowledged) {
return;
}
}
@@ -794,20 +782,18 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
}
async deleteUser(user: OrganizationUserView) {
if (this.accountDeprovisioningEnabled) {
const warningAcknowledged = await firstValueFrom(
this.deleteManagedMemberWarningService.warningAcknowledged(this.organization.id),
);
const warningAcknowledged = await firstValueFrom(
this.deleteManagedMemberWarningService.warningAcknowledged(this.organization.id),
);
if (
!warningAcknowledged &&
this.organization.canManageUsers &&
this.organization.productTierType === ProductTierType.Enterprise
) {
const acknowledged = await this.deleteManagedMemberWarningService.showWarning();
if (!acknowledged) {
return false;
}
if (
!warningAcknowledged &&
this.organization.canManageUsers &&
this.organization.productTierType === ProductTierType.Enterprise
) {
const acknowledged = await this.deleteManagedMemberWarningService.showWarning();
if (!acknowledged) {
return false;
}
}
@@ -829,9 +815,7 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
return false;
}
if (this.accountDeprovisioningEnabled) {
await this.deleteManagedMemberWarningService.acknowledgeWarning(this.organization.id);
}
await this.deleteManagedMemberWarningService.acknowledgeWarning(this.organization.id);
this.actionPromise = this.organizationUserApiService.deleteOrganizationUser(
this.organization.id,
@@ -864,56 +848,23 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
});
}
get showBulkConfirmUsers(): boolean {
if (!this.accountDeprovisioningEnabled) {
return super.showBulkConfirmUsers;
}
return this.dataSource
.getCheckedUsers()
.every((member) => member.status == this.userStatusType.Accepted);
}
get showBulkReinviteUsers(): boolean {
if (!this.accountDeprovisioningEnabled) {
return super.showBulkReinviteUsers;
}
return this.dataSource
.getCheckedUsers()
.every((member) => member.status == this.userStatusType.Invited);
}
get showBulkRestoreUsers(): boolean {
return (
!this.accountDeprovisioningEnabled ||
this.dataSource
.getCheckedUsers()
.every((member) => member.status == this.userStatusType.Revoked)
);
return this.dataSource
.getCheckedUsers()
.every((member) => member.status == this.userStatusType.Revoked);
}
get showBulkRevokeUsers(): boolean {
return (
!this.accountDeprovisioningEnabled ||
this.dataSource
.getCheckedUsers()
.every((member) => member.status != this.userStatusType.Revoked)
);
return this.dataSource
.getCheckedUsers()
.every((member) => member.status != this.userStatusType.Revoked);
}
get showBulkRemoveUsers(): boolean {
return (
!this.accountDeprovisioningEnabled ||
this.dataSource.getCheckedUsers().every((member) => !member.managedByOrganization)
);
return this.dataSource.getCheckedUsers().every((member) => !member.managedByOrganization);
}
get showBulkDeleteUsers(): boolean {
if (!this.accountDeprovisioningEnabled) {
return false;
}
const validStatuses = [
this.userStatusType.Accepted,
this.userStatusType.Confirmed,

View File

@@ -1,11 +1,6 @@
<bit-callout *ngIf="accountDeprovisioningEnabled$ | async; else disabledBlock" type="warning">
<bit-callout type="warning">
{{ "singleOrgPolicyMemberWarning" | i18n }}
</bit-callout>
<ng-template #disabledBlock>
<bit-callout type="warning">
{{ "singleOrgPolicyWarning" | i18n }}
</bit-callout>
</ng-template>
<bit-form-control>
<input type="checkbox" bitCheckbox [formControl]="enabled" id="enabled" />

View File

@@ -1,15 +1,12 @@
import { Component, OnInit } from "@angular/core";
import { firstValueFrom, Observable } from "rxjs";
import { PolicyType } from "@bitwarden/common/admin-console/enums";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { BasePolicy, BasePolicyComponent } from "./base-policy.component";
export class SingleOrgPolicy extends BasePolicy {
name = "singleOrg";
description = "singleOrgDesc";
description = "singleOrgPolicyDesc";
type = PolicyType.SingleOrg;
component = SingleOrgPolicyComponent;
}
@@ -19,22 +16,9 @@ export class SingleOrgPolicy extends BasePolicy {
templateUrl: "single-org.component.html",
})
export class SingleOrgPolicyComponent extends BasePolicyComponent implements OnInit {
constructor(private configService: ConfigService) {
super();
}
protected accountDeprovisioningEnabled$: Observable<boolean> = this.configService.getFeatureFlag$(
FeatureFlag.AccountDeprovisioning,
);
async ngOnInit() {
super.ngOnInit();
const isAccountDeprovisioningEnabled = await firstValueFrom(this.accountDeprovisioningEnabled$);
this.policy.description = isAccountDeprovisioningEnabled
? "singleOrgPolicyDesc"
: "singleOrgDesc";
if (!this.policyResponse.canToggleState) {
this.enabled.disable();
}