use std::path::PathBuf; use std::sync::Arc; use axum::extract::{FromRef, FromRequestParts}; use axum::http::request::Parts; use crate::config::Config; use crate::error::AppError; /// Extracted from the X-API-Key header on every authenticated request. pub struct AuthenticatedUser { pub slug: String, pub role: String, pub data_dir: PathBuf, } impl FromRequestParts for AuthenticatedUser where S: Send + Sync, Arc: FromRef, { type Rejection = AppError; async fn from_request_parts(parts: &mut Parts, state: &S) -> Result { let config = Arc::::from_ref(state); let api_key = parts .headers .get("X-API-Key") .and_then(|v| v.to_str().ok()) .ok_or(AppError::Unauthorized)?; let slug = config .api_keys .get(api_key) .ok_or(AppError::Unauthorized)?; let user = config .users .iter() .find(|u| u.slug == *slug) .ok_or(AppError::Unauthorized)?; let data_dir = config.data_path.join(slug); tokio::fs::create_dir_all(data_dir.join("open")).await?; tokio::fs::create_dir_all(data_dir.join("done")).await?; Ok(Self { slug: slug.clone(), role: user.role.clone(), data_dir, }) } }