use super::{AppError, UserData}; use axum::{ body::Body, extract::State, http::Request, middleware::Next, response::{IntoResponse, Redirect}, }; use axum_extra::TypedHeader; use chrono::Utc; use headers::Cookie; use sqlx::SqlitePool; pub async fn inject_user_data( State(db_pool): State, cookie: Option>, mut request: Request, next: Next, ) -> Result { if let Some(cookie) = cookie { if let Some(session_token) = cookie.get("session_token") { let session_token: Vec<&str> = session_token.split('_').collect(); let query: Result<(i64, i64, String), _> = sqlx::query_as( r#"SELECT user_id,expires_at,session_token_p2 FROM user_sessions WHERE session_token_p1=?"#, ) .bind(session_token[0]) .fetch_one(&db_pool) .await; if let Ok(query) = query { if let Ok(session_token_p2_db) = query.2.as_bytes().try_into() { if let Ok(session_token_p2_cookie) = session_token .get(1) .copied() .unwrap_or_default() .as_bytes() .try_into() { if constant_time_eq::constant_time_eq_n::<36>( session_token_p2_cookie, session_token_p2_db, ) { let id = query.0; let expires_at = query.1; if expires_at > Utc::now().timestamp() { let query: Result<(String,), _> = sqlx::query_as(r#"SELECT email FROM users WHERE id=?"#) .bind(id) .fetch_one(&db_pool) .await; if let Ok(query) = query { let email = query.0; request.extensions_mut().insert(Some(UserData { id, email, })); } } } } } } } } Ok(next.run(request).await) } pub async fn check_auth(request: Request, next: Next) -> Result { if request .extensions() .get::>() .ok_or("check_auth: extensions have no UserData")? .is_some() { Ok(next.run(request).await) } else { let login_url = "/login?return_url=".to_owned() + &*request.uri().to_string(); Ok(Redirect::to(login_url.as_str()).into_response()) } }