From 6c1b9709538672b689422cd551012f3c51fdfcb7 Mon Sep 17 00:00:00 2001 From: SquidSpirit Date: Fri, 1 Aug 2025 18:38:19 +0800 Subject: [PATCH] BLOG-100 feat: user retrieval functionality in authentication module --- .../src/adapter/delivery/auth_controller.rs | 11 +++++++ .../adapter/gateway/auth_repository_impl.rs | 10 ++++++- .../src/adapter/gateway/user_db_service.rs | 6 +++- .../application/gateway/auth_repository.rs | 2 ++ .../feature/auth/src/application/use_case.rs | 1 + .../application/use_case/get_user_use_case.rs | 30 +++++++++++++++++++ .../src/framework/db/user_db_service_impl.rs | 22 +++++++++++++- .../auth/src/framework/web/auth_web_routes.rs | 15 ++++++++-- backend/server/src/container.rs | 4 ++- 9 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 backend/feature/auth/src/application/use_case/get_user_use_case.rs diff --git a/backend/feature/auth/src/adapter/delivery/auth_controller.rs b/backend/feature/auth/src/adapter/delivery/auth_controller.rs index 0171f6b..d480b6d 100644 --- a/backend/feature/auth/src/adapter/delivery/auth_controller.rs +++ b/backend/feature/auth/src/adapter/delivery/auth_controller.rs @@ -11,6 +11,7 @@ use crate::{ use_case::{ exchange_auth_code_use_case::ExchangeAuthCodeUseCase, get_auth_url_use_case::{AuthUrl, GetAuthUrlUseCase}, + get_user_use_case::GetUserUseCase, }, }, }; @@ -25,21 +26,26 @@ pub trait AuthController: Send + Sync { expected_state: &str, expected_nonce: &str, ) -> Result; + + async fn get_user(&self, user_id: i32) -> Result; } pub struct AuthControllerImpl { get_auth_url_use_case: Arc, exchange_auth_code_use_case: Arc, + get_user_use_case: Arc, } impl AuthControllerImpl { pub fn new( get_auth_url_use_case: Arc, exchange_auth_code_use_case: Arc, + get_user_use_case: Arc, ) -> Self { Self { get_auth_url_use_case, exchange_auth_code_use_case, + get_user_use_case, } } } @@ -63,4 +69,9 @@ impl AuthController for AuthControllerImpl { result.map(|user| UserResponseDto::from(user)) } + + async fn get_user(&self, user_id: i32) -> Result { + let user = self.get_user_use_case.execute(user_id).await?; + Ok(UserResponseDto::from(user)) + } } diff --git a/backend/feature/auth/src/adapter/gateway/auth_repository_impl.rs b/backend/feature/auth/src/adapter/gateway/auth_repository_impl.rs index 4c42eb6..6e2500b 100644 --- a/backend/feature/auth/src/adapter/gateway/auth_repository_impl.rs +++ b/backend/feature/auth/src/adapter/gateway/auth_repository_impl.rs @@ -4,7 +4,8 @@ use async_trait::async_trait; use crate::{ adapter::gateway::{ - auth_oidc_service::AuthOidcService, user_db_service::UserDbService, user_db_mapper::UserMapper, + auth_oidc_service::AuthOidcService, user_db_mapper::UserMapper, + user_db_service::UserDbService, }, application::{ error::auth_error::AuthError, gateway::auth_repository::AuthRepository, @@ -47,6 +48,13 @@ impl AuthRepository for AuthRepositoryImpl { .map(|dto| dto.into_entity()) } + async fn get_user_by_id(&self, user_id: i32) -> Result { + self.user_db_service + .get_user_by_id(user_id) + .await + .map(|mapper| mapper.into_entity()) + } + async fn get_user_by_source_id( &self, issuer: &str, diff --git a/backend/feature/auth/src/adapter/gateway/user_db_service.rs b/backend/feature/auth/src/adapter/gateway/user_db_service.rs index e8b1c40..63054ea 100644 --- a/backend/feature/auth/src/adapter/gateway/user_db_service.rs +++ b/backend/feature/auth/src/adapter/gateway/user_db_service.rs @@ -1,9 +1,13 @@ use async_trait::async_trait; -use crate::{adapter::gateway::user_db_mapper::UserMapper, application::error::auth_error::AuthError}; +use crate::{ + adapter::gateway::user_db_mapper::UserMapper, application::error::auth_error::AuthError, +}; #[async_trait] pub trait UserDbService: Send + Sync { + async fn get_user_by_id(&self, user_id: i32) -> Result; + async fn get_user_by_source_id( &self, issuer: &str, diff --git a/backend/feature/auth/src/application/gateway/auth_repository.rs b/backend/feature/auth/src/application/gateway/auth_repository.rs index c88567c..92f4470 100644 --- a/backend/feature/auth/src/application/gateway/auth_repository.rs +++ b/backend/feature/auth/src/application/gateway/auth_repository.rs @@ -12,6 +12,8 @@ pub trait AuthRepository: Send + Sync { async fn exchange_auth_code(&self, code: &str, expected_nonce: &str) -> Result; + async fn get_user_by_id(&self, user_id: i32) -> Result; + async fn get_user_by_source_id(&self, issuer: &str, source_id: &str) -> Result; diff --git a/backend/feature/auth/src/application/use_case.rs b/backend/feature/auth/src/application/use_case.rs index 7312b52..81d8513 100644 --- a/backend/feature/auth/src/application/use_case.rs +++ b/backend/feature/auth/src/application/use_case.rs @@ -1,2 +1,3 @@ pub mod exchange_auth_code_use_case; pub mod get_auth_url_use_case; +pub mod get_user_use_case; diff --git a/backend/feature/auth/src/application/use_case/get_user_use_case.rs b/backend/feature/auth/src/application/use_case/get_user_use_case.rs new file mode 100644 index 0000000..eba8fe4 --- /dev/null +++ b/backend/feature/auth/src/application/use_case/get_user_use_case.rs @@ -0,0 +1,30 @@ +use std::sync::Arc; + +use async_trait::async_trait; + +use crate::{ + application::{error::auth_error::AuthError, gateway::auth_repository::AuthRepository}, + domain::entity::user::User, +}; + +#[async_trait] +pub trait GetUserUseCase: Send + Sync { + async fn execute(&self, user_id: i32) -> Result; +} + +pub struct GetUserUseCaseImpl { + auth_repository: Arc, +} + +impl GetUserUseCaseImpl { + pub fn new(auth_repository: Arc) -> Self { + Self { auth_repository } + } +} + +#[async_trait] +impl GetUserUseCase for GetUserUseCaseImpl { + async fn execute(&self, user_id: i32) -> Result { + self.auth_repository.get_user_by_id(user_id).await + } +} diff --git a/backend/feature/auth/src/framework/db/user_db_service_impl.rs b/backend/feature/auth/src/framework/db/user_db_service_impl.rs index 6f5cc40..c007d3d 100644 --- a/backend/feature/auth/src/framework/db/user_db_service_impl.rs +++ b/backend/feature/auth/src/framework/db/user_db_service_impl.rs @@ -2,7 +2,7 @@ use async_trait::async_trait; use sqlx::{Pool, Postgres}; use crate::{ - adapter::gateway::{user_db_service::UserDbService, user_db_mapper::UserMapper}, + adapter::gateway::{user_db_mapper::UserMapper, user_db_service::UserDbService}, application::error::auth_error::AuthError, framework::db::user_record::UserRecord, }; @@ -19,6 +19,26 @@ impl UserDbServiceImpl { #[async_trait] impl UserDbService for UserDbServiceImpl { + async fn get_user_by_id(&self, user_id: i32) -> Result { + let record = sqlx::query_as!( + UserRecord, + r#" + SELECT id, issuer, source_id, displayed_name, email + FROM "user" + WHERE id = $1 + "#, + user_id + ) + .fetch_optional(&self.db_pool) + .await + .map_err(|e| AuthError::DatabaseError(e.to_string()))?; + + match record { + Some(record) => Ok(record.into_mapper()), + None => Err(AuthError::UserNotFound), + } + } + async fn get_user_by_source_id( &self, issuer: &str, diff --git a/backend/feature/auth/src/framework/web/auth_web_routes.rs b/backend/feature/auth/src/framework/web/auth_web_routes.rs index 2e06a6a..d5dde49 100644 --- a/backend/feature/auth/src/framework/web/auth_web_routes.rs +++ b/backend/feature/auth/src/framework/web/auth_web_routes.rs @@ -101,6 +101,17 @@ async fn logout_handler(session: Session) -> impl Responder { .finish() } -async fn get_logged_in_user_handler(user_id: UserId) -> impl Responder { - HttpResponse::Ok().body(format!("Logged in user ID: {}", user_id.get())) +async fn get_logged_in_user_handler( + auth_controller: web::Data, + user_id: UserId, +) -> impl Responder { + let result = auth_controller.get_user(user_id.get()).await; + + match result { + Ok(user) => HttpResponse::Ok().json(user), + Err(e) => { + log::error!("{e:?}"); + HttpResponse::InternalServerError().finish() + } + } } diff --git a/backend/server/src/container.rs b/backend/server/src/container.rs index 50be621..8786768 100644 --- a/backend/server/src/container.rs +++ b/backend/server/src/container.rs @@ -7,7 +7,7 @@ use auth::{ }, application::use_case::{ exchange_auth_code_use_case::ExchangeAuthCodeUseCaseImpl, - get_auth_url_use_case::LoginUseCaseImpl, + get_auth_url_use_case::LoginUseCaseImpl, get_user_use_case::GetUserUseCaseImpl, }, framework::{ db::user_db_service_impl::UserDbServiceImpl, @@ -68,9 +68,11 @@ impl Container { let get_auth_url_use_case = Arc::new(LoginUseCaseImpl::new(auth_repository.clone())); let exchange_auth_code_use_case = Arc::new(ExchangeAuthCodeUseCaseImpl::new(auth_repository.clone())); + let get_user_use_case = Arc::new(GetUserUseCaseImpl::new(auth_repository.clone())); let auth_controller = Arc::new(AuthControllerImpl::new( get_auth_url_use_case, exchange_auth_code_use_case, + get_user_use_case, )); let post_db_service = Arc::new(PostDbServiceImpl::new(db_pool.clone()));