mirror of
https://github.com/bitwarden/browser
synced 2026-01-06 02:23:44 +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>
110 lines
3.3 KiB
TypeScript
110 lines
3.3 KiB
TypeScript
import { Injectable } from "@angular/core";
|
|
import { firstValueFrom } 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 { SshKeyPasswordPromptComponent } from "@bitwarden/importer-ui";
|
|
import { import_ssh_key, SshKeyImportError, SshKeyView } from "@bitwarden/sdk-internal";
|
|
|
|
import { SshImportPromptService } from "./ssh-import-prompt.service";
|
|
|
|
/**
|
|
* Used to import ssh keys and prompt for their password.
|
|
*/
|
|
@Injectable()
|
|
export class DefaultSshImportPromptService implements SshImportPromptService {
|
|
constructor(
|
|
private dialogService: DialogService,
|
|
private toastService: ToastService,
|
|
private platformUtilsService: PlatformUtilsService,
|
|
private i18nService: I18nService,
|
|
) {}
|
|
|
|
async importSshKeyFromClipboard(): Promise<SshKeyData | null> {
|
|
const key = await this.platformUtilsService.readFromClipboard();
|
|
|
|
let isPasswordProtectedSshKey = false;
|
|
|
|
let parsedKey: SshKeyView | null = null;
|
|
|
|
try {
|
|
parsedKey = import_ssh_key(key);
|
|
} catch (e) {
|
|
const error = e as SshKeyImportError;
|
|
if (error.variant === "PasswordRequired" || error.variant === "WrongPassword") {
|
|
isPasswordProtectedSshKey = true;
|
|
} else {
|
|
this.toastService.showToast({
|
|
variant: "error",
|
|
title: "",
|
|
message: this.i18nService.t(this.sshImportErrorVariantToI18nKey(error.variant)),
|
|
});
|
|
return null;
|
|
}
|
|
}
|
|
|
|
if (isPasswordProtectedSshKey) {
|
|
for (;;) {
|
|
const password = await this.getSshKeyPassword();
|
|
if (password === "" || password == null) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
parsedKey = import_ssh_key(key, password);
|
|
break;
|
|
} catch (e) {
|
|
const error = e as SshKeyImportError;
|
|
if (error.variant !== "WrongPassword") {
|
|
this.toastService.showToast({
|
|
variant: "error",
|
|
title: "",
|
|
message: this.i18nService.t(this.sshImportErrorVariantToI18nKey(error.variant)),
|
|
});
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
this.toastService.showToast({
|
|
variant: "success",
|
|
title: "",
|
|
message: this.i18nService.t("sshKeyImported"),
|
|
});
|
|
|
|
return new SshKeyData(
|
|
new SshKeyApi({
|
|
privateKey: parsedKey!.privateKey,
|
|
publicKey: parsedKey!.publicKey,
|
|
keyFingerprint: parsedKey!.fingerprint,
|
|
}),
|
|
);
|
|
}
|
|
|
|
private sshImportErrorVariantToI18nKey(variant: string): string {
|
|
switch (variant) {
|
|
case "ParsingError":
|
|
return "invalidSshKey";
|
|
case "UnsupportedKeyType":
|
|
return "sshKeyTypeUnsupported";
|
|
case "PasswordRequired":
|
|
case "WrongPassword":
|
|
return "sshKeyWrongPassword";
|
|
default:
|
|
return "errorOccurred";
|
|
}
|
|
}
|
|
|
|
private async getSshKeyPassword(): Promise<string | undefined> {
|
|
const dialog = this.dialogService.open<string>(SshKeyPasswordPromptComponent, {
|
|
ariaModal: true,
|
|
});
|
|
|
|
return await firstValueFrom(dialog.closed);
|
|
}
|
|
}
|