use super::{CustomSyntheticUserCallback, ExistingUserSignupCallback, UsernameConfig};
use alibi_core::utils::password::PasswordHasher;
use std::sync::Arc;
#[derive(Clone)]
#[expect(
clippy::struct_excessive_bools,
reason = "Independent configuration switches model distinct upstream behavior, rather than mutually exclusive states"
)]
pub struct EmailPasswordConfig {
pub enabled: bool,
pub enable_signup: bool,
pub enable_username: bool,
pub username: UsernameConfig,
pub require_email_verification: bool,
pub password_min_length: usize,
pub password_max_length: usize,
pub auto_sign_in: bool,
pub password_hasher: Option<Arc<dyn PasswordHasher>>,
pub on_existing_user_signup: Option<Arc<ExistingUserSignupCallback>>,
pub custom_synthetic_user: Option<Arc<CustomSyntheticUserCallback>>,
}
pub(crate) fn password_length_limits(
ctx: &alibi_core::AuthContext<impl alibi_core::AuthSchema>,
) -> (usize, usize) {
ctx.extensions
.get::<EmailPasswordConfig>()
.map_or((8, 128), |config| {
(config.effective_min_length(), config.effective_max_length())
})
}
impl EmailPasswordConfig {
pub(in crate::email_password) const fn effective_min_length(&self) -> usize {
if self.password_min_length == 0 {
8
} else {
self.password_min_length
}
}
pub(in crate::email_password) const fn effective_max_length(&self) -> usize {
if self.password_max_length == 0 {
128
} else {
self.password_max_length
}
}
}
impl std::fmt::Debug for EmailPasswordConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EmailPasswordConfig")
.field("enabled", &self.enabled)
.field("enable_signup", &self.enable_signup)
.field("enable_username", &self.enable_username)
.field("username", &self.username)
.field(
"require_email_verification",
&self.require_email_verification,
)
.field("password_min_length", &self.password_min_length)
.field("password_max_length", &self.password_max_length)
.field("auto_sign_in", &self.auto_sign_in)
.field(
"password_hasher",
&self.password_hasher.as_ref().map(|_| "custom"),
)
.field(
"on_existing_user_signup",
&self.on_existing_user_signup.as_ref().map(|_| "custom"),
)
.field(
"custom_synthetic_user",
&self.custom_synthetic_user.as_ref().map(|_| "custom"),
)
.finish()
}
}
impl Default for EmailPasswordConfig {
fn default() -> Self {
Self {
enabled: true,
enable_signup: true,
enable_username: true,
username: UsernameConfig::default(),
require_email_verification: false,
password_min_length: 8,
password_max_length: 128,
auto_sign_in: true,
password_hasher: None,
on_existing_user_signup: None,
custom_synthetic_user: None,
}
}
}