diff --git a/crates/seed-keeper-wit-ui/src/input.rs b/crates/seed-keeper-wit-ui/src/input.rs index 04377fa..2ba38fa 100644 --- a/crates/seed-keeper-wit-ui/src/input.rs +++ b/crates/seed-keeper-wit-ui/src/input.rs @@ -35,46 +35,7 @@ impl From for Input { impl From<&wurbo_types::Content> for Input { fn from(content: &wurbo_types::Content) -> Self { - // if context.load.encrypted is Some, use it, - // the rest of Input is taken from context.input - println!("context.load: {:?}", content.load); - let encrypted = match &content.load { - Some(loaded_str) => { - println!("loaded_str: {:?}", loaded_str); - // try to parse the JSON - let v: serde_json::Value = - serde_json::from_str(&loaded_str).unwrap_or(serde_json::Value::Null); - - println!("v: {:?}", v); - println!("v[\"encrypted\"]: {:?}", v["encrypted"]); - - match &v["encrypted"] { - serde_json::Value::Array(encrypted) => { - println!("encrypted array: {:?}", encrypted); - Some( - // encrypted into Vec - encrypted - .iter() - .map(|v| v.as_u64().unwrap_or_default() as u8) - .collect::>(), - ) - } - // or it could be astring of numbers, likw 1,2,3,4,5... - serde_json::Value::String(encrypted) => { - println!("encrypted string: {:?}", encrypted); - let encrypted = encrypted - .split(',') - .map(|v| v.parse::().unwrap_or_default()) - .collect::>(); - Some(encrypted) - } - _ => None, - } - } - None => None, - }; - - let encrypted: Encrypted = encrypted.into(); + let encrypted = Encrypted::from(content); Input(Some(wurbo_types::Input { placeholder: content diff --git a/crates/seed-keeper-wit-ui/src/lib.rs b/crates/seed-keeper-wit-ui/src/lib.rs index dff3cb2..a8b271d 100644 --- a/crates/seed-keeper-wit-ui/src/lib.rs +++ b/crates/seed-keeper-wit-ui/src/lib.rs @@ -5,6 +5,7 @@ mod bindings; mod input; mod output; mod page; +mod utils; use input::Input; use output::Output; @@ -22,7 +23,7 @@ use bindings::seed_keeper::wit_ui::wurbo_types::{self, Context}; use wurbo::jinja::{Entry, Index, Rest, Templates}; use wurbo::prelude_bindgen; -use crate::output::Encrypted; +use crate::utils::Encrypted; const INDEX_HTML: &str = "index.html"; const INPUT_HTML: &str = "input.html"; @@ -110,7 +111,7 @@ impl From for StructContext { input: Input::from(&content), // We can use default for Output because the minijinja Object impl will // calculate the values from the above inouts for us - output: Output::default(), + output: Output::from(&content), target: None, } } diff --git a/crates/seed-keeper-wit-ui/src/output.rs b/crates/seed-keeper-wit-ui/src/output.rs index 64e56fd..66a5d59 100644 --- a/crates/seed-keeper-wit-ui/src/output.rs +++ b/crates/seed-keeper-wit-ui/src/output.rs @@ -1,6 +1,5 @@ use super::*; -use base64ct::{Base64UrlUnpadded, Encoding}; /// Event types which can can emitted from this UI and listened by others use seed_keeper_events::{Context, Message}; @@ -36,7 +35,7 @@ impl Output { Ok(encrypted) => { // if self.encrypted_seed is None, set it to the encrypted seed if self.encrypted_seed.is_none() { - self.encrypted_seed = Encrypted(Some(encrypted.clone())); + self.encrypted_seed = Encrypted::from(Some(encrypted.clone())); } // if serde feature, emit the serialized encrypted seed as an event @@ -80,6 +79,37 @@ impl From for Credentials { } } +// impl From<&Content> for Output { +impl From<&wurbo_types::Content> for Output { + fn from(content: &wurbo_types::Content) -> Self { + let encrypted = Encrypted::from(content); + + let username: String = content.load.as_ref().map_or_else( + || "".to_string(), + |loaded_str| { + let v: serde_json::Value = + serde_json::from_str(&loaded_str).unwrap_or(serde_json::Value::Null); + + match &v["username"] { + serde_json::Value::String(username) => username.clone(), + _ => "".to_string(), + } + }, + ); + + Output { + username, + password: content + .input + .as_ref() + .map(|c| c.placeholder.clone()) + .unwrap_or_default(), + encrypted_seed: encrypted, + error_message: None, + } + } +} + /// Implement [Object] for Output so we can use minijina to automagically calculate the length /// of the username and password concatenated impl Object for Output { @@ -91,7 +121,7 @@ impl Object for Output { "password" => Some(Value::from(self.password.clone())), // Show encrypted Vec as base64 string "encrypted_seed" => match get_encrypted() { - Ok(encrypted) => Some(Value::from(Encrypted(Some(encrypted)).to_string())), + Ok(encrypted) => Some(Value::from(Encrypted::from(Some(encrypted)).to_string())), _ => None, }, "error_message" => match &self.error_message { @@ -102,38 +132,3 @@ impl Object for Output { } } } - -/// [Encrypted] [Output] is the encrypted seed passed from the User, if any. -#[derive(Debug, Clone, Default)] -pub(super) struct Encrypted(Option>); - -/// impl From Option> for Encrypted -impl From>> for Encrypted { - fn from(context: Option>) -> Self { - Encrypted(context) - } -} - -impl ToString for Encrypted { - fn to_string(&self) -> String { - // encode to base64 - Base64UrlUnpadded::encode_string(&self.as_ref().unwrap_or(&vec![])) - } -} - -/// Decode from base64 into bytes -impl From<&String> for Encrypted { - fn from(context: &String) -> Self { - Encrypted(Some( - Base64UrlUnpadded::decode_vec(context).unwrap_or_default(), - )) - } -} - -impl Deref for Encrypted { - type Target = Option>; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} diff --git a/crates/seed-keeper-wit-ui/src/utils.rs b/crates/seed-keeper-wit-ui/src/utils.rs new file mode 100644 index 0000000..507abfd --- /dev/null +++ b/crates/seed-keeper-wit-ui/src/utils.rs @@ -0,0 +1,75 @@ +//! This module contains the utility types and functions used in the seed-keeper-wit-ui crate. +use super::*; +use base64ct::{Base64UrlUnpadded, Encoding}; + +/// [Encrypted] [Output] is the encrypted seed passed from the User, if any. +#[derive(Debug, Clone, Default)] +pub(super) struct Encrypted(Option>); + +/// impl From Option> for Encrypted +impl From>> for Encrypted { + fn from(context: Option>) -> Self { + Encrypted(context) + } +} + +impl ToString for Encrypted { + fn to_string(&self) -> String { + // encode to base64 + Base64UrlUnpadded::encode_string(&self.as_ref().unwrap_or(&vec![])) + } +} + +/// Decode from base64 into bytes +impl From<&String> for Encrypted { + fn from(context: &String) -> Self { + Encrypted(Some( + Base64UrlUnpadded::decode_vec(context).unwrap_or_default(), + )) + } +} +impl From<&wurbo_types::Content> for Encrypted { + fn from(content: &wurbo_types::Content) -> Self { + // if context.load.encrypted is Some, use it, + // the rest of Input is taken from context.input + let encrypted = match &content.load { + Some(loaded_str) => { + // try to parse the JSON + let v: serde_json::Value = + serde_json::from_str(&loaded_str).unwrap_or(serde_json::Value::Null); + + match &v["encrypted"] { + serde_json::Value::Array(encrypted) => { + Some( + // encrypted into Vec + encrypted + .iter() + .map(|v| v.as_u64().unwrap_or_default() as u8) + .collect::>(), + ) + } + // or it could be astring of numbers, likw 1,2,3,4,5... + serde_json::Value::String(encrypted) => { + let encrypted = encrypted + .split(',') + .map(|v| v.parse::().unwrap_or_default()) + .collect::>(); + Some(encrypted) + } + _ => None, + } + } + None => None, + }; + + encrypted.into() + } +} + +impl Deref for Encrypted { + type Target = Option>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +}