use axum::extract::{Path, Query, State}; use export::data::AppResponseData; use jwt::extractor::AuthUser; use serde::Serialize; use serde_json::Value; use crate::error::PostResult; use crate::features::PostService; use crate::features::post::ListPostQuery; #[derive(Serialize)] #[serde(untagged)] enum GetBoardResponse { Board(crate::features::posts::PostBoardPage), PostList { items: Vec, total: i64, }, } #[utoipa::path( get, path = "/posts/{space_name}", tag = "posts", params( ("space_name" = String, Path), ), responses((status = 200, description = "Posts board view OR post list (when query.status/q/author_id is set)")), security(("bearer_auth" = [])) )] pub(crate) async fn handler( State(svc): State, AuthUser { claims }: AuthUser, Path(space_name): Path, Query(q): Query, ) -> PostResult> { let space_id = space::features::lookup::lookup_space_by_name(&svc, &space_name).await?; space::features::authz::require_active_member(&svc, claims.sub, space_id).await?; let channel_id = crate::features::lookup::channel_for_post_board(&svc, space_id).await?; let wants_post_list = q.status.is_some() || q.q.is_some() || q.author_id.is_some(); if wants_post_list { let page = svc.list_posts(claims.sub, channel_id, q).await?; let resp = GetBoardResponse::PostList { items: page.items, total: page.total, }; Ok(AppResponseData::ok( serde_json::to_value(resp).unwrap_or(Value::Null), )) } else { let board = svc.list_post_collections(claims.sub, channel_id).await?; let resp = GetBoardResponse::Board(board); let _ = claims; Ok(AppResponseData::ok( serde_json::to_value(resp).unwrap_or(Value::Null), )) } }