use axum::{ extract::{Request, State}, http::StatusCode, middleware::Next, response::Response, }; use db::repos::api_keys; use shared::models::User; use crate::state::AppState; #[derive(Clone)] pub struct ApiKeyAuth { pub user: User, pub api_key_id: uuid::Uuid, } pub async fn api_key_middleware( State(state): State, mut req: Request, next: Next, ) -> Result { let api_key = req .headers() .get("x-api-key") .and_then(|v| v.to_str().ok()) .ok_or(StatusCode::UNAUTHORIZED)?; let key_hash = format!("{:x}", md5::compute(api_key)); let api_key_record = api_keys::find_by_key_hash(&state.db, &key_hash) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .ok_or(StatusCode::UNAUTHORIZED)?; let user = db::repos::users::find_by_id(&state.db, api_key_record.user_id) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .ok_or(StatusCode::UNAUTHORIZED)?; api_keys::update_last_used(&state.db, api_key_record.id) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; let auth = ApiKeyAuth { user, api_key_id: api_key_record.id, }; req.extensions_mut().insert(auth); Ok(next.run(req).await) }