BLOG-119 Restricted access to unpublished posts #124

Merged
squid merged 3 commits from BLOG-119_restrict_unpublished_post_access into main 2025-08-06 22:13:55 +08:00
4 changed files with 25 additions and 5 deletions
Showing only changes of commit 1f25fad44a - Show all commits

View File

@ -31,6 +31,7 @@ pub trait PostController: Send + Sync {
async fn get_all_post_info( async fn get_all_post_info(
&self, &self,
query: PostQueryDto, query: PostQueryDto,
user_id: Option<i32>,
) -> Result<Vec<PostInfoResponseDto>, PostError>; ) -> Result<Vec<PostInfoResponseDto>, PostError>;
async fn get_post_by_id( async fn get_post_by_id(
@ -103,10 +104,11 @@ impl PostController for PostControllerImpl {
async fn get_all_post_info( async fn get_all_post_info(
&self, &self,
query: PostQueryDto, query: PostQueryDto,
user_id: Option<i32>,
) -> Result<Vec<PostInfoResponseDto>, PostError> { ) -> Result<Vec<PostInfoResponseDto>, PostError> {
let result = self let result = self
.get_all_post_info_use_case .get_all_post_info_use_case
.execute(query.is_published_only.unwrap_or(true)) .execute(query.is_published_only.unwrap_or(true), user_id)
.await; .await;
result.map(|post_info_list| { result.map(|post_info_list| {

View File

@ -9,7 +9,11 @@ use crate::{
#[async_trait] #[async_trait]
pub trait GetAllPostInfoUseCase: Send + Sync { pub trait GetAllPostInfoUseCase: Send + Sync {
async fn execute(&self, is_published_only: bool) -> Result<Vec<PostInfo>, PostError>; async fn execute(
&self,
is_published_only: bool,
user_id: Option<i32>,
) -> Result<Vec<PostInfo>, PostError>;
} }
pub struct GetAllPostInfoUseCaseImpl { pub struct GetAllPostInfoUseCaseImpl {
@ -24,7 +28,15 @@ impl GetAllPostInfoUseCaseImpl {
#[async_trait] #[async_trait]
impl GetAllPostInfoUseCase for GetAllPostInfoUseCaseImpl { impl GetAllPostInfoUseCase for GetAllPostInfoUseCaseImpl {
async fn execute(&self, is_published_only: bool) -> Result<Vec<PostInfo>, PostError> { async fn execute(
self.post_repository.get_all_post_info(is_published_only).await &self,
is_published_only: bool,
user_id: Option<i32>,
) -> Result<Vec<PostInfo>, PostError> {
let is_published_only = is_published_only || user_id.is_some();
self.post_repository
.get_all_post_info(is_published_only)
.await
} }
} }

View File

@ -1,5 +1,6 @@
use actix_web::{HttpResponse, Responder, web}; use actix_web::{HttpResponse, Responder, web};
use anyhow::anyhow; use anyhow::anyhow;
use auth::framework::web::auth_middleware::UserId;
use sentry::integrations::anyhow::capture_anyhow; use sentry::integrations::anyhow::capture_anyhow;
use crate::{ use crate::{
@ -15,6 +16,7 @@ use crate::{
path = "/post", path = "/post",
tag = "post", tag = "post",
summary = "Get all post information", summary = "Get all post information",
description = "`is_published_only` query is only available for authenticated users.",
params( params(
PostQueryDto PostQueryDto
), ),
@ -25,8 +27,11 @@ use crate::{
pub async fn get_all_post_info_handler( pub async fn get_all_post_info_handler(
post_controller: web::Data<dyn PostController>, post_controller: web::Data<dyn PostController>,
query: web::Query<PostQueryDto>, query: web::Query<PostQueryDto>,
user_id: Option<UserId>,
) -> impl Responder { ) -> impl Responder {
let result = post_controller.get_all_post_info(query.into_inner()).await; let result = post_controller
.get_all_post_info(query.into_inner(), user_id.map(|id| id.get()))
.await;
match result { match result {
Ok(post_info_list) => HttpResponse::Ok().json(post_info_list), Ok(post_info_list) => HttpResponse::Ok().json(post_info_list),

View File

@ -12,6 +12,7 @@ use crate::{
path = "/post/{id}", path = "/post/{id}",
tag = "post", tag = "post",
summary = "Get post by ID", summary = "Get post by ID",
description = "Only authenticated users can access unpublished posts.",
responses ( responses (
(status = 200, body = PostResponseDto), (status = 200, body = PostResponseDto),
(status = 404, description = "Post not found") (status = 404, description = "Post not found")