1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

[PM-24096] replace getOrgKey with orgKey$, refactor collectionAdminService (#15928)

* replace getOrgKey with orgKey$, refactor collectionAdminService

* clean up

* uncomment accidental commet

* remove cache
This commit is contained in:
Brandon Treston
2025-08-12 12:06:55 -04:00
committed by GitHub
parent 04489b9fef
commit d4952d211e
27 changed files with 226 additions and 73 deletions

View File

@@ -1,14 +1,15 @@
import { Observable } from "rxjs";
import { CollectionDetailsResponse } from "@bitwarden/admin-console/common";
import { UserId } from "@bitwarden/common/types/guid";
import { CollectionAccessSelectionView, CollectionAdminView } from "../models";
export abstract class CollectionAdminService {
abstract getAll(organizationId: string): Promise<CollectionAdminView[]>;
abstract get(
abstract collectionAdminViews$(
organizationId: string,
collectionId: string,
): Promise<CollectionAdminView | undefined>;
userId: UserId,
): Observable<CollectionAdminView[]>;
abstract save(
collection: CollectionAdminView,
userId: UserId,

View File

@@ -1,11 +1,14 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { combineLatest, firstValueFrom, from, map, Observable, of, switchMap } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
import { CollectionId, UserId } from "@bitwarden/common/types/guid";
import { CollectionId, OrganizationId, UserId } from "@bitwarden/common/types/guid";
import { OrgKey } from "@bitwarden/common/types/key";
import { KeyService } from "@bitwarden/key-management";
import { CollectionAdminService, CollectionService } from "../abstractions";
@@ -28,37 +31,23 @@ export class DefaultCollectionAdminService implements CollectionAdminService {
private collectionService: CollectionService,
) {}
async getAll(organizationId: string): Promise<CollectionAdminView[]> {
const collectionResponse =
await this.apiService.getManyCollectionsWithAccessDetails(organizationId);
collectionAdminViews$(organizationId: string, userId: UserId): Observable<CollectionAdminView[]> {
return combineLatest([
this.keyService.orgKeys$(userId),
from(this.apiService.getManyCollectionsWithAccessDetails(organizationId)),
]).pipe(
switchMap(([orgKey, res]) => {
if (res?.data == null || res.data.length === 0) {
return of([]);
}
if (collectionResponse?.data == null || collectionResponse.data.length === 0) {
return [];
}
return await this.decryptMany(organizationId, collectionResponse.data);
}
async get(
organizationId: string,
collectionId: string,
): Promise<CollectionAdminView | undefined> {
const collectionResponse = await this.apiService.getCollectionAccessDetails(
organizationId,
collectionId,
return this.decryptMany(organizationId, res.data, orgKey);
}),
);
if (collectionResponse == null) {
return undefined;
}
const [view] = await this.decryptMany(organizationId, [collectionResponse]);
return view;
}
async save(collection: CollectionAdminView, userId: UserId): Promise<CollectionDetailsResponse> {
const request = await this.encrypt(collection);
const request = await this.encrypt(collection, userId);
let response: CollectionDetailsResponse;
if (collection.id == null) {
@@ -112,13 +101,15 @@ export class DefaultCollectionAdminService implements CollectionAdminService {
private async decryptMany(
organizationId: string,
collections: CollectionResponse[] | CollectionAccessDetailsResponse[],
orgKeys: Record<OrganizationId, OrgKey>,
): Promise<CollectionAdminView[]> {
const orgKey = await this.keyService.getOrgKey(organizationId);
const promises = collections.map(async (c) => {
const view = new CollectionAdminView();
view.id = c.id;
view.name = await this.encryptService.decryptString(new EncString(c.name), orgKey);
view.name = await this.encryptService.decryptString(
new EncString(c.name),
orgKeys[organizationId as OrganizationId],
);
view.externalId = c.externalId;
view.organizationId = c.organizationId;
@@ -138,11 +129,15 @@ export class DefaultCollectionAdminService implements CollectionAdminService {
return await Promise.all(promises);
}
private async encrypt(model: CollectionAdminView): Promise<CollectionRequest> {
private async encrypt(model: CollectionAdminView, userId: UserId): Promise<CollectionRequest> {
if (model.organizationId == null) {
throw new Error("Collection has no organization id.");
}
const key = await this.keyService.getOrgKey(model.organizationId);
const key = await firstValueFrom(
this.keyService
.orgKeys$(userId)
.pipe(map((orgKeys) => orgKeys[model.organizationId] ?? null)),
);
if (key == null) {
throw new Error("No key for this collection's organization.");
}