Skip to main content

openauth_core/options/
root.rs

1use std::fmt;
2use std::sync::Arc;
3
4use openauth_oauth::oauth2::SocialOAuthProvider;
5
6use super::storage::SecondaryStorage;
7use crate::crypto::SecretEntry;
8use crate::plugin::AuthPlugin;
9
10use super::account::AccountOptions;
11use super::advanced::AdvancedOptions;
12use super::email_verification::EmailVerificationOptions;
13use super::origins::TrustedOriginOptions;
14use super::password::PasswordOptions;
15use super::rate_limit::RateLimitOptions;
16use super::session::SessionOptions;
17use super::user::UserOptions;
18
19/// Telemetry collection settings (parity with Better Auth `telemetry` init option).
20#[derive(Debug, Clone, PartialEq, Eq, Default)]
21pub struct TelemetryOptions {
22    /// When `None`, option-side telemetry is off unless overridden by environment.
23    pub enabled: Option<bool>,
24    pub debug: bool,
25}
26
27impl TelemetryOptions {
28    pub fn new() -> Self {
29        Self::default()
30    }
31
32    #[must_use]
33    pub fn enabled(mut self, enabled: bool) -> Self {
34        self.enabled = Some(enabled);
35        self
36    }
37
38    #[must_use]
39    pub fn debug(mut self, debug: bool) -> Self {
40        self.debug = debug;
41        self
42    }
43}
44
45/// Experimental feature flags.
46#[derive(Debug, Clone, PartialEq, Eq, Default)]
47pub struct ExperimentalOptions {
48    pub joins: bool,
49}
50
51impl ExperimentalOptions {
52    pub fn new() -> Self {
53        Self::default()
54    }
55
56    #[must_use]
57    pub fn joins(mut self, enabled: bool) -> Self {
58        self.joins = enabled;
59        self
60    }
61}
62
63/// Top-level OpenAuth configuration.
64#[derive(Clone, Default)]
65pub struct OpenAuthOptions {
66    pub base_url: Option<String>,
67    pub base_path: Option<String>,
68    pub secret: Option<String>,
69    pub secrets: Vec<SecretEntry>,
70    pub trusted_origins: TrustedOriginOptions,
71    pub disabled_paths: Vec<String>,
72    pub session: SessionOptions,
73    pub user: UserOptions,
74    pub email_verification: EmailVerificationOptions,
75    pub password: PasswordOptions,
76    pub account: AccountOptions,
77    pub advanced: AdvancedOptions,
78    pub rate_limit: RateLimitOptions,
79    pub secondary_storage: Option<Arc<dyn SecondaryStorage>>,
80    pub plugins: Vec<AuthPlugin>,
81    pub social_providers: Vec<Arc<dyn SocialOAuthProvider>>,
82    pub production: bool,
83    pub telemetry: TelemetryOptions,
84    pub experimental: ExperimentalOptions,
85}
86
87impl OpenAuthOptions {
88    pub fn new() -> Self {
89        Self::default()
90    }
91
92    pub fn builder() -> Self {
93        Self::new()
94    }
95
96    #[must_use]
97    pub fn base_url(mut self, base_url: impl Into<String>) -> Self {
98        self.base_url = Some(base_url.into());
99        self
100    }
101
102    #[must_use]
103    pub fn base_path(mut self, base_path: impl Into<String>) -> Self {
104        self.base_path = Some(base_path.into());
105        self
106    }
107
108    #[must_use]
109    pub fn secret(mut self, secret: impl Into<String>) -> Self {
110        self.secret = Some(secret.into());
111        self
112    }
113
114    #[must_use]
115    pub fn secrets(mut self, secrets: Vec<SecretEntry>) -> Self {
116        self.secrets = secrets;
117        self
118    }
119
120    #[must_use]
121    pub fn trusted_origins(mut self, trusted_origins: TrustedOriginOptions) -> Self {
122        self.trusted_origins = trusted_origins;
123        self
124    }
125
126    #[must_use]
127    pub fn disabled_path(mut self, path: impl Into<String>) -> Self {
128        self.disabled_paths.push(path.into());
129        self
130    }
131
132    #[must_use]
133    pub fn disabled_paths<I, S>(mut self, paths: I) -> Self
134    where
135        I: IntoIterator<Item = S>,
136        S: Into<String>,
137    {
138        self.disabled_paths = paths.into_iter().map(Into::into).collect();
139        self
140    }
141
142    #[must_use]
143    pub fn session(mut self, session: SessionOptions) -> Self {
144        self.session = session;
145        self
146    }
147
148    #[must_use]
149    pub fn user(mut self, user: UserOptions) -> Self {
150        self.user = user;
151        self
152    }
153
154    #[must_use]
155    pub fn email_verification(mut self, email_verification: EmailVerificationOptions) -> Self {
156        self.email_verification = email_verification;
157        self
158    }
159
160    #[must_use]
161    pub fn password(mut self, password: PasswordOptions) -> Self {
162        self.password = password;
163        self
164    }
165
166    #[must_use]
167    pub fn account(mut self, account: AccountOptions) -> Self {
168        self.account = account;
169        self
170    }
171
172    #[must_use]
173    pub fn advanced(mut self, advanced: AdvancedOptions) -> Self {
174        self.advanced = advanced;
175        self
176    }
177
178    #[must_use]
179    pub fn rate_limit(mut self, rate_limit: RateLimitOptions) -> Self {
180        self.rate_limit = rate_limit;
181        self
182    }
183
184    #[must_use]
185    pub fn secondary_storage(mut self, storage: Arc<dyn SecondaryStorage>) -> Self {
186        self.secondary_storage = Some(storage);
187        self
188    }
189
190    #[must_use]
191    pub fn plugin(mut self, plugin: AuthPlugin) -> Self {
192        self.plugins.push(plugin);
193        self
194    }
195
196    #[must_use]
197    pub fn plugins(mut self, plugins: Vec<AuthPlugin>) -> Self {
198        self.plugins = plugins;
199        self
200    }
201
202    #[must_use]
203    pub fn social_provider<P>(mut self, provider: P) -> Self
204    where
205        P: SocialOAuthProvider,
206    {
207        self.social_providers.push(Arc::new(provider));
208        self
209    }
210
211    #[must_use]
212    pub fn social_provider_arc(mut self, provider: Arc<dyn SocialOAuthProvider>) -> Self {
213        self.social_providers.push(provider);
214        self
215    }
216
217    #[must_use]
218    pub fn production(mut self, production: bool) -> Self {
219        self.production = production;
220        self
221    }
222
223    #[must_use]
224    pub fn telemetry(mut self, telemetry: TelemetryOptions) -> Self {
225        self.telemetry = telemetry;
226        self
227    }
228
229    #[must_use]
230    pub fn experimental(mut self, experimental: ExperimentalOptions) -> Self {
231        self.experimental = experimental;
232        self
233    }
234}
235
236impl fmt::Debug for OpenAuthOptions {
237    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
238        formatter
239            .debug_struct("OpenAuthOptions")
240            .field("base_url", &self.base_url)
241            .field("base_path", &self.base_path)
242            .field("secret", &self.secret.as_ref().map(|_| "<redacted>"))
243            .field(
244                "secrets",
245                &format_args!("{} secret(s) redacted", self.secrets.len()),
246            )
247            .field("trusted_origins", &self.trusted_origins)
248            .field("disabled_paths", &self.disabled_paths)
249            .field("session", &self.session)
250            .field("user", &self.user)
251            .field("email_verification", &self.email_verification)
252            .field("password", &self.password)
253            .field("account", &self.account)
254            .field("advanced", &self.advanced)
255            .field("rate_limit", &self.rate_limit)
256            .field(
257                "secondary_storage",
258                &self
259                    .secondary_storage
260                    .as_ref()
261                    .map(|_| "<secondary-storage>"),
262            )
263            .field("plugins", &self.plugins)
264            .field(
265                "social_providers",
266                &self
267                    .social_providers
268                    .iter()
269                    .map(|provider| provider.id())
270                    .collect::<Vec<_>>(),
271            )
272            .field("production", &self.production)
273            .field("telemetry", &self.telemetry)
274            .field("experimental", &self.experimental)
275            .finish()
276    }
277}