1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-03 02:03:53 +00:00

Tools changes

This commit is contained in:
Bernd Schoolmann
2025-10-29 11:56:57 +01:00
parent 2b34351b44
commit df1cea0f1b
9 changed files with 72 additions and 42 deletions

View File

@@ -1,6 +1,7 @@
import { mock } from "jest-mock-extended";
import { of } from "rxjs";
import { mockEnc } from "../../../../../spec";
import { makeSymmetricCryptoKey, mockContainerService, mockEnc } from "../../../../../spec";
import { SendType } from "../../enums/send-type";
import { SendAccessResponse } from "../response/send-access.response";
@@ -55,6 +56,10 @@ describe("SendAccess", () => {
});
it("Decrypt", async () => {
const containerService = mockContainerService();
containerService.getKeyService().userKey$.mockReturnValue(of(makeSymmetricCryptoKey(64)));
containerService.getEncryptService().decryptString.mockResolvedValue("name");
const sendAccess = new SendAccess();
sendAccess.id = "id";
sendAccess.type = SendType.Text;

View File

@@ -1,5 +1,6 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { EncString } from "../../../../key-management/crypto/models/enc-string";
import Domain from "../../../../platform/models/domain/domain-base";
import { SymmetricCryptoKey } from "../../../../platform/models/domain/symmetric-crypto-key";
@@ -54,7 +55,7 @@ export class SendAccess extends Domain {
async decrypt(key: SymmetricCryptoKey): Promise<SendAccessView> {
const model = new SendAccessView(this);
await this.decryptObj<SendAccess, SendAccessView>(this, model, ["name"], null, key);
await this.decryptObj<SendAccess, SendAccessView>(this, model, ["name"], null, key, null);
switch (this.type) {
case SendType.File:

View File

@@ -1,4 +1,6 @@
import { mockEnc } from "../../../../../spec";
import { of } from "rxjs";
import { makeSymmetricCryptoKey, mockContainerService, mockEnc } from "../../../../../spec";
import { SendFileData } from "../data/send-file.data";
import { SendFile } from "./send-file";
@@ -39,6 +41,10 @@ describe("SendFile", () => {
});
it("Decrypt", async () => {
const containerService = mockContainerService();
containerService.getKeyService().userKey$.mockReturnValue(of(makeSymmetricCryptoKey(64)));
containerService.getEncryptService().decryptString.mockResolvedValue("fileName");
const sendFile = new SendFile();
sendFile.id = "id";
sendFile.size = "1100";

View File

@@ -40,6 +40,7 @@ export class SendFile extends Domain {
["fileName"],
null,
key,
null,
);
}

View File

@@ -1,4 +1,6 @@
import { mockEnc } from "../../../../../spec";
import { of } from "rxjs";
import { makeSymmetricCryptoKey, mockContainerService, mockEnc } from "../../../../../spec";
import { SendTextData } from "../data/send-text.data";
import { SendText } from "./send-text";
@@ -33,11 +35,15 @@ describe("SendText", () => {
});
it("Decrypt", async () => {
const secureNote = new SendText();
secureNote.text = mockEnc("text");
secureNote.hidden = true;
const containerService = mockContainerService();
containerService.getKeyService().userKey$.mockReturnValue(of(makeSymmetricCryptoKey(64)));
containerService.getEncryptService().decryptString.mockResolvedValue("text");
const view = await secureNote.decrypt(null);
const sendText = new SendText();
sendText.text = mockEnc("text");
sendText.hidden = true;
const view = await sendText.decrypt(null);
expect(view).toEqual({
text: "text",

View File

@@ -36,6 +36,7 @@ export class SendText extends Domain {
["text"],
null,
key,
null,
);
}

View File

@@ -1,16 +1,14 @@
import { mock } from "jest-mock-extended";
import { of } from "rxjs";
import mock from "@bitwarden/common/platform/spec/mock-deep";
import { emptyGuid, UserId } from "@bitwarden/common/types/guid";
// 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 { KeyService } from "@bitwarden/key-management";
import { makeStaticByteArray, mockEnc } from "../../../../../spec";
import { EncryptService } from "../../../../key-management/crypto/abstractions/encrypt.service";
import { SymmetricCryptoKey } from "../../../../platform/models/domain/symmetric-crypto-key";
import { ContainerService } from "../../../../platform/services/container.service";
import { UserKey } from "../../../../types/key";
import {
mockEnc,
makeStaticByteArray,
mockContainerService,
makeSymmetricCryptoKey,
} from "../../../../../spec";
import { SendType } from "../../enums/send-type";
import { SendData } from "../data/send.data";
@@ -96,9 +94,18 @@ describe("Send", () => {
});
it("Decrypt", async () => {
const containerService = mockContainerService();
containerService.getKeyService().userKey$.mockReturnValue(of(makeSymmetricCryptoKey(64)));
containerService
.getEncryptService()
.decryptString.mockResolvedValueOnce("name")
.mockResolvedValueOnce("notes");
containerService
.getEncryptService()
.decryptBytes.mockResolvedValueOnce(makeStaticByteArray(32));
const text = mock<SendText>();
text.decrypt.mockResolvedValue("textView" as any);
const userKey = new SymmetricCryptoKey(new Uint8Array(32)) as UserKey;
const userId = emptyGuid as UserId;
const send = new Send();
@@ -117,24 +124,15 @@ describe("Send", () => {
send.disabled = false;
send.hideEmail = true;
const encryptService = mock<EncryptService>();
const keyService = mock<KeyService>();
encryptService.decryptBytes
.calledWith(send.key, userKey)
.mockResolvedValue(makeStaticByteArray(32));
keyService.makeSendKey.mockResolvedValue("cryptoKey" as any);
keyService.userKey$.calledWith(userId).mockReturnValue(of(userKey));
(window as any).bitwardenContainerService = new ContainerService(keyService, encryptService);
containerService.getKeyService().makeSendKey.mockResolvedValue("cryptoKey" as any);
const view = await send.decrypt(userId);
expect(text.decrypt).toHaveBeenNthCalledWith(1, "cryptoKey");
expect(send.name.decrypt).toHaveBeenNthCalledWith(
expect(text.decrypt).toHaveBeenNthCalledWith(1, userId, "cryptoKey");
expect(containerService.getEncryptService().decryptString).toHaveBeenNthCalledWith(
1,
null,
"name",
"cryptoKey",
"Property: name; ObjectContext: No Domain Context",
);
expect(view).toMatchObject({

View File

@@ -89,7 +89,14 @@ export class Send extends Domain {
model.key = await encryptService.decryptBytes(this.key, sendKeyEncryptionKey);
model.cryptoKey = await keyService.makeSendKey(model.key);
await this.decryptObj<Send, SendView>(this, model, ["name", "notes"], null, model.cryptoKey);
await this.decryptObj<Send, SendView>(
this,
model,
["name", "notes"],
null,
model.cryptoKey,
null,
);
switch (this.type) {
case SendType.File:

View File

@@ -6,6 +6,7 @@ import { concatMap, firstValueFrom, map } from "rxjs";
// eslint-disable-next-line no-restricted-imports
import { Collection, CollectionView } from "@bitwarden/admin-console/common";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { getUserId } from "@bitwarden/common/auth/services/account.service";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
import {
@@ -15,7 +16,7 @@ import {
} from "@bitwarden/common/models/export";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { OrganizationId } from "@bitwarden/common/types/guid";
import { OrganizationId, UserId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
import { KeyService } from "@bitwarden/key-management";
@@ -52,10 +53,11 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
return this.result;
}
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
if (results.encrypted) {
await this.parseEncrypted(results as any);
await this.parseEncrypted(results as any, userId);
} else {
await this.parseDecrypted(results as any);
await this.parseDecrypted(results as any, userId);
}
return this.result;
@@ -63,14 +65,13 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
private async parseEncrypted(
results: BitwardenEncryptedIndividualJsonExport | BitwardenEncryptedOrgJsonExport,
userId: UserId,
) {
const account = await firstValueFrom(this.accountService.activeAccount$);
if (results.encKeyValidation_DO_NOT_EDIT != null) {
const orgKeys = await firstValueFrom(this.keyService.orgKeys$(account.id));
const orgKeys = await firstValueFrom(this.keyService.orgKeys$(userId));
let keyForDecryption: SymmetricCryptoKey = orgKeys?.[this.organizationId];
if (keyForDecryption == null) {
keyForDecryption = await firstValueFrom(this.keyService.userKey$(account.id));
keyForDecryption = await firstValueFrom(this.keyService.userKey$(userId));
}
const encKeyValidation = new EncString(results.encKeyValidation_DO_NOT_EDIT);
try {
@@ -84,7 +85,7 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
const groupingsMap = this.organization
? await this.parseCollections(results as BitwardenEncryptedOrgJsonExport)
: await this.parseFolders(results as BitwardenEncryptedIndividualJsonExport);
: await this.parseFolders(results as BitwardenEncryptedIndividualJsonExport, userId);
for (const c of results.items) {
const cipher = CipherWithIdExport.toDomain(c);
@@ -114,7 +115,7 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
});
}
const view = await this.cipherService.decrypt(cipher, account.id);
const view = await this.cipherService.decrypt(cipher, userId);
this.cleanupCipher(view);
this.result.ciphers.push(view);
}
@@ -124,10 +125,11 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
private async parseDecrypted(
results: BitwardenUnEncryptedIndividualJsonExport | BitwardenUnEncryptedOrgJsonExport,
userId: UserId,
) {
const groupingsMap = this.organization
? await this.parseCollections(results as BitwardenUnEncryptedOrgJsonExport)
: await this.parseFolders(results as BitwardenUnEncryptedIndividualJsonExport);
: await this.parseFolders(results as BitwardenUnEncryptedIndividualJsonExport, userId);
results.items.forEach((c) => {
const cipher = CipherWithIdExport.toView(c);
@@ -166,6 +168,7 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
private async parseFolders(
data: BitwardenUnEncryptedIndividualJsonExport | BitwardenEncryptedIndividualJsonExport,
userId: UserId,
): Promise<Map<string, number>> | null {
if (data.folders == null) {
return null;
@@ -178,6 +181,8 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
if (data.encrypted) {
const folder = FolderWithIdExport.toDomain(f);
if (folder != null) {
// A follow-up PR in the PR chain https://bitwarden.atlassian.net/browse/PM-24102 will use the userId here
// after vault's changes.
folderView = await folder.decrypt();
}
} else {