Skip to main content

openauth_core/options/
advanced.rs

1use std::future::Future;
2use std::pin::Pin;
3use std::sync::Arc;
4
5use crate::utils::ip::Ipv6Subnet;
6
7use super::cookies::CookieConfig;
8
9/// Advanced configuration.
10pub type BackgroundTaskFuture = Pin<Box<dyn Future<Output = ()> + Send + 'static>>;
11
12pub trait BackgroundTaskRunner: Send + Sync + 'static {
13    fn spawn(&self, task: BackgroundTaskFuture);
14}
15
16#[derive(Clone, Default)]
17pub struct AdvancedOptions {
18    pub use_secure_cookies: Option<bool>,
19    pub cookie_prefix: Option<String>,
20    pub cross_subdomain_cookies: Option<CookieConfig>,
21    pub default_cookie_attributes: CookieAttributesOverride,
22    pub disable_csrf_check: bool,
23    pub disable_origin_check: bool,
24    pub skip_trailing_slashes: bool,
25    pub ip_address: IpAddressOptions,
26    pub background_tasks: Option<Arc<dyn BackgroundTaskRunner>>,
27}
28
29impl AdvancedOptions {
30    pub fn new() -> Self {
31        Self::default()
32    }
33
34    pub fn builder() -> Self {
35        Self::new()
36    }
37
38    #[must_use]
39    pub fn use_secure_cookies(mut self, enabled: bool) -> Self {
40        self.use_secure_cookies = Some(enabled);
41        self
42    }
43
44    #[must_use]
45    pub fn cookie_prefix(mut self, prefix: impl Into<String>) -> Self {
46        self.cookie_prefix = Some(prefix.into());
47        self
48    }
49
50    #[must_use]
51    pub fn cross_subdomain_cookies(mut self, config: CookieConfig) -> Self {
52        self.cross_subdomain_cookies = Some(config);
53        self
54    }
55
56    #[must_use]
57    pub fn default_cookie_attributes(mut self, attributes: CookieAttributesOverride) -> Self {
58        self.default_cookie_attributes = attributes;
59        self
60    }
61
62    #[must_use]
63    pub fn disable_csrf_check(mut self, disabled: bool) -> Self {
64        self.disable_csrf_check = disabled;
65        self
66    }
67
68    #[must_use]
69    pub fn disable_origin_check(mut self, disabled: bool) -> Self {
70        self.disable_origin_check = disabled;
71        self
72    }
73
74    #[must_use]
75    pub fn skip_trailing_slashes(mut self, enabled: bool) -> Self {
76        self.skip_trailing_slashes = enabled;
77        self
78    }
79
80    #[must_use]
81    pub fn ip_address(mut self, ip_address: IpAddressOptions) -> Self {
82        self.ip_address = ip_address;
83        self
84    }
85
86    #[must_use]
87    pub fn background_tasks(mut self, runner: Arc<dyn BackgroundTaskRunner>) -> Self {
88        self.background_tasks = Some(runner);
89        self
90    }
91}
92
93impl std::fmt::Debug for AdvancedOptions {
94    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95        formatter
96            .debug_struct("AdvancedOptions")
97            .field("use_secure_cookies", &self.use_secure_cookies)
98            .field("cookie_prefix", &self.cookie_prefix)
99            .field("cross_subdomain_cookies", &self.cross_subdomain_cookies)
100            .field("default_cookie_attributes", &self.default_cookie_attributes)
101            .field("disable_csrf_check", &self.disable_csrf_check)
102            .field("disable_origin_check", &self.disable_origin_check)
103            .field("skip_trailing_slashes", &self.skip_trailing_slashes)
104            .field("ip_address", &self.ip_address)
105            .field(
106                "background_tasks",
107                &self.background_tasks.as_ref().map(|_| "<background-tasks>"),
108            )
109            .finish()
110    }
111}
112
113#[derive(Debug, Clone, PartialEq, Eq)]
114pub struct IpAddressOptions {
115    pub headers: Vec<String>,
116    pub disable_ip_tracking: bool,
117    pub ipv6_subnet: Ipv6Subnet,
118}
119
120impl Default for IpAddressOptions {
121    fn default() -> Self {
122        Self {
123            headers: Vec::new(),
124            disable_ip_tracking: false,
125            ipv6_subnet: Ipv6Subnet::Prefix64,
126        }
127    }
128}
129
130impl IpAddressOptions {
131    pub fn new() -> Self {
132        Self::default()
133    }
134
135    pub fn builder() -> Self {
136        Self::new()
137    }
138
139    #[must_use]
140    pub fn header(mut self, header: impl Into<String>) -> Self {
141        self.headers.push(header.into());
142        self
143    }
144
145    #[must_use]
146    pub fn headers<I, S>(mut self, headers: I) -> Self
147    where
148        I: IntoIterator<Item = S>,
149        S: Into<String>,
150    {
151        self.headers = headers.into_iter().map(Into::into).collect();
152        self
153    }
154
155    #[must_use]
156    pub fn disable_ip_tracking(mut self, disabled: bool) -> Self {
157        self.disable_ip_tracking = disabled;
158        self
159    }
160
161    #[must_use]
162    pub fn ipv6_subnet(mut self, subnet: Ipv6Subnet) -> Self {
163        self.ipv6_subnet = subnet;
164        self
165    }
166}
167
168/// User-supplied cookie attribute defaults.
169#[derive(Debug, Clone, Default, PartialEq, Eq)]
170pub struct CookieAttributesOverride {
171    pub domain: Option<String>,
172    pub path: Option<String>,
173    pub secure: Option<bool>,
174    pub http_only: Option<bool>,
175    pub same_site: Option<String>,
176    pub max_age: Option<u64>,
177    pub partitioned: Option<bool>,
178}
179
180impl CookieAttributesOverride {
181    pub fn new() -> Self {
182        Self::default()
183    }
184
185    pub fn builder() -> Self {
186        Self::new()
187    }
188
189    #[must_use]
190    pub fn domain(mut self, domain: impl Into<String>) -> Self {
191        self.domain = Some(domain.into());
192        self
193    }
194
195    #[must_use]
196    pub fn path(mut self, path: impl Into<String>) -> Self {
197        self.path = Some(path.into());
198        self
199    }
200
201    #[must_use]
202    pub fn secure(mut self, secure: bool) -> Self {
203        self.secure = Some(secure);
204        self
205    }
206
207    #[must_use]
208    pub fn http_only(mut self, http_only: bool) -> Self {
209        self.http_only = Some(http_only);
210        self
211    }
212
213    #[must_use]
214    pub fn same_site(mut self, same_site: impl Into<String>) -> Self {
215        self.same_site = Some(same_site.into());
216        self
217    }
218
219    #[must_use]
220    pub fn max_age(mut self, max_age: u64) -> Self {
221        self.max_age = Some(max_age);
222        self
223    }
224
225    #[must_use]
226    pub fn partitioned(mut self, partitioned: bool) -> Self {
227        self.partitioned = Some(partitioned);
228        self
229    }
230}