mirror of
https://github.com/bitwarden/browser
synced 2025-12-20 18:23:31 +00:00
* [PM-10395] Add new item type ssh key (#10360) * Implement ssh-key cipher type * Fix linting * Fix edit and view components for ssh-keys on desktop * Fix tests * Remove ssh key type references * Remove add ssh key option * Fix typo * Add tests * [PM-10399] Add ssh key import export for bitwarden json (#10529) * Add ssh key import export for bitwarden json * Remove key type from ssh key export * [PM-10406] Add privatekey publickey and fingerprint to both add-edit and view co… (#11046) * Add privatekey publickey and fingerprint to both add-edit and view components * Remove wrong a11y title * Fix testid * [PM-10098] SSH Agent & SSH Key creation for Bitwarden Desktop (#10293) * Add ssh agent, generator & import * Move ssh agent code to bitwarden-russh crate * Remove generator component * Cleanup * Cleanup * Remove left over sshGenerator reference * Cleanup * Add documentation to sshkeyimportstatus * Fix outdated variable name * Update apps/desktop/src/platform/preload.ts Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com> * Rename renderersshagent * Rename MainSshAgentService * Improve clarity of 'id' variables being used * Improve clarity of 'id' variables being used * Update apps/desktop/src/vault/app/vault/add-edit.component.html Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com> * Fix outdated cipher/messageid names * Rename SSH to Ssh * Make agent syncing more reactive * Move constants to top of class * Make sshkey cipher filtering clearer * Add stricter equality check on ssh key unlock * Fix build and messages * Fix incorrect featureflag name * Replace anonymous async function with switchmap pipe * Fix build * Update apps/desktop/desktop_native/napi/src/lib.rs Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com> * Revert incorrectly renamed 'Ssh' usages to SSH * Run cargo fmt * Clean up ssh agent sock path logic * Cleanup and split to platform specific files * Small cleanup * Pull out generator and importer into core * Rename renderersshagentservice to sshagentservice * Rename cipheruuid to cipher_id * Drop ssh dependencies from napi crate * Clean up windows build * Small cleanup * Small cleanup * Cleanup * Add rxjs pipeline for agent services * [PM-12555] Pkcs8 sshkey import & general ssh key import tests (#11048) * Add pkcs8 import and tests * Add key type unsupported error * Remove unsupported formats * Remove code for unsupported formats * Fix encrypted pkcs8 import * Add ed25519 pkcs8 unencrypted test file * SSH agent rxjs tweaks (#11148) * feat: rewrite sshagent.signrequest as purely observable * feat: fail the request when unlock times out * chore: clean up, add some clarifying comments * chore: remove unused dependency * fix: result `undefined` crashing in NAPI -> Rust * Allow concurrent SSH requests in rust * Remove unwraps * Cleanup and add init service init call * Fix windows * Fix timeout behavior on locked vault --------- Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com> * Fix libc dependency being duplicated * fix SSH casing (#11840) * Move ssh agent behind feature flag (#11841) * Move ssh agent behind feature flag * Add separate flag for ssh agent * [PM-14215] fix unsupported key type error message (#11788) * Fix error message for import of unsupported ssh keys * Use triple equals in add-edit component for ssh keys --------- Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com> Co-authored-by: aj-bw <81774843+aj-bw@users.noreply.github.com>
196 lines
6.0 KiB
TypeScript
196 lines
6.0 KiB
TypeScript
import { EncString } from "../../platform/models/domain/enc-string";
|
|
import { CipherRepromptType } from "../../vault/enums/cipher-reprompt-type";
|
|
import { CipherType } from "../../vault/enums/cipher-type";
|
|
import { Cipher as CipherDomain } from "../../vault/models/domain/cipher";
|
|
import { CipherView } from "../../vault/models/view/cipher.view";
|
|
|
|
import { CardExport } from "./card.export";
|
|
import { FieldExport } from "./field.export";
|
|
import { IdentityExport } from "./identity.export";
|
|
import { LoginExport } from "./login.export";
|
|
import { PasswordHistoryExport } from "./password-history.export";
|
|
import { SecureNoteExport } from "./secure-note.export";
|
|
import { SshKeyExport } from "./ssh-key.export";
|
|
import { safeGetString } from "./utils";
|
|
|
|
export class CipherExport {
|
|
static template(): CipherExport {
|
|
const req = new CipherExport();
|
|
req.organizationId = null;
|
|
req.collectionIds = null;
|
|
req.folderId = null;
|
|
req.type = CipherType.Login;
|
|
req.name = "Item name";
|
|
req.notes = "Some notes about this item.";
|
|
req.favorite = false;
|
|
req.fields = [];
|
|
req.login = null;
|
|
req.secureNote = null;
|
|
req.card = null;
|
|
req.identity = null;
|
|
req.sshKey = null;
|
|
req.reprompt = CipherRepromptType.None;
|
|
req.passwordHistory = [];
|
|
req.creationDate = null;
|
|
req.revisionDate = null;
|
|
req.deletedDate = null;
|
|
return req;
|
|
}
|
|
|
|
static toView(req: CipherExport, view = new CipherView()) {
|
|
view.type = req.type;
|
|
view.folderId = req.folderId;
|
|
if (view.organizationId == null) {
|
|
view.organizationId = req.organizationId;
|
|
}
|
|
if (view.collectionIds || req.collectionIds) {
|
|
const set = new Set((view.collectionIds ?? []).concat(req.collectionIds ?? []));
|
|
view.collectionIds = Array.from(set.values());
|
|
}
|
|
view.name = req.name;
|
|
view.notes = req.notes;
|
|
view.favorite = req.favorite;
|
|
view.reprompt = req.reprompt ?? CipherRepromptType.None;
|
|
|
|
if (req.fields != null) {
|
|
view.fields = req.fields.map((f) => FieldExport.toView(f));
|
|
}
|
|
|
|
switch (req.type) {
|
|
case CipherType.Login:
|
|
view.login = LoginExport.toView(req.login);
|
|
break;
|
|
case CipherType.SecureNote:
|
|
view.secureNote = SecureNoteExport.toView(req.secureNote);
|
|
break;
|
|
case CipherType.Card:
|
|
view.card = CardExport.toView(req.card);
|
|
break;
|
|
case CipherType.Identity:
|
|
view.identity = IdentityExport.toView(req.identity);
|
|
break;
|
|
case CipherType.SshKey:
|
|
view.sshKey = SshKeyExport.toView(req.sshKey);
|
|
}
|
|
|
|
if (req.passwordHistory != null) {
|
|
view.passwordHistory = req.passwordHistory.map((ph) => PasswordHistoryExport.toView(ph));
|
|
}
|
|
|
|
view.creationDate = req.creationDate;
|
|
view.revisionDate = req.revisionDate;
|
|
view.deletedDate = req.deletedDate;
|
|
return view;
|
|
}
|
|
|
|
static toDomain(req: CipherExport, domain = new CipherDomain()) {
|
|
domain.type = req.type;
|
|
domain.folderId = req.folderId;
|
|
if (domain.organizationId == null) {
|
|
domain.organizationId = req.organizationId;
|
|
}
|
|
domain.name = req.name != null ? new EncString(req.name) : null;
|
|
domain.notes = req.notes != null ? new EncString(req.notes) : null;
|
|
domain.favorite = req.favorite;
|
|
domain.reprompt = req.reprompt ?? CipherRepromptType.None;
|
|
domain.key = req.key != null ? new EncString(req.key) : null;
|
|
|
|
if (req.fields != null) {
|
|
domain.fields = req.fields.map((f) => FieldExport.toDomain(f));
|
|
}
|
|
|
|
switch (req.type) {
|
|
case CipherType.Login:
|
|
domain.login = LoginExport.toDomain(req.login);
|
|
break;
|
|
case CipherType.SecureNote:
|
|
domain.secureNote = SecureNoteExport.toDomain(req.secureNote);
|
|
break;
|
|
case CipherType.Card:
|
|
domain.card = CardExport.toDomain(req.card);
|
|
break;
|
|
case CipherType.Identity:
|
|
domain.identity = IdentityExport.toDomain(req.identity);
|
|
break;
|
|
case CipherType.SshKey:
|
|
domain.sshKey = SshKeyExport.toDomain(req.sshKey);
|
|
break;
|
|
}
|
|
|
|
if (req.passwordHistory != null) {
|
|
domain.passwordHistory = req.passwordHistory.map((ph) => PasswordHistoryExport.toDomain(ph));
|
|
}
|
|
|
|
domain.creationDate = req.creationDate;
|
|
domain.revisionDate = req.revisionDate;
|
|
domain.deletedDate = req.deletedDate;
|
|
return domain;
|
|
}
|
|
|
|
type: CipherType;
|
|
folderId: string;
|
|
organizationId: string;
|
|
collectionIds: string[];
|
|
name: string;
|
|
notes: string;
|
|
favorite: boolean;
|
|
fields: FieldExport[];
|
|
login: LoginExport;
|
|
secureNote: SecureNoteExport;
|
|
card: CardExport;
|
|
identity: IdentityExport;
|
|
sshKey: SshKeyExport;
|
|
reprompt: CipherRepromptType;
|
|
passwordHistory: PasswordHistoryExport[] = null;
|
|
revisionDate: Date = null;
|
|
creationDate: Date = null;
|
|
deletedDate: Date = null;
|
|
key: string;
|
|
|
|
// Use build method instead of ctor so that we can control order of JSON stringify for pretty print
|
|
build(o: CipherView | CipherDomain) {
|
|
this.organizationId = o.organizationId;
|
|
this.folderId = o.folderId;
|
|
this.type = o.type;
|
|
this.reprompt = o.reprompt;
|
|
|
|
this.name = safeGetString(o.name);
|
|
this.notes = safeGetString(o.notes);
|
|
if ("key" in o) {
|
|
this.key = o.key?.encryptedString;
|
|
}
|
|
|
|
this.favorite = o.favorite;
|
|
|
|
if (o.fields != null) {
|
|
this.fields = o.fields.map((f) => new FieldExport(f));
|
|
}
|
|
|
|
switch (o.type) {
|
|
case CipherType.Login:
|
|
this.login = new LoginExport(o.login);
|
|
break;
|
|
case CipherType.SecureNote:
|
|
this.secureNote = new SecureNoteExport(o.secureNote);
|
|
break;
|
|
case CipherType.Card:
|
|
this.card = new CardExport(o.card);
|
|
break;
|
|
case CipherType.Identity:
|
|
this.identity = new IdentityExport(o.identity);
|
|
break;
|
|
case CipherType.SshKey:
|
|
this.sshKey = new SshKeyExport(o.sshKey);
|
|
break;
|
|
}
|
|
|
|
if (o.passwordHistory != null) {
|
|
this.passwordHistory = o.passwordHistory.map((ph) => new PasswordHistoryExport(ph));
|
|
}
|
|
|
|
this.creationDate = o.creationDate;
|
|
this.revisionDate = o.revisionDate;
|
|
this.deletedDate = o.deletedDate;
|
|
}
|
|
}
|