diff --git a/apub-privatekey/Cargo.toml b/apub-privatekey/Cargo.toml new file mode 100644 index 0000000..5fa2d58 --- /dev/null +++ b/apub-privatekey/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "apub-privatekey" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-trait = "0.1.51" +serde = { version = "1", features = ["derive"] } +url = { version = "2", features = ["serde"] } diff --git a/apub-privatekey/src/lib.rs b/apub-privatekey/src/lib.rs new file mode 100644 index 0000000..a2c7007 --- /dev/null +++ b/apub-privatekey/src/lib.rs @@ -0,0 +1,184 @@ +use std::{ + ops::{Deref, DerefMut}, + rc::Rc, + str::FromStr, + sync::Arc, +}; +use url::Url; + +#[async_trait::async_trait(?Send)] +pub trait PrivateKeyRepo { + type Error; + + async fn store( + &self, + actor_id: Url, + key_id: KeyId, + private_key_pem: String, + ) -> Result<(), Self::Error>; + + async fn fetch(&self, actor_id: &Url) -> Result<(KeyId, String), Self::Error>; +} + +pub trait PrivateKeyRepoFactory { + type PrivateKeyRepo: PrivateKeyRepo; + + fn build_private_key_repo(&self) -> Self::PrivateKeyRepo; +} + +#[derive( + Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Deserialize, serde::Serialize, +)] +#[serde(transparent)] +pub struct KeyId(Url); + +impl KeyId { + pub fn into_inner(this: Self) -> Url { + this.0 + } +} + +impl FromStr for KeyId { + type Err = ::Err; + + fn from_str(s: &str) -> Result { + Ok(KeyId(Url::from_str(s)?)) + } +} + +impl Deref for KeyId { + type Target = Url; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for KeyId { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl AsRef for KeyId { + fn as_ref(&self) -> &Url { + &self.0 + } +} + +impl AsMut for KeyId { + fn as_mut(&mut self) -> &mut Url { + &mut self.0 + } +} + +impl From for KeyId { + fn from(url: Url) -> Self { + KeyId(url) + } +} + +#[async_trait::async_trait(?Send)] +impl<'a, T> PrivateKeyRepo for &'a T +where + T: PrivateKeyRepo, +{ + type Error = T::Error; + + async fn store( + &self, + actor_id: Url, + key_id: KeyId, + private_key_pem: String, + ) -> Result<(), Self::Error> { + T::store(self, actor_id, key_id, private_key_pem).await + } + + async fn fetch(&self, actor_id: &Url) -> Result<(KeyId, String), Self::Error> { + T::fetch(self, actor_id).await + } +} + +#[async_trait::async_trait(?Send)] +impl<'a, T> PrivateKeyRepo for &'a mut T +where + T: PrivateKeyRepo, +{ + type Error = T::Error; + + async fn store( + &self, + actor_id: Url, + key_id: KeyId, + private_key_pem: String, + ) -> Result<(), Self::Error> { + T::store(self, actor_id, key_id, private_key_pem).await + } + + async fn fetch(&self, actor_id: &Url) -> Result<(KeyId, String), Self::Error> { + T::fetch(self, actor_id).await + } +} + +#[async_trait::async_trait(?Send)] +impl PrivateKeyRepo for Box +where + T: PrivateKeyRepo, +{ + type Error = T::Error; + + async fn store( + &self, + actor_id: Url, + key_id: KeyId, + private_key_pem: String, + ) -> Result<(), Self::Error> { + T::store(self, actor_id, key_id, private_key_pem).await + } + + async fn fetch(&self, actor_id: &Url) -> Result<(KeyId, String), Self::Error> { + T::fetch(self, actor_id).await + } +} + +#[async_trait::async_trait(?Send)] +impl PrivateKeyRepo for Rc +where + T: PrivateKeyRepo, +{ + type Error = T::Error; + + async fn store( + &self, + actor_id: Url, + key_id: KeyId, + private_key_pem: String, + ) -> Result<(), Self::Error> { + T::store(self, actor_id, key_id, private_key_pem).await + } + + async fn fetch(&self, actor_id: &Url) -> Result<(KeyId, String), Self::Error> { + T::fetch(self, actor_id).await + } +} + +#[async_trait::async_trait(?Send)] +impl PrivateKeyRepo for Arc +where + T: PrivateKeyRepo, +{ + type Error = T::Error; + + async fn store( + &self, + actor_id: Url, + key_id: KeyId, + private_key_pem: String, + ) -> Result<(), Self::Error> { + T::store(self, actor_id, key_id, private_key_pem).await + } + + async fn fetch(&self, actor_id: &Url) -> Result<(KeyId, String), Self::Error> { + T::fetch(self, actor_id).await + } +}