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 1eea053d1f..a52530dde1 100644 --- a/apps/web/src/app/vault/org-vault/vault.component.ts +++ b/apps/web/src/app/vault/org-vault/vault.component.ts @@ -1249,6 +1249,8 @@ export class VaultComponent implements OnInit, OnDestroy { organizationId: this.organization?.id as OrganizationId, availableCollections, activeCollection: this.activeFilter?.selectedCollectionNode?.node, + isSingleCipherAdmin: + items.length === 1 && (this.organization?.canEditAllCiphers || items[0].isUnassigned), }, }); diff --git a/libs/common/src/vault/abstractions/cipher.service.ts b/libs/common/src/vault/abstractions/cipher.service.ts index 061bd5cedb..e82c07653c 100644 --- a/libs/common/src/vault/abstractions/cipher.service.ts +++ b/libs/common/src/vault/abstractions/cipher.service.ts @@ -113,6 +113,13 @@ export abstract class CipherService implements UserKeyRotationDataProvider Promise; + + /** + * Save the collections for a cipher with the server as an admin. + * Used for Unassigned ciphers or when the user only has admin access to the cipher (not assigned normally). + * @param cipher + */ + saveCollectionsWithServerAdmin: (cipher: Cipher) => Promise; /** * Bulk update collections for many ciphers with the server * @param orgId diff --git a/libs/common/src/vault/services/cipher.service.ts b/libs/common/src/vault/services/cipher.service.ts index 9761387284..a06ca4d793 100644 --- a/libs/common/src/vault/services/cipher.service.ts +++ b/libs/common/src/vault/services/cipher.service.ts @@ -858,6 +858,11 @@ export class CipherService implements CipherServiceAbstraction { return new Cipher(updated[cipher.id as CipherId], cipher.localData); } + async saveCollectionsWithServerAdmin(cipher: Cipher): Promise { + const request = new CipherCollectionsRequest(cipher.collectionIds); + await this.apiService.putCipherCollectionsAdmin(cipher.id, request); + } + /** * Bulk update collections for many ciphers with the server * @param orgId diff --git a/libs/vault/src/components/assign-collections.component.ts b/libs/vault/src/components/assign-collections.component.ts index db4d61691c..884a79bf1d 100644 --- a/libs/vault/src/components/assign-collections.component.ts +++ b/libs/vault/src/components/assign-collections.component.ts @@ -64,6 +64,15 @@ export interface CollectionAssignmentParams { * removed from the ciphers upon submission. */ activeCollection?: CollectionView; + + /** + * Flag indicating if the user is performing the action as an admin on a SINGLE cipher. When true, + * the `/admin` endpoint will be used to update the cipher's collections. Required when updating + * ciphers an Admin does not normally have access to or for Unassigned ciphers. + * + * The bulk method already handles admin actions internally. + */ + isSingleCipherAdmin?: boolean; } export enum CollectionAssignmentResult { @@ -463,6 +472,10 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI const { collections } = this.formGroup.getRawValue(); cipherView.collectionIds = collections.map((i) => i.id as CollectionId); const cipher = await this.cipherService.encrypt(cipherView, this.activeUserId); - await this.cipherService.saveCollectionsWithServer(cipher); + if (this.params.isSingleCipherAdmin) { + await this.cipherService.saveCollectionsWithServerAdmin(cipher); + } else { + await this.cipherService.saveCollectionsWithServer(cipher); + } } }