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:
@@ -7,3 +7,4 @@ export type OrganizationId = Opaque<string, "OrganizationId">;
|
||||
export type CollectionId = Opaque<string, "CollectionId">;
|
||||
export type ProviderId = Opaque<string, "ProviderId">;
|
||||
export type PolicyId = Opaque<string, "PolicyId">;
|
||||
export type CipherId = Opaque<string, "CipherId">;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user