Skip to main content

rustauth_core/options/
advanced.rs

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