summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2021-11-28 18:59:40 +0100
committerMatthias Beyer <mail@beyermatthias.de>2021-12-02 18:59:32 +0100
commit9bfda194d73aa01ca34925f0dd40df281fd9d993 (patch)
tree8b02f749c447c9de48ff66a432b30c54e3afea6a /src
parentba75b3000040ff0064252620b82ec969808e4523 (diff)
Implement Profile type for publishing profile(s)
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
Diffstat (limited to 'src')
-rw-r--r--src/main.rs1
-rw-r--r--src/profile.rs99
2 files changed, 100 insertions, 0 deletions
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<Self> {
+ 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<PathBuf> {
+ 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<Option<Self>> {
+ 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<R: AsyncReadExt + std::marker::Unpin>(mut r: R, name: &str, client: &Client) -> Result<Option<Self>> {
+ 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(())
+ }
+
+}