From 66ade70273b999e33631a6155e69f5210a158ef3 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Mon, 4 May 2026 20:58:20 +0200 Subject: [PATCH] feat: add GET /users/{id}/feed.rss per-user RSS feed handler --- crates/presentation/src/handlers.rs | 37 +++++++++++++++++++++++++++-- crates/presentation/src/routes.rs | 1 + 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/crates/presentation/src/handlers.rs b/crates/presentation/src/handlers.rs index bd6622a..dc13cf7 100644 --- a/crates/presentation/src/handlers.rs +++ b/crates/presentation/src/handlers.rs @@ -362,13 +362,14 @@ pub mod posters { pub mod rss { use axum::{ - extract::State, + extract::{Path, State}, http::header, response::IntoResponse, }; + use uuid::Uuid; use application::{queries::GetDiaryQuery, use_cases::get_diary}; - use domain::{errors::DomainError, models::SortDirection}; + use domain::{errors::DomainError, models::SortDirection, value_objects::UserId}; use crate::{errors::ApiError, state::AppState}; @@ -387,6 +388,38 @@ pub mod rss { .map_err(|e| ApiError(DomainError::InfrastructureError(e)))?; Ok(([(header::CONTENT_TYPE, "application/rss+xml; charset=utf-8")], xml)) } + + pub async fn get_user_feed( + State(state): State, + Path(user_id): Path, + ) -> Result { + let user = state + .app_ctx + .user_repository + .find_by_id(&UserId::from_uuid(user_id)) + .await + .map_err(ApiError)? + .ok_or_else(|| ApiError(DomainError::NotFound(format!("User {user_id}"))))?; + + let query = GetDiaryQuery { + limit: Some(50), + offset: Some(0), + sort_by: Some(SortDirection::Descending), + movie_id: None, + user_id: Some(user_id), + }; + let page = get_diary::execute(&state.app_ctx, query).await?; + + let display_name = user.email().value().split('@').next().unwrap_or("User"); + let title = format!("{}'s Movie Diary", display_name); + + let xml = state + .rss_renderer + .render_feed(&page.items, &title) + .map_err(|e| ApiError(DomainError::InfrastructureError(e)))?; + + Ok(([(header::CONTENT_TYPE, "application/rss+xml; charset=utf-8")], xml)) + } } pub mod api { diff --git a/crates/presentation/src/routes.rs b/crates/presentation/src/routes.rs index d1c12a8..1d84bec 100644 --- a/crates/presentation/src/routes.rs +++ b/crates/presentation/src/routes.rs @@ -33,6 +33,7 @@ fn html_routes() -> Router { .route("/reviews/{id}/delete", routing::post(handlers::html::post_delete_review)) .route("/posters/{path}", routing::get(handlers::posters::get_poster)) .route("/feed.rss", routing::get(handlers::rss::get_feed)) + .route("/users/{id}/feed.rss", routing::get(handlers::rss::get_user_feed)) } fn api_routes() -> Router {