use axum::{Extension, Json, extract::State, http::StatusCode, response::IntoResponse}; use axum_extra::extract::cookie::CookieJar; use serde_json::json; use crate::{ auth::{AuthenticatedSession, cleared_session_cookie, extract_session_token, session_cookie}, error::ApiError, service::{ChangePasswordPayload, LoginPayload, UpdateProfilePayload}, state::AppState, }; pub async fn login( State(state): State, jar: CookieJar, Json(payload): Json, ) -> Result { let (session_data, session) = state.service.login(payload).await?; let cookie_value = format!( "{}.{}", session_data.session_id.as_str(), session_data.value ); let jar = jar.add(session_cookie(state.service.auth_settings(), &cookie_value)); Ok((jar, Json(serde_json::json!(session)))) } pub async fn logout( State(state): State, jar: CookieJar, ) -> Result { if let Some((session_id, session_value)) = extract_session_token(&jar) { state.service.logout(&session_id, &session_value).await?; } let jar = jar.remove(cleared_session_cookie(state.service.auth_settings())); Ok((jar, StatusCode::NO_CONTENT)) } pub async fn get_session( State(state): State, jar: CookieJar, ) -> Result, ApiError> { let (session_id, session_value) = extract_session_token(&jar) .ok_or_else(|| ApiError::unauthorized("authentication required"))?; let session = state .service .session_response(&session_id, &session_value) .await? .ok_or_else(|| ApiError::unauthorized("session is invalid or expired"))?; Ok(Json(serde_json::json!(session))) } pub async fn get_profile( Extension(session): Extension, ) -> Result, ApiError> { Ok(Json( json!({ "user": session.user, "memberships": session.memberships }), )) } pub async fn update_profile( State(state): State, Extension(session): Extension, Json(payload): Json, ) -> Result, ApiError> { let updated = state .service .update_profile(&session.user.id, payload) .await?; Ok(Json(json!(updated))) } pub async fn change_password( State(state): State, Extension(session): Extension, Json(payload): Json, ) -> Result { state .service .change_password(&session.user.id, payload) .await?; Ok(StatusCode::NO_CONTENT) }