();
- constructor(
- private i18nService: I18nService,
- private configService: ConfigService,
- ) {}
+ constructor(private i18nService: I18nService) {}
- async ngOnInit() {
- this.extensionRefreshEnabled = await firstValueFrom(
- this.configService.getFeatureFlag$(FeatureFlag.ExtensionRefresh),
- );
- }
+ async ngOnInit() {}
/**
* The id of the organization that is currently being filtered on.
diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.html b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.html
index b9647e3237d..aa56daac071 100644
--- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.html
+++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.html
@@ -22,12 +22,7 @@
{{ "onboardingImportDataDetailsPartOne" | i18n }}
{{ "onboardingImportDataDetailsPartTwoNoOrgs" | i18n }}
diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts
index e017bc9b35d..327a077dc6a 100644
--- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts
+++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts
@@ -7,7 +7,6 @@ import { Subject, of } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateProvider } from "@bitwarden/common/platform/state";
@@ -28,7 +27,6 @@ describe("VaultOnboardingComponent", () => {
let mockStateProvider: Partial;
let setInstallExtLinkSpy: any;
let individualVaultPolicyCheckSpy: any;
- let mockConfigService: MockProxy;
beforeEach(() => {
mockPolicyService = mock();
@@ -47,7 +45,6 @@ describe("VaultOnboardingComponent", () => {
}),
),
};
- mockConfigService = mock();
// eslint-disable-next-line @typescript-eslint/no-floating-promises
TestBed.configureTestingModule({
@@ -60,7 +57,6 @@ describe("VaultOnboardingComponent", () => {
{ provide: I18nService, useValue: mockI18nService },
{ provide: ApiService, useValue: mockApiService },
{ provide: StateProvider, useValue: mockStateProvider },
- { provide: ConfigService, useValue: mockConfigService },
],
}).compileComponents();
fixture = TestBed.createComponent(VaultOnboardingComponent);
diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts
index 3535d31852e..e3bd8fc10bd 100644
--- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts
+++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts
@@ -18,8 +18,6 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { PolicyType } from "@bitwarden/common/admin-console/enums";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
-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 { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
import { VaultOnboardingMessages } from "@bitwarden/common/vault/enums/vault-onboarding.enum";
@@ -58,14 +56,12 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy {
protected onboardingTasks$: Observable;
protected showOnboarding = false;
- protected extensionRefreshEnabled = false;
constructor(
protected platformUtilsService: PlatformUtilsService,
protected policyService: PolicyService,
private apiService: ApiService,
private vaultOnboardingService: VaultOnboardingServiceAbstraction,
- private configService: ConfigService,
) {}
async ngOnInit() {
@@ -74,9 +70,6 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy {
this.setInstallExtLink();
this.individualVaultPolicyCheck();
this.checkForBrowserExtension();
- this.extensionRefreshEnabled = await this.configService.getFeatureFlag(
- FeatureFlag.ExtensionRefresh,
- );
}
async ngOnChanges(changes: SimpleChanges) {
diff --git a/apps/web/src/app/vault/individual-vault/vault.component.ts b/apps/web/src/app/vault/individual-vault/vault.component.ts
index 950c1d77731..ff8a008bcc5 100644
--- a/apps/web/src/app/vault/individual-vault/vault.component.ts
+++ b/apps/web/src/app/vault/individual-vault/vault.component.ts
@@ -1,15 +1,7 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { DialogRef } from "@angular/cdk/dialog";
-import {
- ChangeDetectorRef,
- Component,
- NgZone,
- OnDestroy,
- OnInit,
- ViewChild,
- ViewContainerRef,
-} from "@angular/core";
+import { ChangeDetectorRef, Component, NgZone, OnDestroy, OnInit, ViewChild } from "@angular/core";
import { ActivatedRoute, Params, Router } from "@angular/router";
import {
BehaviorSubject,
@@ -42,7 +34,6 @@ import {
Unassigned,
} from "@bitwarden/admin-console/common";
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
-import { ModalService } from "@bitwarden/angular/services/modal.service";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
import { SearchService } from "@bitwarden/common/abstractions/search.service";
@@ -57,9 +48,7 @@ import { OrganizationBillingServiceAbstraction } from "@bitwarden/common/billing
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
import { EventType } from "@bitwarden/common/enums";
-import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.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 { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@@ -71,7 +60,6 @@ import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.servi
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
import { CipherType } from "@bitwarden/common/vault/enums";
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
-import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { ServiceUtils } from "@bitwarden/common/vault/service-utils";
@@ -105,13 +93,11 @@ import { VaultItemEvent } from "../components/vault-items/vault-item-event";
import { VaultItemsModule } from "../components/vault-items/vault-items.module";
import { getNestedCollectionTree } from "../utils/collection-utils";
-import { AddEditComponent } from "./add-edit.component";
import {
AttachmentDialogCloseResult,
AttachmentDialogResult,
AttachmentsV2Component,
} from "./attachments-v2.component";
-import { AttachmentsComponent } from "./attachments.component";
import {
BulkDeleteDialogResult,
openBulkDeleteDialog,
@@ -160,15 +146,6 @@ const SearchTextDebounceInterval = 200;
})
export class VaultComponent implements OnInit, OnDestroy {
@ViewChild("vaultFilter", { static: true }) filterComponent: VaultFilterComponent;
- @ViewChild("attachments", { read: ViewContainerRef, static: true })
- attachmentsModalRef: ViewContainerRef;
- @ViewChild("folderAddEdit", { read: ViewContainerRef, static: true })
- folderAddEditModalRef: ViewContainerRef;
- @ViewChild("cipherAddEdit", { read: ViewContainerRef, static: true })
- cipherAddEditModalRef: ViewContainerRef;
- @ViewChild("share", { read: ViewContainerRef, static: true }) shareModalRef: ViewContainerRef;
- @ViewChild("collectionsModal", { read: ViewContainerRef, static: true })
- collectionsModalRef: ViewContainerRef;
trashCleanupWarning: string = null;
kdfIterations: number;
@@ -193,7 +170,6 @@ export class VaultComponent implements OnInit, OnDestroy {
private searchText$ = new Subject();
private refresh$ = new BehaviorSubject(null);
private destroy$ = new Subject();
- private extensionRefreshEnabled: boolean;
private hasSubscription$ = new BehaviorSubject(false);
private vaultItemDialogRef?: DialogRef | undefined;
@@ -260,7 +236,6 @@ export class VaultComponent implements OnInit, OnDestroy {
private router: Router,
private changeDetectorRef: ChangeDetectorRef,
private i18nService: I18nService,
- private modalService: ModalService,
private dialogService: DialogService,
private messagingService: MessagingService,
private platformUtilsService: PlatformUtilsService,
@@ -278,7 +253,6 @@ export class VaultComponent implements OnInit, OnDestroy {
private eventCollectionService: EventCollectionService,
private searchService: SearchService,
private searchPipe: SearchPipe,
- private configService: ConfigService,
private apiService: ApiService,
private billingAccountProfileStateService: BillingAccountProfileStateService,
private toastService: ToastService,
@@ -437,15 +411,15 @@ export class VaultComponent implements OnInit, OnDestroy {
firstSetup$
.pipe(
switchMap(() => this.route.queryParams),
- // Only process the queryParams if the dialog is not open (only when extension refresh is enabled)
- filter(() => this.vaultItemDialogRef == undefined || !this.extensionRefreshEnabled),
+ // Only process the queryParams if the dialog is not open
+ filter(() => this.vaultItemDialogRef == undefined),
switchMap(async (params) => {
const cipherId = getCipherIdFromParams(params);
if (cipherId) {
if (await this.cipherService.get(cipherId)) {
let action = params.action;
- // Default to "view" if extension refresh is enabled
- if (action == null && this.extensionRefreshEnabled) {
+ // Default to "view"
+ if (action == null) {
action = "view";
}
@@ -544,11 +518,6 @@ export class VaultComponent implements OnInit, OnDestroy {
this.refreshing = false;
},
);
-
- // Check if the extension refresh feature flag is enabled
- this.extensionRefreshEnabled = await this.configService.getFeatureFlag(
- FeatureFlag.ExtensionRefresh,
- );
}
ngOnDestroy() {
@@ -642,8 +611,7 @@ export class VaultComponent implements OnInit, OnDestroy {
* Handles opening the attachments dialog for a cipher.
* Runs several checks to ensure that the user has the correct permissions
* and then opens the attachments dialog.
- * Uses the new AttachmentsV2Component if the extensionRefresh feature flag is enabled.
- *
+ * Uses the new AttachmentsV2Component
* @param cipher
* @returns
*/
@@ -668,51 +636,20 @@ export class VaultComponent implements OnInit, OnDestroy {
}
}
- const canEditAttachments = await this.canEditAttachments(cipher);
+ const dialogRef = AttachmentsV2Component.open(this.dialogService, {
+ cipherId: cipher.id as CipherId,
+ });
- let madeAttachmentChanges = false;
+ const result: AttachmentDialogCloseResult = await lastValueFrom(dialogRef.closed);
- if (this.extensionRefreshEnabled) {
- const dialogRef = AttachmentsV2Component.open(this.dialogService, {
- cipherId: cipher.id as CipherId,
- });
-
- const result: AttachmentDialogCloseResult = await lastValueFrom(dialogRef.closed);
-
- if (
- result.action === AttachmentDialogResult.Uploaded ||
- result.action === AttachmentDialogResult.Removed
- ) {
- this.refresh();
- }
-
- return;
+ if (
+ result.action === AttachmentDialogResult.Uploaded ||
+ result.action === AttachmentDialogResult.Removed
+ ) {
+ this.refresh();
}
- const [modal] = await this.modalService.openViewRef(
- AttachmentsComponent,
- this.attachmentsModalRef,
- (comp) => {
- comp.cipherId = cipher.id;
- comp.viewOnly = !canEditAttachments;
- comp.onUploadedAttachment
- .pipe(takeUntil(this.destroy$))
- .subscribe(() => (madeAttachmentChanges = true));
- comp.onDeletedAttachment
- .pipe(takeUntil(this.destroy$))
- .subscribe(() => (madeAttachmentChanges = true));
- comp.onReuploadedAttachment
- .pipe(takeUntil(this.destroy$))
- .subscribe(() => (madeAttachmentChanges = true));
- },
- );
-
- modal.onClosed.pipe(takeUntil(this.destroy$)).subscribe(() => {
- if (madeAttachmentChanges) {
- this.refresh();
- }
- madeAttachmentChanges = false;
- });
+ return;
}
/**
@@ -751,48 +688,13 @@ export class VaultComponent implements OnInit, OnDestroy {
await this.go({ cipherId: null, itemId: null, action: null });
}
- async addCipher(cipherType?: CipherType) {
- const type = cipherType ?? this.activeFilter.cipherType;
-
- if (this.extensionRefreshEnabled) {
- return this.addCipherV2(type);
- }
-
- const component = (await this.editCipher(null)) as AddEditComponent;
- component.type = type;
- if (
- this.activeFilter.organizationId !== "MyVault" &&
- this.activeFilter.organizationId != null
- ) {
- component.organizationId = this.activeFilter.organizationId;
- component.collections = (
- await firstValueFrom(this.vaultFilterService.filteredCollections$)
- ).filter((c) => !c.readOnly && c.id != null);
- }
- const selectedColId = this.activeFilter.collectionId;
- if (selectedColId !== "AllCollections" && selectedColId != null) {
- const selectedCollection = (
- await firstValueFrom(this.vaultFilterService.filteredCollections$)
- ).find((c) => c.id === selectedColId);
- component.organizationId = selectedCollection?.organizationId;
- if (!selectedCollection.readOnly) {
- component.collectionIds = [selectedColId];
- }
- }
- component.folderId = this.activeFilter.folderId;
- }
-
/**
* Opens the add cipher dialog.
* @param cipherType The type of cipher to add.
- * @returns The dialog reference.
*/
- async addCipherV2(cipherType?: CipherType) {
- const cipherFormConfig = await this.cipherFormConfigService.buildConfig(
- "add",
- null,
- cipherType,
- );
+ async addCipher(cipherType?: CipherType) {
+ const type = cipherType ?? this.activeFilter.cipherType;
+ const cipherFormConfig = await this.cipherFormConfigService.buildConfig("add", null, type);
const collectionId =
this.activeFilter.collectionId !== "AllCollections" && this.activeFilter.collectionId != null
? this.activeFilter.collectionId
@@ -823,6 +725,12 @@ export class VaultComponent implements OnInit, OnDestroy {
return this.editCipherId(cipher?.id, cloneMode);
}
+ /**
+ * Edit a cipher using the new VaultItemDialog.
+ * @param id
+ * @param cloneMode
+ * @returns
+ */
async editCipherId(id: string, cloneMode?: boolean) {
const cipher = await this.cipherService.get(id);
@@ -836,49 +744,6 @@ export class VaultComponent implements OnInit, OnDestroy {
return;
}
- if (this.extensionRefreshEnabled) {
- await this.editCipherIdV2(cipher, cloneMode);
- return;
- }
-
- const [modal, childComponent] = await this.modalService.openViewRef(
- AddEditComponent,
- this.cipherAddEditModalRef,
- (comp) => {
- comp.cipherId = id;
- comp.collectionId = this.selectedCollection?.node.id;
-
- comp.onSavedCipher.pipe(takeUntil(this.destroy$)).subscribe(() => {
- modal.close();
- this.refresh();
- });
- comp.onDeletedCipher.pipe(takeUntil(this.destroy$)).subscribe(() => {
- modal.close();
- this.refresh();
- });
- comp.onRestoredCipher.pipe(takeUntil(this.destroy$)).subscribe(() => {
- modal.close();
- this.refresh();
- });
- },
- );
-
- // 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
- modal.onClosedPromise().then(() => {
- void this.go({ cipherId: null, itemId: null, action: null });
- });
-
- return childComponent;
- }
-
- /**
- * Edit a cipher using the new VaultItemDialog.
- *
- * @param cipher
- * @param cloneMode
- */
- private async editCipherIdV2(cipher: Cipher, cloneMode?: boolean) {
const cipherFormConfig = await this.cipherFormConfigService.buildConfig(
cloneMode ? "clone" : "edit",
cipher.id as CipherId,
@@ -1076,11 +941,7 @@ export class VaultComponent implements OnInit, OnDestroy {
}
}
- const component = await this.editCipher(cipher, true);
-
- if (component != null) {
- component.cloneMode = true;
- }
+ await this.editCipher(cipher, true);
}
restore = async (c: CipherView): Promise => {
@@ -1331,15 +1192,6 @@ export class VaultComponent implements OnInit, OnDestroy {
this.refresh$.next();
}
- private async canEditAttachments(cipher: CipherView) {
- if (cipher.organizationId == null || cipher.edit) {
- return true;
- }
-
- const organization = this.allOrganizations.find((o) => o.id === cipher.organizationId);
- return organization.canEditAllCiphers;
- }
-
private async go(queryParams: any = null) {
if (queryParams == null) {
queryParams = {
diff --git a/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.html b/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.html
index 8178e3b2935..edba6e4753c 100644
--- a/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.html
+++ b/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.html
@@ -104,8 +104,8 @@
*ngIf="filter.type !== 'trash' && filter.collectionId !== Unassigned && organization"
class="tw-shrink-0"
>
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.ts b/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.ts
index 7f118a48db3..e3c99231a86 100644
--- a/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.ts
+++ b/apps/web/src/app/vault/org-vault/vault-header/vault-header.component.ts
@@ -13,7 +13,6 @@ import {
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { ProductTierType } from "@bitwarden/common/billing/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 { CipherType } from "@bitwarden/common/vault/enums";
@@ -90,11 +89,6 @@ export class VaultHeaderComponent implements OnInit {
protected CollectionDialogTabType = CollectionDialogTabType;
- /**
- * Whether the extension refresh feature flag is enabled.
- */
- protected extensionRefreshEnabled = false;
-
/** The cipher type enum. */
protected CipherType = CipherType;
@@ -106,11 +100,7 @@ export class VaultHeaderComponent implements OnInit {
private configService: ConfigService,
) {}
- async ngOnInit() {
- this.extensionRefreshEnabled = await this.configService.getFeatureFlag(
- FeatureFlag.ExtensionRefresh,
- );
- }
+ async ngOnInit() {}
get title() {
const headerType = this.i18nService.t("collections").toLowerCase();
diff --git a/apps/web/src/app/vault/org-vault/vault.component.ts b/apps/web/src/app/vault/org-vault/vault.component.ts
index fe76f9842e9..b4ba9ff5512 100644
--- a/apps/web/src/app/vault/org-vault/vault.component.ts
+++ b/apps/web/src/app/vault/org-vault/vault.component.ts
@@ -1,15 +1,7 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { DialogRef } from "@angular/cdk/dialog";
-import {
- ChangeDetectorRef,
- Component,
- NgZone,
- OnDestroy,
- OnInit,
- ViewChild,
- ViewContainerRef,
-} from "@angular/core";
+import { ChangeDetectorRef, Component, NgZone, OnDestroy, OnInit } from "@angular/core";
import { ActivatedRoute, Params, Router } from "@angular/router";
import {
BehaviorSubject,
@@ -37,12 +29,10 @@ import {
import {
CollectionAdminService,
CollectionAdminView,
- CollectionService,
CollectionView,
Unassigned,
} from "@bitwarden/admin-console/common";
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
-import { ModalService } from "@bitwarden/angular/services/modal.service";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
import { SearchService } from "@bitwarden/common/abstractions/search.service";
@@ -127,7 +117,6 @@ import {
import { VaultHeaderComponent } from "../org-vault/vault-header/vault-header.component";
import { getNestedCollectionTree } from "../utils/collection-utils";
-import { AddEditComponent } from "./add-edit.component";
import {
BulkCollectionsDialogComponent,
BulkCollectionsDialogResult,
@@ -166,13 +155,6 @@ enum AddAccessStatusType {
export class VaultComponent implements OnInit, OnDestroy {
protected Unassigned = Unassigned;
- @ViewChild("attachments", { read: ViewContainerRef, static: true })
- attachmentsModalRef: ViewContainerRef;
- @ViewChild("cipherAddEdit", { read: ViewContainerRef, static: true })
- cipherAddEditModalRef: ViewContainerRef;
- @ViewChild("collectionsModal", { read: ViewContainerRef, static: true })
- collectionsModalRef: ViewContainerRef;
-
trashCleanupWarning: string = null;
activeFilter: VaultFilter = new VaultFilter();
@@ -210,7 +192,6 @@ export class VaultComponent implements OnInit, OnDestroy {
private refresh$ = new BehaviorSubject(null);
private destroy$ = new Subject();
protected addAccessStatus$ = new BehaviorSubject(0);
- private extensionRefreshEnabled: boolean;
private resellerManagedOrgAlert: boolean;
private vaultItemDialogRef?: DialogRef | undefined;
@@ -249,7 +230,6 @@ export class VaultComponent implements OnInit, OnDestroy {
private changeDetectorRef: ChangeDetectorRef,
private syncService: SyncService,
private i18nService: I18nService,
- private modalService: ModalService,
private dialogService: DialogService,
private messagingService: MessagingService,
private broadcasterService: BroadcasterService,
@@ -265,7 +245,6 @@ export class VaultComponent implements OnInit, OnDestroy {
private eventCollectionService: EventCollectionService,
private totpService: TotpService,
private apiService: ApiService,
- private collectionService: CollectionService,
private toastService: ToastService,
private configService: ConfigService,
private cipherFormConfigService: CipherFormConfigService,
@@ -278,10 +257,6 @@ export class VaultComponent implements OnInit, OnDestroy {
) {}
async ngOnInit() {
- this.extensionRefreshEnabled = await this.configService.getFeatureFlag(
- FeatureFlag.ExtensionRefresh,
- );
-
this.resellerManagedOrgAlert = await this.configService.getFeatureFlag(
FeatureFlag.ResellerManagedOrgAlert,
);
@@ -555,7 +530,7 @@ export class VaultComponent implements OnInit, OnDestroy {
firstSetup$
.pipe(
switchMap(() => combineLatest([this.route.queryParams, allCipherMap$])),
- filter(() => this.vaultItemDialogRef == undefined || !this.extensionRefreshEnabled),
+ filter(() => this.vaultItemDialogRef == undefined),
switchMap(async ([qParams, allCiphersMap]) => {
const cipherId = getCipherIdFromParams(qParams);
@@ -586,15 +561,15 @@ export class VaultComponent implements OnInit, OnDestroy {
return;
}
- // Default to "view" if extension refresh is enabled
- if (action == null && this.extensionRefreshEnabled) {
+ // Default to "view"
+ if (action == null) {
action = "view";
}
if (action === "view") {
await this.viewCipherById(cipher);
} else {
- await this.editCipherId(cipher, false);
+ await this.editCipher(cipher, false);
}
} else {
this.toastService.showToast({
@@ -836,27 +811,8 @@ export class VaultComponent implements OnInit, OnDestroy {
}
}
+ /** Opens the Add/Edit Dialog */
async addCipher(cipherType?: CipherType) {
- if (this.extensionRefreshEnabled) {
- return this.addCipherV2(cipherType);
- }
-
- let collections: CollectionView[] = [];
-
- // Admins limited to only adding items to collections they have access to.
- collections = await firstValueFrom(this.editableCollections$);
-
- await this.editCipher(null, false, (comp) => {
- comp.type = cipherType || this.activeFilter.cipherType;
- comp.collections = collections;
- if (this.activeFilter.collectionId) {
- comp.collectionIds = [this.activeFilter.collectionId];
- }
- });
- }
-
- /** Opens the Add/Edit Dialog. Only to be used when the BrowserExtension feature flag is active */
- async addCipherV2(cipherType?: CipherType) {
const cipherFormConfig = await this.cipherFormConfigService.buildConfig(
"add",
null,
@@ -877,24 +833,8 @@ export class VaultComponent implements OnInit, OnDestroy {
* Edit the given cipher or add a new cipher
* @param cipherView - When set, the cipher to be edited
* @param cloneCipher - `true` when the cipher should be cloned.
- * Used in place of the `additionalComponentParameters`, as
- * the `editCipherIdV2` method has a differing implementation.
- * @param defaultComponentParameters - A method that takes in an instance of
- * the `AddEditComponent` to edit methods directly.
*/
- async editCipher(
- cipher: CipherView | null,
- cloneCipher: boolean,
- additionalComponentParameters?: (comp: AddEditComponent) => void,
- ) {
- return this.editCipherId(cipher, cloneCipher, additionalComponentParameters);
- }
-
- async editCipherId(
- cipher: CipherView | null,
- cloneCipher: boolean,
- additionalComponentParameters?: (comp: AddEditComponent) => void,
- ) {
+ async editCipher(cipher: CipherView | null, cloneCipher: boolean) {
if (
cipher &&
cipher.reprompt !== 0 &&
@@ -905,55 +845,6 @@ export class VaultComponent implements OnInit, OnDestroy {
return;
}
- if (this.extensionRefreshEnabled) {
- await this.editCipherIdV2(cipher, cloneCipher);
- return;
- }
-
- const defaultComponentParameters = (comp: AddEditComponent) => {
- comp.organization = this.organization;
- comp.organizationId = this.organization.id;
- comp.cipherId = cipher?.id;
- comp.collectionId = this.activeFilter.collectionId;
- comp.onSavedCipher.pipe(takeUntil(this.destroy$)).subscribe(() => {
- modal.close();
- this.refresh();
- });
- comp.onDeletedCipher.pipe(takeUntil(this.destroy$)).subscribe(() => {
- modal.close();
- this.refresh();
- });
- comp.onRestoredCipher.pipe(takeUntil(this.destroy$)).subscribe(() => {
- modal.close();
- this.refresh();
- });
- };
-
- const [modal, childComponent] = await this.modalService.openViewRef(
- AddEditComponent,
- this.cipherAddEditModalRef,
- additionalComponentParameters == null
- ? defaultComponentParameters
- : (comp) => {
- defaultComponentParameters(comp);
- additionalComponentParameters(comp);
- },
- );
-
- // 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
- modal.onClosedPromise().then(() => {
- this.go({ cipherId: null, itemId: null, action: null });
- });
-
- return childComponent;
- }
-
- /**
- * Edit a cipher using the new AddEditCipherDialogV2 component.
- * Only to be used behind the ExtensionRefresh feature flag.
- */
- private async editCipherIdV2(cipher: CipherView | null, cloneCipher: boolean) {
const cipherFormConfig = await this.cipherFormConfigService.buildConfig(
cloneCipher ? "clone" : "edit",
cipher?.id as CipherId | null,
@@ -1038,16 +929,7 @@ export class VaultComponent implements OnInit, OnDestroy {
}
}
- let collections: CollectionView[] = [];
-
- // Admins limited to only adding items to collections they have access to.
- collections = await firstValueFrom(this.editableCollections$);
-
- await this.editCipher(cipher, true, (comp) => {
- comp.cloneMode = true;
- comp.collections = collections;
- comp.collectionIds = cipher.collectionIds;
- });
+ await this.editCipher(cipher, true);
}
restore = async (c: CipherView): Promise => {
diff --git a/libs/angular/src/utils/extension-refresh-redirect.spec.ts b/libs/angular/src/utils/extension-refresh-redirect.spec.ts
deleted file mode 100644
index 3291a4496ff..00000000000
--- a/libs/angular/src/utils/extension-refresh-redirect.spec.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { TestBed } from "@angular/core/testing";
-import { Navigation, Router, UrlTree } from "@angular/router";
-import { mock, MockProxy } from "jest-mock-extended";
-
-import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-
-import { extensionRefreshRedirect } from "./extension-refresh-redirect";
-
-describe("extensionRefreshRedirect", () => {
- let configService: MockProxy;
- let router: MockProxy;
-
- beforeEach(() => {
- configService = mock();
- router = mock();
-
- TestBed.configureTestingModule({
- providers: [
- { provide: ConfigService, useValue: configService },
- { provide: Router, useValue: router },
- ],
- });
- });
-
- it("returns true when ExtensionRefresh flag is disabled", async () => {
- configService.getFeatureFlag.mockResolvedValue(false);
-
- const result = await TestBed.runInInjectionContext(() =>
- extensionRefreshRedirect("/redirect")(),
- );
-
- expect(result).toBe(true);
- expect(configService.getFeatureFlag).toHaveBeenCalledWith(FeatureFlag.ExtensionRefresh);
- expect(router.parseUrl).not.toHaveBeenCalled();
- });
-
- it("returns UrlTree when ExtensionRefresh flag is enabled and preserves query params", async () => {
- configService.getFeatureFlag.mockResolvedValue(true);
-
- const urlTree = new UrlTree();
- urlTree.queryParams = { test: "test" };
-
- const navigation: Navigation = {
- extras: {},
- id: 0,
- initialUrl: new UrlTree(),
- extractedUrl: urlTree,
- trigger: "imperative",
- previousNavigation: undefined,
- };
-
- router.getCurrentNavigation.mockReturnValue(navigation);
-
- await TestBed.runInInjectionContext(() => extensionRefreshRedirect("/redirect")());
-
- expect(configService.getFeatureFlag).toHaveBeenCalledWith(FeatureFlag.ExtensionRefresh);
- expect(router.createUrlTree).toHaveBeenCalledWith(["/redirect"], {
- queryParams: urlTree.queryParams,
- });
- });
-});
diff --git a/libs/angular/src/utils/extension-refresh-redirect.ts b/libs/angular/src/utils/extension-refresh-redirect.ts
deleted file mode 100644
index 2baa3a3ec89..00000000000
--- a/libs/angular/src/utils/extension-refresh-redirect.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { inject } from "@angular/core";
-import { UrlTree, Router } from "@angular/router";
-
-import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-
-/**
- * Helper function to redirect to a new URL based on the ExtensionRefresh feature flag.
- * @param redirectUrl - The URL to redirect to if the ExtensionRefresh flag is enabled.
- */
-export function extensionRefreshRedirect(redirectUrl: string): () => Promise {
- return async () => {
- const configService = inject(ConfigService);
- const router = inject(Router);
-
- const shouldRedirect = await configService.getFeatureFlag(FeatureFlag.ExtensionRefresh);
- if (shouldRedirect) {
- const currentNavigation = router.getCurrentNavigation();
- const queryParams = currentNavigation?.extractedUrl?.queryParams || {};
-
- // Preserve query params when redirecting as it is likely that the refreshed component
- // will be consuming the same query params.
- return router.createUrlTree([redirectUrl], { queryParams });
- } else {
- return true;
- }
- };
-}
diff --git a/libs/angular/src/utils/extension-refresh-swap.ts b/libs/angular/src/utils/extension-refresh-swap.ts
deleted file mode 100644
index 6512be032d2..00000000000
--- a/libs/angular/src/utils/extension-refresh-swap.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { Type, inject } from "@angular/core";
-import { Route, Routes } from "@angular/router";
-
-import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-
-import { componentRouteSwap } from "./component-route-swap";
-
-/**
- * Helper function to swap between two components based on the ExtensionRefresh feature flag.
- * @param defaultComponent - The current non-refreshed component to render.
- * @param refreshedComponent - The new refreshed component to render.
- * @param options - The shared route options to apply to the default component, and to the alt component if altOptions is not provided.
- * @param altOptions - The alt route options to apply to the alt component.
- */
-export function extensionRefreshSwap(
- defaultComponent: Type,
- refreshedComponent: Type,
- options: Route,
- altOptions?: Route,
-): Routes {
- return componentRouteSwap(
- defaultComponent,
- refreshedComponent,
- async () => {
- const configService = inject(ConfigService);
- return configService.getFeatureFlag(FeatureFlag.ExtensionRefresh);
- },
- options,
- altOptions,
- );
-}
From 13a80ccff23d42c99d2ffefa3142d590a186b4ab Mon Sep 17 00:00:00 2001
From: Daniel James Smith <2670567+djsmith85@users.noreply.github.com>
Date: Mon, 10 Feb 2025 14:31:41 +0100
Subject: [PATCH 15/95] Remove conditional code around extensionRefreshFlag
(#13146)
Co-authored-by: Daniel James Smith
---
.../app/billing/services/stripe.service.ts | 40 +++++--------------
.../payment/payment-label.component.html | 23 ++++-------
.../shared/payment/payment-label.component.ts | 19 ++-------
3 files changed, 21 insertions(+), 61 deletions(-)
diff --git a/apps/web/src/app/billing/services/stripe.service.ts b/apps/web/src/app/billing/services/stripe.service.ts
index 61bc0b6cdd2..caf43334795 100644
--- a/apps/web/src/app/billing/services/stripe.service.ts
+++ b/apps/web/src/app/billing/services/stripe.service.ts
@@ -3,8 +3,6 @@
import { Injectable } from "@angular/core";
import { BankAccount } from "@bitwarden/common/billing/models/domain";
-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 { BillingServicesModule } from "./billing-services.module";
@@ -19,10 +17,7 @@ export class StripeService {
cardCvc: string;
};
- constructor(
- private logService: LogService,
- private configService: ConfigService,
- ) {}
+ constructor(private logService: LogService) {}
/**
* Loads [Stripe JS]{@link https://docs.stripe.com/js} in the element of the current page and mounts
@@ -43,19 +38,10 @@ export class StripeService {
const window$ = window as any;
this.stripe = window$.Stripe(process.env.STRIPE_KEY);
this.elements = this.stripe.elements();
- const isExtensionRefresh = await this.configService.getFeatureFlag(
- FeatureFlag.ExtensionRefresh,
- );
setTimeout(() => {
- this.elements.create(
- "cardNumber",
- this.getElementOptions("cardNumber", isExtensionRefresh),
- );
- this.elements.create(
- "cardExpiry",
- this.getElementOptions("cardExpiry", isExtensionRefresh),
- );
- this.elements.create("cardCvc", this.getElementOptions("cardCvc", isExtensionRefresh));
+ this.elements.create("cardNumber", this.getElementOptions("cardNumber"));
+ this.elements.create("cardExpiry", this.getElementOptions("cardExpiry"));
+ this.elements.create("cardCvc", this.getElementOptions("cardCvc"));
if (autoMount) {
this.mountElements();
}
@@ -150,10 +136,7 @@ export class StripeService {
}, 500);
}
- private getElementOptions(
- element: "cardNumber" | "cardExpiry" | "cardCvc",
- isExtensionRefresh: boolean,
- ): any {
+ private getElementOptions(element: "cardNumber" | "cardExpiry" | "cardCvc"): any {
const options: any = {
style: {
base: {
@@ -178,15 +161,12 @@ export class StripeService {
},
};
- // Unique settings that should only be applied when the extension refresh flag is active
- if (isExtensionRefresh) {
- options.style.base.fontWeight = "500";
- options.classes.base = "v2";
+ options.style.base.fontWeight = "500";
+ options.classes.base = "v2";
- // Remove the placeholder for number and CVC fields
- if (["cardNumber", "cardCvc"].includes(element)) {
- options.placeholder = "";
- }
+ // Remove the placeholder for number and CVC fields
+ if (["cardNumber", "cardCvc"].includes(element)) {
+ options.placeholder = "";
}
const style = getComputedStyle(document.documentElement);
diff --git a/apps/web/src/app/billing/shared/payment/payment-label.component.html b/apps/web/src/app/billing/shared/payment/payment-label.component.html
index a2e1c92a050..a931b0524e3 100644
--- a/apps/web/src/app/billing/shared/payment/payment-label.component.html
+++ b/apps/web/src/app/billing/shared/payment/payment-label.component.html
@@ -2,21 +2,12 @@
-
-
-
-
- ({{ "required" | i18n }})
-
-
-
-
-
-