mirror of
https://github.com/bitwarden/browser
synced 2025-12-06 00:13:28 +00:00
[PM-1071] Display import-details-dialog on successful import (#4817)
* 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
This commit is contained in:
committed by
GitHub
parent
19626a7837
commit
cf2d8b266a
@@ -1,77 +1,89 @@
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { Substitute, Arg, SubstituteOf } from "@fluffy-spoon/substitute";
|
||||
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 } from "../src/importers";
|
||||
import { ImportResult } from "../src/models/import-result";
|
||||
import {
|
||||
BitwardenPasswordProtectedImporter,
|
||||
BitwardenJsonImporter,
|
||||
} from "../src/importers/bitwarden";
|
||||
|
||||
import { data as emptyDecryptedData } from "./test-data/bitwarden-json/empty.json";
|
||||
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: SubstituteOf<CryptoService>;
|
||||
let i18nService: SubstituteOf<I18nService>;
|
||||
let cryptoService: MockProxy<CryptoService>;
|
||||
let i18nService: MockProxy<I18nService>;
|
||||
const password = Utils.newGuid();
|
||||
const result = new ImportResult();
|
||||
let jDoc: {
|
||||
encrypted?: boolean;
|
||||
passwordProtected?: boolean;
|
||||
salt?: string;
|
||||
kdfIterations?: any;
|
||||
kdfType?: any;
|
||||
encKeyValidation_DO_NOT_EDIT?: string;
|
||||
data?: string;
|
||||
const promptForPassword_callback = async () => {
|
||||
return password;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
cryptoService = Substitute.for<CryptoService>();
|
||||
i18nService = Substitute.for<I18nService>();
|
||||
cryptoService = mock<CryptoService>();
|
||||
i18nService = mock<I18nService>();
|
||||
|
||||
jDoc = {
|
||||
encrypted: true,
|
||||
passwordProtected: true,
|
||||
salt: "c2FsdA==",
|
||||
kdfIterations: 100000,
|
||||
kdfType: KdfType.PBKDF2_SHA256,
|
||||
encKeyValidation_DO_NOT_EDIT: Utils.newGuid(),
|
||||
data: Utils.newGuid(),
|
||||
};
|
||||
|
||||
result.success = true;
|
||||
importer = new BitwardenPasswordProtectedImporter(cryptoService, i18nService, password);
|
||||
importer = new BitwardenPasswordProtectedImporter(
|
||||
cryptoService,
|
||||
i18nService,
|
||||
promptForPassword_callback
|
||||
);
|
||||
});
|
||||
|
||||
describe("Required Json Data", () => {
|
||||
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(Arg.any(), Arg.any()).resolves(emptyDecryptedData);
|
||||
cryptoService.decryptToUtf8.mockReturnValue(Promise.resolve(emptyUnencryptedExport));
|
||||
|
||||
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(true);
|
||||
});
|
||||
|
||||
it("fails if encrypted === false", async () => {
|
||||
jDoc.encrypted = false;
|
||||
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false);
|
||||
});
|
||||
|
||||
it("fails if encrypted === null", async () => {
|
||||
jDoc.encrypted = null;
|
||||
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false);
|
||||
});
|
||||
|
||||
it("fails if passwordProtected === false", async () => {
|
||||
jDoc.passwordProtected = false;
|
||||
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false);
|
||||
});
|
||||
|
||||
it("fails if passwordProtected === null", async () => {
|
||||
jDoc.passwordProtected = null;
|
||||
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false);
|
||||
});
|
||||
|
||||
it("fails if salt === null", async () => {
|
||||
jDoc.salt = null;
|
||||
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false);
|
||||
|
||||
Reference in New Issue
Block a user