use super::*;
#[async_trait]
pub trait SendTwoFactorOtp: Send + Sync {
async fn send(&self, user: &UserView, otp: &str) -> AuthResult<()>;
}
#[derive(Debug, Clone)]
pub struct AccountLockoutConfig {
pub enabled: bool,
pub max_failed_attempts: f64,
pub duration_seconds: f64,
}
impl Default for AccountLockoutConfig {
fn default() -> Self {
Self {
enabled: true,
max_failed_attempts: 10.0,
duration_seconds: 900.0,
}
}
}
#[derive(Clone, alibi_core::PluginConfig)]
#[plugin(name = "TwoFactorPlugin")]
pub struct TwoFactorConfig {
#[config(default = false)]
pub allow_passwordless: bool,
#[config(default = None)]
pub totp_allow_passwordless: Option<bool>,
#[config(default = None)]
pub backup_allow_passwordless: Option<bool>,
#[config(default = 10.0)]
pub backup_code_amount: f64,
#[config(default = 10.0)]
pub backup_code_length: f64,
#[config(default = None, skip)]
pub custom_backup_codes_generate:
Option<Arc<dyn Fn() -> AuthResult<Vec<String>> + Send + Sync>>,
#[config(default = TwoFactorBackupStorage::default(), skip)]
pub backup_storage: TwoFactorBackupStorage,
#[config(default = AccountLockoutConfig::default())]
pub account_lockout: AccountLockoutConfig,
#[config(default = None)]
pub issuer: Option<String>,
#[config(default = false)]
pub skip_verification_on_enable: bool,
#[config(default = DEFAULT_TWO_FACTOR_COOKIE_MAX_AGE_SECS)]
pub two_factor_cookie_max_age: f64,
#[config(default = DEFAULT_TRUST_DEVICE_MAX_AGE_SECS)]
pub trust_device_max_age: f64,
#[config(default = DEFAULT_TOTP_PERIOD_SECS)]
pub totp_period: f64,
#[config(default = DEFAULT_TOTP_DIGITS)]
pub totp_digits: f64,
#[config(default = None)]
pub totp_issuer: Option<String>,
#[config(default = false)]
pub totp_disabled: bool,
#[config(default = None, skip)]
pub send_otp: Option<Arc<dyn SendTwoFactorOtp>>,
#[config(default = 6.0)]
pub otp_digits: f64,
#[config(default = 3.0)]
pub otp_period_minutes: f64,
#[config(default = 5.0)]
pub otp_allowed_attempts: f64,
#[config(default = TwoFactorOtpStorage::default(), skip)]
pub otp_storage: TwoFactorOtpStorage,
}
impl std::fmt::Debug for TwoFactorConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TwoFactorConfig")
.field("allow_passwordless", &self.allow_passwordless)
.field("totp_allow_passwordless", &self.totp_allow_passwordless)
.field("backup_allow_passwordless", &self.backup_allow_passwordless)
.field("backup_code_amount", &self.backup_code_amount)
.field("backup_code_length", &self.backup_code_length)
.field(
"custom_backup_codes_generate",
&self.custom_backup_codes_generate.is_some(),
)
.field("backup_storage", &self.backup_storage)
.field("account_lockout", &self.account_lockout)
.field("issuer", &self.issuer)
.field(
"skip_verification_on_enable",
&self.skip_verification_on_enable,
)
.field("two_factor_cookie_max_age", &self.two_factor_cookie_max_age)
.field("trust_device_max_age", &self.trust_device_max_age)
.field("totp_period", &self.totp_period)
.field("totp_digits", &self.totp_digits)
.field("totp_issuer", &self.totp_issuer)
.field("totp_disabled", &self.totp_disabled)
.field("send_otp", &self.send_otp.as_ref().map(|_| "custom"))
.field("otp_digits", &self.otp_digits)
.field("otp_period_minutes", &self.otp_period_minutes)
.field("otp_allowed_attempts", &self.otp_allowed_attempts)
.field("otp_storage", &self.otp_storage)
.finish()
}
}