diff --git a/libs/common/src/vault/abstractions/cipher.service.ts b/libs/common/src/vault/abstractions/cipher.service.ts index 88cd476606..2e34f0ac60 100644 --- a/libs/common/src/vault/abstractions/cipher.service.ts +++ b/libs/common/src/vault/abstractions/cipher.service.ts @@ -93,7 +93,7 @@ export abstract class CipherService implements UserKeyRotationDataProvider Promise; + ) => Promise; shareManyWithServer: ( ciphers: CipherView[], organizationId: string, diff --git a/libs/common/src/vault/services/cipher.service.ts b/libs/common/src/vault/services/cipher.service.ts index fe946fbb06..b1cdf72e08 100644 --- a/libs/common/src/vault/services/cipher.service.ts +++ b/libs/common/src/vault/services/cipher.service.ts @@ -786,7 +786,7 @@ export class CipherService implements CipherServiceAbstraction { organizationId: string, collectionIds: string[], userId: UserId, - ): Promise { + ): Promise { const attachmentPromises: Promise[] = []; if (cipher.attachments != null) { cipher.attachments.forEach((attachment) => { @@ -806,6 +806,7 @@ export class CipherService implements CipherServiceAbstraction { const response = await this.apiService.putShareCipher(cipher.id, request); const data = new CipherData(response, collectionIds); await this.upsert(data); + return new Cipher(data, cipher.localData); } async shareManyWithServer( 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 ee1f27b712..26f967e4a5 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 @@ -157,8 +157,11 @@ describe("ItemDetailsSectionComponent", () => { }); describe("allowOwnershipChange", () => { - it("should not allow ownership change in edit mode", () => { + it("should not allow ownership change if in edit mode and the cipher is owned by an organization", () => { component.config.mode = "edit"; + component.originalCipherView = { + organizationId: "org1", + } as CipherView; expect(component.allowOwnershipChange).toBe(false); }); @@ -195,6 +198,7 @@ describe("ItemDetailsSectionComponent", () => { it("should show personal ownership when the configuration allows", () => { component.config.mode = "edit"; component.config.allowPersonalOwnership = true; + component.originalCipherView = {} as CipherView; component.config.organizations = [{ id: "134-433-22" } as Organization]; fixture.detectChanges(); @@ -208,6 +212,7 @@ describe("ItemDetailsSectionComponent", () => { it("should show personal ownership when the control is disabled", async () => { component.config.mode = "edit"; component.config.allowPersonalOwnership = false; + component.originalCipherView = {} as CipherView; component.config.organizations = [{ id: "134-433-22" } as Organization]; await component.ngOnInit(); fixture.detectChanges(); 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 a01d25f060..e6799c54cb 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 @@ -150,8 +150,8 @@ export class ItemDetailsSectionComponent implements OnInit { } get allowOwnershipChange() { - // Do not allow ownership change in edit mode. - if (this.config.mode === "edit") { + // Do not allow ownership change in edit mode and the cipher is owned by an organization + if (this.config.mode === "edit" && this.originalCipherView.organizationId != null) { return false; } diff --git a/libs/vault/src/cipher-form/services/default-cipher-form.service.ts b/libs/vault/src/cipher-form/services/default-cipher-form.service.ts index 92a28f9b15..059214cc18 100644 --- a/libs/vault/src/cipher-form/services/default-cipher-form.service.ts +++ b/libs/vault/src/cipher-form/services/default-cipher-form.service.ts @@ -63,8 +63,16 @@ export class DefaultCipherFormService implements CipherFormService { const originalCollectionIds = new Set(config.originalCipher.collectionIds ?? []); const newCollectionIds = new Set(cipher.collectionIds ?? []); - // If the collectionIds are the same, update the cipher normally - if (isSetEqual(originalCollectionIds, newCollectionIds)) { + // Call shareWithServer if the owner is changing from a user to an organization + if (config.originalCipher.organizationId === null && cipher.organizationId != null) { + savedCipher = await this.cipherService.shareWithServer( + cipher, + cipher.organizationId, + cipher.collectionIds, + activeUserId, + ); + // If the collectionIds are the same, update the cipher normally + } else if (isSetEqual(originalCollectionIds, newCollectionIds)) { savedCipher = await this.cipherService.updateWithServer(encryptedCipher, config.admin); } else { // Updating a cipher with collection changes is not supported with a single request currently