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 8875676e88d..6fe54b66786 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 @@ -243,7 +243,8 @@ 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) { @@ -254,6 +255,7 @@ export class ItemDetailsSectionComponent implements OnInit { } else { this.cipherFormContainer.enableFormFields(); this.isFavoriteButtonDisabled = false; + this.setCollectionControlState(); } } } @@ -348,22 +350,32 @@ 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(); - } + this.setCollectionControlState(); } } } + private setCollectionControlState() { + const prefillCipher = this.cipherFormContainer.getInitialCipherView(); + const orgId = this.itemDetailsForm.controls.organizationId.value as OrganizationId; + const organization = this.organizations.find((o) => o.id === orgId); + // 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 && !prefillCipher.canAssignToCollections) || + (organization?.allowAdminAccessToAllCollectionItems && + (!this.originalCipherView.viewPassword || !this.originalCipherView.edit)) || + (organization?.type === OrganizationUserType.Custom && !this.originalCipherView.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.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) {