feat: add global inbox get, which respects privacy

This commit is contained in:
əlemi 2024-03-24 04:58:49 +01:00
parent 2ac7fa0588
commit 28ba5f1b40
Signed by: alemi
GPG key ID: A4895B84D311642C
4 changed files with 45 additions and 19 deletions

View file

@ -1,20 +1,45 @@
use axum::{extract::State, http::StatusCode, Json};
use sea_orm::{EntityTrait, QueryOrder, QuerySelect};
use axum::{extract::{Query, State}, http::StatusCode};
use sea_orm::{ColumnTrait, Condition, EntityTrait, QueryFilter, QueryOrder, QuerySelect};
use crate::{model, server::Context};
use crate::{activitystream::{object::collection::{page::CollectionPageMut, CollectionMut, CollectionType}, BaseMut, Node}, model, server::Context, url};
use super::JsonLD;
use super::{activity::ap_activity, jsonld::LD, JsonLD, Pagination, PUBLIC_TARGET};
pub async fn get(State(ctx) : State<Context>, Json(_object): Json<serde_json::Value>) -> Result<JsonLD<serde_json::Value>, StatusCode> {
match model::activity::Entity::find()
.order_by(model::activity::Column::Published, sea_orm::Order::Desc)
.limit(20)
pub async fn get(State(ctx) : State<Context>, Query(page): Query<Pagination>) -> Result<JsonLD<serde_json::Value>, StatusCode> {
let limit = page.batch.unwrap_or(20).min(100);
let offset = page.offset.unwrap_or(0);
if let Some(true) = page.page {
match model::addressing::Entity::find()
.filter(Condition::all().add(model::addressing::Column::Actor.eq(PUBLIC_TARGET)))
.order_by(model::addressing::Column::Published, sea_orm::Order::Desc)
.find_also_related(model::activity::Entity) // TODO join also with objects
.limit(limit)
.offset(offset)
.all(ctx.db())
.await
{
Ok(x) => todo!(),
Ok(x) => Ok(JsonLD(serde_json::Value::new_object()
.set_id(Some(&url!(ctx, "/inbox")))
.set_collection_type(Some(CollectionType::OrderedCollection))
.set_part_of(Node::link(url!(ctx, "/inbox")))
.set_next(Node::link(url!(ctx, "/inbox?page=true&offset={}", offset+limit)))
.set_ordered_items(Node::array(
x.into_iter()
.filter_map(|(_, a)| Some(ap_activity(a?)))
.collect()
))
.ld_context()
)),
Err(_e) => Err(StatusCode::INTERNAL_SERVER_ERROR),
}
} else {
Ok(JsonLD(serde_json::Value::new_object()
.set_id(Some(&url!(ctx, "/inbox")))
.set_collection_type(Some(CollectionType::OrderedCollection))
.set_first(Node::link(url!(ctx, "/inbox?page=true")))
.ld_context()
))
}
}

View file

@ -8,6 +8,7 @@ pub struct Model {
pub actor: String,
pub activity: String,
pub object: Option<String>,
pub published: ChronoDateTimeUtc,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]

View file

@ -8,8 +8,10 @@ pub async fn serve(db: DatabaseConnection, domain: String) {
// core server inbox/outbox, maybe for feeds? TODO do we need these?
.route("/", get(ap::view))
// TODO shared inboxes and instance stream will come later, just use users *boxes for now
// .route("/inbox", post(ap::inbox))
// .route("/outbox", get(ap::outbox))
.route("/inbox", get(ap::inbox::get))
// .route("/inbox", post(ap::inbox::post))
// .route("/outbox", get(ap::outbox::get))
// .route("/outbox", get(ap::outbox::post))
// .well-known and discovery
.route("/.well-known/webfinger", get(ap::well_known::webfinger))
.route("/.well-known/host-meta", get(ap::well_known::host_meta))
@ -26,8 +28,8 @@ pub async fn serve(db: DatabaseConnection, domain: String) {
.route("/objects/:id", get(ap::object::view))
.with_state(crate::server::Context::new(db, domain));
// run our app with hyper, listening globally on port 3000
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
// run our app with hyper, listening locally on port 3000
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
axum::serve(listener, app)
.await

View file

@ -1,8 +1,6 @@
use std::sync::Arc;
use axum::{routing::{get, post}, Router};
use sea_orm::DatabaseConnection;
use crate::activitypub as ap;
#[derive(Clone)]
pub struct Context(Arc<ContextInner>);