koprogo_api/infrastructure/web/handlers/
auth_handlers.rs

1use crate::application::dto::{LoginRequest, RefreshTokenRequest, RegisterRequest};
2use crate::infrastructure::web::AppState;
3use actix_web::{get, post, web, HttpRequest, HttpResponse, Responder};
4use validator::Validate;
5
6#[post("/auth/login")]
7pub async fn login(data: web::Data<AppState>, request: web::Json<LoginRequest>) -> impl Responder {
8    // Validate request
9    if let Err(errors) = request.validate() {
10        return HttpResponse::BadRequest().json(serde_json::json!({
11            "error": "Validation failed",
12            "details": errors.to_string()
13        }));
14    }
15
16    match data.auth_use_cases.login(request.into_inner()).await {
17        Ok(response) => HttpResponse::Ok().json(response),
18        Err(e) => HttpResponse::Unauthorized().json(serde_json::json!({
19            "error": e
20        })),
21    }
22}
23
24#[post("/auth/register")]
25pub async fn register(
26    data: web::Data<AppState>,
27    request: web::Json<RegisterRequest>,
28) -> impl Responder {
29    // Validate request
30    if let Err(errors) = request.validate() {
31        return HttpResponse::BadRequest().json(serde_json::json!({
32            "error": "Validation failed",
33            "details": errors.to_string()
34        }));
35    }
36
37    match data.auth_use_cases.register(request.into_inner()).await {
38        Ok(response) => HttpResponse::Created().json(response),
39        Err(e) => HttpResponse::BadRequest().json(serde_json::json!({
40            "error": e
41        })),
42    }
43}
44
45#[get("/auth/me")]
46pub async fn get_current_user(data: web::Data<AppState>, req: HttpRequest) -> impl Responder {
47    // Extract Authorization header
48    let auth_header = match req.headers().get("Authorization") {
49        Some(header) => match header.to_str() {
50            Ok(s) => s,
51            Err(_) => {
52                return HttpResponse::BadRequest().json(serde_json::json!({
53                    "error": "Invalid authorization header"
54                }))
55            }
56        },
57        None => {
58            return HttpResponse::Unauthorized().json(serde_json::json!({
59                "error": "Missing authorization header"
60            }))
61        }
62    };
63
64    let token = auth_header.trim_start_matches("Bearer ").trim();
65
66    match data.auth_use_cases.verify_token(token) {
67        Ok(claims) => match uuid::Uuid::parse_str(&claims.sub) {
68            Ok(user_id) => match data.auth_use_cases.get_user_by_id(user_id).await {
69                Ok(user) => HttpResponse::Ok().json(user),
70                Err(e) => HttpResponse::NotFound().json(serde_json::json!({
71                    "error": e
72                })),
73            },
74            Err(e) => HttpResponse::BadRequest().json(serde_json::json!({
75                "error": format!("Invalid user ID: {}", e)
76            })),
77        },
78        Err(e) => HttpResponse::Unauthorized().json(serde_json::json!({
79            "error": e
80        })),
81    }
82}
83
84#[post("/auth/refresh")]
85pub async fn refresh_token(
86    data: web::Data<AppState>,
87    request: web::Json<RefreshTokenRequest>,
88) -> impl Responder {
89    match data
90        .auth_use_cases
91        .refresh_token(request.into_inner())
92        .await
93    {
94        Ok(response) => HttpResponse::Ok().json(response),
95        Err(e) => HttpResponse::Unauthorized().json(serde_json::json!({
96            "error": e
97        })),
98    }
99}