diff --git a/backend/feature/label/src/adapter/delivery/label_controller.rs b/backend/feature/label/src/adapter/delivery/label_controller.rs index e931adb..3b8376c 100644 --- a/backend/feature/label/src/adapter/delivery/label_controller.rs +++ b/backend/feature/label/src/adapter/delivery/label_controller.rs @@ -12,6 +12,7 @@ use crate::{ use_case::{ create_label_use_case::CreateLabelUseCase, get_all_labels_use_case::GetAllLabelsUseCase, + get_label_by_id_use_case::GetLabelByIdUseCase, update_label_use_case::UpdateLabelUseCase, }, }, @@ -31,12 +32,15 @@ pub trait LabelController: Send + Sync { ) -> Result; async fn get_all_labels(&self) -> Result, LabelError>; + + async fn get_label_by_id(&self, id: i32) -> Result; } pub struct LabelControllerImpl { create_label_use_case: Arc, update_label_use_case: Arc, get_all_labels_use_case: Arc, + get_label_by_id_use_case: Arc, } impl LabelControllerImpl { @@ -44,11 +48,13 @@ impl LabelControllerImpl { create_label_use_case: Arc, update_label_use_case: Arc, get_all_labels_use_case: Arc, + get_label_by_id_use_case: Arc, ) -> Self { Self { create_label_use_case, update_label_use_case, get_all_labels_use_case, + get_label_by_id_use_case, } } } @@ -83,13 +89,17 @@ impl LabelController for LabelControllerImpl { } async fn get_all_labels(&self) -> Result, LabelError> { - let result = self.get_all_labels_use_case.execute().await; + let result = self.get_all_labels_use_case.execute().await?; - result.map(|labels| { - labels - .into_iter() - .map(|label| LabelResponseDto::from(label)) - .collect() - }) + Ok(result + .into_iter() + .map(|label| LabelResponseDto::from(label)) + .collect()) + } + + async fn get_label_by_id(&self, id: i32) -> Result { + let label = self.get_label_by_id_use_case.execute(id).await?; + + Ok(LabelResponseDto::from(label)) } } diff --git a/backend/feature/label/src/application/use_case.rs b/backend/feature/label/src/application/use_case.rs index 883d99d..8046cc4 100644 --- a/backend/feature/label/src/application/use_case.rs +++ b/backend/feature/label/src/application/use_case.rs @@ -1,3 +1,4 @@ pub mod create_label_use_case; pub mod get_all_labels_use_case; +pub mod get_label_by_id_use_case; pub mod update_label_use_case; diff --git a/backend/feature/label/src/application/use_case/get_label_by_id_use_case.rs b/backend/feature/label/src/application/use_case/get_label_by_id_use_case.rs new file mode 100644 index 0000000..8b15eee --- /dev/null +++ b/backend/feature/label/src/application/use_case/get_label_by_id_use_case.rs @@ -0,0 +1,30 @@ +use std::sync::Arc; + +use async_trait::async_trait; + +use crate::{ + application::{error::label_error::LabelError, gateway::label_repository::LabelRepository}, + domain::entity::label::Label, +}; + +#[async_trait] +pub trait GetLabelByIdUseCase: Send + Sync { + async fn execute(&self, id: i32) -> Result; +} + +pub struct GetLabelByIdUseCaseImpl { + repository: Arc, +} + +impl GetLabelByIdUseCaseImpl { + pub fn new(repository: Arc) -> Self { + Self { repository } + } +} + +#[async_trait] +impl GetLabelByIdUseCase for GetLabelByIdUseCaseImpl { + async fn execute(&self, id: i32) -> Result { + self.repository.get_label_by_id(id).await + } +} diff --git a/backend/feature/label/src/framework/web.rs b/backend/feature/label/src/framework/web.rs index d9c80eb..f0d4ba8 100644 --- a/backend/feature/label/src/framework/web.rs +++ b/backend/feature/label/src/framework/web.rs @@ -1,5 +1,6 @@ pub mod create_label_handler; pub mod get_all_labels_handler; +pub mod get_label_by_id_handler; pub mod label_api_doc; pub mod label_web_routes; pub mod update_label_handler; diff --git a/backend/feature/label/src/framework/web/get_label_by_id_handler.rs b/backend/feature/label/src/framework/web/get_label_by_id_handler.rs new file mode 100644 index 0000000..03e0ed3 --- /dev/null +++ b/backend/feature/label/src/framework/web/get_label_by_id_handler.rs @@ -0,0 +1,41 @@ +use actix_web::{HttpResponse, Responder, web}; +use anyhow::anyhow; +use sentry::integrations::anyhow::capture_anyhow; + +use crate::{ + adapter::delivery::{label_controller::LabelController, label_response_dto::LabelResponseDto}, + application::error::label_error::LabelError, +}; + +#[utoipa::path( + get, + path = "/label/{id}", + tag = "label", + summary = "Get the label by ID", + responses( + (status = 200, body = LabelResponseDto), + (status = 404, description = LabelError::NotFound), + ) +)] +pub async fn get_label_by_id_handler( + label_controller: web::Data, + path: web::Path, +) -> impl Responder { + let id = path.into_inner(); + let result = label_controller.get_label_by_id(id).await; + + match result { + Ok(labels) => HttpResponse::Ok().json(labels), + Err(e) => match e { + LabelError::NotFound => HttpResponse::NotFound().finish(), + LabelError::Unauthorized | LabelError::DuplicatedLabelName => { + capture_anyhow(&anyhow!(e)); + HttpResponse::InternalServerError().finish() + } + LabelError::Unexpected(e) => { + capture_anyhow(&e); + HttpResponse::InternalServerError().finish() + } + }, + } +} diff --git a/backend/feature/label/src/framework/web/label_api_doc.rs b/backend/feature/label/src/framework/web/label_api_doc.rs index 5e44d95..66feea6 100644 --- a/backend/feature/label/src/framework/web/label_api_doc.rs +++ b/backend/feature/label/src/framework/web/label_api_doc.rs @@ -1,11 +1,14 @@ -use crate::framework::web::{create_label_handler, get_all_labels_handler, update_label_handler}; +use crate::framework::web::{ + create_label_handler, get_all_labels_handler, get_label_by_id_handler, update_label_handler, +}; use utoipa::{OpenApi, openapi}; #[derive(OpenApi)] #[openapi(paths( create_label_handler::create_label_handler, update_label_handler::update_label_handler, - get_all_labels_handler::get_all_labels_handler + get_all_labels_handler::get_all_labels_handler, + get_label_by_id_handler::get_label_by_id_handler ))] struct ApiDoc; diff --git a/backend/feature/label/src/framework/web/label_web_routes.rs b/backend/feature/label/src/framework/web/label_web_routes.rs index f3d2701..9e0a8fb 100644 --- a/backend/feature/label/src/framework/web/label_web_routes.rs +++ b/backend/feature/label/src/framework/web/label_web_routes.rs @@ -2,13 +2,14 @@ use actix_web::web; use crate::framework::web::{ create_label_handler::create_label_handler, get_all_labels_handler::get_all_labels_handler, - update_label_handler::update_label_handler, + get_label_by_id_handler::get_label_by_id_handler, update_label_handler::update_label_handler, }; pub fn configure_label_routes(cfg: &mut web::ServiceConfig) { cfg.service( web::scope("/label") .route("", web::get().to(get_all_labels_handler)) + .route("/{id}", web::get().to(get_label_by_id_handler)) .route("", web::post().to(create_label_handler)) .route("/{id}", web::put().to(update_label_handler)), ); diff --git a/backend/server/src/container.rs b/backend/server/src/container.rs index 287ee33..920f18c 100644 --- a/backend/server/src/container.rs +++ b/backend/server/src/container.rs @@ -35,6 +35,7 @@ use label::{ application::use_case::{ create_label_use_case::CreateLabelUseCaseImpl, get_all_labels_use_case::GetAllLabelsUseCaseImpl, + get_label_by_id_use_case::GetLabelByIdUseCaseImpl, update_label_use_case::UpdateLabelUseCaseImpl, }, framework::db::label_db_service_impl::LabelDbServiceImpl, @@ -104,11 +105,14 @@ impl Container { let update_label_use_case = Arc::new(UpdateLabelUseCaseImpl::new(label_repository.clone())); let get_all_labels_use_case = Arc::new(GetAllLabelsUseCaseImpl::new(label_repository.clone())); + let get_label_by_id_use_case = + Arc::new(GetLabelByIdUseCaseImpl::new(label_repository.clone())); let label_controller = Arc::new(LabelControllerImpl::new( create_label_use_case, update_label_use_case, get_all_labels_use_case, + get_label_by_id_use_case, )); // Post