use axum::{
extract::State,
response::IntoResponse,
Json,
};
use cookie::{Cookie, SameSite};
use serde::{Deserialize, Serialize};
use validator::Validate;
use crate::error::Result;
use crate::state::AppState;
use crate::auth::ports::AuthUser;
#[derive(Debug, Deserialize, Validate)]
pub struct LoginRequest {
#[validate(email)]
pub email: String,
#[validate(length(min = 8))]
pub password: String,
}
#[derive(Debug, Serialize)]
pub struct LoginResponse {
pub user: UserInfo,
}
#[derive(Debug, Serialize)]
pub struct UserInfo {
pub id: i64,
pub email: String,
pub role: String,
}
impl From<AuthUser> for UserInfo {
fn from(user: AuthUser) -> Self {
Self {
id: user.id,
email: user.email,
role: user.role,
}
}
}
pub async fn infra_login(
State(state): State<AppState>,
Json(req): Json<LoginRequest>,
) -> Result<impl IntoResponse> {
req.validate()?;
let user = state.infra_auth.authenticate(&req.email, &req.password).await?;
let session = state.infra_auth.create_session(user.id).await?;
let cookie = Cookie::build(("infra_session", session.token))
.path("/")
.http_only(true)
.same_site(SameSite::Strict)
.max_age(cookie::time::Duration::hours(state.config.auth.session_expiration_hours))
.build();
let response = LoginResponse {
user: user.into(),
};
use axum::response::AppendHeaders;
Ok((
AppendHeaders([(axum::http::header::SET_COOKIE, cookie.to_string())]),
Json(response),
))
}
pub async fn infra_logout(
State(state): State<AppState>,
axum::extract::Extension(session_token): axum::extract::Extension<String>,
) -> Result<impl IntoResponse> {
state.infra_auth.destroy_session(&session_token).await?;
let cookie = Cookie::build(("infra_session", ""))
.path("/")
.max_age(cookie::time::Duration::ZERO)
.build();
use axum::response::AppendHeaders;
Ok((
AppendHeaders([(axum::http::header::SET_COOKIE, cookie.to_string())]),
Json(serde_json::json!({"message": "Logged out successfully"})),
))
}
pub async fn infra_me(
axum::extract::Extension(user): axum::extract::Extension<AuthUser>,
) -> Result<impl IntoResponse> {
Ok(Json(UserInfo::from(user)))
}