From 9bfda194d73aa01ca34925f0dd40df281fd9d993 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 28 Nov 2021 18:59:40 +0100 Subject: Implement Profile type for publishing profile(s) Signed-off-by: Matthias Beyer --- src/main.rs | 1 + src/profile.rs | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 src/profile.rs (limited to 'src') diff --git a/src/main.rs b/src/main.rs index a672ae0..51408f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ pub mod client; pub mod config; pub mod consts; pub mod ipfs_client; +pub mod profile; pub mod types; #[tokio::main] diff --git a/src/profile.rs b/src/profile.rs new file mode 100644 index 0000000..b78dfc1 --- /dev/null +++ b/src/profile.rs @@ -0,0 +1,99 @@ +use std::path::PathBuf; + +use anyhow::Result; +use ipfs_api_backend_hyper::IpfsApi; +use tokio::io::AsyncWriteExt; +use tokio::io::AsyncReadExt; + +use crate::client::Client; +use crate::cid::Cid; + +#[derive(Debug, serde::Serialize, serde::Deserialize)] +pub struct Profile { + key_name: String, + key_id: String, +} + +impl Profile { + pub async fn create(name: &str, client: &Client) -> Result { + let key = client.ipfs.key_gen(name, ipfs_api_backend_hyper::KeyType::Ed25519, 64).await?; + + Ok(Profile { + key_name: key.name, + key_id: key.id + }) + } + + pub fn config_path(name: &str) -> String { + format!("distrox-{}", name) + } + + pub fn config_file_path(name: &str) -> Result { + xdg::BaseDirectories::with_prefix("distrox") + .map_err(anyhow::Error::from) + .and_then(|dirs| { + let name = Self::config_path(name); + dirs.place_config_file(name) + .map_err(anyhow::Error::from) + }) + } + + /// Store the Profile on disk + pub async fn write_to_filesystem(&self) -> Result<()> { + let config_path = Self::config_file_path(&self.key_name)?; + + let mut config_file = tokio::fs::OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(config_path) + .await?; + + let config = serde_json::to_string(&self)?; + config_file.write_all(config.as_bytes()).await?; + config_file.sync_all().await?; + Ok(()) + } + + /// Load the Profile from disk and ensure the keys exist in IPFS + pub async fn load_from_filesystem(name: &str, client: &Client) -> Result> { + let config_path = Self::config_file_path(name)?; + let file_reader = tokio::fs::OpenOptions::new() + .read(true) + .open(config_path) + .await + .map(tokio::io::BufReader::new)?; + + Self::load_from_reader(file_reader, name, client).await + } + + async fn load_from_reader(mut r: R, name: &str, client: &Client) -> Result> { + let mut buf = String::new(); + let _ = r.read_to_string(&mut buf).await?; + let config: Self = serde_json::from_str(&buf)?; + + client.ipfs + .key_list() + .await? + .keys + .into_iter() + .find(|keypair| keypair.name == name) + .map(|_| Ok(config)) + .transpose() + } + + pub async fn publish(&self, client: &Client, cid: Cid) -> Result<()> { + let path = format!("/ipfs/{}", cid.as_ref()); + let resolve = true; + let lifetime = Some("10m"); + let ttl = None; + + let publish_response = client.ipfs + .name_publish(&path, resolve, lifetime, ttl, Some(&self.key_name)) + .await?; + + log::debug!("Publish response = {{ name: {}, value: {} }}", publish_response.name, publish_response.value); + Ok(()) + } + +} -- cgit v1.2.3