feat: inbox/outbox security and obj embedding

This commit is contained in:
əlemi 2024-04-12 19:36:00 +02:00
parent 0d340185cf
commit af8d11e75b
Signed by: alemi
GPG key ID: A4895B84D311642C
6 changed files with 42 additions and 49 deletions

View file

@ -5,6 +5,7 @@ use apb::{ActivityMut, ObjectMut, BaseMut, Node};
use super::{jsonld::LD, JsonLD};
// TODO this is used outside /routes, maybe move in model?
pub fn ap_activity(activity: model::activity::Model) -> serde_json::Value {
serde_json::Value::new_object()
.set_id(Some(&activity.id))

View file

@ -1,7 +1,7 @@
use axum::{extract::{Query, State}, http::StatusCode};
use sea_orm::{ColumnTrait, Condition, EntityTrait, Order, QueryFilter, QueryOrder, QuerySelect};
use sea_orm::{Order, QueryFilter, QueryOrder, QuerySelect};
use crate::{server::auth::{AuthIdentity, Identity}, errors::UpubError, model, server::Context, url};
use crate::{server::auth::AuthIdentity, errors::UpubError, model, server::Context, url};
use super::{activity::ap_activity, jsonld::LD, JsonLD, Pagination};
@ -19,14 +19,8 @@ pub async fn page(
) -> Result<JsonLD<serde_json::Value>, UpubError> {
let limit = page.batch.unwrap_or(20).min(50);
let offset = page.offset.unwrap_or(0);
let mut condition = Condition::any()
.add(model::addressing::Column::Actor.eq(apb::target::PUBLIC));
if let Identity::Local(user) = auth {
condition = condition
.add(model::addressing::Column::Actor.eq(user));
}
let activities = model::addressing::Entity::find()
.filter(condition)
let activities = model::addressing::Entity::find_activities()
.filter(auth.filter_condition())
.order_by(model::addressing::Column::Published, Order::Asc)
.find_also_related(model::activity::Entity)
.limit(limit)

View file

@ -6,6 +6,7 @@ use crate::{model::{self, object}, server::Context};
use super::{jsonld::LD, JsonLD};
// TODO this is used outside /routes, maybe move in model?
pub fn ap_object(object: model::object::Model) -> serde_json::Value {
serde_json::Value::new_object()
.set_id(Some(&object.id))

View file

@ -1,8 +1,8 @@
use axum::{extract::{Path, Query, State}, http::StatusCode, Json};
use sea_orm::{ColumnTrait, Condition, EntityTrait, JoinType, Order, QueryFilter, QueryOrder, QuerySelect, RelationTrait};
use apb::{server::Inbox, ActivityMut, ActivityType, Base, BaseType, ObjectType};
use crate::{errors::UpubError, model, routes::activitypub::{activity::ap_activity, jsonld::LD, object::ap_object, JsonLD, Pagination}, server::{auth::{AuthIdentity, Identity}, Context}, tools::ActivityWithObject, url};
use sea_orm::{ColumnTrait, Condition, QueryFilter, QuerySelect};
use crate::{errors::UpubError, model::{self, addressing::EmbeddedActivity}, routes::activitypub::{activity::ap_activity, jsonld::LD, object::ap_object, JsonLD, Pagination}, server::{auth::{AuthIdentity, Identity}, Context}, url};
pub async fn get(
State(ctx): State<Context>,
@ -33,20 +33,11 @@ pub async fn page(
Identity::Local(user) => if uid == user {
let limit = page.batch.unwrap_or(20).min(50);
let offset = page.offset.unwrap_or(0);
let select = model::addressing::Entity::find()
.filter(Condition::all().add(model::addressing::Column::Actor.eq(uid)))
.order_by(model::addressing::Column::Published, Order::Asc)
.select_only();
match crate::tools::Prefixer::new(select)
.add_columns(model::activity::Entity)
.add_columns(model::object::Entity)
.selector
.join(JoinType::LeftJoin, model::activity::Relation::Addressing.def().rev())
.join(JoinType::LeftJoin, model::object::Relation::Activity.def().rev())
.limit(limit)
match model::addressing::Entity::find_activities()
.filter(Condition::all().add(model::addressing::Column::Actor.eq(&user)))
.offset(offset)
.into_model::<crate::tools::ActivityWithObject>()
.limit(limit)
.into_model::<EmbeddedActivity>()
.all(ctx.db())
.await
{
@ -57,9 +48,11 @@ pub async fn page(
offset, limit,
activities
.into_iter()
.map(|ActivityWithObject { activity, object }| {
.map(|EmbeddedActivity { activity, object }| match object {
None => ap_activity(activity),
Some(x) =>
ap_activity(activity)
.set_object(apb::Node::maybe_object(object.map(ap_object)))
.set_object(apb::Node::object(ap_object(x))),
})
.collect::<Vec<serde_json::Value>>()
).ld_context()

View file

@ -1,8 +1,8 @@
use axum::{extract::{Path, Query, State}, http::StatusCode, Json};
use sea_orm::{EntityTrait, Order, QueryOrder, QuerySelect};
use sea_orm::{ColumnTrait, Condition, Order, QueryFilter, QueryOrder, QuerySelect};
use apb::{server::Outbox, AcceptType, ActivityMut, ActivityType, Base, BaseType, Node, ObjectType, RejectType};
use crate::{routes::activitypub::{jsonld::LD, CreationResult, JsonLD, Pagination}, server::auth::{AuthIdentity, Identity}, errors::UpubError, model, server::Context, url};
use crate::{errors::UpubError, model::{self, addressing::EmbeddedActivity}, routes::activitypub::{jsonld::LD, CreationResult, JsonLD, Pagination}, server::{auth::{AuthIdentity, Identity}, Context}, url};
pub async fn get(
State(ctx): State<Context>,
@ -17,27 +17,19 @@ pub async fn page(
State(ctx): State<Context>,
Path(id): Path<String>,
Query(page): Query<Pagination>,
AuthIdentity(_auth): AuthIdentity,
AuthIdentity(auth): AuthIdentity,
) -> Result<JsonLD<serde_json::Value>, StatusCode> {
let uid = ctx.uid(id.clone());
let limit = page.batch.unwrap_or(20).min(50);
let offset = page.offset.unwrap_or(0);
// let mut conditions = Condition::any()
// .add(model::addressing::Column::Actor.eq(PUBLIC_TARGET));
// if let Identity::User(ref x) = auth {
// conditions = conditions.add(model::addressing::Column::Actor.eq(x));
// }
// if let Identity::Server(ref x) = auth {
// conditions = conditions.add(model::addressing::Column::Server.eq(x));
// }
match model::activity::Entity::find()
.find_also_related(model::object::Entity)
.order_by(model::activity::Column::Published, Order::Desc)
match model::addressing::Entity::find_activities()
.filter(Condition::all().add(model::activity::Column::Actor.eq(&uid)))
.filter(auth.filter_condition())
.order_by(model::addressing::Column::Published, Order::Desc)
.limit(limit)
.offset(offset)
.into_model::<EmbeddedActivity>()
.all(ctx.db()).await
{
Err(_e) => Err(StatusCode::INTERNAL_SERVER_ERROR),
@ -48,10 +40,10 @@ pub async fn page(
offset, limit,
items
.into_iter()
.map(|(a, o)| {
let oid = a.object.clone();
super::super::activity::ap_activity(a)
.set_object(match o {
.map(|EmbeddedActivity { activity, object }| {
let oid = activity.object.clone();
super::super::activity::ap_activity(activity)
.set_object(match object {
Some(o) => Node::object(super::super::object::ap_object(o)),
None => Node::maybe_link(oid),
})

View file

@ -13,6 +13,18 @@ pub enum Identity {
Remote(String),
}
impl Identity {
pub fn filter_condition(&self) -> Condition {
let base_cond = Condition::all().add(model::addressing::Column::Actor.eq(apb::target::PUBLIC));
match self {
Identity::Anonymous => base_cond,
Identity::Local(uid) => base_cond.add(model::addressing::Column::Actor.eq(uid)),
Identity::Remote(server) => base_cond.add(model::addressing::Column::Server.eq(server)),
// TODO should we allow all users on same server to see? or just specific user??
}
}
}
pub struct AuthIdentity(pub Identity);
#[axum::async_trait]