1
0
Fork 0
forked from alemi/upub

feat: multi-join maybe? fix inbox not embedding obj

got this from https://github.com/SeaQL/sea-orm/discussions/1502, not
sure it's what i need but i'm trying some stuff
This commit is contained in:
əlemi 2024-04-11 17:00:09 +02:00
parent d5c5d341e8
commit 9e67eead69
Signed by: alemi
GPG key ID: A4895B84D311642C
3 changed files with 59 additions and 6 deletions

View file

@ -2,6 +2,7 @@ pub mod server;
pub mod model;
pub mod routes;
pub mod tools;
pub mod errors;
#[cfg(feature = "migrations")]

View file

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

41
src/tools.rs Normal file
View file

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