mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
* Move import to sdk and enable it in browser/web * Add uncomitted files * Update package lock * Fix prettier formatting * Fix build * Rewrite import logic * Update ssh import logic for cipher form component * Fix build on browser * Break early in retry logic * Fix build * Fix build * Fix build errors * Update paste icons and throw error on wrong import * Fix tests * Fix build for cli * Undo change to jest config * Undo change to feature flag enum * Remove unneeded lifetime * Fix browser build * Refactor control flow * Fix i18n key and improve import behavior * Remove for loop limit * Clean up tests * Remove unused code * Update libs/vault/src/cipher-form/components/sshkey-section/sshkey-section.component.ts Co-authored-by: SmithThe4th <gsmith@bitwarden.com> * Move import logic to service and add tests * Fix linting * Remove erroneous includes * Attempt to fix storybook * Fix storybook, explicitly implement ssh-import-prompt service abstraction * Fix eslint * Update libs/importer/src/importers/bitwarden/bitwarden-json-importer.ts Co-authored-by: ✨ Audrey ✨ <ajensen@bitwarden.com> * Fix services module * Remove ssh import sdk init code * Add tests for errors * Fix import * Fix import * Fix pkcs8 encrypted key not parsing * Fix import button showing on web --------- Co-authored-by: SmithThe4th <gsmith@bitwarden.com> Co-authored-by: ✨ Audrey ✨ <ajensen@bitwarden.com>
112 lines
4.2 KiB
TypeScript
112 lines
4.2 KiB
TypeScript
import { MockProxy, mock } from "jest-mock-extended";
|
|
import { BehaviorSubject } from "rxjs";
|
|
|
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
|
import { SshKeyApi } from "@bitwarden/common/vault/models/api/ssh-key.api";
|
|
import { SshKeyData } from "@bitwarden/common/vault/models/data/ssh-key.data";
|
|
import { DialogService, ToastService } from "@bitwarden/components";
|
|
import * as sdkInternal from "@bitwarden/sdk-internal";
|
|
|
|
import { DefaultSshImportPromptService } from "./default-ssh-import-prompt.service";
|
|
|
|
jest.mock("@bitwarden/sdk-internal");
|
|
|
|
const exampleSshKey = {
|
|
privateKey: "private_key",
|
|
publicKey: "public_key",
|
|
fingerprint: "key_fingerprint",
|
|
} as sdkInternal.SshKeyView;
|
|
|
|
const exampleSshKeyData = new SshKeyData(
|
|
new SshKeyApi({
|
|
publicKey: exampleSshKey.publicKey,
|
|
privateKey: exampleSshKey.privateKey,
|
|
keyFingerprint: exampleSshKey.fingerprint,
|
|
}),
|
|
);
|
|
|
|
describe("SshImportPromptService", () => {
|
|
let sshImportPromptService: DefaultSshImportPromptService;
|
|
|
|
let dialogService: MockProxy<DialogService>;
|
|
let toastService: MockProxy<ToastService>;
|
|
let platformUtilsService: MockProxy<PlatformUtilsService>;
|
|
let i18nService: MockProxy<I18nService>;
|
|
|
|
beforeEach(() => {
|
|
dialogService = mock<DialogService>();
|
|
toastService = mock<ToastService>();
|
|
platformUtilsService = mock<PlatformUtilsService>();
|
|
i18nService = mock<I18nService>();
|
|
|
|
sshImportPromptService = new DefaultSshImportPromptService(
|
|
dialogService,
|
|
toastService,
|
|
platformUtilsService,
|
|
i18nService,
|
|
);
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
describe("importSshKeyFromClipboard()", () => {
|
|
it("imports unencrypted ssh key", async () => {
|
|
jest.spyOn(sdkInternal, "import_ssh_key").mockReturnValue(exampleSshKey);
|
|
platformUtilsService.readFromClipboard.mockResolvedValue("ssh_key");
|
|
expect(await sshImportPromptService.importSshKeyFromClipboard()).toEqual(exampleSshKeyData);
|
|
});
|
|
|
|
it("requests password for encrypted ssh key", async () => {
|
|
jest
|
|
.spyOn(sdkInternal, "import_ssh_key")
|
|
.mockImplementationOnce(() => {
|
|
throw { variant: "PasswordRequired" };
|
|
})
|
|
.mockImplementationOnce(() => exampleSshKey);
|
|
dialogService.open.mockReturnValue({ closed: new BehaviorSubject("password") } as any);
|
|
platformUtilsService.readFromClipboard.mockResolvedValue("ssh_key");
|
|
|
|
expect(await sshImportPromptService.importSshKeyFromClipboard()).toEqual(exampleSshKeyData);
|
|
expect(dialogService.open).toHaveBeenCalled();
|
|
});
|
|
|
|
it("cancels when no password was provided", async () => {
|
|
jest.spyOn(sdkInternal, "import_ssh_key").mockImplementationOnce(() => {
|
|
throw { variant: "PasswordRequired" };
|
|
});
|
|
dialogService.open.mockReturnValue({ closed: new BehaviorSubject("") } as any);
|
|
platformUtilsService.readFromClipboard.mockResolvedValue("ssh_key");
|
|
|
|
expect(await sshImportPromptService.importSshKeyFromClipboard()).toEqual(null);
|
|
expect(dialogService.open).toHaveBeenCalled();
|
|
});
|
|
|
|
it("passes through error on no password", async () => {
|
|
jest.spyOn(sdkInternal, "import_ssh_key").mockImplementationOnce(() => {
|
|
throw { variant: "UnsupportedKeyType" };
|
|
});
|
|
platformUtilsService.readFromClipboard.mockResolvedValue("ssh_key");
|
|
|
|
expect(await sshImportPromptService.importSshKeyFromClipboard()).toEqual(null);
|
|
expect(i18nService.t).toHaveBeenCalledWith("sshKeyTypeUnsupported");
|
|
});
|
|
|
|
it("passes through error with password", async () => {
|
|
jest
|
|
.spyOn(sdkInternal, "import_ssh_key")
|
|
.mockClear()
|
|
.mockImplementationOnce(() => {
|
|
throw { variant: "PasswordRequired" };
|
|
})
|
|
.mockImplementationOnce(() => {
|
|
throw { variant: "UnsupportedKeyType" };
|
|
});
|
|
platformUtilsService.readFromClipboard.mockResolvedValue("ssh_key");
|
|
dialogService.open.mockReturnValue({ closed: new BehaviorSubject("password") } as any);
|
|
|
|
expect(await sshImportPromptService.importSshKeyFromClipboard()).toEqual(null);
|
|
expect(i18nService.t).toHaveBeenCalledWith("sshKeyTypeUnsupported");
|
|
});
|
|
});
|
|
});
|