Skip to content

Commit

Permalink
Cleanup exporter
Browse files Browse the repository at this point in the history
  • Loading branch information
Hinton committed Nov 28, 2024
1 parent 95c6f87 commit cc68ca9
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 38 deletions.
5 changes: 5 additions & 0 deletions crates/bitwarden-exporters/src/cxp/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
use std::borrow::Cow;

use thiserror::Error;

#[derive(Error, Debug)]
pub enum CxpError {
#[error("JSON error: {0}")]
Serde(#[from] serde_json::Error),

#[error("Internal error: {0}")]
Internal(Cow<'static, str>),
}
48 changes: 32 additions & 16 deletions crates/bitwarden-exporters/src/cxp/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use uuid::Uuid;
use crate::{cxp::CxpError, Cipher, CipherType, Fido2Credential, Login};

/// Temporary struct to hold metadata related to current account
///
/// Eventually the SDK itself should have this state and we get rid of this struct.
#[derive(Debug)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
pub struct Account {
Expand All @@ -24,55 +26,65 @@ pub struct Account {
name: Option<String>,
}

/// Builds a Credential Exchange Format (CXF) payload
pub(crate) fn build_cxf(account: Account, ciphers: Vec<Cipher>) -> Result<String, CxpError> {
let items: Vec<Item> = ciphers.into_iter().map(|cipher| cipher.into()).collect();
let items: Vec<Item> = ciphers
.into_iter()
.flat_map(|cipher| cipher.try_into())
.collect();

let account = CxpAccount {
id: account.id.as_bytes().as_slice().into(),
user_name: "".to_owned(),
email: account.email,
full_name: account.name,
icon: None,
collections: vec![],
collections: vec![], // TODO: Add support for folders
items,
extensions: None,
};

Ok(serde_json::to_string(&account)?)
}

Check warning on line 48 in crates/bitwarden-exporters/src/cxp/export.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-exporters/src/cxp/export.rs#L30-L48

Added lines #L30 - L48 were not covered by tests

impl From<Cipher> for Item {
fn from(value: Cipher) -> Self {
impl TryFrom<Cipher> for Item {
type Error = CxpError;

fn try_from(value: Cipher) -> Result<Self, Self::Error> {
let mut credentials: Vec<Credential> = value.r#type.clone().into();

if let Some(note) = value.notes {
credentials.push(Credential::Note { content: note });
}

Self {
Ok(Self {
id: value.id.as_bytes().as_slice().into(),
creation_at: value.creation_date.timestamp() as u64,
modified_at: value.revision_date.timestamp() as u64,
ty: value.r#type.into(),
ty: value.r#type.try_into()?,
title: value.name,
subtitle: None,
favorite: Some(value.favorite),
credentials,
tags: None,
extensions: None,
}
})
}
}

impl From<CipherType> for ItemType {
// TODO: We should probably change this to try_from, so we can ignore types
fn from(value: CipherType) -> Self {
impl TryFrom<CipherType> for ItemType {
type Error = CxpError;

fn try_from(value: CipherType) -> Result<Self, Self::Error> {
match value {
CipherType::Login(_) => ItemType::Login,
CipherType::Card(_) => ItemType::Login,
CipherType::Identity(_) => ItemType::Identity,
CipherType::SecureNote(_) => ItemType::Document,
CipherType::SshKey(_) => todo!(),
CipherType::Login(_) => Ok(ItemType::Login),
CipherType::Card(_) => Ok(ItemType::Login),
CipherType::Identity(_) => Ok(ItemType::Identity),
CipherType::SecureNote(_) => Ok(ItemType::Document),

Check warning on line 83 in crates/bitwarden-exporters/src/cxp/export.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-exporters/src/cxp/export.rs#L81-L83

Added lines #L81 - L83 were not covered by tests
CipherType::SshKey(_) => {
// TODO(PM-15448): Add support for SSH Keys
Err(CxpError::Internal("Unsupported CipherType: SshKey".into()))

Check warning on line 86 in crates/bitwarden-exporters/src/cxp/export.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-exporters/src/cxp/export.rs#L86

Added line #L86 was not covered by tests
}
}
}
}
Expand All @@ -81,9 +93,13 @@ impl From<CipherType> for Vec<Credential> {
fn from(value: CipherType) -> Self {
match value {
CipherType::Login(login) => (*login).into(),
// TODO(PM-15450): Add support for credit cards.
CipherType::Card(_) => vec![],

Check warning on line 97 in crates/bitwarden-exporters/src/cxp/export.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-exporters/src/cxp/export.rs#L97

Added line #L97 was not covered by tests
// TODO(PM-15451): Add support for identities.
CipherType::Identity(_) => vec![],

Check warning on line 99 in crates/bitwarden-exporters/src/cxp/export.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-exporters/src/cxp/export.rs#L99

Added line #L99 was not covered by tests
// Secure Notes only contains a note field which is handled by `TryFrom<Cipher> for Item`.
CipherType::SecureNote(_) => vec![],

Check warning on line 101 in crates/bitwarden-exporters/src/cxp/export.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-exporters/src/cxp/export.rs#L101

Added line #L101 was not covered by tests
// TODO(PM-15448): Add support for SSH Keys.
CipherType::SshKey(_) => vec![],

Check warning on line 103 in crates/bitwarden-exporters/src/cxp/export.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-exporters/src/cxp/export.rs#L103

Added line #L103 was not covered by tests
}
}
Expand Down Expand Up @@ -281,7 +297,7 @@ mod tests {
deleted_date: None,
};

let item: Item = cipher.into();
let item: Item = cipher.try_into().unwrap();

assert_eq!(
item.creation_at,
Expand Down
28 changes: 6 additions & 22 deletions crates/bitwarden-exporters/src/cxp/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,12 @@ mod tests {
extensions: None,
};

let _ciphers: Vec<ImportingCipher> = parse_item(item);
let ciphers: Vec<ImportingCipher> = parse_item(item);
assert_eq!(ciphers.len(), 1);
let cipher = ciphers.first().unwrap();

assert_eq!(cipher.folder_id, None);
assert_eq!(cipher.name, "Bitwarden");
}

#[test]
Expand Down Expand Up @@ -162,26 +167,5 @@ mod tests {
};

let _ciphers: Vec<ImportingCipher> = parse_item(item);

/*
{
"id": "Njk1RERENTItNkQ0Ny00NERBLTlFN0EtNDM1MjNEQjYzNjVF",
"title": "opotonniee.github.io",
"modifiedAt": 1732182026,
"type": "login",
"credentials": [
{
"key": "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPzvtWYWmIsvqqr3LsZB0K-cbjuhJSGTGziL1LksHAPShRANCAAT-vqHTyEDS9QBNNi2BNLyu6TunubJT_L3G3i7KLpEDhMD15hi24IjGBH0QylJIrvlT4JN2tdRGF436XGc-VoAl",
"userName": "alex muller",
"userHandle": "YWxleCBtdWxsZXI",
"credentialID": "6NiHiekW4ZY8vYHa-ucbvA",
"userDisplayName": "alex muller",
"rpID": "opotonniee.github.io",
"type": "passkey"
}
],
"creationAt": 1732181986
},
*/
}
}

0 comments on commit cc68ca9

Please sign in to comment.