1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-20 18:23:31 +00:00
Files
browser/libs/common/src/models/export/cipher.export.ts
Bernd Schoolmann 081fe83d83 PM-10393 SSH keys (#10825)
* [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>
2024-11-08 11:01:31 +01:00

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