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

[PM-12048] Wire up vNextCollectionService (#14871)

* remove derived state, add cache in service. Fix ts strict errors

* cleanup

* promote vNextCollectionService

* wip

* replace callers in web WIP

* refactor tests for web

* update callers to use vNextCollectionServcie methods in CLI

* WIP make decryptMany public again, fix callers, imports

* wip cli

* wip desktop

* update callers in browser, fix tests

* remove in service cache

* cleanup

* fix test

* clean up

* address cr feedback

* remove duplicate userId

* clean up

* remove unused import

* fix vault-settings-import-nudge.service

* fix caching issue

* clean up

* refactor decryption, cleanup, update callers

* clean up

* Use in-memory statedefinition

* Ac/pm 12048 v next collection service pairing (#15239)

* Draft from pairing with Gibson

* Add todos

* Add comment

* wip

* refactor upsert

---------

Co-authored-by: Brandon <btreston@bitwarden.com>

* clean up

* fix state definitions

* fix linter error

* cleanup

* add test, fix shareReplay

* fix item-more-options component

* fix desktop build

* refactor state to account for null as an initial value, remove caching

* add proper cache, add unit test, update callers

* clean up

* fix routing when deleting collections

* cleanup

* use combineLatest

* fix ts-strict errors, fix error handling

* refactor Collection and CollectionView properties for ts-strict

* Revert "refactor Collection and CollectionView properties for ts-strict"

This reverts commit a5c63aab76.

---------

Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
This commit is contained in:
Brandon Treston
2025-07-23 19:05:15 -04:00
committed by GitHub
parent 7a24a538a4
commit d0d1359ff4
56 changed files with 906 additions and 1112 deletions

View File

@@ -1,7 +1,7 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import * as papa from "papaparse";
import { firstValueFrom } from "rxjs";
import { firstValueFrom, map } from "rxjs";
import {
CollectionService,
@@ -225,15 +225,8 @@ export class OrganizationVaultExportService
): Promise<string> {
let decCiphers: CipherView[] = [];
let allDecCiphers: CipherView[] = [];
let decCollections: CollectionView[] = [];
const promises = [];
promises.push(
this.collectionService.getAllDecrypted().then(async (collections) => {
decCollections = collections.filter((c) => c.organizationId == organizationId && c.manage);
}),
);
promises.push(
this.cipherService.getAllDecrypted(activeUserId).then((ciphers) => {
allDecCiphers = ciphers;
@@ -241,6 +234,16 @@ export class OrganizationVaultExportService
);
await Promise.all(promises);
const decCollections: CollectionView[] = await firstValueFrom(
this.collectionService
.decryptedCollections$(activeUserId)
.pipe(
map((collections) =>
collections.filter((c) => c.organizationId == organizationId && c.manage),
),
),
);
const restrictions = await firstValueFrom(this.restrictedItemTypesService.restricted$);
decCiphers = allDecCiphers.filter(
@@ -263,15 +266,8 @@ export class OrganizationVaultExportService
): Promise<string> {
let encCiphers: Cipher[] = [];
let allCiphers: Cipher[] = [];
let encCollections: Collection[] = [];
const promises = [];
promises.push(
this.collectionService.getAll().then((collections) => {
encCollections = collections.filter((c) => c.organizationId == organizationId && c.manage);
}),
);
promises.push(
this.cipherService.getAll(activeUserId).then((ciphers) => {
allCiphers = ciphers;
@@ -280,6 +276,15 @@ export class OrganizationVaultExportService
await Promise.all(promises);
const encCollections: Collection[] = await firstValueFrom(
this.collectionService.encryptedCollections$(activeUserId).pipe(
map((collections) => collections ?? []),
map((collections) =>
collections.filter((c) => c.organizationId == organizationId && c.manage),
),
),
);
const restrictions = await firstValueFrom(this.restrictedItemTypesService.restricted$);
encCiphers = allCiphers.filter(

View File

@@ -272,25 +272,29 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit {
return;
}
this.organizations$ = combineLatest({
collections: this.collectionService.decryptedCollections$,
memberOrganizations: this.accountService.activeAccount$.pipe(
this.organizations$ = this.accountService.activeAccount$
.pipe(
getUserId,
switchMap((userId) => this.organizationService.memberOrganizations$(userId)),
),
}).pipe(
map(({ collections, memberOrganizations }) => {
const managedCollectionsOrgIds = new Set(
collections.filter((c) => c.manage).map((c) => c.organizationId),
);
// Filter organizations that exist in managedCollectionsOrgIds
const filteredOrgs = memberOrganizations.filter((org) =>
managedCollectionsOrgIds.has(org.id),
);
// Sort the filtered organizations based on the name
return filteredOrgs.sort(Utils.getSortFunction(this.i18nService, "name"));
}),
);
switchMap((userId) =>
combineLatest({
collections: this.collectionService.decryptedCollections$(userId),
memberOrganizations: this.organizationService.memberOrganizations$(userId),
}),
),
)
.pipe(
map(({ collections, memberOrganizations }) => {
const managedCollectionsOrgIds = new Set(
collections.filter((c) => c.manage).map((c) => c.organizationId),
);
// Filter organizations that exist in managedCollectionsOrgIds
const filteredOrgs = memberOrganizations.filter((org) =>
managedCollectionsOrgIds.has(org.id),
);
// Sort the filtered organizations based on the name
return filteredOrgs.sort(Utils.getSortFunction(this.i18nService, "name"));
}),
);
combineLatest([
this.disablePersonalVaultExportPolicy$,