1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 07:43:35 +00:00
Files
browser/libs/vault/src/services/ssh-import-prompt.service.spec.ts
Bernd Schoolmann 01f6fd7ee3 [PM-16227] Move import to sdk and enable it in browser/web (#12479)
* 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>
2025-03-10 18:41:47 +01:00

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");
});
});
});