diff --git a/apps/browser/src/autofill/utils/index.ts b/apps/browser/src/autofill/utils/index.ts index 614a5b014f2..0e102dcfd99 100644 --- a/apps/browser/src/autofill/utils/index.ts +++ b/apps/browser/src/autofill/utils/index.ts @@ -37,9 +37,7 @@ export function requestIdleCallbackPolyfill( return globalThis.requestIdleCallback(() => callback(), options); } - const timeoutDelay = options?.timeout || 1; - - return globalThis.setTimeout(() => callback(), timeoutDelay); + return globalThis.setTimeout(() => callback(), 1); } /** diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index ce8833420ed..096bbe76e40 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -299,7 +299,6 @@ import { OffscreenStorageService } from "../platform/storage/offscreen-storage.s import { SyncServiceListener } from "../platform/sync/sync-service.listener"; import { BrowserSystemNotificationService } from "../platform/system-notifications/browser-system-notification.service"; import { fromChromeRuntimeMessaging } from "../platform/utils/from-chrome-runtime-messaging"; -import { VaultFilterService } from "../vault/services/vault-filter.service"; import CommandsBackground from "./commands.background"; import IdleBackground from "./idle.background"; @@ -364,7 +363,6 @@ export default class MainBackground { providerService: ProviderServiceAbstraction; keyConnectorService: KeyConnectorServiceAbstraction; userVerificationService: UserVerificationServiceAbstraction; - vaultFilterService: VaultFilterService; usernameGenerationService: UsernameGenerationServiceAbstraction; encryptService: EncryptService; folderApiService: FolderApiServiceAbstraction; @@ -919,18 +917,6 @@ export default class MainBackground { this.biometricsService, ); - this.vaultFilterService = new VaultFilterService( - this.organizationService, - this.folderService, - this.cipherService, - this.collectionService, - this.policyService, - this.stateProvider, - this.accountService, - this.configService, - this.i18nService, - ); - this.vaultSettingsService = new VaultSettingsService( this.stateProvider, this.restrictedItemTypesService, @@ -1385,12 +1371,14 @@ export default class MainBackground { this.accountService, this.authService, ); - } - async bootstrap() { + // Synchronous startup if (this.webPushConnectionService instanceof WorkerWebPushConnectionService) { this.webPushConnectionService.start(); } + } + + async bootstrap() { this.containerService.attachToGlobal(self); await this.sdkLoadService.loadAndInit(); @@ -1601,7 +1589,6 @@ export default class MainBackground { this.cipherService.clear(userBeingLoggedOut), this.folderService.clear(userBeingLoggedOut), this.vaultTimeoutSettingsService.clear(userBeingLoggedOut), - this.vaultFilterService.clear(), this.biometricStateService.logout(userBeingLoggedOut), this.popupViewCacheBackgroundService.clearState(), /* We intentionally do not clear: diff --git a/apps/browser/src/popup/app.component.ts b/apps/browser/src/popup/app.component.ts index bd7b41b6e5f..ee75dbaf7af 100644 --- a/apps/browser/src/popup/app.component.ts +++ b/apps/browser/src/popup/app.component.ts @@ -49,7 +49,6 @@ import { BiometricsService, BiometricStateService, KeyService } from "@bitwarden import { PopupCompactModeService } from "../platform/popup/layout/popup-compact-mode.service"; import { PopupSizeService } from "../platform/popup/layout/popup-size.service"; import { initPopupClosedListener } from "../platform/services/popup-view-cache-background.service"; -import { VaultBrowserStateService } from "../vault/services/vault-browser-state.service"; import { routerTransition } from "./app-routing.animations"; import { DesktopSyncVerificationDialogComponent } from "./components/desktop-sync-verification-dialog.component"; @@ -103,7 +102,6 @@ export class AppComponent implements OnInit, OnDestroy { private i18nService: I18nService, private router: Router, private readonly tokenService: TokenService, - private vaultBrowserStateService: VaultBrowserStateService, private cipherService: CipherService, private changeDetectorRef: ChangeDetectorRef, private ngZone: NgZone, @@ -135,10 +133,6 @@ export class AppComponent implements OnInit, OnDestroy { this.compactModeService.init(); await this.popupSizeService.setHeight(); - // Component states must not persist between closing and reopening the popup, otherwise they become dead objects - // Clear them aggressively to make sure this doesn't occur - await this.clearComponentStates(); - this.accountService.activeAccount$.pipe(takeUntil(this.destroy$)).subscribe((account) => { this.activeUserId = account?.id; }); @@ -249,13 +243,6 @@ export class AppComponent implements OnInit, OnDestroy { this.router.events.pipe(takeUntil(this.destroy$)).subscribe(async (event) => { if (event instanceof NavigationEnd) { const url = event.urlAfterRedirects || event.url || ""; - if ( - url.startsWith("/tabs/") && - (window as any).previousPopupUrl != null && - (window as any).previousPopupUrl.startsWith("/tabs/") - ) { - await this.clearComponentStates(); - } if (url.startsWith("/tabs/")) { await this.cipherService.setAddEditCipherInfo(null, this.activeUserId); } @@ -320,20 +307,6 @@ export class AppComponent implements OnInit, OnDestroy { return firstValueFrom(dialogRef.closed); } - private async clearComponentStates() { - if (this.activeUserId == null) { - return; - } - if (!(await firstValueFrom(this.tokenService.hasAccessToken$(this.activeUserId)))) { - return; - } - - await Promise.all([ - this.vaultBrowserStateService.setBrowserGroupingsComponentState(null), - this.vaultBrowserStateService.setBrowserVaultItemsComponentState(null), - ]); - } - // Displaying toasts isn't super useful on the popup due to the reloads we do. // However, it is visible for a moment on the FF sidebar logout. private async displayLogoutReason(logoutReason: LogoutReason) { diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index d8b4b1d600f..aaf85389f9c 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -39,7 +39,6 @@ import { import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; -import { DefaultOrganizationService } from "@bitwarden/common/admin-console/services/organization/default-organization.service"; import { AccountService, AccountService as AccountServiceAbstraction, @@ -112,10 +111,7 @@ import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.s import { InternalSendService } from "@bitwarden/common/tools/send/services/send.service.abstraction"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction"; -import { - FolderService as FolderServiceAbstraction, - InternalFolderService, -} from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; +import { InternalFolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; import { TotpService as TotpServiceAbstraction } from "@bitwarden/common/vault/abstractions/totp.service"; import { RestrictedItemTypesService } from "@bitwarden/common/vault/services/restricted-item-types.service"; import { TotpService } from "@bitwarden/common/vault/services/totp.service"; @@ -186,8 +182,6 @@ import { BrowserSystemNotificationService } from "../../platform/system-notifica import { fromChromeRuntimeMessaging } from "../../platform/utils/from-chrome-runtime-messaging"; import { FilePopoutUtilsService } from "../../tools/popup/services/file-popout-utils.service"; import { Fido2UserVerificationService } from "../../vault/services/fido2-user-verification.service"; -import { VaultBrowserStateService } from "../../vault/services/vault-browser-state.service"; -import { VaultFilterService } from "../../vault/services/vault-filter.service"; import { ExtensionAnonLayoutWrapperDataService } from "../components/extension-anon-layout-wrapper/extension-anon-layout-wrapper-data.service"; import { DebounceNavigationService } from "./debounce-navigation.service"; @@ -402,21 +396,6 @@ const safeProviders: SafeProvider[] = [ useClass: ForegroundVaultTimeoutService, deps: [MessagingServiceAbstraction], }), - safeProvider({ - provide: VaultFilterService, - useClass: VaultFilterService, - deps: [ - DefaultOrganizationService, - FolderServiceAbstraction, - CipherService, - CollectionService, - PolicyService, - StateProvider, - AccountServiceAbstraction, - ConfigService, - I18nServiceAbstraction, - ], - }), safeProvider({ provide: SECURE_STORAGE, useExisting: AbstractStorageService, // Secure storage is not available in the browser, so we use normal storage instead and warn users when it is used. @@ -454,13 +433,6 @@ const safeProviders: SafeProvider[] = [ provide: OBSERVABLE_DISK_STORAGE, useExisting: AbstractStorageService, }), - safeProvider({ - provide: VaultBrowserStateService, - useFactory: (stateProvider: StateProvider) => { - return new VaultBrowserStateService(stateProvider); - }, - deps: [StateProvider], - }), safeProvider({ provide: FileDownloadService, useClass: BrowserFileDownloadService, diff --git a/apps/browser/src/vault/popup/components/vault-v2/attachments/open-attachments/open-attachments.component.html b/apps/browser/src/vault/popup/components/vault-v2/attachments/open-attachments/open-attachments.component.html index 6345c3ea4e1..2650345e94b 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/attachments/open-attachments/open-attachments.component.html +++ b/apps/browser/src/vault/popup/components/vault-v2/attachments/open-attachments/open-attachments.component.html @@ -1,5 +1,10 @@ - @@ -104,6 +105,7 @@ [label]="'reorderToggleButton' | i18n: field.value.name" (keydown)="handleKeyDown($event, field.value.name, i)" data-testid="reorder-toggle-button" + [disabled]="parentFormDisabled" *ngIf="canEdit(field.value.type)" > @@ -113,7 +115,8 @@ bitLink linkType="primary" (click)="openAddEditCustomFieldDialog()" - *ngIf="!isPartialEdit" + data-testid="add-field-button" + *ngIf="!isPartialEdit && !parentFormDisabled" > {{ "addField" | i18n }} diff --git a/libs/vault/src/cipher-form/components/custom-fields/custom-fields.component.spec.ts b/libs/vault/src/cipher-form/components/custom-fields/custom-fields.component.spec.ts index ced8763f895..1d1bcfa1ee0 100644 --- a/libs/vault/src/cipher-form/components/custom-fields/custom-fields.component.spec.ts +++ b/libs/vault/src/cipher-form/components/custom-fields/custom-fields.component.spec.ts @@ -4,6 +4,7 @@ import { DebugElement } from "@angular/core"; import { ComponentFixture, TestBed } from "@angular/core/testing"; import { By } from "@angular/platform-browser"; import { mock } from "jest-mock-extended"; +import { BehaviorSubject } from "rxjs"; import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; @@ -16,7 +17,12 @@ import { } from "@bitwarden/common/vault/enums"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { FieldView } from "@bitwarden/common/vault/models/view/field.view"; -import { DialogRef, BitPasswordInputToggleDirective, DialogService } from "@bitwarden/components"; +import { + DialogRef, + BitPasswordInputToggleDirective, + DialogService, + BitIconButtonComponent, +} from "@bitwarden/components"; import { CipherFormConfig } from "../../abstractions/cipher-form-config.service"; import { CipherFormContainer } from "../../cipher-form-container"; @@ -39,6 +45,7 @@ describe("CustomFieldsComponent", () => { let announce: jest.Mock; let patchCipher: jest.Mock; let config: CipherFormConfig; + const formStatusChange$ = new BehaviorSubject<"disabled" | "enabled">("enabled"); beforeEach(async () => { open = jest.fn(); @@ -65,6 +72,7 @@ describe("CustomFieldsComponent", () => { registerChildForm: jest.fn(), config, getInitialCipherView: jest.fn(() => originalCipherView), + formStatusChange$, }, }, { @@ -552,4 +560,54 @@ describe("CustomFieldsComponent", () => { expect(editButtons).toHaveLength(3); }); }); + + describe("parent form disabled", () => { + beforeEach(() => { + originalCipherView!.fields = mockFieldViews; + formStatusChange$.next("disabled"); + component.ngOnInit(); + + fixture.detectChanges(); + }); + + afterEach(() => { + formStatusChange$.next("enabled"); + fixture.detectChanges(); + }); + + it("disables edit and reorder buttons", () => { + const reorderButtonQuery = By.directive(BitIconButtonComponent); + const editButtonQuery = By.directive(BitIconButtonComponent); + + let reorderButton = fixture.debugElement.query(reorderButtonQuery); + let editButton = fixture.debugElement.query(editButtonQuery); + + expect(reorderButton.componentInstance.disabled()).toBe(true); + expect(editButton.componentInstance.disabled()).toBe(true); + + formStatusChange$.next("enabled"); + fixture.detectChanges(); + + reorderButton = fixture.debugElement.query(reorderButtonQuery); + editButton = fixture.debugElement.query(editButtonQuery); + + expect(reorderButton.componentInstance.disabled()).toBe(false); + expect(editButton.componentInstance.disabled()).toBe(false); + }); + + it("hides add field button", () => { + const query = By.css('button[data-testid="add-field-button"]'); + + let addFieldButton = fixture.debugElement.query(query); + + expect(addFieldButton).toBeNull(); + + formStatusChange$.next("enabled"); + fixture.detectChanges(); + + addFieldButton = fixture.debugElement.query(query); + + expect(addFieldButton).not.toBeNull(); + }); + }); }); diff --git a/libs/vault/src/cipher-form/components/custom-fields/custom-fields.component.ts b/libs/vault/src/cipher-form/components/custom-fields/custom-fields.component.ts index c8edba6c9fd..e3612e75a1b 100644 --- a/libs/vault/src/cipher-form/components/custom-fields/custom-fields.component.ts +++ b/libs/vault/src/cipher-form/components/custom-fields/custom-fields.component.ts @@ -113,6 +113,9 @@ export class CustomFieldsComponent implements OnInit, AfterViewInit { /** Emits when a new custom field should be focused */ private focusOnNewInput$ = new Subject(); + /** Tracks the disabled status of the edit cipher form */ + protected parentFormDisabled: boolean = false; + disallowHiddenField?: boolean; destroyed$: DestroyRef; @@ -133,6 +136,10 @@ export class CustomFieldsComponent implements OnInit, AfterViewInit { // getRawValue ensures disabled fields are included this.updateCipher(this.fields.getRawValue()); }); + + this.cipherFormContainer.formStatusChange$.pipe(takeUntilDestroyed()).subscribe((status) => { + this.parentFormDisabled = status === "disabled"; + }); } /** Fields form array, referenced via a getter to avoid type-casting in multiple places */ diff --git a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.html b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.html index fc208bd9b92..9bf6dc32758 100644 --- a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.html +++ b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.html @@ -11,6 +11,7 @@ [attr.aria-checked]="itemDetailsForm.value.favorite" [label]="'favorite' | i18n" (click)="toggleFavorite()" + [disabled]="favoriteButtonDisabled" > diff --git a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.spec.ts b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.spec.ts index 6aa7175d373..e3d863a0af3 100644 --- a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.spec.ts +++ b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.spec.ts @@ -33,23 +33,24 @@ const createMockCollection = ( readOnly = false, canEdit = true, ): CollectionView => { - return { - id: id as CollectionId, + const cv = new CollectionView({ name, organizationId: organizationId as OrganizationId, - externalId: "", - readOnly, - hidePasswords: false, - manage: true, - assigned: true, - type: CollectionTypes.DefaultUserCollection, - isDefaultCollection: true, - canEditItems: jest.fn().mockReturnValue(canEdit), - canEdit: jest.fn(), - canDelete: jest.fn(), - canViewCollectionInfo: jest.fn(), - encrypt: jest.fn(), - }; + id: id as CollectionId, + }); + cv.readOnly = readOnly; + cv.manage = true; + cv.type = CollectionTypes.DefaultUserCollection; + cv.externalId = ""; + cv.hidePasswords = false; + cv.assigned = true; + cv.canEditName = jest.fn().mockReturnValue(true); + cv.canEditItems = jest.fn().mockReturnValue(canEdit); + cv.canEdit = jest.fn(); + cv.canDelete = jest.fn(); + cv.canViewCollectionInfo = jest.fn(); + + return cv; }; describe("ItemDetailsSectionComponent", () => { diff --git a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.ts b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.ts index 4fd999ae601..bc5e7c43d12 100644 --- a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.ts +++ b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.ts @@ -82,6 +82,8 @@ export class ItemDetailsSectionComponent implements OnInit { protected userId: UserId; + protected favoriteButtonDisabled = false; + @Input({ required: true }) config: CipherFormConfig; @@ -241,15 +243,19 @@ export class ItemDetailsSectionComponent implements OnInit { /** * When the cipher does not belong to an organization but the user's organization * requires all ciphers to be owned by an organization, disable the entire form - * until the user selects an organization. + * until the user selects an organization. Once the organization is set, enable the form. + * Ensure to properly set the collections control state when the form is enabled. */ private setFormState() { if (this.config.originalCipher && !this.allowPersonalOwnership) { if (this.itemDetailsForm.controls.organizationId.value === null) { this.cipherFormContainer.disableFormFields(); this.itemDetailsForm.controls.organizationId.enable(); + this.favoriteButtonDisabled = true; } else { this.cipherFormContainer.enableFormFields(); + this.favoriteButtonDisabled = false; + this.setCollectionControlState(); } } } @@ -305,7 +311,6 @@ export class ItemDetailsSectionComponent implements OnInit { }); const orgId = this.itemDetailsForm.controls.organizationId.value as OrganizationId; - const organization = this.organizations.find((o) => o.id === orgId); const initializedWithCachedCipher = this.cipherFormContainer.initializedWithCachedCipher(); // Configure form for clone mode. @@ -327,9 +332,7 @@ export class ItemDetailsSectionComponent implements OnInit { await this.updateCollectionOptions(prefillCollections); - if (!organization?.canEditAllCiphers && !prefillCipher.canAssignToCollections) { - this.itemDetailsForm.controls.collectionIds.disable(); - } + this.setCollectionControlState(); if (this.partialEdit) { this.itemDetailsForm.disable(); @@ -344,22 +347,34 @@ export class ItemDetailsSectionComponent implements OnInit { c.readOnly && this.originalCipherView.collectionIds.includes(c.id as CollectionId), ); - - // When Owners/Admins access setting is turned on. - // Disable Collections Options if Owner/Admin does not have Edit/Manage permissions on item - // Disable Collections Options if Custom user does not have Edit/Manage permissions on item - if ( - (organization?.allowAdminAccessToAllCollectionItems && - (!this.originalCipherView.viewPassword || !this.originalCipherView.edit)) || - (organization?.type === OrganizationUserType.Custom && - !this.originalCipherView.viewPassword) - ) { - this.itemDetailsForm.controls.collectionIds.disable(); - } } } } + private setCollectionControlState() { + const initialCipherView = this.cipherFormContainer.getInitialCipherView(); + const orgId = this.itemDetailsForm.controls.organizationId.value as OrganizationId; + const organization = this.organizations.find((o) => o.id === orgId); + if (!organization || !initialCipherView) { + return; + } + // Disable the collection control if either of the following apply: + // 1. The organization does not allow editing all ciphers and the existing cipher cannot be assigned to + // collections + // 2. When Owners/Admins access setting is turned on. + // AND either: + // a. Disable Collections Options if Owner/Admin does not have Edit/Manage permissions on item + // b. Disable Collections Options if Custom user does not have Edit/Manage permissions on item + if ( + (!organization.canEditAllCiphers && !initialCipherView.canAssignToCollections) || + (organization.allowAdminAccessToAllCollectionItems && + (!initialCipherView.viewPassword || !initialCipherView.edit)) || + (organization.type === OrganizationUserType.Custom && !initialCipherView.viewPassword) + ) { + this.itemDetailsForm.controls.collectionIds.disable(); + } + } + /** * Updates the collection options based on the selected organization. * @param startingSelection - Optional starting selection of collectionIds to be automatically selected. diff --git a/libs/vault/src/cipher-form/components/login-details-section/login-details-section.component.spec.ts b/libs/vault/src/cipher-form/components/login-details-section/login-details-section.component.spec.ts index c5b1fc7897b..b07a50fd383 100644 --- a/libs/vault/src/cipher-form/components/login-details-section/login-details-section.component.spec.ts +++ b/libs/vault/src/cipher-form/components/login-details-section/login-details-section.component.spec.ts @@ -3,6 +3,7 @@ import { Component } from "@angular/core"; import { ComponentFixture, fakeAsync, TestBed, tick } from "@angular/core/testing"; import { By } from "@angular/platform-browser"; import { mock, MockProxy } from "jest-mock-extended"; +import { BehaviorSubject } from "rxjs"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service"; @@ -47,6 +48,7 @@ describe("LoginDetailsSectionComponent", () => { getInitialCipherView.mockClear(); cipherFormContainer = mock({ getInitialCipherView, + formStatusChange$: new BehaviorSubject<"enabled" | "disabled">("enabled"), website: "example.com", }); diff --git a/libs/vault/src/cipher-form/components/login-details-section/login-details-section.component.ts b/libs/vault/src/cipher-form/components/login-details-section/login-details-section.component.ts index e74d9915cdb..061a8c4abf4 100644 --- a/libs/vault/src/cipher-form/components/login-details-section/login-details-section.component.ts +++ b/libs/vault/src/cipher-form/components/login-details-section/login-details-section.component.ts @@ -1,7 +1,7 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore import { DatePipe, NgIf } from "@angular/common"; -import { Component, inject, OnInit, Optional } from "@angular/core"; +import { Component, DestroyRef, inject, OnInit, Optional } from "@angular/core"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { FormBuilder, ReactiveFormsModule } from "@angular/forms"; import { map } from "rxjs"; @@ -81,6 +81,8 @@ export class LoginDetailsSectionComponent implements OnInit { */ private existingFido2Credentials?: Fido2CredentialView[]; + private destroyRef = inject(DestroyRef); + get hasPasskey(): boolean { return this.existingFido2Credentials != null && this.existingFido2Credentials.length > 0; } @@ -148,6 +150,19 @@ export class LoginDetailsSectionComponent implements OnInit { if (this.cipherFormContainer.config.mode === "partial-edit") { this.loginDetailsForm.disable(); } + + // If the form is enabled, ensure to disable password or TOTP + // for hidden password users + this.cipherFormContainer.formStatusChange$ + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((status) => { + if (status === "enabled") { + if (!this.viewHiddenFields) { + this.loginDetailsForm.controls.password.disable(); + this.loginDetailsForm.controls.totp.disable(); + } + } + }); } private initFromExistingCipher(existingLogin: LoginView) { diff --git a/libs/vault/src/cipher-form/components/sshkey-section/sshkey-section.component.ts b/libs/vault/src/cipher-form/components/sshkey-section/sshkey-section.component.ts index f83f93267c9..f92c4420d03 100644 --- a/libs/vault/src/cipher-form/components/sshkey-section/sshkey-section.component.ts +++ b/libs/vault/src/cipher-form/components/sshkey-section/sshkey-section.component.ts @@ -98,9 +98,13 @@ export class SshKeySectionComponent implements OnInit { // Disable the form if the cipher form container is enabled // to prevent user interaction - this.cipherFormContainer.formEnabled$ + this.cipherFormContainer.formStatusChange$ .pipe(takeUntilDestroyed(this.destroyRef)) - .subscribe(() => this.sshKeyForm.disable()); + .subscribe((status) => { + if (status === "enabled") { + this.sshKeyForm.disable(); + } + }); } /** Set form initial form values from the current cipher */ diff --git a/package-lock.json b/package-lock.json index 5f4aedffd1f..c414adb416d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,7 +41,7 @@ "bufferutil": "4.0.9", "chalk": "4.1.2", "commander": "11.1.0", - "core-js": "3.44.0", + "core-js": "3.45.0", "form-data": "4.0.4", "https-proxy-agent": "7.0.6", "inquirer": "8.2.6", @@ -204,7 +204,7 @@ "browser-hrtime": "1.1.8", "chalk": "4.1.2", "commander": "11.1.0", - "core-js": "3.44.0", + "core-js": "3.45.0", "form-data": "4.0.4", "https-proxy-agent": "7.0.6", "inquirer": "8.2.6", @@ -18802,9 +18802,9 @@ } }, "node_modules/core-js": { - "version": "3.44.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.44.0.tgz", - "integrity": "sha512-aFCtd4l6GvAXwVEh3XbbVqJGHDJt0OZRa+5ePGx3LLwi12WfexqQxcsohb2wgsa/92xtl19Hd66G/L+TaAxDMw==", + "version": "3.45.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.45.0.tgz", + "integrity": "sha512-c2KZL9lP4DjkN3hk/an4pWn5b5ZefhRJnAc42n6LJ19kSnbeRbdQZE5dSeE2LBol1OwJD3X1BQvFTAsa8ReeDA==", "hasInstallScript": true, "license": "MIT", "funding": { diff --git a/package.json b/package.json index 331292b9076..bf6be11a616 100644 --- a/package.json +++ b/package.json @@ -176,7 +176,7 @@ "bufferutil": "4.0.9", "chalk": "4.1.2", "commander": "11.1.0", - "core-js": "3.44.0", + "core-js": "3.45.0", "form-data": "4.0.4", "https-proxy-agent": "7.0.6", "inquirer": "8.2.6",