Skip to main content

alibi_core/session/
request.rs

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