Files
thoughts/crates/presentation/src/handlers/federation_actors.rs

122 lines
3.3 KiB
Rust

use crate::{
errors::ApiError, extractors::OptionalAuthUser, handlers::feed::to_thought_response,
state::AppState,
};
use api_types::{
requests::PaginationQuery,
responses::{ActorConnectionPageResponse, ActorConnectionResponse},
};
use application::use_cases::federation_management::{
get_actor_connections_page, get_remote_actor_posts,
};
use axum::{
extract::{Path, Query, State},
Json,
};
use domain::models::feed::PageParams;
pub async fn remote_actor_posts_handler(
State(s): State<AppState>,
Path(handle): Path<String>,
Query(q): Query<PaginationQuery>,
OptionalAuthUser(viewer): OptionalAuthUser,
) -> Result<Json<serde_json::Value>, ApiError> {
let page = PageParams {
page: q.page(),
per_page: q.per_page(),
};
let result = get_remote_actor_posts(
&*s.federation,
&*s.ap_repo,
&*s.feed,
&*s.federation_scheduler,
&handle,
page,
viewer.as_ref(),
)
.await?;
Ok(Json(serde_json::json!({
"total": result.total,
"page": result.page,
"per_page": result.per_page,
"items": result.items.iter().map(to_thought_response).collect::<Vec<_>>(),
})))
}
pub async fn actor_followers_handler(
State(s): State<AppState>,
Path(handle): Path<String>,
Query(q): Query<PaginationQuery>,
) -> Result<Json<ActorConnectionPageResponse>, ApiError> {
actor_connections_handler(s, handle, "followers", q.page() as u32).await
}
pub async fn actor_following_handler(
State(s): State<AppState>,
Path(handle): Path<String>,
Query(q): Query<PaginationQuery>,
) -> Result<Json<ActorConnectionPageResponse>, ApiError> {
actor_connections_handler(s, handle, "following", q.page() as u32).await
}
async fn actor_connections_handler(
s: AppState,
handle: String,
connection_type: &str,
page: u32,
) -> Result<Json<ActorConnectionPageResponse>, ApiError> {
let (items, has_more) = get_actor_connections_page(
&*s.federation,
&*s.remote_actor_connections,
&*s.federation_scheduler,
&handle,
connection_type,
page,
)
.await?;
Ok(Json(ActorConnectionPageResponse {
items: items
.into_iter()
.map(|a| ActorConnectionResponse {
handle: a.handle,
display_name: a.display_name,
avatar_url: a.avatar_url,
url: a.url,
})
.collect(),
page,
has_more,
}))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::testing::make_state;
use axum::{body::Body, http::Request, routing::get, Router};
use tower::ServiceExt;
fn app() -> Router {
Router::new()
.route(
"/federation/actors/{handle}/posts",
get(remote_actor_posts_handler),
)
.with_state(make_state())
}
#[tokio::test]
async fn unknown_actor_returns_404() {
let resp = app()
.oneshot(
Request::builder()
.uri("/federation/actors/%40alice%40example.com/posts")
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();
assert_eq!(resp.status(), 404);
}
}