From 27c23367add594d7096c4792f74b0df9d7fa1a3f Mon Sep 17 00:00:00 2001 From: SquidSpirit Date: Sat, 2 Aug 2025 13:31:23 +0800 Subject: [PATCH] BLOG-104 feat: create and update post functionality with corresponding DTOs and handlers --- backend/feature/post/src/adapter/delivery.rs | 2 + .../delivery/create_post_request_dto.rs | 37 ++++++ .../src/adapter/delivery/post_controller.rs | 48 ++++++- .../delivery/update_post_request_dto.rs | 37 ++++++ .../src/adapter/gateway/post_db_service.rs | 6 +- .../adapter/gateway/post_repository_impl.rs | 47 ++++++- .../application/gateway/post_repository.rs | 4 +- .../feature/post/src/application/use_case.rs | 2 + .../use_case/create_post_use_case.rs | 32 +++++ .../use_case/get_full_post_use_case.rs | 2 +- .../use_case/update_post_use_case.rs | 30 +++++ .../src/framework/db/post_db_service_impl.rs | 121 +++++++++++++++++- backend/feature/post/src/framework/web.rs | 2 + .../src/framework/web/create_post_handler.rs | 35 +++++ .../post/src/framework/web/post_api_doc.rs | 6 +- .../post/src/framework/web/post_web_routes.rs | 8 +- .../src/framework/web/update_post_handler.rs | 42 ++++++ backend/server/src/container.rs | 6 + 18 files changed, 452 insertions(+), 15 deletions(-) create mode 100644 backend/feature/post/src/adapter/delivery/create_post_request_dto.rs create mode 100644 backend/feature/post/src/adapter/delivery/update_post_request_dto.rs create mode 100644 backend/feature/post/src/application/use_case/create_post_use_case.rs create mode 100644 backend/feature/post/src/application/use_case/update_post_use_case.rs create mode 100644 backend/feature/post/src/framework/web/create_post_handler.rs create mode 100644 backend/feature/post/src/framework/web/update_post_handler.rs diff --git a/backend/feature/post/src/adapter/delivery.rs b/backend/feature/post/src/adapter/delivery.rs index c9d70c0..67542af 100644 --- a/backend/feature/post/src/adapter/delivery.rs +++ b/backend/feature/post/src/adapter/delivery.rs @@ -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; diff --git a/backend/feature/post/src/adapter/delivery/create_post_request_dto.rs b/backend/feature/post/src/adapter/delivery/create_post_request_dto.rs new file mode 100644 index 0000000..9c273d2 --- /dev/null +++ b/backend/feature/post/src/adapter/delivery/create_post_request_dto.rs @@ -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, + + #[schema(required)] + pub published_time: Option, +} + +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::::from_timestamp_micros(micros)) + .flatten(), + }, + content: self.content, + } + } +} diff --git a/backend/feature/post/src/adapter/delivery/post_controller.rs b/backend/feature/post/src/adapter/delivery/post_controller.rs index 1b94cb5..736d765 100644 --- a/backend/feature/post/src/adapter/delivery/post_controller.rs +++ b/backend/feature/post/src/adapter/delivery/post_controller.rs @@ -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; + async fn create_post(&self, post: CreatePostRequestDto) -> Result; + + async fn update_post( + &self, + id: i32, + post: UpdatePostRequestDto, + ) -> Result; + 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, get_full_post_use_case: Arc, + create_post_use_case: Arc, + update_post_use_case: Arc, create_label_use_case: Arc, update_label_use_case: Arc, get_all_labels_use_case: Arc, @@ -58,6 +71,8 @@ impl PostControllerImpl { pub fn new( get_all_post_info_use_case: Arc, get_full_post_use_case: Arc, + create_post_use_case: Arc, + update_post_use_case: Arc, create_label_use_case: Arc, update_label_use_case: Arc, get_all_labels_use_case: Arc, @@ -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 { + 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 { + 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 + } } diff --git a/backend/feature/post/src/adapter/delivery/update_post_request_dto.rs b/backend/feature/post/src/adapter/delivery/update_post_request_dto.rs new file mode 100644 index 0000000..f7f3683 --- /dev/null +++ b/backend/feature/post/src/adapter/delivery/update_post_request_dto.rs @@ -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, + + #[schema(required)] + pub published_time: Option, +} + +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::::from_timestamp_micros(micros)) + .flatten(), + }, + content: self.content, + } + } +} diff --git a/backend/feature/post/src/adapter/gateway/post_db_service.rs b/backend/feature/post/src/adapter/gateway/post_db_service.rs index 489a0b2..ff330b8 100644 --- a/backend/feature/post/src/adapter/gateway/post_db_service.rs +++ b/backend/feature/post/src/adapter/gateway/post_db_service.rs @@ -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, PostError>; - async fn get_full_post(&self, id: i32) -> Result; + async fn get_post_by_id(&self, id: i32) -> Result; + async fn create_post(&self, post: PostMapper, label_ids: &[i32]) -> Result; + async fn update_post(&self, post: PostMapper, label_ids: &[i32]) -> Result<(), PostError>; } diff --git a/backend/feature/post/src/adapter/gateway/post_repository_impl.rs b/backend/feature/post/src/adapter/gateway/post_repository_impl.rs index 6b9da9c..6fb0f97 100644 --- a/backend/feature/post/src/adapter/gateway/post_repository_impl.rs +++ b/backend/feature/post/src/adapter/gateway/post_repository_impl.rs @@ -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 { + async fn get_post_by_id(&self, id: i32) -> Result { 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 { + 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 + } } diff --git a/backend/feature/post/src/application/gateway/post_repository.rs b/backend/feature/post/src/application/gateway/post_repository.rs index 4e6c9e5..36f910e 100644 --- a/backend/feature/post/src/application/gateway/post_repository.rs +++ b/backend/feature/post/src/application/gateway/post_repository.rs @@ -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, PostError>; - async fn get_full_post(&self, id: i32) -> Result; + async fn get_post_by_id(&self, id: i32) -> Result; + async fn create_post(&self, post: Post, label_ids: &[i32]) -> Result; + async fn update_post(&self, post: Post, label_ids: &[i32]) -> Result<(), PostError>; } diff --git a/backend/feature/post/src/application/use_case.rs b/backend/feature/post/src/application/use_case.rs index c523e59..88d3d50 100644 --- a/backend/feature/post/src/application/use_case.rs +++ b/backend/feature/post/src/application/use_case.rs @@ -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; diff --git a/backend/feature/post/src/application/use_case/create_post_use_case.rs b/backend/feature/post/src/application/use_case/create_post_use_case.rs new file mode 100644 index 0000000..892f9a7 --- /dev/null +++ b/backend/feature/post/src/application/use_case/create_post_use_case.rs @@ -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; +} + +pub struct CreatePostUseCaseImpl { + post_repository: Arc, +} + +impl CreatePostUseCaseImpl { + pub fn new(post_repository: Arc) -> Self { + Self { post_repository } + } +} + +#[async_trait] +impl CreatePostUseCase for CreatePostUseCaseImpl { + async fn execute(&self, post: Post, label_ids: &[i32]) -> Result { + self.post_repository + .create_post(post, label_ids) + .await + } +} diff --git a/backend/feature/post/src/application/use_case/get_full_post_use_case.rs b/backend/feature/post/src/application/use_case/get_full_post_use_case.rs index fe882b0..9fe345f 100644 --- a/backend/feature/post/src/application/use_case/get_full_post_use_case.rs +++ b/backend/feature/post/src/application/use_case/get_full_post_use_case.rs @@ -25,6 +25,6 @@ impl GetFullPostUseCaseImpl { #[async_trait] impl GetFullPostUseCase for GetFullPostUseCaseImpl { async fn execute(&self, id: i32) -> Result { - self.post_repository.get_full_post(id).await + self.post_repository.get_post_by_id(id).await } } diff --git a/backend/feature/post/src/application/use_case/update_post_use_case.rs b/backend/feature/post/src/application/use_case/update_post_use_case.rs new file mode 100644 index 0000000..295cdba --- /dev/null +++ b/backend/feature/post/src/application/use_case/update_post_use_case.rs @@ -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, +} + +impl UpdatePostUseCaseImpl { + pub fn new(post_repository: Arc) -> 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 + } +} diff --git a/backend/feature/post/src/framework/db/post_db_service_impl.rs b/backend/feature/post/src/framework/db/post_db_service_impl.rs index a6e3948..9d31551 100644 --- a/backend/feature/post/src/framework/db/post_db_service_impl.rs +++ b/backend/feature/post/src/framework/db/post_db_service_impl.rs @@ -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 { + async fn get_post_by_id(&self, id: i32) -> Result { 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 { + 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(()) + } } diff --git a/backend/feature/post/src/framework/web.rs b/backend/feature/post/src/framework/web.rs index b826afd..f066568 100644 --- a/backend/feature/post/src/framework/web.rs +++ b/backend/feature/post/src/framework/web.rs @@ -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; diff --git a/backend/feature/post/src/framework/web/create_post_handler.rs b/backend/feature/post/src/framework/web/create_post_handler.rs new file mode 100644 index 0000000..c26a6b9 --- /dev/null +++ b/backend/feature/post/src/framework/web/create_post_handler.rs @@ -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, + post_dto: web::Json, + _: 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() + } + } +} diff --git a/backend/feature/post/src/framework/web/post_api_doc.rs b/backend/feature/post/src/framework/web/post_api_doc.rs index 42cf667..9353710 100644 --- a/backend/feature/post/src/framework/web/post_api_doc.rs +++ b/backend/feature/post/src/framework/web/post_api_doc.rs @@ -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 diff --git a/backend/feature/post/src/framework/web/post_web_routes.rs b/backend/feature/post/src/framework/web/post_web_routes.rs index a42d4ac..220b1ee 100644 --- a/backend/feature/post/src/framework/web/post_web_routes.rs +++ b/backend/feature/post/src/framework/web/post_web_routes.rs @@ -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( diff --git a/backend/feature/post/src/framework/web/update_post_handler.rs b/backend/feature/post/src/framework/web/update_post_handler.rs new file mode 100644 index 0000000..62a5857 --- /dev/null +++ b/backend/feature/post/src/framework/web/update_post_handler.rs @@ -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, + path: web::Path, + post_dto: web::Json, + _: 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(), + } + } + } +} diff --git a/backend/server/src/container.rs b/backend/server/src/container.rs index b787292..d8685da 100644 --- a/backend/server/src/container.rs +++ b/backend/server/src/container.rs @@ -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,