feat: implement retrieval of posts by semantic ID and update related use cases
This commit is contained in:
parent
6efd941395
commit
43582af2a5
@ -15,8 +15,9 @@ use crate::{
|
||||
create_label_use_case::CreateLabelUseCase, create_post_use_case::CreatePostUseCase,
|
||||
get_all_labels_use_case::GetAllLabelsUseCase,
|
||||
get_all_post_info_use_case::GetAllPostInfoUseCase,
|
||||
get_full_post_use_case::GetFullPostUseCase, update_label_use_case::UpdateLabelUseCase,
|
||||
update_post_use_case::UpdatePostUseCase,
|
||||
get_post_by_id_use_case::GetPostByIdUseCase,
|
||||
get_post_by_sementic_id_use_case::GetPostBySemanticIdUseCase,
|
||||
update_label_use_case::UpdateLabelUseCase, update_post_use_case::UpdatePostUseCase,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -34,9 +35,9 @@ pub trait PostController: Send + Sync {
|
||||
user_id: Option<i32>,
|
||||
) -> Result<Vec<PostInfoResponseDto>, PostError>;
|
||||
|
||||
async fn get_post_by_id(
|
||||
async fn get_post_by_id_or_semantic_id(
|
||||
&self,
|
||||
id: i32,
|
||||
id_or_semantic_id: &str,
|
||||
user_id: Option<i32>,
|
||||
) -> Result<PostResponseDto, PostError>;
|
||||
|
||||
@ -69,7 +70,8 @@ pub trait PostController: Send + Sync {
|
||||
|
||||
pub struct PostControllerImpl {
|
||||
get_all_post_info_use_case: Arc<dyn GetAllPostInfoUseCase>,
|
||||
get_full_post_use_case: Arc<dyn GetFullPostUseCase>,
|
||||
get_post_by_id_use_case: Arc<dyn GetPostByIdUseCase>,
|
||||
get_post_by_semantic_id_use_case: Arc<dyn GetPostBySemanticIdUseCase>,
|
||||
create_post_use_case: Arc<dyn CreatePostUseCase>,
|
||||
update_post_use_case: Arc<dyn UpdatePostUseCase>,
|
||||
create_label_use_case: Arc<dyn CreateLabelUseCase>,
|
||||
@ -80,7 +82,8 @@ pub struct PostControllerImpl {
|
||||
impl PostControllerImpl {
|
||||
pub fn new(
|
||||
get_all_post_info_use_case: Arc<dyn GetAllPostInfoUseCase>,
|
||||
get_full_post_use_case: Arc<dyn GetFullPostUseCase>,
|
||||
get_post_by_id_use_case: Arc<dyn GetPostByIdUseCase>,
|
||||
get_post_by_semantic_id_use_case: Arc<dyn GetPostBySemanticIdUseCase>,
|
||||
create_post_use_case: Arc<dyn CreatePostUseCase>,
|
||||
update_post_use_case: Arc<dyn UpdatePostUseCase>,
|
||||
create_label_use_case: Arc<dyn CreateLabelUseCase>,
|
||||
@ -89,7 +92,8 @@ impl PostControllerImpl {
|
||||
) -> Self {
|
||||
Self {
|
||||
get_all_post_info_use_case,
|
||||
get_full_post_use_case,
|
||||
get_post_by_id_use_case,
|
||||
get_post_by_semantic_id_use_case,
|
||||
create_post_use_case,
|
||||
update_post_use_case,
|
||||
create_label_use_case,
|
||||
@ -97,6 +101,29 @@ impl PostControllerImpl {
|
||||
get_all_labels_use_case,
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_post_by_id(
|
||||
&self,
|
||||
id: i32,
|
||||
user_id: Option<i32>,
|
||||
) -> Result<PostResponseDto, PostError> {
|
||||
let result = self.get_post_by_id_use_case.execute(id, user_id).await;
|
||||
|
||||
result.map(PostResponseDto::from)
|
||||
}
|
||||
|
||||
async fn get_post_by_semantic_id(
|
||||
&self,
|
||||
semantic_id: &str,
|
||||
user_id: Option<i32>,
|
||||
) -> Result<PostResponseDto, PostError> {
|
||||
let result = self
|
||||
.get_post_by_semantic_id_use_case
|
||||
.execute(semantic_id, user_id)
|
||||
.await;
|
||||
|
||||
result.map(PostResponseDto::from)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@ -121,14 +148,17 @@ impl PostController for PostControllerImpl {
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_post_by_id(
|
||||
async fn get_post_by_id_or_semantic_id(
|
||||
&self,
|
||||
id: i32,
|
||||
id_or_semantic_id: &str,
|
||||
user_id: Option<i32>,
|
||||
) -> Result<PostResponseDto, PostError> {
|
||||
let result = self.get_full_post_use_case.execute(id, user_id).await;
|
||||
|
||||
result.map(PostResponseDto::from)
|
||||
if let Ok(id) = id_or_semantic_id.parse::<i32>() {
|
||||
self.get_post_by_id(id, user_id).await
|
||||
} else {
|
||||
let semantic_id = id_or_semantic_id;
|
||||
self.get_post_by_semantic_id(semantic_id, user_id).await
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_label(
|
||||
|
@ -14,4 +14,5 @@ pub trait PostDbService: Send + Sync {
|
||||
async fn get_post_by_id(&self, id: i32) -> Result<PostMapper, PostError>;
|
||||
async fn create_post(&self, post: PostMapper, label_ids: &[i32]) -> Result<i32, PostError>;
|
||||
async fn update_post(&self, post: PostMapper, label_ids: &[i32]) -> Result<(), PostError>;
|
||||
async fn get_id_by_semantic_id(&self, semantic_id: &str) -> Result<i32, PostError>;
|
||||
}
|
||||
|
@ -84,4 +84,8 @@ impl PostRepository for PostRepositoryImpl {
|
||||
.update_post(post_mapper, label_ids)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_id_by_semantic_id(&self, semantic_id: &str) -> Result<i32, PostError> {
|
||||
self.post_db_service.get_id_by_semantic_id(semantic_id).await
|
||||
}
|
||||
}
|
||||
|
@ -11,4 +11,5 @@ pub trait PostRepository: Send + Sync {
|
||||
async fn get_post_by_id(&self, id: i32) -> Result<Post, PostError>;
|
||||
async fn create_post(&self, post: Post, label_ids: &[i32]) -> Result<i32, PostError>;
|
||||
async fn update_post(&self, post: Post, label_ids: &[i32]) -> Result<(), PostError>;
|
||||
async fn get_id_by_semantic_id(&self, semantic_id: &str) -> Result<i32, PostError>;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ pub mod create_label_use_case;
|
||||
pub mod create_post_use_case;
|
||||
pub mod get_all_labels_use_case;
|
||||
pub mod get_all_post_info_use_case;
|
||||
pub mod get_full_post_use_case;
|
||||
pub mod get_post_by_id_use_case;
|
||||
pub mod get_post_by_sementic_id_use_case;
|
||||
pub mod update_label_use_case;
|
||||
pub mod update_post_use_case;
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
};
|
||||
|
||||
#[async_trait]
|
||||
pub trait GetFullPostUseCase: Send + Sync {
|
||||
pub trait GetPostByIdUseCase: Send + Sync {
|
||||
async fn execute(&self, id: i32, user_id: Option<i32>) -> Result<Post, PostError>;
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ impl GetFullPostUseCaseImpl {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl GetFullPostUseCase for GetFullPostUseCaseImpl {
|
||||
impl GetPostByIdUseCase for GetFullPostUseCaseImpl {
|
||||
async fn execute(&self, id: i32, user_id: Option<i32>) -> Result<Post, PostError> {
|
||||
let post = self.post_repository.get_post_by_id(id).await?;
|
||||
|
@ -0,0 +1,45 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::{
|
||||
application::{
|
||||
error::post_error::PostError, gateway::post_repository::PostRepository,
|
||||
use_case::get_post_by_id_use_case::GetPostByIdUseCase,
|
||||
},
|
||||
domain::entity::post::Post,
|
||||
};
|
||||
|
||||
#[async_trait]
|
||||
pub trait GetPostBySemanticIdUseCase: Send + Sync {
|
||||
async fn execute(&self, semantic_id: &str, user_id: Option<i32>) -> Result<Post, PostError>;
|
||||
}
|
||||
|
||||
pub struct GetPostIdBySemanticIdUseCaseImpl {
|
||||
post_repository: Arc<dyn PostRepository>,
|
||||
get_post_by_id_use_case: Arc<dyn GetPostByIdUseCase>,
|
||||
}
|
||||
|
||||
impl GetPostIdBySemanticIdUseCaseImpl {
|
||||
pub fn new(
|
||||
post_repository: Arc<dyn PostRepository>,
|
||||
get_post_by_id_use_case: Arc<dyn GetPostByIdUseCase>,
|
||||
) -> Self {
|
||||
Self {
|
||||
post_repository,
|
||||
get_post_by_id_use_case,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl GetPostBySemanticIdUseCase for GetPostIdBySemanticIdUseCaseImpl {
|
||||
async fn execute(&self, semantic_id: &str, user_id: Option<i32>) -> Result<Post, PostError> {
|
||||
let id = self
|
||||
.post_repository
|
||||
.get_id_by_semantic_id(semantic_id)
|
||||
.await?;
|
||||
|
||||
self.get_post_by_id_use_case.execute(id, user_id).await
|
||||
}
|
||||
}
|
@ -307,4 +307,23 @@ impl PostDbService for PostDbServiceImpl {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_id_by_semantic_id(&self, semantic_id: &str) -> Result<i32, PostError> {
|
||||
let id = sqlx::query_scalar!(
|
||||
r#"
|
||||
SELECT id
|
||||
FROM post
|
||||
WHERE semantic_id = $1 AND deleted_time IS NULL
|
||||
"#,
|
||||
semantic_id,
|
||||
)
|
||||
.fetch_optional(&self.db_pool)
|
||||
.await
|
||||
.map_err(|e| PostError::Unexpected(DatabaseError(e).into()))?;
|
||||
|
||||
match id {
|
||||
Some(id) => Ok(id),
|
||||
None => Err(PostError::NotFound),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ use crate::{
|
||||
get,
|
||||
path = "/post/{id}",
|
||||
tag = "post",
|
||||
summary = "Get post by ID",
|
||||
description = "Only authenticated users can access unpublished posts.",
|
||||
summary = "Get post by ID or semantic ID",
|
||||
description = "Only authenticated users can access unpublished posts. Accepts either numeric ID or semantic ID.",
|
||||
responses (
|
||||
(status = 200, body = PostResponseDto),
|
||||
(status = 404, description = "Post not found")
|
||||
@ -20,12 +20,12 @@ use crate::{
|
||||
)]
|
||||
pub async fn get_post_by_id_handler(
|
||||
post_controller: web::Data<dyn PostController>,
|
||||
path: web::Path<i32>,
|
||||
path: web::Path<String>,
|
||||
user_id: Option<UserId>,
|
||||
) -> impl Responder {
|
||||
let id = path.into_inner();
|
||||
let id_or_semantic_id = path.into_inner();
|
||||
let result = post_controller
|
||||
.get_post_by_id(id, user_id.map(|id| id.get()))
|
||||
.get_post_by_id_or_semantic_id(&id_or_semantic_id, user_id.map(|id| id.get()))
|
||||
.await;
|
||||
|
||||
match result {
|
||||
|
@ -36,13 +36,12 @@ use post::{
|
||||
},
|
||||
},
|
||||
application::use_case::{
|
||||
create_label_use_case::CreateLabelUseCaseImpl,
|
||||
create_post_use_case::CreatePostUseCaseImpl,
|
||||
create_label_use_case::CreateLabelUseCaseImpl, create_post_use_case::CreatePostUseCaseImpl,
|
||||
get_all_labels_use_case::GetAllLabelsUseCaseImpl,
|
||||
get_all_post_info_use_case::GetAllPostInfoUseCaseImpl,
|
||||
get_full_post_use_case::GetFullPostUseCaseImpl,
|
||||
update_label_use_case::UpdateLabelUseCaseImpl,
|
||||
update_post_use_case::UpdatePostUseCaseImpl,
|
||||
get_post_by_id_use_case::GetFullPostUseCaseImpl,
|
||||
get_post_by_sementic_id_use_case::GetPostIdBySemanticIdUseCaseImpl,
|
||||
update_label_use_case::UpdateLabelUseCaseImpl, update_post_use_case::UpdatePostUseCaseImpl,
|
||||
},
|
||||
framework::db::{
|
||||
label_db_service_impl::LabelDbServiceImpl, post_db_service_impl::PostDbServiceImpl,
|
||||
@ -97,7 +96,12 @@ impl Container {
|
||||
|
||||
let get_all_post_info_use_case =
|
||||
Arc::new(GetAllPostInfoUseCaseImpl::new(post_repository.clone()));
|
||||
let get_full_post_use_case = Arc::new(GetFullPostUseCaseImpl::new(post_repository.clone()));
|
||||
let get_post_by_id_use_case =
|
||||
Arc::new(GetFullPostUseCaseImpl::new(post_repository.clone()));
|
||||
let get_post_by_semantic_id_use_case = Arc::new(GetPostIdBySemanticIdUseCaseImpl::new(
|
||||
post_repository.clone(),
|
||||
get_post_by_id_use_case.clone(),
|
||||
));
|
||||
let create_post_use_case = Arc::new(CreatePostUseCaseImpl::new(post_repository.clone()));
|
||||
let update_post_use_case = Arc::new(UpdatePostUseCaseImpl::new(post_repository.clone()));
|
||||
let create_label_use_case = Arc::new(CreateLabelUseCaseImpl::new(label_repository.clone()));
|
||||
@ -107,7 +111,8 @@ impl Container {
|
||||
|
||||
let post_controller = Arc::new(PostControllerImpl::new(
|
||||
get_all_post_info_use_case,
|
||||
get_full_post_use_case,
|
||||
get_post_by_id_use_case,
|
||||
get_post_by_semantic_id_use_case,
|
||||
create_post_use_case,
|
||||
update_post_use_case,
|
||||
create_label_use_case,
|
||||
|
Loading…
x
Reference in New Issue
Block a user