BLOG-104 Implement CRUD functionality for Posts #108
@ -1,9 +1,11 @@
|
||||
pub mod color_request_dto;
|
||||
pub mod color_response_dto;
|
||||
pub mod create_label_request_dto;
|
||||
pub mod create_post_request_dto;
|
||||
pub mod label_response_dto;
|
||||
pub mod post_controller;
|
||||
pub mod post_info_query_dto;
|
||||
pub mod post_info_response_dto;
|
||||
pub mod post_response_dto;
|
||||
pub mod update_label_request_dto;
|
||||
pub mod update_post_request_dto;
|
||||
|
@ -0,0 +1,37 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::Deserialize;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::domain::entity::{post::Post, post_info::PostInfo};
|
||||
|
||||
#[derive(Deserialize, ToSchema, Clone)]
|
||||
pub struct CreatePostRequestDto {
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub preview_image_url: String,
|
||||
pub content: String,
|
||||
pub label_ids: Vec<i32>,
|
||||
|
||||
#[schema(required)]
|
||||
pub published_time: Option<i64>,
|
||||
}
|
||||
|
||||
impl CreatePostRequestDto {
|
||||
pub fn into_entity(self) -> Post {
|
||||
Post {
|
||||
id: -1,
|
||||
info: PostInfo {
|
||||
id: -1,
|
||||
title: self.title,
|
||||
description: self.description,
|
||||
preview_image_url: self.preview_image_url,
|
||||
labels: Vec::new(),
|
||||
published_time: self
|
||||
.published_time
|
||||
.map(|micros| DateTime::<Utc>::from_timestamp_micros(micros))
|
||||
.flatten(),
|
||||
},
|
||||
content: self.content,
|
||||
}
|
||||
}
|
||||
}
|
@ -4,16 +4,19 @@ use async_trait::async_trait;
|
||||
|
||||
use crate::{
|
||||
adapter::delivery::{
|
||||
create_label_request_dto::CreateLabelRequestDto, post_info_query_dto::PostQueryDto,
|
||||
create_label_request_dto::CreateLabelRequestDto,
|
||||
create_post_request_dto::CreatePostRequestDto, post_info_query_dto::PostQueryDto,
|
||||
update_label_request_dto::UpdateLabelRequestDto,
|
||||
update_post_request_dto::UpdatePostRequestDto,
|
||||
},
|
||||
application::{
|
||||
error::post_error::PostError,
|
||||
use_case::{
|
||||
create_label_use_case::CreateLabelUseCase,
|
||||
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,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -32,6 +35,14 @@ pub trait PostController: Send + Sync {
|
||||
|
||||
async fn get_post_by_id(&self, id: i32) -> Result<PostResponseDto, PostError>;
|
||||
|
||||
async fn create_post(&self, post: CreatePostRequestDto) -> Result<PostResponseDto, PostError>;
|
||||
|
||||
async fn update_post(
|
||||
&self,
|
||||
id: i32,
|
||||
post: UpdatePostRequestDto,
|
||||
) -> Result<PostResponseDto, PostError>;
|
||||
|
||||
async fn create_label(
|
||||
&self,
|
||||
label: CreateLabelRequestDto,
|
||||
@ -49,6 +60,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>,
|
||||
create_post_use_case: Arc<dyn CreatePostUseCase>,
|
||||
update_post_use_case: Arc<dyn UpdatePostUseCase>,
|
||||
create_label_use_case: Arc<dyn CreateLabelUseCase>,
|
||||
update_label_use_case: Arc<dyn UpdateLabelUseCase>,
|
||||
get_all_labels_use_case: Arc<dyn GetAllLabelsUseCase>,
|
||||
@ -58,6 +71,8 @@ impl PostControllerImpl {
|
||||
pub fn new(
|
||||
get_all_post_info_use_case: Arc<dyn GetAllPostInfoUseCase>,
|
||||
get_full_post_use_case: Arc<dyn GetFullPostUseCase>,
|
||||
create_post_use_case: Arc<dyn CreatePostUseCase>,
|
||||
update_post_use_case: Arc<dyn UpdatePostUseCase>,
|
||||
create_label_use_case: Arc<dyn CreateLabelUseCase>,
|
||||
update_label_use_case: Arc<dyn UpdateLabelUseCase>,
|
||||
get_all_labels_use_case: Arc<dyn GetAllLabelsUseCase>,
|
||||
@ -65,6 +80,8 @@ impl PostControllerImpl {
|
||||
Self {
|
||||
get_all_post_info_use_case,
|
||||
get_full_post_use_case,
|
||||
create_post_use_case,
|
||||
update_post_use_case,
|
||||
create_label_use_case,
|
||||
update_label_use_case,
|
||||
get_all_labels_use_case,
|
||||
@ -136,4 +153,31 @@ impl PostController for PostControllerImpl {
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
async fn create_post(&self, post: CreatePostRequestDto) -> Result<PostResponseDto, PostError> {
|
||||
let label_ids = post.label_ids.clone();
|
||||
let post_entity = post.into_entity();
|
||||
|
||||
let id = self
|
||||
.create_post_use_case
|
||||
.execute(post_entity, &label_ids)
|
||||
.await?;
|
||||
|
||||
self.get_post_by_id(id).await
|
||||
}
|
||||
|
||||
async fn update_post(
|
||||
&self,
|
||||
id: i32,
|
||||
post: UpdatePostRequestDto,
|
||||
) -> Result<PostResponseDto, PostError> {
|
||||
let label_ids = post.label_ids.clone();
|
||||
let post_entity = post.into_entity(id);
|
||||
|
||||
self.update_post_use_case
|
||||
.execute(post_entity, &label_ids)
|
||||
.await?;
|
||||
|
||||
self.get_post_by_id(id).await
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::Deserialize;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::domain::entity::{post::Post, post_info::PostInfo};
|
||||
|
||||
#[derive(Deserialize, ToSchema, Clone)]
|
||||
pub struct UpdatePostRequestDto {
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub preview_image_url: String,
|
||||
pub content: String,
|
||||
pub label_ids: Vec<i32>,
|
||||
|
||||
#[schema(required)]
|
||||
pub published_time: Option<i64>,
|
||||
}
|
||||
|
||||
impl UpdatePostRequestDto {
|
||||
pub fn into_entity(self, id: i32) -> Post {
|
||||
Post {
|
||||
id,
|
||||
info: PostInfo {
|
||||
id,
|
||||
title: self.title,
|
||||
description: self.description,
|
||||
preview_image_url: self.preview_image_url,
|
||||
labels: Vec::new(),
|
||||
published_time: self
|
||||
.published_time
|
||||
.map(|micros| DateTime::<Utc>::from_timestamp_micros(micros))
|
||||
.flatten(),
|
||||
},
|
||||
content: self.content,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::{
|
||||
adapter::gateway::{post_info_db_mapper::PostInfoMapper, post_db_mapper::PostMapper},
|
||||
adapter::gateway::{post_db_mapper::PostMapper, post_info_db_mapper::PostInfoMapper},
|
||||
application::error::post_error::PostError,
|
||||
};
|
||||
|
||||
@ -11,5 +11,7 @@ pub trait PostDbService: Send + Sync {
|
||||
&self,
|
||||
is_published_only: bool,
|
||||
) -> Result<Vec<PostInfoMapper>, PostError>;
|
||||
async fn get_full_post(&self, id: i32) -> Result<PostMapper, PostError>;
|
||||
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>;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ use std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::{
|
||||
adapter::gateway::{post_db_mapper::PostMapper, post_info_db_mapper::PostInfoMapper},
|
||||
application::{error::post_error::PostError, gateway::post_repository::PostRepository},
|
||||
domain::entity::{post::Post, post_info::PostInfo},
|
||||
};
|
||||
@ -33,10 +34,52 @@ impl PostRepository for PostRepositoryImpl {
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_full_post(&self, id: i32) -> Result<Post, PostError> {
|
||||
async fn get_post_by_id(&self, id: i32) -> Result<Post, PostError> {
|
||||
self.post_db_service
|
||||
.get_full_post(id)
|
||||
.get_post_by_id(id)
|
||||
.await
|
||||
.map(|mapper| mapper.into_entity())
|
||||
}
|
||||
|
||||
async fn create_post(&self, post: Post, label_ids: &[i32]) -> Result<i32, PostError> {
|
||||
let info_mapper = PostInfoMapper {
|
||||
id: post.info.id,
|
||||
title: post.info.title,
|
||||
description: post.info.description,
|
||||
preview_image_url: post.info.preview_image_url,
|
||||
labels: Vec::new(),
|
||||
published_time: post.info.published_time.map(|dt| dt.naive_utc()),
|
||||
};
|
||||
|
||||
let post_mapper = PostMapper {
|
||||
id: post.id,
|
||||
info: info_mapper,
|
||||
content: post.content,
|
||||
};
|
||||
|
||||
self.post_db_service
|
||||
.create_post(post_mapper, label_ids)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn update_post(&self, post: Post, label_ids: &[i32]) -> Result<(), PostError> {
|
||||
let info_mapper = PostInfoMapper {
|
||||
id: post.info.id,
|
||||
title: post.info.title,
|
||||
description: post.info.description,
|
||||
preview_image_url: post.info.preview_image_url,
|
||||
labels: Vec::new(),
|
||||
published_time: post.info.published_time.map(|dt| dt.naive_utc()),
|
||||
};
|
||||
|
||||
let post_mapper = PostMapper {
|
||||
id: post.id,
|
||||
info: info_mapper,
|
||||
content: post.content,
|
||||
};
|
||||
|
||||
self.post_db_service
|
||||
.update_post(post_mapper, label_ids)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
@ -8,5 +8,7 @@ use crate::{
|
||||
#[async_trait]
|
||||
pub trait PostRepository: Send + Sync {
|
||||
async fn get_all_post_info(&self, is_published_only: bool) -> Result<Vec<PostInfo>, PostError>;
|
||||
async fn get_full_post(&self, id: i32) -> Result<Post, PostError>;
|
||||
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>;
|
||||
}
|
||||
|
@ -1,5 +1,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 update_label_use_case;
|
||||
pub mod update_post_use_case;
|
||||
|
@ -0,0 +1,32 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::{
|
||||
application::{error::post_error::PostError, gateway::post_repository::PostRepository},
|
||||
domain::entity::post::Post,
|
||||
};
|
||||
|
||||
#[async_trait]
|
||||
pub trait CreatePostUseCase: Send + Sync {
|
||||
async fn execute(&self, post: Post, label_ids: &[i32]) -> Result<i32, PostError>;
|
||||
}
|
||||
|
||||
pub struct CreatePostUseCaseImpl {
|
||||
post_repository: Arc<dyn PostRepository>,
|
||||
}
|
||||
|
||||
impl CreatePostUseCaseImpl {
|
||||
pub fn new(post_repository: Arc<dyn PostRepository>) -> Self {
|
||||
Self { post_repository }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl CreatePostUseCase for CreatePostUseCaseImpl {
|
||||
async fn execute(&self, post: Post, label_ids: &[i32]) -> Result<i32, PostError> {
|
||||
self.post_repository
|
||||
.create_post(post, label_ids)
|
||||
.await
|
||||
}
|
||||
}
|
@ -25,6 +25,6 @@ impl GetFullPostUseCaseImpl {
|
||||
#[async_trait]
|
||||
impl GetFullPostUseCase for GetFullPostUseCaseImpl {
|
||||
async fn execute(&self, id: i32) -> Result<Post, PostError> {
|
||||
self.post_repository.get_full_post(id).await
|
||||
self.post_repository.get_post_by_id(id).await
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::{
|
||||
application::{error::post_error::PostError, gateway::post_repository::PostRepository},
|
||||
domain::entity::post::Post,
|
||||
};
|
||||
|
||||
#[async_trait]
|
||||
pub trait UpdatePostUseCase: Send + Sync {
|
||||
async fn execute(&self, post: Post, label_ids: &[i32]) -> Result<(), PostError>;
|
||||
}
|
||||
|
||||
pub struct UpdatePostUseCaseImpl {
|
||||
post_repository: Arc<dyn PostRepository>,
|
||||
}
|
||||
|
||||
impl UpdatePostUseCaseImpl {
|
||||
pub fn new(post_repository: Arc<dyn PostRepository>) -> Self {
|
||||
Self { post_repository }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl UpdatePostUseCase for UpdatePostUseCaseImpl {
|
||||
async fn execute(&self, post: Post, label_ids: &[i32]) -> Result<(), PostError> {
|
||||
self.post_repository.update_post(post, label_ids).await
|
||||
}
|
||||
}
|
@ -5,8 +5,8 @@ use sqlx::{Pool, Postgres};
|
||||
|
||||
use crate::{
|
||||
adapter::gateway::{
|
||||
color_db_mapper::ColorMapper, label_db_mapper::LabelMapper, post_db_service::PostDbService,
|
||||
post_info_db_mapper::PostInfoMapper, post_db_mapper::PostMapper,
|
||||
color_db_mapper::ColorMapper, label_db_mapper::LabelMapper, post_db_mapper::PostMapper,
|
||||
post_db_service::PostDbService, post_info_db_mapper::PostInfoMapper,
|
||||
},
|
||||
application::error::post_error::PostError,
|
||||
};
|
||||
@ -105,7 +105,7 @@ impl PostDbService for PostDbServiceImpl {
|
||||
Ok(ordered_posts)
|
||||
}
|
||||
|
||||
async fn get_full_post(&self, id: i32) -> Result<PostMapper, PostError> {
|
||||
async fn get_post_by_id(&self, id: i32) -> Result<PostMapper, PostError> {
|
||||
let mut query_builder = sqlx::QueryBuilder::new(
|
||||
r#"
|
||||
SELECT
|
||||
@ -182,4 +182,119 @@ impl PostDbService for PostDbServiceImpl {
|
||||
None => Err(PostError::NotFound),
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_post(&self, post: PostMapper, label_ids: &[i32]) -> Result<i32, PostError> {
|
||||
let mut tx = self
|
||||
.db_pool
|
||||
.begin()
|
||||
.await
|
||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
||||
|
||||
let post_id = sqlx::query_scalar!(
|
||||
r#"
|
||||
INSERT INTO post (
|
||||
title, description, preview_image_url, content, published_time
|
||||
) VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id
|
||||
"#,
|
||||
post.info.title,
|
||||
post.info.description,
|
||||
post.info.preview_image_url,
|
||||
post.content,
|
||||
post.info.published_time,
|
||||
)
|
||||
.fetch_one(&mut *tx)
|
||||
.await
|
||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
||||
|
||||
for label_id in label_ids {
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO post_label (
|
||||
post_id, label_id
|
||||
) VALUES ($1, $2)
|
||||
ON CONFLICT DO NOTHING
|
||||
"#,
|
||||
post_id,
|
||||
label_id,
|
||||
)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
||||
}
|
||||
|
||||
tx.commit()
|
||||
.await
|
||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
||||
|
||||
Ok(post_id)
|
||||
}
|
||||
|
||||
async fn update_post(&self, post: PostMapper, label_ids: &[i32]) -> Result<(), PostError> {
|
||||
let mut tx = self
|
||||
.db_pool
|
||||
.begin()
|
||||
.await
|
||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
||||
|
||||
let affected_rows = sqlx::query!(
|
||||
r#"
|
||||
UPDATE post
|
||||
SET
|
||||
title = $1,
|
||||
description = $2,
|
||||
preview_image_url = $3,
|
||||
content = $4,
|
||||
published_time = $5
|
||||
WHERE id = $6
|
||||
"#,
|
||||
post.info.title,
|
||||
post.info.description,
|
||||
post.info.preview_image_url,
|
||||
post.content,
|
||||
post.info.published_time,
|
||||
post.id,
|
||||
)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?
|
||||
.rows_affected();
|
||||
|
||||
if affected_rows == 0 {
|
||||
return Err(PostError::NotFound);
|
||||
}
|
||||
|
||||
sqlx::query!(
|
||||
r#"
|
||||
DELETE FROM post_label
|
||||
WHERE post_id = $1
|
||||
"#,
|
||||
post.id,
|
||||
)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
||||
|
||||
for label_id in label_ids {
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO post_label (
|
||||
post_id, label_id
|
||||
) VALUES ($1, $2)
|
||||
ON CONFLICT DO NOTHING
|
||||
"#,
|
||||
post.id,
|
||||
label_id,
|
||||
)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
||||
}
|
||||
|
||||
tx.commit()
|
||||
.await
|
||||
.map_err(|err| PostError::DatabaseError(err.to_string()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,9 @@ pub mod post_api_doc;
|
||||
pub mod post_web_routes;
|
||||
|
||||
mod create_label_handler;
|
||||
mod create_post_handler;
|
||||
mod get_all_labels_handler;
|
||||
mod get_all_post_info_handler;
|
||||
mod get_post_by_id_handler;
|
||||
mod update_label_handler;
|
||||
mod update_post_handler;
|
||||
|
@ -0,0 +1,35 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use auth::framework::web::auth_middleware::UserId;
|
||||
|
||||
use crate::adapter::delivery::{
|
||||
create_post_request_dto::CreatePostRequestDto, post_controller::PostController,
|
||||
post_response_dto::PostResponseDto,
|
||||
};
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/post",
|
||||
tag = "post",
|
||||
summary = "Create a new post",
|
||||
responses(
|
||||
(status = 201, body = PostResponseDto),
|
||||
),
|
||||
security(
|
||||
("oauth2" = [])
|
||||
)
|
||||
)]
|
||||
pub async fn create_post_handler(
|
||||
post_controller: web::Data<dyn PostController>,
|
||||
post_dto: web::Json<CreatePostRequestDto>,
|
||||
_: UserId,
|
||||
) -> impl Responder {
|
||||
let result = post_controller.create_post(post_dto.into_inner()).await;
|
||||
|
||||
match result {
|
||||
Ok(post) => HttpResponse::Created().json(post),
|
||||
Err(e) => {
|
||||
log::error!("{e:?}");
|
||||
HttpResponse::InternalServerError().finish()
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
use crate::framework::web::{
|
||||
create_label_handler, get_all_labels_handler, get_all_post_info_handler,
|
||||
get_post_by_id_handler, update_label_handler,
|
||||
create_label_handler, create_post_handler, get_all_labels_handler, get_all_post_info_handler,
|
||||
get_post_by_id_handler, update_label_handler, update_post_handler,
|
||||
};
|
||||
use utoipa::{OpenApi, openapi};
|
||||
|
||||
@ -8,6 +8,8 @@ use utoipa::{OpenApi, openapi};
|
||||
#[openapi(paths(
|
||||
get_all_post_info_handler::get_all_post_info_handler,
|
||||
get_post_by_id_handler::get_post_by_id_handler,
|
||||
create_post_handler::create_post_handler,
|
||||
update_post_handler::update_post_handler,
|
||||
create_label_handler::create_label_handler,
|
||||
update_label_handler::update_label_handler,
|
||||
get_all_labels_handler::get_all_labels_handler
|
||||
|
@ -1,16 +1,20 @@
|
||||
use actix_web::web;
|
||||
|
||||
use crate::framework::web::{
|
||||
create_label_handler::create_label_handler, get_all_labels_handler::get_all_labels_handler,
|
||||
create_label_handler::create_label_handler, create_post_handler::create_post_handler,
|
||||
get_all_labels_handler::get_all_labels_handler,
|
||||
get_all_post_info_handler::get_all_post_info_handler,
|
||||
get_post_by_id_handler::get_post_by_id_handler, update_label_handler::update_label_handler,
|
||||
update_post_handler::update_post_handler,
|
||||
};
|
||||
|
||||
pub fn configure_post_routes(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(
|
||||
web::scope("/post")
|
||||
.route("", web::get().to(get_all_post_info_handler))
|
||||
.route("/{id}", web::get().to(get_post_by_id_handler)),
|
||||
.route("", web::post().to(create_post_handler))
|
||||
.route("/{id}", web::get().to(get_post_by_id_handler))
|
||||
.route("/{id}", web::put().to(update_post_handler)),
|
||||
);
|
||||
|
||||
cfg.service(
|
||||
|
@ -0,0 +1,42 @@
|
||||
use actix_web::{HttpResponse, Responder, web};
|
||||
use auth::framework::web::auth_middleware::UserId;
|
||||
|
||||
use crate::adapter::delivery::{
|
||||
post_controller::PostController, post_response_dto::PostResponseDto,
|
||||
update_post_request_dto::UpdatePostRequestDto,
|
||||
};
|
||||
|
||||
#[utoipa::path(
|
||||
put,
|
||||
path = "/post/{id}",
|
||||
tag = "post",
|
||||
summary = "Update a post by ID",
|
||||
responses(
|
||||
(status = 200, body = PostResponseDto),
|
||||
),
|
||||
security(
|
||||
("oauth2" = [])
|
||||
)
|
||||
)]
|
||||
pub async fn update_post_handler(
|
||||
post_controller: web::Data<dyn PostController>,
|
||||
path: web::Path<i32>,
|
||||
post_dto: web::Json<UpdatePostRequestDto>,
|
||||
_: UserId,
|
||||
) -> impl Responder {
|
||||
let id = path.into_inner();
|
||||
let result = post_controller.update_post(id, post_dto.into_inner()).await;
|
||||
|
||||
match result {
|
||||
Ok(post) => HttpResponse::Ok().json(post),
|
||||
Err(e) => {
|
||||
log::error!("{e:?}");
|
||||
match e {
|
||||
crate::application::error::post_error::PostError::NotFound => {
|
||||
HttpResponse::NotFound().finish()
|
||||
}
|
||||
_ => HttpResponse::InternalServerError().finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -37,10 +37,12 @@ use post::{
|
||||
},
|
||||
application::use_case::{
|
||||
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,
|
||||
},
|
||||
framework::db::{
|
||||
label_db_service_impl::LabelDbServiceImpl, post_db_service_impl::PostDbServiceImpl,
|
||||
@ -96,6 +98,8 @@ 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 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()));
|
||||
let update_label_use_case = Arc::new(UpdateLabelUseCaseImpl::new(label_repository.clone()));
|
||||
let get_all_labels_use_case =
|
||||
@ -104,6 +108,8 @@ impl Container {
|
||||
let post_controller = Arc::new(PostControllerImpl::new(
|
||||
get_all_post_info_use_case,
|
||||
get_full_post_use_case,
|
||||
create_post_use_case,
|
||||
update_post_use_case,
|
||||
create_label_use_case,
|
||||
update_label_use_case,
|
||||
get_all_labels_use_case,
|
||||
|
Loading…
x
Reference in New Issue
Block a user