diff --git a/crates/presentation/src/handlers/federation_management.rs b/crates/presentation/src/handlers/federation_management.rs new file mode 100644 index 0000000..f9a9df5 --- /dev/null +++ b/crates/presentation/src/handlers/federation_management.rs @@ -0,0 +1,93 @@ +use crate::{errors::ApiError, extractors::AuthUser, state::AppState}; +use api_types::responses::RemoteActorResponse; +use application::use_cases::federation_management::{ + accept_follow_request, list_pending_requests, list_remote_followers, list_remote_following, + reject_follow_request, +}; +use axum::{extract::State, http::StatusCode, Json}; +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct ActorUrlBody { + pub actor_url: String, +} + +#[derive(Deserialize)] +pub struct HandleBody { + pub handle: String, +} + +fn to_response(a: domain::models::remote_actor::RemoteActor) -> RemoteActorResponse { + RemoteActorResponse { + handle: a.handle, + display_name: a.display_name, + avatar_url: a.avatar_url, + url: a.url, + bio: a.bio, + banner_url: a.banner_url, + also_known_as: a.also_known_as, + outbox_url: a.outbox_url, + followers_url: a.followers_url, + following_url: a.following_url, + attachment: vec![], + } +} + +pub async fn get_pending_requests( + State(s): State, + AuthUser(uid): AuthUser, +) -> Result>, ApiError> { + let actors = list_pending_requests(&*s.federation, &uid).await?; + Ok(Json(actors.into_iter().map(to_response).collect())) +} + +pub async fn post_accept_request( + State(s): State, + AuthUser(uid): AuthUser, + Json(body): Json, +) -> Result { + accept_follow_request(&*s.federation, &uid, &body.actor_url).await?; + Ok(StatusCode::NO_CONTENT) +} + +pub async fn delete_follower( + State(s): State, + AuthUser(uid): AuthUser, + Json(body): Json, +) -> Result { + reject_follow_request(&*s.federation, &uid, &body.actor_url).await?; + Ok(StatusCode::NO_CONTENT) +} + +pub async fn get_remote_followers( + State(s): State, + AuthUser(uid): AuthUser, +) -> Result>, ApiError> { + let actors = list_remote_followers(&*s.federation, &uid).await?; + Ok(Json(actors.into_iter().map(to_response).collect())) +} + +pub async fn get_remote_following( + State(s): State, + AuthUser(uid): AuthUser, +) -> Result>, ApiError> { + let actors = list_remote_following(&*s.federation, &uid).await?; + Ok(Json(actors.into_iter().map(to_response).collect())) +} + +pub async fn delete_following( + State(s): State, + AuthUser(uid): AuthUser, + Json(body): Json, +) -> Result { + application::use_cases::social::unfollow_actor( + &*s.follows, + &*s.users, + &*s.federation, + &*s.events, + &uid, + &body.handle, + ) + .await?; + Ok(StatusCode::NO_CONTENT) +} diff --git a/crates/presentation/src/handlers/mod.rs b/crates/presentation/src/handlers/mod.rs index 6649c72..44351c1 100644 --- a/crates/presentation/src/handlers/mod.rs +++ b/crates/presentation/src/handlers/mod.rs @@ -1,6 +1,7 @@ pub mod api_keys; pub mod auth; pub mod federation_actors; +pub mod federation_management; pub mod feed; pub mod health; pub mod notifications; diff --git a/crates/presentation/src/routes.rs b/crates/presentation/src/routes.rs index 9061134..d0025cc 100644 --- a/crates/presentation/src/routes.rs +++ b/crates/presentation/src/routes.rs @@ -77,6 +77,24 @@ pub fn router() -> Router { "/federation/actors/{handle}/following-list", get(federation_actors::actor_following_handler), ) + .route( + "/federation/me/followers/pending", + get(federation_management::get_pending_requests), + ) + .route( + "/federation/me/followers/accept", + post(federation_management::post_accept_request), + ) + .route( + "/federation/me/followers", + get(federation_management::get_remote_followers) + .delete(federation_management::delete_follower), + ) + .route( + "/federation/me/following", + get(federation_management::get_remote_following) + .delete(federation_management::delete_following), + ) .route("/tags/popular", get(feed::get_popular_tags)) .route("/tags/{name}", get(feed::tag_thoughts_handler)) // notifications