oxidite_auth/
api_key_middleware.rs1use oxidite_core::{OxiditeRequest, Result as OxiditeResult, Error};
2use oxidite_db::Database;
3use std::sync::Arc;
4use crate::api_key::ApiKey;
5
6pub struct ApiKeyMiddleware {
8 db: Arc<dyn Database>,
9}
10
11impl ApiKeyMiddleware {
12 pub fn new(db: Arc<dyn Database>) -> Self {
13 Self { db }
14 }
15
16 pub async fn authenticate(&self, req: &mut OxiditeRequest) -> OxiditeResult<i64> {
18 let key = self.extract_key(req)?;
20
21 let api_key = ApiKey::verify_key(&*self.db, &key).await
23 .map_err(|_| Error::InternalServerError("Database error".to_string()))?
24 .ok_or_else(|| Error::Unauthorized("Invalid or expired API key".to_string()))?;
25
26 req.extensions_mut().insert(api_key.user_id);
28
29 Ok(api_key.user_id)
30 }
31
32 fn extract_key(&self, req: &OxiditeRequest) -> OxiditeResult<String> {
34 if let Some(auth_header) = req.headers().get("authorization") {
36 if let Ok(auth_str) = auth_header.to_str() {
37 if let Some(key) = auth_str.strip_prefix("Bearer ") {
38 return Ok(key.to_string());
39 }
40 }
41 }
42
43 if let Some(api_key_header) = req.headers().get("x-api-key") {
45 if let Ok(key) = api_key_header.to_str() {
46 return Ok(key.to_string());
47 }
48 }
49
50 if let Some(query) = req.uri().query() {
52 for param in query.split('&') {
53 if let Some((k, v)) = param.split_once('=') {
54 if k == "api_key" {
55 return Ok(v.to_string());
56 }
57 }
58 }
59 }
60
61 Err(Error::Unauthorized("API key required".to_string()))
62 }
63}