Skip to main content

openauth_core/options/
root.rs

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