feat: add pubkey to actor

veeeeery crude impl, with hardcoded pubkey in faker cmd, but whatevs i
want activitupub.academy to fetch meeee
This commit is contained in:
əlemi 2024-03-21 02:11:31 +01:00
parent fe36ed2a52
commit de9c3498bc
Signed by: alemi
GPG key ID: A4895B84D311642C
7 changed files with 76 additions and 4 deletions

34
src/activitystream/key.rs Normal file
View file

@ -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
}
}

View file

@ -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(

View file

@ -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<impl Collection>;
fn outbox(&self) -> Node<impl Collection>;
fn following(&self) -> Node<impl Collection> { Node::Empty::<serde_json::Value> }
fn followers(&self) -> Node<impl Collection> { Node::Empty::<serde_json::Value> }
fn liked(&self) -> Node<impl Collection> { Node::Empty::<serde_json::Value> }
fn streams(&self) -> Node<impl Collection> { Node::Empty::<serde_json::Value> }
fn following(&self) -> Node<impl Collection> { Node::empty() }
fn followers(&self) -> Node<impl Collection> { Node::empty() }
fn liked(&self) -> Node<impl Collection> { Node::empty() }
fn streams(&self) -> Node<impl Collection> { Node::empty() }
fn endpoints(&self) -> Option<serde_json::Map<String, String>> { None }
fn public_key(&self) -> Node<impl PublicKey> { Node::empty() }
}
pub trait ActorMut : super::ObjectMut {
@ -34,6 +36,7 @@ pub trait ActorMut : super::ObjectMut {
fn set_liked(self, val: Node<impl Collection>) -> Self;
fn set_streams(self, val: Node<impl Collection>) -> Self;
fn set_endpoints(self, val: Option<serde_json::Map<String, String>>) -> Self;
fn set_public_key(self, val: Node<impl PublicKey>) -> 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<serde_json::Map<String, String>> {
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<serde_json::Map<String, String>>) -> Self {
todo!()

View file

@ -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 _,

View file

@ -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,
}

View file

@ -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?;

View file

@ -24,6 +24,9 @@ pub struct Model {
pub following: Option<String>,
pub followers: Option<String>,
pub public_key: String,
pub private_key: Option<String>,
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<impl Collection> {
Node::link(self.following.clone().unwrap_or(format!("https://{}/users/{}/followers", self.domain, self.name)))
}
fn public_key(&self) -> Node<impl crate::activitystream::key::PublicKey> {
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
})
}
}