diff --git a/src/activitypub/user/inbox.rs b/src/activitypub/user/inbox.rs index fffed10d..a93167a7 100644 --- a/src/activitypub/user/inbox.rs +++ b/src/activitypub/user/inbox.rs @@ -1,7 +1,7 @@ use axum::{extract::{Path, State}, http::StatusCode, Json}; use sea_orm::{sea_query::Expr, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter}; -use crate::{activitypub::JsonLD, activitystream::{object::{activity::{Activity, ActivityType}, ObjectType}, Base, BaseType, Node}, errors::LoggableError, model::{self, activity, object}, server::Context}; +use crate::{activitypub::JsonLD, activitystream::{object::{activity::{Activity, ActivityType}, Addressed, ObjectType}, Base, BaseType, Node}, errors::LoggableError, model::{self, activity, addressing, object}, server::Context}; pub async fn inbox( State(ctx): State, @@ -88,12 +88,29 @@ pub async fn inbox( return Err(StatusCode::UNPROCESSABLE_ENTITY); }; tracing::info!("processing Create activity by {} for {}", activity_entity.actor, activity_entity.object.as_deref().unwrap_or("")); + let object_id = obj_entity.id.clone(); + let activity_id = activity_entity.id.clone(); object::Entity::insert(obj_entity.into_active_model()) .exec(ctx.db()) .await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; activity::Entity::insert(activity_entity.into_active_model()) .exec(ctx.db()) .await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + addressing::Entity::insert_many( + object.addressed() + .into_iter() + .map(|actor| + addressing::ActiveModel{ + id: sea_orm::ActiveValue::NotSet, + actor: sea_orm::Set(actor), + activity: sea_orm::Set(activity_id.clone()), + object: sea_orm::Set(Some(object_id.clone())), + published: sea_orm::Set(chrono::Utc::now()), + } + ) + ) + .exec(ctx.db()) + .await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; Ok(JsonLD(serde_json::Value::Null)) // TODO hmmmmmmmmmmm not the best value to return.... }, Some(BaseType::Object(ObjectType::Activity(_x))) => { diff --git a/src/activitystream/node.rs b/src/activitystream/node.rs index faf46670..23149b27 100644 --- a/src/activitystream/node.rs +++ b/src/activitystream/node.rs @@ -29,7 +29,8 @@ impl Node { } } - pub fn all(&self) -> Option> { + // TODO extremely unforgiving, is this even useful? + pub fn get_items(&self) -> Option> { match self { Node::Empty | Node::Link(_) => None, Node::Object(x) => Some(vec![x]), @@ -40,6 +41,24 @@ impl Node { }).collect()), } } + + pub fn get_links(&self) -> Vec { + match self { + Node::Empty => vec![], + Node::Link(x) => vec![x.href().to_string()], + Node::Object(x) => match x.id() { + Some(x) => vec![x.to_string()], + None => vec![], + }, + Node::Array(v) => + v.iter().filter_map(|x| match x { + Node::Link(x) => Some(x.href().to_string()), + Node::Object(x) => x.id().map(|x| x.to_string()), + // TODO handle array of arrays maybe? + _ => None, + }).collect(), + } + } pub fn is_empty(&self) -> bool { match self { diff --git a/src/activitystream/object/mod.rs b/src/activitystream/object/mod.rs index 665a5473..0a113964 100644 --- a/src/activitystream/object/mod.rs +++ b/src/activitystream/object/mod.rs @@ -64,6 +64,16 @@ pub trait Object : super::Base { fn duration(&self) -> Option<&str> { None } // TODO how to parse xsd:duration ? } +pub trait Addressed : Object { + fn addressed(&self) -> Vec { + let mut to = self.to().get_links(); + to.append(&mut self.bto().get_links()); + to.append(&mut self.cc().get_links()); + to.append(&mut self.bcc().get_links()); + to + } +} + pub trait ObjectMut : super::BaseMut { fn set_object_type(self, val: Option) -> Self; fn set_attachment(self, val: Node) -> Self; @@ -135,6 +145,8 @@ impl Object for serde_json::Value { } } +impl Addressed for serde_json::Value {} + impl ObjectMut for serde_json::Value { setter! { object_type -> type ObjectType } setter! { attachment -> node impl Object }