fix: make @context addition explicit

also moved things around: object() is now into LD trait
This commit is contained in:
əlemi 2024-03-21 19:15:19 +01:00
parent 483076b6b2
commit c4f677097b
Signed by: alemi
GPG key ID: A4895B84D311642C
9 changed files with 63 additions and 59 deletions

View file

@ -1,8 +1,8 @@
use axum::{extract::{Path, State}, http::StatusCode};
use sea_orm::EntityTrait;
use crate::{activitystream::{prelude::*, Node}, model::{activity, object}, server::Context};
use crate::{activitystream::{object::activity::ActivityMut, Base, Node}, model::{activity, object}, server::Context};
use super::JsonLD;
use super::{jsonld::LD, JsonLD};
pub async fn view(State(ctx) : State<Context>, Path(id): Path<String>) -> Result<JsonLD<serde_json::Value>, StatusCode> {
@ -11,7 +11,12 @@ pub async fn view(State(ctx) : State<Context>, Path(id): Path<String>) -> Result
.one(ctx.db())
.await
{
Ok(Some((activity, object))) => Ok(JsonLD(activity.underlying_json_object().set_object(Node::maybe_object(object)))),
Ok(Some((activity, object))) => Ok(JsonLD(
activity
.underlying_json_object()
.set_object(Node::maybe_object(object))
.ld_context()
)),
Ok(None) => Err(StatusCode::NOT_FOUND),
Err(e) => {
tracing::error!("error querying for activity: {e}");

View file

@ -1,26 +1,34 @@
use axum::response::{IntoResponse, Response};
pub trait LD {
fn ld_context(self) -> Self;
fn new_object() -> serde_json::Value {
serde_json::Value::Object(serde_json::Map::default())
}
}
impl LD for serde_json::Value {
fn ld_context(mut self) -> Self {
if let Some(obj) = self.as_object_mut() {
obj.insert(
"@context".to_string(),
serde_json::Value::Array(vec![
serde_json::Value::String("https://www.w3.org/ns/activitystreams".into())
]),
);
} else {
tracing::warn!("cannot add @context to json value different than object");
}
self
}
}
// got this from https://github.com/kitsune-soc/kitsune/blob/b023a12b687dd9a274233a5a9950f2de5e192344/kitsune/src/http/responder.rs
// i was trying to do it with middlewares but this is way cleaner
use axum::{
response::{IntoResponse, Response},
Json,
};
use serde::Serialize;
pub struct JsonLD<T>(pub T);
impl<T> IntoResponse for JsonLD<T>
where
T: Serialize,
{
impl<T: serde::Serialize> IntoResponse for JsonLD<T> {
fn into_response(self) -> Response {
(
[(
"Content-Type",
"application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"",
)],
Json(self.0),
)
.into_response()
// headers body
([("Content-Type", "application/ld+json")], axum::Json(self.0)).into_response()
}
}

View file

@ -7,7 +7,9 @@ pub use jsonld::JsonLD;
use axum::{extract::State, http::StatusCode, Json};
use sea_orm::{EntityTrait, IntoActiveModel};
use crate::{activitystream::{self, object::{activity::{Activity, ActivityType}, actor::{ActorMut, ActorType}, ObjectMut, ObjectType}, Base, BaseMut, BaseType, Node}, model, server::Context, url};
use crate::{activitystream::{object::{activity::{Activity, ActivityType}, actor::{ActorMut, ActorType}, ObjectMut, ObjectType}, Base, BaseMut, BaseType, Node}, model, server::Context, url};
use self::jsonld::LD;
pub const PUBLIC_TARGET : &str = "https://www.w3.org/ns/activitystreams#Public";
@ -38,7 +40,7 @@ pub struct Page {
pub async fn view(State(ctx): State<Context>) -> Result<Json<serde_json::Value>, StatusCode> {
Ok(Json(
activitystream::object()
serde_json::Value::new_object()
.set_actor_type(Some(ActorType::Application))
.set_id(Some(&url!(ctx, "")))
.set_name(Some("μpub"))

View file

@ -1,12 +1,11 @@
use std::sync::Arc;
use crate::activitystream::prelude::*;
use axum::{extract::{Path, Query, State}, http::StatusCode, Json};
use sea_orm::{ColumnTrait, Condition, DatabaseConnection, EntityTrait, IntoActiveModel, Order, QueryFilter, QueryOrder, QuerySelect};
use crate::{activitystream::{self, object::{activity::ActivityType, collection::CollectionType, ObjectType}, BaseType, Node}, model::{self, activity, object, user}, server::Context, url};
use crate::{activitystream::{object::{activity::{Activity, ActivityMut, ActivityType}, collection::{page::CollectionPageMut, CollectionMut, CollectionType}, ObjectType}, Base, BaseMut, BaseType, Node}, model::{self, activity, object, user}, server::Context, url};
use super::JsonLD;
use super::{jsonld::LD, JsonLD};
pub async fn list(State(_db) : State<Arc<DatabaseConnection>>) -> Result<JsonLD<serde_json::Value>, StatusCode> {
todo!()
@ -14,7 +13,7 @@ pub async fn list(State(_db) : State<Arc<DatabaseConnection>>) -> Result<JsonLD<
pub async fn view(State(ctx) : State<Context>, Path(id): Path<String>) -> Result<JsonLD<serde_json::Value>, StatusCode> {
match user::Entity::find_by_id(ctx.uid(id)).one(ctx.db()).await {
Ok(Some(user)) => Ok(JsonLD(user.underlying_json_object())),
Ok(Some(user)) => Ok(JsonLD(user.underlying_json_object().ld_context())),
Ok(None) => Err(StatusCode::NOT_FOUND),
Err(e) => {
tracing::error!("error querying for user: {e}");
@ -59,7 +58,7 @@ pub async fn outbox(
.map(|(a, o)| a.underlying_json_object().set_object(Node::maybe_object(o)))
.collect();
Ok(JsonLD(
activitystream::object()
serde_json::Value::new_object()
// TODO set id, calculate uri from given args
.set_collection_type(Some(CollectionType::OrderedCollectionPage))
.set_part_of(Node::link(url!(ctx, "/users/{id}/outbox")))
@ -71,7 +70,7 @@ pub async fn outbox(
} else {
Ok(JsonLD(
crate::activitystream::object()
serde_json::Value::new_object()
.set_id(Some(&url!(ctx, "/users/{id}/outbox")))
.set_collection_type(Some(CollectionType::OrderedCollection))
.set_first(Node::link(url!(ctx, "/users/{id}/outbox?page=true")))

View file

@ -32,17 +32,6 @@ 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(
"@context".to_string(),
serde_json::Value::Array(vec![
serde_json::Value::String("https://www.w3.org/ns/activitystreams".into())
]),
);
serde_json::Value::Object(map)
}
pub trait BaseMut {
fn set_id(self, val: Option<&str>) -> Self;

View file

@ -8,8 +8,7 @@ strenum! {
Application,
Group,
Organization,
Person,
Object;
Person;
};
}

View file

@ -1,6 +1,6 @@
use sea_orm::{entity::prelude::*, FromJsonQueryResult};
use crate::activitystream::{self, link::Link, object::{activity::{Activity, ActivityMut, ActivityType}, actor::Actor, Object, ObjectMut, ObjectType}, Base, BaseMut, BaseType, Node};
use crate::{activitypub::jsonld::LD, activitystream::{link::Link, object::{activity::{Activity, ActivityMut, ActivityType}, actor::Actor, Object, ObjectMut, ObjectType}, Base, BaseMut, BaseType, Node}};
#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize, FromJsonQueryResult)]
pub struct Audience(pub Vec<String>);
@ -80,7 +80,7 @@ impl Base for Model {
}
fn underlying_json_object(self) -> serde_json::Value {
activitystream::object()
serde_json::Value::new_object()
.set_id(Some(&self.id))
.set_activity_type(Some(self.activity_type))
.set_actor(Node::link(self.actor))

View file

@ -1,7 +1,6 @@
use sea_orm::entity::prelude::*;
use crate::activitystream::prelude::*;
use crate::activitystream::{object::ObjectType, BaseType, Node};
use crate::{activitypub::jsonld::LD, activitystream::{object::{ObjectMut, ObjectType}, BaseMut, BaseType, Node}};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "objects")]
@ -54,7 +53,7 @@ impl crate::activitystream::Base for Model {
}
fn underlying_json_object(self) -> serde_json::Value {
crate::activitystream::object()
serde_json::Value::new_object()
.set_id(Some(&self.id))
.set_object_type(Some(self.object_type))
.set_attributed_to(Node::maybe_link(self.attributed_to))

View file

@ -1,7 +1,11 @@
use sea_orm::entity::prelude::*;
use crate::activitystream::object::document::DocumentType;
use crate::activitystream::prelude::*;
use crate::activitypub::jsonld::LD;
use crate::activitystream::key::{PublicKey as _, PublicKeyMut as _};
use crate::activitystream::object::actor::ActorMut as _;
use crate::activitystream::object::document::{DocumentMut as _, DocumentType};
use crate::activitystream::object::ObjectMut as _;
use crate::activitystream::{BaseMut as _, Object as _};
use crate::{activitypub, activitystream::{object::actor::ActorType, BaseType, Node, ObjectType}};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
@ -71,7 +75,7 @@ impl crate::activitystream::Base for Model {
}
fn underlying_json_object(self) -> serde_json::Value {
crate::activitystream::object()
serde_json::Value::new_object()
.set_id(Some(&self.id))
.set_actor_type(Some(self.actor_type))
.set_name(self.name.as_deref())
@ -87,7 +91,6 @@ impl crate::activitystream::Base for Model {
.set_public_key(self.public_key())
.set_discoverable(Some(true))
.set_endpoints(None) // TODO dirty fix to put an empty object
.underlying_json_object()
}
}
@ -103,7 +106,7 @@ impl crate::activitystream::object::Object for Model {
fn icon(&self) -> Node<impl Image> {
match &self.icon {
Some(x) => Node::object(
crate::activitystream::raw_object()
serde_json::Value::new_object()
.set_document_type(Some(DocumentType::Image))
.set_url(Node::link(x.clone()))
),
@ -114,7 +117,7 @@ impl crate::activitystream::object::Object for Model {
fn image(&self) -> Node<impl Image> {
match &self.image {
Some(x) => Node::object(
crate::activitystream::raw_object()
serde_json::Value::new_object()
.set_document_type(Some(DocumentType::Image))
.set_url(Node::link(x.clone()))
),
@ -154,7 +157,7 @@ impl crate::activitystream::object::actor::Actor for Model {
fn public_key(&self) -> Node<impl crate::activitystream::key::PublicKey> {
Node::object(
crate::activitystream::raw_object()
serde_json::Value::new_object()
.set_id(Some(&format!("{}#main-key", self.id))) // TODO is this some standard??
.set_public_key_pem(&self.public_key)
.set_owner(Some(&self.id))