mirror of
https://github.com/bitwarden/browser
synced 2024-12-14 18:25:52 +01:00
cf2d8b266a
* Prefer callback over error-flow to prompt for password Remove error-flow to request file password Prefer callback, which has to be provided when retrieving/creating an instance. Delete ImportError Call BitwardenPasswordProtector for all Bitwarden json imports, as it extends BitwardenJsonImporter Throw errors instead of returning Return ImportResult Fix and extend tests import.service Replace "@fluffy-spoon/substitute" with "jest-mock-extended" * Fix up test cases Delete bitwarden-json-importer.spec.ts Add test case to ensure bitwarden-json-importer.ts is called given unencrypted or account-protected files * Move file-password-prompt into dialog-folder * Add import success dialog * Fix typo * Only list the type when at least one got imported * update copy based on design feedback * Remove unnecessary /index import * Remove promptForPassword_callback from interface PR feedback from @MGibson1 that giving every importer the ability to request a password is unnecessary. Instead, we can pass the callback into the constructor for every importer that needs this functionality * Remove unneeded import of BitwardenJsonImporter * Fix spec constructor * Fixed organizational import Added an else statement, or else we'd import into an org and then also import into an individual vault
128 lines
4.1 KiB
TypeScript
128 lines
4.1 KiB
TypeScript
import { mock, MockProxy } from "jest-mock-extended";
|
|
|
|
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
|
import { KdfType } from "@bitwarden/common/enums";
|
|
import { Utils } from "@bitwarden/common/misc/utils";
|
|
|
|
import {
|
|
BitwardenPasswordProtectedImporter,
|
|
BitwardenJsonImporter,
|
|
} from "../src/importers/bitwarden";
|
|
|
|
import { emptyAccountEncrypted } from "./test-data/bitwarden-json/account-encrypted.json";
|
|
import { emptyUnencryptedExport } from "./test-data/bitwarden-json/unencrypted.json";
|
|
|
|
describe("BitwardenPasswordProtectedImporter", () => {
|
|
let importer: BitwardenPasswordProtectedImporter;
|
|
let cryptoService: MockProxy<CryptoService>;
|
|
let i18nService: MockProxy<I18nService>;
|
|
const password = Utils.newGuid();
|
|
const promptForPassword_callback = async () => {
|
|
return password;
|
|
};
|
|
|
|
beforeEach(() => {
|
|
cryptoService = mock<CryptoService>();
|
|
i18nService = mock<I18nService>();
|
|
|
|
importer = new BitwardenPasswordProtectedImporter(
|
|
cryptoService,
|
|
i18nService,
|
|
promptForPassword_callback
|
|
);
|
|
});
|
|
|
|
describe("Unencrypted", () => {
|
|
beforeAll(() => {
|
|
jest.spyOn(BitwardenJsonImporter.prototype, "parse");
|
|
});
|
|
|
|
it("Should call BitwardenJsonImporter", async () => {
|
|
expect((await importer.parse(emptyUnencryptedExport)).success).toEqual(true);
|
|
expect(BitwardenJsonImporter.prototype.parse).toHaveBeenCalledWith(emptyUnencryptedExport);
|
|
});
|
|
});
|
|
|
|
describe("Account encrypted", () => {
|
|
beforeAll(() => {
|
|
jest.spyOn(BitwardenJsonImporter.prototype, "parse");
|
|
});
|
|
|
|
it("Should call BitwardenJsonImporter", async () => {
|
|
expect((await importer.parse(emptyAccountEncrypted)).success).toEqual(true);
|
|
expect(BitwardenJsonImporter.prototype.parse).toHaveBeenCalledWith(emptyAccountEncrypted);
|
|
});
|
|
});
|
|
|
|
describe("Password protected", () => {
|
|
let jDoc: {
|
|
encrypted?: boolean;
|
|
passwordProtected?: boolean;
|
|
salt?: string;
|
|
kdfIterations?: any;
|
|
kdfType?: any;
|
|
encKeyValidation_DO_NOT_EDIT?: string;
|
|
data?: string;
|
|
};
|
|
|
|
beforeEach(() => {
|
|
jDoc = {
|
|
encrypted: true,
|
|
passwordProtected: true,
|
|
salt: "c2FsdA==",
|
|
kdfIterations: 100000,
|
|
kdfType: KdfType.PBKDF2_SHA256,
|
|
encKeyValidation_DO_NOT_EDIT: Utils.newGuid(),
|
|
data: Utils.newGuid(),
|
|
};
|
|
});
|
|
|
|
it("succeeds with default jdoc", async () => {
|
|
cryptoService.decryptToUtf8.mockReturnValue(Promise.resolve(emptyUnencryptedExport));
|
|
|
|
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(true);
|
|
});
|
|
|
|
it("fails if salt === null", async () => {
|
|
jDoc.salt = null;
|
|
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false);
|
|
});
|
|
|
|
it("fails if kdfIterations === null", async () => {
|
|
jDoc.kdfIterations = null;
|
|
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false);
|
|
});
|
|
|
|
it("fails if kdfIterations is not a number", async () => {
|
|
jDoc.kdfIterations = "not a number";
|
|
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false);
|
|
});
|
|
|
|
it("fails if kdfType === null", async () => {
|
|
jDoc.kdfType = null;
|
|
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false);
|
|
});
|
|
|
|
it("fails if kdfType is not a string", async () => {
|
|
jDoc.kdfType = "not a valid kdf type";
|
|
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false);
|
|
});
|
|
|
|
it("fails if kdfType is not a known kdfType", async () => {
|
|
jDoc.kdfType = -1;
|
|
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false);
|
|
});
|
|
|
|
it("fails if encKeyValidation_DO_NOT_EDIT === null", async () => {
|
|
jDoc.encKeyValidation_DO_NOT_EDIT = null;
|
|
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false);
|
|
});
|
|
|
|
it("fails if data === null", async () => {
|
|
jDoc.data = null;
|
|
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false);
|
|
});
|
|
});
|
|
});
|