Skip to content
use crate::config::Config;
use crate::session::SessionStore;
use actix_web::HttpRequest;

#[must_use]
pub fn extract_pin(req: &HttpRequest) -> Option<String> {
    if let Some(s) = req
        .headers()
        .get("x-admin-pin")
        .and_then(|h| h.to_str().ok())
    {
        return Some(s.to_string());
    }

    actix_web::web::Query::<std::collections::HashMap<String, String>>::from_query(
        req.query_string(),
    )
    .ok()
    .and_then(|q| q.get("pin").cloned())
}

#[must_use]
pub fn is_admin(req: &HttpRequest, config: &Config, session_store: &SessionStore) -> bool {
    session_store.is_authenticated(req)
        || extract_pin(req).is_some_and(|pin| config.is_valid_pin(&pin))
}

#[cfg(test)]
mod tests {
    use super::*;
    use actix_web::test::TestRequest;

    #[test]
    fn test_extract_pin_header_and_query() {
        let req_hdr = TestRequest::default()
            .insert_header(("x-admin-pin", "1234"))
            .to_http_request();
        assert_eq!(extract_pin(&req_hdr), Some("1234".to_string()));

        let req_query = TestRequest::default()
            .uri("/debug?pin=5678")
            .to_http_request();
        assert_eq!(extract_pin(&req_query), Some("5678".to_string()));

        let req_empty = TestRequest::default().to_http_request();
        assert_eq!(extract_pin(&req_empty), None);
    }
}