1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 15:53:27 +00:00

[PM-24227] Enable TS-strict for Collection Domain models (#15765)

* wip ts-strict

* wip ts-strict

* wip

* cleanup

* cleanup

* fix story

* fix story

* fix story

* wip

* clean up CollectionAdminView construction

* fix deprecated function call

* fix cli

* clean up

* fix story

* wip

* fix cli

* requested changes

* clean up, fixing minor bugs, more type saftey

* assign props in static ctor, clean up
This commit is contained in:
Brandon Treston
2025-08-14 13:08:24 -04:00
committed by GitHub
parent ac7e873813
commit 27089fbb57
41 changed files with 537 additions and 379 deletions

View File

@@ -4,12 +4,12 @@ import * as papa from "papaparse";
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
// eslint-disable-next-line no-restricted-imports
import { CollectionView } from "@bitwarden/admin-console/common";
import { Collection, CollectionView } from "@bitwarden/admin-console/common";
import { normalizeExpiryYearFormat } from "@bitwarden/common/autofill/utils";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
import { OrganizationId } from "@bitwarden/common/types/guid";
import { FieldType, SecureNoteType, CipherType } from "@bitwarden/common/vault/enums";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { FieldView } from "@bitwarden/common/vault/models/view/field.view";
@@ -278,9 +278,12 @@ export abstract class BaseImporter {
protected moveFoldersToCollections(result: ImportResult) {
result.folderRelationships.forEach((r) => result.collectionRelationships.push(r));
result.collections = result.folders.map((f) => {
const collection = new CollectionView();
collection.name = f.name;
collection.id = (f.id as CollectionId) ?? undefined; // folder id may be null, which is not suitable for collections.
const collection = new CollectionView({
name: f.name,
organizationId: this.organizationId,
// FIXME: Folder.id may be null, this should be changed when refactoring Folders to be ts-strict
id: Collection.isCollectionId(f.id) ? f.id : null,
});
return collection;
});
result.folderRelationships = [];

View File

@@ -1,10 +1,10 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { firstValueFrom, map } from "rxjs";
import { concatMap, firstValueFrom, map } from "rxjs";
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
// eslint-disable-next-line no-restricted-imports
import { CollectionView } from "@bitwarden/admin-console/common";
import { Collection, CollectionView } from "@bitwarden/admin-console/common";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
@@ -206,11 +206,20 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
for (const c of data.collections) {
let collectionView: CollectionView;
if (data.encrypted) {
const collection = CollectionWithIdExport.toDomain(c);
collection.organizationId = this.organizationId;
collectionView = await firstValueFrom(this.keyService.activeUserOrgKeys$).then((orgKeys) =>
collection.decrypt(orgKeys[c.organizationId as OrganizationId]),
const collection = CollectionWithIdExport.toDomain(
c,
new Collection({
id: c.id,
name: new EncString(c.name),
organizationId: this.organizationId,
}),
);
const collection$ = this.keyService.activeUserOrgKeys$.pipe(
// FIXME: replace type assertion with narrowing
map((keys) => keys[c.organizationId as OrganizationId]),
concatMap((key) => collection.decrypt(key, this.encryptService)),
);
collectionView = await firstValueFrom(collection$);
} else {
collectionView = CollectionWithIdExport.toView(c);
collectionView.organizationId = null;

View File

@@ -46,8 +46,11 @@ export class PadlockCsvImporter extends BaseImporter implements Importer {
}
if (addCollection) {
const collection = new CollectionView();
collection.name = tag;
// FIXME use a different model if ID is not required.
// @ts-expect-error current functionality creates this view with no Id since its being imported.
const collection = new CollectionView({
name: tag,
});
result.collections.push(collection);
}

View File

@@ -47,8 +47,11 @@ export class PasspackCsvImporter extends BaseImporter implements Importer {
}
if (addCollection) {
const collection = new CollectionView();
collection.name = tag;
// FIXME use a different model if ID is not required.
// @ts-expect-error current functionality creates this view with no Id since its being imported.
const collection = new CollectionView({
name: tag,
});
result.collections.push(collection);
}

View File

@@ -487,8 +487,11 @@ describe("Password Depot 17 Xml Importer", () => {
it("should parse groups nodes into collections when importing into an organization", async () => {
const importer = new PasswordDepot17XmlImporter();
importer.organizationId = "someOrgId" as OrganizationId;
const collection = new CollectionView();
collection.name = "tempDB";
const collection = new CollectionView({
name: "tempDB",
organizationId: importer.organizationId,
id: null,
});
const actual = [collection];
const result = await importer.parse(PasswordTestData);

View File

@@ -145,20 +145,29 @@ describe("ImportService", () => {
);
});
const mockImportTargetCollection = new CollectionView();
mockImportTargetCollection.id = "myImportTarget" as CollectionId;
mockImportTargetCollection.name = "myImportTarget";
mockImportTargetCollection.organizationId = organizationId;
const mockName = "myImportTarget";
const mockId = "myImportTarget" as CollectionId;
const mockImportTargetCollection = new CollectionView({
name: mockName,
id: mockId,
organizationId,
});
const mockCollection1 = new CollectionView();
mockCollection1.id = "collection1" as CollectionId;
mockCollection1.name = "collection1";
mockCollection1.organizationId = organizationId;
const mockName1 = "collection1";
const mockId1 = "collection1" as CollectionId;
const mockCollection1 = new CollectionView({
name: mockName1,
id: mockId1,
organizationId,
});
const mockCollection2 = new CollectionView();
mockCollection2.id = "collection2" as CollectionId;
mockCollection2.name = "collection2";
mockCollection2.organizationId = organizationId;
const mockName2 = "collection2";
const mockId2 = "collection2" as CollectionId;
const mockCollection2 = new CollectionView({
name: mockName2,
id: mockId2,
organizationId,
});
it("passing importTarget adds it to collections", async () => {
await importService["setImportTarget"](

View File

@@ -501,7 +501,7 @@ export class ImportService implements ImportServiceAbstraction {
const collections: CollectionView[] = [...importResult.collections];
importResult.collections = [importTarget as CollectionView];
collections.map((x) => {
const f = new CollectionView();
const f = new CollectionView(x);
f.name = `${importTarget.name}/${x.name}`;
importResult.collections.push(f);
});