refactor: restructure application to CQRS, update api-types + presentation
- application: replace flat use_cases/ with identity/{commands,queries}/ and organization/commands/
- each use case now split into Command/Query struct + Handler struct
- api-types: add username to RegisterRequest/UserResponse, add CreateAlbumRequest/AlbumResponse
- presentation: update state, handlers, factory to use new handler types
- tests: restructured to match CQRS module layout, added get_profile tests
This commit is contained in:
@@ -3,6 +3,7 @@ use api_types::{
|
||||
requests::{LoginRequest, RegisterRequest},
|
||||
responses::{AuthResponse, UserResponse},
|
||||
};
|
||||
use application::identity::{RegisterUserCommand, LoginUserCommand, GetProfileQuery};
|
||||
use crate::{errors::AppError, extractors::{JwtClaims, ValidatedJson}, state::AppState};
|
||||
|
||||
#[utoipa::path(
|
||||
@@ -18,7 +19,12 @@ pub async fn register(
|
||||
State(state): State<AppState>,
|
||||
ValidatedJson(req): ValidatedJson<RegisterRequest>,
|
||||
) -> Result<(StatusCode, Json<AuthResponse>), AppError> {
|
||||
let user = state.register_uc.execute(&req.email, &req.password).await?;
|
||||
let cmd = RegisterUserCommand {
|
||||
username: req.username,
|
||||
email: req.email,
|
||||
password: req.password,
|
||||
};
|
||||
let user = state.register_handler.execute(cmd).await?;
|
||||
let token = state.token_issuer.issue(&user.id, "user").await.map_err(AppError::from)?;
|
||||
Ok((StatusCode::CREATED, Json(AuthResponse { token, user: UserResponse::from_domain(&user) })))
|
||||
}
|
||||
@@ -35,7 +41,11 @@ pub async fn login(
|
||||
State(state): State<AppState>,
|
||||
ValidatedJson(req): ValidatedJson<LoginRequest>,
|
||||
) -> Result<Json<AuthResponse>, AppError> {
|
||||
let (user, token) = state.login_uc.execute(&req.email, &req.password).await?;
|
||||
let cmd = LoginUserCommand {
|
||||
email: req.email,
|
||||
password: req.password,
|
||||
};
|
||||
let (user, token) = state.login_handler.execute(cmd).await?;
|
||||
Ok(Json(AuthResponse { token, user: UserResponse::from_domain(&user) }))
|
||||
}
|
||||
|
||||
@@ -51,6 +61,7 @@ pub async fn me(
|
||||
State(state): State<AppState>,
|
||||
claims: JwtClaims,
|
||||
) -> Result<Json<UserResponse>, AppError> {
|
||||
let user = state.get_profile_uc.execute(&claims.user_id).await?;
|
||||
let query = GetProfileQuery { user_id: claims.user_id };
|
||||
let user = state.get_profile_handler.execute(query).await?;
|
||||
Ok(Json(UserResponse::from_domain(&user)))
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
use std::sync::Arc;
|
||||
use application::use_cases::{GetProfile, LoginUser, RegisterUser};
|
||||
use application::identity::{RegisterUserHandler, LoginUserHandler, GetProfileHandler};
|
||||
|
||||
use domain::ports::{StoragePort, TokenIssuer};
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AppState {
|
||||
pub register_uc: Arc<RegisterUser>,
|
||||
pub login_uc: Arc<LoginUser>,
|
||||
pub get_profile_uc: Arc<GetProfile>,
|
||||
pub register_handler: Arc<RegisterUserHandler>,
|
||||
pub login_handler: Arc<LoginUserHandler>,
|
||||
pub get_profile_handler: Arc<GetProfileHandler>,
|
||||
pub token_issuer: Arc<dyn TokenIssuer>,
|
||||
pub storage: Arc<dyn StoragePort>,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
pub fn new(
|
||||
register_uc: Arc<RegisterUser>,
|
||||
login_uc: Arc<LoginUser>,
|
||||
get_profile_uc: Arc<GetProfile>,
|
||||
register_handler: Arc<RegisterUserHandler>,
|
||||
login_handler: Arc<LoginUserHandler>,
|
||||
get_profile_handler: Arc<GetProfileHandler>,
|
||||
token_issuer: Arc<dyn TokenIssuer>,
|
||||
storage: Arc<dyn StoragePort>,
|
||||
) -> Self {
|
||||
Self { register_uc, login_uc, get_profile_uc, token_issuer, storage }
|
||||
Self { register_handler, login_handler, get_profile_handler, token_issuer, storage }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user