Skip to main content

alibi_core/session/
request.rs

1//! Session authentication consumes logical credential input, not an invented HTTP request.
2
3use crate::AuthContext;
4use crate::types::RequestExtensions;
5use crate::utils::json::JsValue;
6use crate::{AuthRequest, AuthSchema, HttpMethod, SessionView, UserView};
7use std::collections::HashMap;
8
9/// Input and trusted state used by the shared physical/cache session readers.
10/// Implementations must never populate authenticated state from client data.
11pub trait SessionRequest: Send + Sync {
12    /// Retain a genuine logical endpoint call when this input has one.
13    fn endpoint_call(&self) -> Option<&crate::endpoint::EndpointCall> {
14        None
15    }
16    fn session_headers(&self) -> &HashMap<String, String>;
17    fn session_method(&self) -> &HttpMethod;
18    fn session_query_truthy(&self, name: &str) -> bool;
19    fn extensions(&self) -> &RequestExtensions;
20    fn virtual_session<S: AuthSchema>(&self, context: &AuthContext<S>) -> Option<SessionView>;
21    fn authenticated_user<S: AuthSchema>(&self, _context: &AuthContext<S>) -> Option<S::User> {
22        None
23    }
24    fn take_response_headers(&self) -> crate::Headers;
25    fn queue_response_header(&self, name: impl Into<String>, value: impl Into<String>);
26    fn set_session_hook_snapshot(&self, user: UserView, session: SessionView);
27}
28
29impl SessionRequest for AuthRequest {
30    fn session_headers(&self) -> &HashMap<String, String> {
31        &self.headers
32    }
33    fn session_method(&self) -> &HttpMethod {
34        self.method()
35    }
36    fn session_query_truthy(&self, name: &str) -> bool {
37        self.query.get(name).is_some_and(|value| !value.is_empty())
38    }
39    fn extensions(&self) -> &RequestExtensions {
40        self.extensions()
41    }
42    fn virtual_session<S: AuthSchema>(&self, _context: &AuthContext<S>) -> Option<SessionView> {
43        self.virtual_session().cloned()
44    }
45    fn take_response_headers(&self) -> crate::Headers {
46        self.take_response_headers()
47    }
48    fn queue_response_header(&self, name: impl Into<String>, value: impl Into<String>) {
49        self.queue_response_header(name, value);
50    }
51    fn set_session_hook_snapshot(&self, user: UserView, session: SessionView) {
52        self.set_session_hook_snapshot(user, session);
53    }
54}
55
56impl SessionRequest for crate::endpoint::EndpointCall {
57    fn endpoint_call(&self) -> Option<&crate::endpoint::EndpointCall> {
58        Some(self)
59    }
60    fn session_headers(&self) -> &HashMap<String, String> {
61        static EMPTY: std::sync::LazyLock<HashMap<String, String>> =
62            std::sync::LazyLock::new(HashMap::new);
63        self.headers().unwrap_or(&EMPTY)
64    }
65    fn session_method(&self) -> &HttpMethod {
66        self.method().unwrap_or_else(|| self.default_method())
67    }
68    fn session_query_truthy(&self, name: &str) -> bool {
69        self.query()
70            .and_then(|query| query.get(name))
71            .is_some_and(|value| match value {
72                JsValue::Null => false,
73                JsValue::Bool(value) => *value,
74                JsValue::Number(value) => *value != 0.0 && !value.is_nan(),
75                JsValue::String(value) => !value.is_empty(),
76                JsValue::Array(_) | JsValue::Object(_) => true,
77            })
78    }
79    fn extensions(&self) -> &RequestExtensions {
80        self.extensions()
81    }
82    fn virtual_session<S: AuthSchema>(&self, context: &AuthContext<S>) -> Option<SessionView> {
83        self.authenticated_user(context)
84            .and_then(|_| self.virtual_session())
85    }
86    fn authenticated_user<S: AuthSchema>(&self, context: &AuthContext<S>) -> Option<S::User> {
87        self.authenticated_user::<S>(context)
88    }
89    fn take_response_headers(&self) -> crate::Headers {
90        self.take_response_headers()
91    }
92    fn queue_response_header(&self, name: impl Into<String>, value: impl Into<String>) {
93        self.queue_response_header(name, value);
94    }
95    fn set_session_hook_snapshot(&self, user: UserView, session: SessionView) {
96        self.set_session_hook_snapshot(user, session);
97    }
98}