docs(openapi): annotate all federation management handlers and add doc module

This commit is contained in:
2026-05-29 02:04:59 +02:00
parent 989004dd74
commit 86d0497509
2 changed files with 96 additions and 5 deletions

View File

@@ -3,7 +3,7 @@ use crate::{
errors::ApiError, errors::ApiError,
extractors::{AuthUser, Deps}, extractors::{AuthUser, Deps},
}; };
use api_types::responses::{ProfileField, RemoteActorResponse}; use api_types::responses::{ErrorResponse, ProfileField, RemoteActorResponse};
use application::use_cases::federation_management::{ use application::use_cases::federation_management::{
accept_follow_request, get_remote_friends, initiate_actor_move, list_pending_requests, accept_follow_request, get_remote_friends, initiate_actor_move, list_pending_requests,
list_remote_followers, list_remote_following, reject_follow_request, remove_remote_following, list_remote_followers, list_remote_following, reject_follow_request, remove_remote_following,
@@ -12,18 +12,21 @@ use axum::{http::StatusCode, Json};
use domain::ports::{EventPublisher, FederationActionPort, FollowRepository, UserRepository}; use domain::ports::{EventPublisher, FederationActionPort, FollowRepository, UserRepository};
use serde::Deserialize; use serde::Deserialize;
#[derive(Deserialize)] #[derive(Deserialize, utoipa::ToSchema)]
pub struct ActorUrlBody { pub struct ActorUrlBody {
/// Full ActivityPub actor URL
pub actor_url: String, pub actor_url: String,
} }
#[derive(Deserialize)] #[derive(Deserialize, utoipa::ToSchema)]
pub struct HandleBody { pub struct HandleBody {
/// Fediverse handle (`@user@instance.tld`)
pub handle: String, pub handle: String,
} }
#[derive(Deserialize)] #[derive(Deserialize, utoipa::ToSchema)]
pub struct MoveBody { pub struct MoveBody {
/// New actor URL to migrate to
pub new_actor_url: String, pub new_actor_url: String,
} }
@@ -54,6 +57,11 @@ fn to_response(a: domain::models::remote_actor::RemoteActor) -> RemoteActorRespo
} }
} }
#[utoipa::path(
get, path = "/federation/me/followers/pending",
responses((status = 200, description = "Pending inbound follow requests", body = Vec<RemoteActorResponse>)),
security(("bearer_auth" = []))
)]
pub async fn get_pending_requests( pub async fn get_pending_requests(
Deps(d): Deps<FederationManagementDeps>, Deps(d): Deps<FederationManagementDeps>,
AuthUser(uid): AuthUser, AuthUser(uid): AuthUser,
@@ -62,6 +70,15 @@ pub async fn get_pending_requests(
Ok(Json(actors.into_iter().map(to_response).collect())) Ok(Json(actors.into_iter().map(to_response).collect()))
} }
#[utoipa::path(
post, path = "/federation/me/followers/accept",
request_body = ActorUrlBody,
responses(
(status = 204, description = "Follow request accepted"),
(status = 400, description = "Invalid request", body = ErrorResponse),
),
security(("bearer_auth" = []))
)]
pub async fn post_accept_request( pub async fn post_accept_request(
Deps(d): Deps<FederationManagementDeps>, Deps(d): Deps<FederationManagementDeps>,
AuthUser(uid): AuthUser, AuthUser(uid): AuthUser,
@@ -71,6 +88,15 @@ pub async fn post_accept_request(
Ok(StatusCode::NO_CONTENT) Ok(StatusCode::NO_CONTENT)
} }
#[utoipa::path(
delete, path = "/federation/me/followers",
request_body = ActorUrlBody,
responses(
(status = 204, description = "Follower removed / request rejected"),
(status = 400, description = "Invalid request", body = ErrorResponse),
),
security(("bearer_auth" = []))
)]
pub async fn delete_follower( pub async fn delete_follower(
Deps(d): Deps<FederationManagementDeps>, Deps(d): Deps<FederationManagementDeps>,
AuthUser(uid): AuthUser, AuthUser(uid): AuthUser,
@@ -80,6 +106,11 @@ pub async fn delete_follower(
Ok(StatusCode::NO_CONTENT) Ok(StatusCode::NO_CONTENT)
} }
#[utoipa::path(
get, path = "/federation/me/followers",
responses((status = 200, description = "Accepted remote followers", body = Vec<RemoteActorResponse>)),
security(("bearer_auth" = []))
)]
pub async fn get_remote_followers( pub async fn get_remote_followers(
Deps(d): Deps<FederationManagementDeps>, Deps(d): Deps<FederationManagementDeps>,
AuthUser(uid): AuthUser, AuthUser(uid): AuthUser,
@@ -88,6 +119,11 @@ pub async fn get_remote_followers(
Ok(Json(actors.into_iter().map(to_response).collect())) Ok(Json(actors.into_iter().map(to_response).collect()))
} }
#[utoipa::path(
get, path = "/federation/me/following",
responses((status = 200, description = "Remote accounts I follow", body = Vec<RemoteActorResponse>)),
security(("bearer_auth" = []))
)]
pub async fn get_remote_following( pub async fn get_remote_following(
Deps(d): Deps<FederationManagementDeps>, Deps(d): Deps<FederationManagementDeps>,
AuthUser(uid): AuthUser, AuthUser(uid): AuthUser,
@@ -96,6 +132,11 @@ pub async fn get_remote_following(
Ok(Json(actors.into_iter().map(to_response).collect())) Ok(Json(actors.into_iter().map(to_response).collect()))
} }
#[utoipa::path(
get, path = "/federation/me/friends",
responses((status = 200, description = "Remote mutual follows (I follow them and they follow me)", body = Vec<RemoteActorResponse>)),
security(("bearer_auth" = []))
)]
pub async fn get_remote_friends_handler( pub async fn get_remote_friends_handler(
Deps(d): Deps<FederationManagementDeps>, Deps(d): Deps<FederationManagementDeps>,
AuthUser(uid): AuthUser, AuthUser(uid): AuthUser,
@@ -104,6 +145,15 @@ pub async fn get_remote_friends_handler(
Ok(Json(actors.into_iter().map(to_response).collect())) Ok(Json(actors.into_iter().map(to_response).collect()))
} }
#[utoipa::path(
delete, path = "/federation/me/following",
request_body = HandleBody,
responses(
(status = 204, description = "Unfollowed remote account"),
(status = 400, description = "Invalid handle", body = ErrorResponse),
),
security(("bearer_auth" = []))
)]
pub async fn delete_following( pub async fn delete_following(
Deps(d): Deps<FederationManagementDeps>, Deps(d): Deps<FederationManagementDeps>,
AuthUser(uid): AuthUser, AuthUser(uid): AuthUser,
@@ -121,6 +171,15 @@ pub async fn delete_following(
Ok(StatusCode::NO_CONTENT) Ok(StatusCode::NO_CONTENT)
} }
#[utoipa::path(
post, path = "/federation/me/move",
request_body = MoveBody,
responses(
(status = 204, description = "Account move initiated"),
(status = 400, description = "Invalid URL", body = ErrorResponse),
),
security(("bearer_auth" = []))
)]
pub async fn post_move_account( pub async fn post_move_account(
Deps(d): Deps<FederationManagementDeps>, Deps(d): Deps<FederationManagementDeps>,
AuthUser(uid): AuthUser, AuthUser(uid): AuthUser,
@@ -132,11 +191,18 @@ pub async fn post_move_account(
Ok(StatusCode::NO_CONTENT) Ok(StatusCode::NO_CONTENT)
} }
#[derive(Deserialize)] #[derive(Deserialize, utoipa::ToSchema)]
pub struct AlsoKnownAsBody { pub struct AlsoKnownAsBody {
/// Actor URL of the account this identity is also known as (for migration verification)
pub also_known_as: Option<String>, pub also_known_as: Option<String>,
} }
#[utoipa::path(
patch, path = "/federation/me/also-known-as",
request_body = AlsoKnownAsBody,
responses((status = 204, description = "Also-known-as updated")),
security(("bearer_auth" = []))
)]
pub async fn patch_also_known_as( pub async fn patch_also_known_as(
Deps(d): Deps<FederationManagementDeps>, Deps(d): Deps<FederationManagementDeps>,
AuthUser(uid): AuthUser, AuthUser(uid): AuthUser,

View File

@@ -0,0 +1,25 @@
use utoipa::OpenApi;
#[derive(OpenApi)]
#[openapi(
paths(
crate::handlers::federation_management::get_pending_requests,
crate::handlers::federation_management::post_accept_request,
crate::handlers::federation_management::delete_follower,
crate::handlers::federation_management::get_remote_followers,
crate::handlers::federation_management::get_remote_following,
crate::handlers::federation_management::get_remote_friends_handler,
crate::handlers::federation_management::delete_following,
crate::handlers::federation_management::post_move_account,
crate::handlers::federation_management::patch_also_known_as,
),
components(schemas(
api_types::responses::RemoteActorResponse,
api_types::responses::ProfileField,
crate::handlers::federation_management::ActorUrlBody,
crate::handlers::federation_management::HandleBody,
crate::handlers::federation_management::MoveBody,
crate::handlers::federation_management::AlsoKnownAsBody,
)),
)]
pub struct FederationManagementDoc;