From de9c3498bc5bd0d1b4095fe12bc00b2c3bb57111 Mon Sep 17 00:00:00 2001 From: alemi Date: Thu, 21 Mar 2024 02:11:31 +0100 Subject: [PATCH] feat: add pubkey to actor veeeeery crude impl, with hardcoded pubkey in faker cmd, but whatevs i want activitupub.academy to fetch meeee --- src/activitystream/key.rs | 34 +++++++++++++++++++ src/activitystream/mod.rs | 3 ++ src/activitystream/object/actor.rs | 13 ++++--- src/activitystream/prelude.rs | 1 + .../m20240316_000001_create_table.rs | 4 +++ src/model/mod.rs | 11 ++++++ src/model/user.rs | 14 ++++++++ 7 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 src/activitystream/key.rs diff --git a/src/activitystream/key.rs b/src/activitystream/key.rs new file mode 100644 index 00000000..470a4536 --- /dev/null +++ b/src/activitystream/key.rs @@ -0,0 +1,34 @@ +// TODO technically this is not part of ActivityStreams + +use crate::{getter, setter}; + + +pub trait PublicKey : super::Base { + fn owner(&self) -> Option<&str> { None } + fn public_key_pem(&self) -> &str; +} + +pub trait PublicKeyMut : super::BaseMut { + fn set_owner(self, val: Option<&str>) -> Self; + fn set_public_key_pem(self, val: &str) -> Self; +} + +impl PublicKey for serde_json::Value { + getter! { owner -> &str } + + fn public_key_pem(&self) -> &str { + self.get("publicKeyPem").unwrap().as_str().unwrap() + } +} + +impl PublicKeyMut for serde_json::Value { + setter! { owner -> &str } + + fn set_public_key_pem(mut self, val: &str) -> Self { + self.as_object_mut().unwrap().insert( + "publicKeyPem".to_string(), + serde_json::Value::String(val.to_string()), + ); + self + } +} diff --git a/src/activitystream/mod.rs b/src/activitystream/mod.rs index 9ef5c087..bea9bb57 100644 --- a/src/activitystream/mod.rs +++ b/src/activitystream/mod.rs @@ -10,6 +10,8 @@ pub use node::Node; pub mod macros; pub mod prelude; +pub mod key; + use crate::{getter, setter, strenum}; strenum! { @@ -30,6 +32,7 @@ pub trait Base { fn underlying_json_object(self) -> serde_json::Value; } +pub fn raw_object() -> serde_json::Value { serde_json::Value::Object(serde_json::Map::default()) } pub fn object() -> serde_json::Value { let mut map = serde_json::Map::default(); map.insert( diff --git a/src/activitystream/object/actor.rs b/src/activitystream/object/actor.rs index 016847c7..b1758278 100644 --- a/src/activitystream/object/actor.rs +++ b/src/activitystream/object/actor.rs @@ -1,6 +1,7 @@ use crate::{activitystream::Node, getter, setter, strenum}; use super::collection::Collection; +use super::super::key::PublicKey; strenum! { pub enum ActorType { @@ -17,11 +18,12 @@ pub trait Actor : super::Object { fn preferred_username(&self) -> Option<&str> { None } fn inbox(&self) -> Node; fn outbox(&self) -> Node; - fn following(&self) -> Node { Node::Empty:: } - fn followers(&self) -> Node { Node::Empty:: } - fn liked(&self) -> Node { Node::Empty:: } - fn streams(&self) -> Node { Node::Empty:: } + fn following(&self) -> Node { Node::empty() } + fn followers(&self) -> Node { Node::empty() } + fn liked(&self) -> Node { Node::empty() } + fn streams(&self) -> Node { Node::empty() } fn endpoints(&self) -> Option> { None } + fn public_key(&self) -> Node { Node::empty() } } pub trait ActorMut : super::ObjectMut { @@ -34,6 +36,7 @@ pub trait ActorMut : super::ObjectMut { fn set_liked(self, val: Node) -> Self; fn set_streams(self, val: Node) -> Self; fn set_endpoints(self, val: Option>) -> Self; + fn set_public_key(self, val: Node) -> Self; } impl Actor for serde_json::Value { @@ -45,6 +48,7 @@ impl Actor for serde_json::Value { getter! { followers -> node impl Collection } getter! { liked -> node impl Collection } getter! { streams -> node impl Collection } + getter! { public_key::publicKey -> node impl PublicKey } fn endpoints(&self) -> Option> { todo!() @@ -60,6 +64,7 @@ impl ActorMut for serde_json::Value { setter! { followers -> node impl Collection } setter! { liked -> node impl Collection } setter! { streams -> node impl Collection } + setter! { public_key::publicKey -> node impl PublicKey } fn set_endpoints(self, _val: Option>) -> Self { todo!() diff --git a/src/activitystream/prelude.rs b/src/activitystream/prelude.rs index c3ed9123..e6d8d240 100644 --- a/src/activitystream/prelude.rs +++ b/src/activitystream/prelude.rs @@ -1,5 +1,6 @@ pub use super::{ Base as _, BaseMut as _, + key::{PublicKey as _, PublicKeyMut as _}, link::{Link as _, LinkMut as _}, object::{ Object as _, ObjectMut as _, diff --git a/src/migrations/m20240316_000001_create_table.rs b/src/migrations/m20240316_000001_create_table.rs index 34f4ab05..d0faa021 100644 --- a/src/migrations/m20240316_000001_create_table.rs +++ b/src/migrations/m20240316_000001_create_table.rs @@ -29,6 +29,8 @@ impl MigrationTrait for Migration { .col(ColumnDef::new(Users::Outbox).string().null()) .col(ColumnDef::new(Users::Following).string().null()) .col(ColumnDef::new(Users::Followers).string().null()) + .col(ColumnDef::new(Users::PublicKey).string().not_null()) + .col(ColumnDef::new(Users::PrivateKey).string().null()) .col(ColumnDef::new(Users::Created).date_time().not_null()) .col(ColumnDef::new(Users::Updated).date_time().not_null()) .to_owned() @@ -114,6 +116,8 @@ enum Users { Outbox, Following, Followers, + PublicKey, + PrivateKey, Created, Updated, } diff --git a/src/model/mod.rs b/src/model/mod.rs index 9921718f..4ef7afd3 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -29,6 +29,17 @@ pub async fn faker(db: &sea_orm::DatabaseConnection, domain: String) -> Result<( actor_type: super::activitystream::object::actor::ActorType::Person, created: chrono::Utc::now(), updated: chrono::Utc::now(), + private_key: None, + // TODO generate a fresh one every time + public_key: "-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA01IkF1A8t7zUS7x3ZqIx +NvG/X43JEJTdgPOFufOKMBTK48uMqrODK3wflaK6cSOMWkoOYHyWNhw10vL53GR9 +iOOGUHTaU7aoV7KBb5Fbh/tN9ZyN/S6FdCfpXze93CzpKQGNJa4SZ4FAFw2Ji1JJ +pdT7r+vaa5TkYTQuIgeHFisVEQAhmlz9xPbfPRPxSskroK7OnJSLMZ+aJvJHc9uX +kOq9wKgagV/I5ka7H3rRLTG1mBC97lrSfNdXfPRF//S4mFs095s+Pbnj0Hajf+qf +1Dryarmn6EmQi+diyhxFD3E8PWtMSBHrK+nmsiE58zjR/gd7G8SrXr4jtW+jcI6n +UQIDAQAB +-----END PUBLIC KEY-----".into() }; user::Entity::insert(root.clone().into_active_model()).exec(db).await?; diff --git a/src/model/user.rs b/src/model/user.rs index 9f053f24..cc953656 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -24,6 +24,9 @@ pub struct Model { pub following: Option, pub followers: Option, + pub public_key: String, + pub private_key: Option, + pub created: ChronoDateTimeUtc, pub updated: ChronoDateTimeUtc, @@ -79,6 +82,7 @@ impl crate::activitystream::Base for Model { .set_outbox(self.outbox()) .set_following(self.following()) .set_followers(self.followers()) + .set_public_key(self.public_key()) .underlying_json_object() } } @@ -135,6 +139,14 @@ impl crate::activitystream::object::actor::Actor for Model { fn followers(&self) -> Node { Node::link(self.following.clone().unwrap_or(format!("https://{}/users/{}/followers", self.domain, self.name))) } + + fn public_key(&self) -> Node { + Node::object( + crate::activitystream::raw_object() + .set_public_key_pem(&self.public_key) + .set_owner(Some(&self.id)) + ) + } } impl Model { @@ -155,6 +167,8 @@ impl Model { following: object.following().id().map(|x| x.to_string()), created: object.published().unwrap_or(chrono::Utc::now()), updated: chrono::Utc::now(), + public_key: object.public_key().get().ok_or(super::FieldError("publicKey"))?.public_key_pem().to_string(), + private_key: None, // there's no way to transport privkey over AP json, must come from DB }) } }