feat: added object feed endpoints

This commit is contained in:
əlemi 2024-06-08 02:18:32 +02:00
parent 88915adff7
commit 07e537e454
Signed by: alemi
GPG key ID: A4895B84D311642C
4 changed files with 97 additions and 13 deletions

View file

@ -0,0 +1,47 @@
use axum::extract::{Path, Query, State};
use sea_orm::{sea_query::IntoCondition, ColumnTrait};
use upub::Context;
use crate::{activitypub::Pagination, builders::JsonLD, AuthIdentity, Identity};
pub async fn get(
State(ctx): State<Context>,
Path(id): Path<String>,
AuthIdentity(auth): AuthIdentity,
) -> crate::ApiResult<JsonLD<serde_json::Value>> {
match auth {
Identity::Anonymous => Err(crate::ApiError::forbidden()),
Identity::Remote { .. } => Err(crate::ApiError::forbidden()),
Identity::Local { id: user, .. } => if ctx.uid(&id) == user {
crate::builders::collection(&upub::url!(ctx, "/actors/{id}/feed"), None)
} else {
Err(crate::ApiError::forbidden())
},
}
}
pub async fn page(
State(ctx): State<Context>,
Path(id): Path<String>,
AuthIdentity(auth): AuthIdentity,
Query(page): Query<Pagination>,
) -> crate::ApiResult<JsonLD<serde_json::Value>> {
let Identity::Local { id: uid, internal } = &auth else {
// local inbox is only for local users
return Err(crate::ApiError::forbidden());
};
if uid != &ctx.uid(&id) {
return Err(crate::ApiError::forbidden());
}
crate::builders::paginate_activities(
upub::url!(ctx, "/actors/{id}/feed/page"),
upub::model::addressing::Column::Actor.eq(*internal).into_condition(),
ctx.db(),
page,
auth.my_id(),
false,
)
.await
}

View file

@ -23,6 +23,10 @@ pub async fn view(
.set_actor_type(Some(apb::ActorType::Application))
.set_name(Some(&ctx.cfg().instance.name))
.set_summary(Some(&ctx.cfg().instance.description))
.set_streams(apb::Node::links(vec![
upub::url!(ctx, "/feed"),
upub::url!(ctx, "/local"),
]))
.set_inbox(apb::Node::link(upub::url!(ctx, "/inbox")))
.set_outbox(apb::Node::link(upub::url!(ctx, "/outbox")))
.set_published(Some(ctx.actor().published))

View file

@ -0,0 +1,29 @@
use axum::extract::{Query, State};
use upub::Context;
use crate::{AuthIdentity, builders::JsonLD};
use super::Pagination;
pub async fn get(
State(ctx): State<Context>,
) -> crate::ApiResult<JsonLD<serde_json::Value>> {
crate::builders::collection(&upub::url!(ctx, "/feed"), None)
}
pub async fn page(
State(ctx): State<Context>,
AuthIdentity(auth): AuthIdentity,
Query(page): Query<Pagination>,
) -> crate::ApiResult<JsonLD<serde_json::Value>> {
crate::builders::paginate_objects(
upub::url!(ctx, "/feed/page"),
auth.filter_objects(),
ctx.db(),
page,
auth.my_id(),
false,
)
.await
}

View file

@ -1,6 +1,7 @@
pub mod user;
pub mod actor;
pub mod inbox;
pub mod outbox;
pub mod feed;
pub mod object;
pub mod activity;
pub mod application;
@ -24,13 +25,14 @@ impl ActivityPubRouter for Router<upub::Context> {
.route("/proxy", post(ap::application::proxy_form))
.route("/proxy", get(ap::application::proxy_get))
.route("/proxy/:uri", get(ap::application::proxy_path))
// TODO shared inboxes and instance stream will come later, just use users *boxes for now
.route("/inbox", post(ap::inbox::post))
.route("/inbox", get(ap::inbox::get))
.route("/inbox/page", get(ap::inbox::page))
.route("/outbox", post(ap::outbox::post))
.route("/outbox", get(ap::outbox::get))
.route("/outbox/page", get(ap::outbox::page))
.route("/feed", get(ap::feed::get))
.route("/feed/page", get(ap::feed::page))
// AUTH routes
.route("/auth", put(ap::auth::register))
.route("/auth", post(ap::auth::login))
@ -42,17 +44,19 @@ impl ActivityPubRouter for Router<upub::Context> {
.route("/.well-known/oauth-authorization-server", get(ap::well_known::oauth_authorization_server))
.route("/nodeinfo/:version", get(ap::well_known::nodeinfo))
// actor routes
.route("/actors/:id", get(ap::user::view))
.route("/actors/:id/inbox", post(ap::user::inbox::post))
.route("/actors/:id/inbox", get(ap::user::inbox::get))
.route("/actors/:id/inbox/page", get(ap::user::inbox::page))
.route("/actors/:id/outbox", post(ap::user::outbox::post))
.route("/actors/:id/outbox", get(ap::user::outbox::get))
.route("/actors/:id/outbox/page", get(ap::user::outbox::page))
.route("/actors/:id/followers", get(ap::user::following::get::<false>))
.route("/actors/:id/followers/page", get(ap::user::following::page::<false>))
.route("/actors/:id/following", get(ap::user::following::get::<true>))
.route("/actors/:id/following/page", get(ap::user::following::page::<true>))
.route("/actors/:id", get(ap::actor::view))
.route("/actors/:id/inbox", post(ap::actor::inbox::post))
.route("/actors/:id/inbox", get(ap::actor::inbox::get))
.route("/actors/:id/inbox/page", get(ap::actor::inbox::page))
.route("/actors/:id/outbox", post(ap::actor::outbox::post))
.route("/actors/:id/outbox", get(ap::actor::outbox::get))
.route("/actors/:id/outbox/page", get(ap::actor::outbox::page))
.route("/actors/:id/feed", get(ap::actor::feed::get))
.route("/actors/:id/feed/page", get(ap::actor::feed::page))
.route("/actors/:id/followers", get(ap::actor::following::get::<false>))
.route("/actors/:id/followers/page", get(ap::actor::following::page::<false>))
.route("/actors/:id/following", get(ap::actor::following::get::<true>))
.route("/actors/:id/following/page", get(ap::actor::following::page::<true>))
// activities
.route("/activities/:id", get(ap::activity::view))
// specific object routes