1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 16:53:34 +00:00

[PM-2383] Bulk collection assignment (#8429)

* [PM-2383] Add bulkUpdateCollectionsWithServer method to CipherService

* [PM-2383] Introduce bulk-collection-assignment-dialog.component

* [PM-2383] Add bulk assign collections option to org vault
This commit is contained in:
Shane Melton
2024-03-22 13:16:29 -07:00
committed by GitHub
parent 905d177873
commit bac0874dc0
13 changed files with 443 additions and 2 deletions

View File

@@ -1,5 +1,6 @@
import { UriMatchStrategySetting } from "../../models/domain/domain-service";
import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypto-key";
import { CipherId, CollectionId, OrganizationId } from "../../types/guid";
import { CipherType } from "../enums/cipher-type";
import { CipherData } from "../models/data/cipher.data";
import { Cipher } from "../models/domain/cipher";
@@ -63,6 +64,19 @@ export abstract class CipherService {
admin?: boolean,
) => Promise<Cipher>;
saveCollectionsWithServer: (cipher: Cipher) => Promise<any>;
/**
* Bulk update collections for many ciphers with the server
* @param orgId
* @param cipherIds
* @param collectionIds
* @param removeCollections - If true, the collections will be removed from the ciphers, otherwise they will be added
*/
bulkUpdateCollectionsWithServer: (
orgId: OrganizationId,
cipherIds: CipherId[],
collectionIds: CollectionId[],
removeCollections: boolean,
) => Promise<void>;
upsert: (cipher: CipherData | CipherData[]) => Promise<any>;
replace: (ciphers: { [id: string]: CipherData }) => Promise<any>;
clear: (userId: string) => Promise<any>;

View File

@@ -0,0 +1,19 @@
import { CipherId, CollectionId, OrganizationId } from "../../../types/guid";
export class CipherBulkUpdateCollectionsRequest {
organizationId: OrganizationId;
cipherIds: CipherId[];
collectionIds: CollectionId[];
removeCollections: boolean;
constructor(
organizationId: OrganizationId,
cipherIds: CipherId[],
collectionIds: CollectionId[],
removeCollections: boolean = false,
) {
this.organizationId = organizationId;
this.cipherIds = cipherIds;
this.collectionIds = collectionIds;
this.removeCollections = removeCollections;
}
}

View File

@@ -21,7 +21,8 @@ import Domain from "../../platform/models/domain/domain-base";
import { EncArrayBuffer } from "../../platform/models/domain/enc-array-buffer";
import { EncString } from "../../platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypto-key";
import { UserKey, OrgKey } from "../../types/key";
import { CipherId, CollectionId, OrganizationId } from "../../types/guid";
import { OrgKey, UserKey } from "../../types/key";
import { CipherService as CipherServiceAbstraction } from "../abstractions/cipher.service";
import { CipherFileUploadService } from "../abstractions/file-upload/cipher-file-upload.service";
import { FieldType } from "../enums";
@@ -42,6 +43,7 @@ import { CipherBulkDeleteRequest } from "../models/request/cipher-bulk-delete.re
import { CipherBulkMoveRequest } from "../models/request/cipher-bulk-move.request";
import { CipherBulkRestoreRequest } from "../models/request/cipher-bulk-restore.request";
import { CipherBulkShareRequest } from "../models/request/cipher-bulk-share.request";
import { CipherBulkUpdateCollectionsRequest } from "../models/request/cipher-bulk-update-collections.request";
import { CipherCollectionsRequest } from "../models/request/cipher-collections.request";
import { CipherCreateRequest } from "../models/request/cipher-create.request";
import { CipherPartialRequest } from "../models/request/cipher-partial.request";
@@ -685,6 +687,49 @@ export class CipherService implements CipherServiceAbstraction {
await this.upsert(data);
}
/**
* Bulk update collections for many ciphers with the server
* @param orgId
* @param cipherIds
* @param collectionIds
* @param removeCollections - If true, the collectionIds will be removed from the ciphers, otherwise they will be added
*/
async bulkUpdateCollectionsWithServer(
orgId: OrganizationId,
cipherIds: CipherId[],
collectionIds: CollectionId[],
removeCollections: boolean = false,
): Promise<void> {
const request = new CipherBulkUpdateCollectionsRequest(
orgId,
cipherIds,
collectionIds,
removeCollections,
);
await this.apiService.send("POST", "/ciphers/bulk-collections", request, true, false);
// Update the local state
const ciphers = await this.stateService.getEncryptedCiphers();
for (const id of cipherIds) {
const cipher = ciphers[id];
if (cipher) {
if (removeCollections) {
cipher.collectionIds = cipher.collectionIds?.filter(
(cid) => !collectionIds.includes(cid as CollectionId),
);
} else {
// Append to the collectionIds if it's not already there
cipher.collectionIds = [...new Set([...(cipher.collectionIds ?? []), ...collectionIds])];
}
}
}
await this.clearCache();
await this.stateService.setEncryptedCiphers(ciphers);
}
async upsert(cipher: CipherData | CipherData[]): Promise<any> {
let ciphers = await this.stateService.getEncryptedCiphers();
if (ciphers == null) {