diff options
author | alemi <me@alemi.dev> | 2024-04-11 17:00:09 +0200 |
---|---|---|
committer | alemi <me@alemi.dev> | 2024-04-11 17:00:09 +0200 |
commit | 9e67eead69f5cbd426939d8003b3374476f6d725 (patch) | |
tree | 9f27aff740f087e0f85ff31d41ee151e8276fe8c | |
parent | d5c5d341e8441b8969089db5f108ebedc8890687 (diff) |
feat: multi-join maybe? fix inbox not embedding objtci
got this from https://github.com/SeaQL/sea-orm/discussions/1502, not
sure it's what i need but i'm trying some stuff
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/routes/activitypub/user/inbox.rs | 23 | ||||
-rw-r--r-- | src/tools.rs | 41 |
3 files changed, 59 insertions, 6 deletions
diff --git a/src/main.rs b/src/main.rs index 3c12cff..6178aa9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ pub mod server; pub mod model; pub mod routes; +pub mod tools; pub mod errors; #[cfg(feature = "migrations")] diff --git a/src/routes/activitypub/user/inbox.rs b/src/routes/activitypub/user/inbox.rs index d59a7cc..2d310ca 100644 --- a/src/routes/activitypub/user/inbox.rs +++ b/src/routes/activitypub/user/inbox.rs @@ -1,8 +1,8 @@ use axum::{extract::{Path, Query, State}, http::StatusCode, Json}; -use sea_orm::{ColumnTrait, Condition, EntityTrait, Order, QueryFilter, QueryOrder, QuerySelect}; +use sea_orm::{ColumnTrait, Condition, EntityTrait, JoinType, Order, QueryFilter, QueryOrder, QuerySelect, RelationTrait}; -use apb::{server::Inbox, ActivityType, Base, BaseType, ObjectType}; -use crate::{routes::activitypub::{activity::ap_activity, jsonld::LD, JsonLD, Pagination}, server::{Context, auth::{AuthIdentity, Identity}}, errors::UpubError, model, url}; +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}; pub async fn get( State(ctx): State<Context>, @@ -33,12 +33,20 @@ 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); - match model::addressing::Entity::find() + let select = model::addressing::Entity::find() .filter(Condition::all().add(model::addressing::Column::Actor.eq(uid))) .order_by(model::addressing::Column::Published, Order::Asc) - .find_also_related(model::activity::Entity) + .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) .offset(offset) + .into_model::<crate::tools::ActivityWithObject>() .all(ctx.db()) .await { @@ -49,7 +57,10 @@ pub async fn page( offset, limit, activities .into_iter() - .filter_map(|(_, a)| Some(ap_activity(a?))) + .map(|ActivityWithObject { activity, object }| { + ap_activity(activity) + .set_object(apb::Node::maybe_object(object.map(ap_object))) + }) .collect::<Vec<serde_json::Value>>() ).ld_context() )) diff --git a/src/tools.rs b/src/tools.rs new file mode 100644 index 0000000..e6cee04 --- /dev/null +++ b/src/tools.rs @@ -0,0 +1,41 @@ +// yanked from https://github.com/SeaQL/sea-orm/discussions/1502 +use sea_orm::{prelude::*, FromQueryResult}; +use sea_orm::sea_query::{Alias, IntoIden, SelectExpr, SelectStatement}; +use sea_orm::{EntityTrait, QueryTrait}; + +pub struct Prefixer<S: QueryTrait<QueryStatement = SelectStatement>> { + pub selector: S, +} + +impl<S: QueryTrait<QueryStatement = SelectStatement>> Prefixer<S> { + pub fn new(selector: S) -> Self { + Self { selector } + } + pub fn add_columns<T: EntityTrait>(mut self, entity: T) -> Self { + for col in <T::Column as sea_orm::entity::Iterable>::iter() { + let alias = format!("{}{}", entity.table_name(), col.to_string()); // we use entity.table_name() as prefix + self.selector.query().expr(SelectExpr { + expr: col.select_as(col.into_expr()), + alias: Some(Alias::new(&alias).into_iden()), + window: None, + }); + } + self + } +} + +// adapted from https://github.com/SeaQL/sea-orm/discussions/1502 +#[derive(Debug)] +pub struct ActivityWithObject { + pub activity: crate::model::activity::Model, + pub object: Option<crate::model::object::Model>, +} + +impl FromQueryResult for ActivityWithObject { + fn from_query_result(res: &sea_orm::QueryResult, _pre: &str) -> Result<Self, sea_orm::DbErr> { + let activity = crate::model::activity::Model::from_query_result(res, crate::model::activity::Entity.table_name())?; + let object = crate::model::object::Model::from_query_result(res, crate::model::object::Entity.table_name()).ok(); + + Ok(Self { activity, object }) + } +} |