use rustlavel::prelude::*;
#[derive(Model, Default, Debug, Clone)]
#[model(table = "login_attempts")]
pub struct LoginAttempt {
#[model(primary_key, generated)]
pub id: i64,
pub user_id: Option<i64>,
pub email: String,
pub successful: bool,
pub reason: Option<String>,
pub ip: Option<String>,
pub user_agent: Option<String>,
pub created_at: Option<String>,
}
impl LoginAttempt {
pub async fn record(
db: &Database,
email: &str,
user_id: Option<i64>,
successful: bool,
reason: Option<&str>,
req: &Request,
) -> Result<()> {
let mut attempt = LoginAttempt {
user_id,
email: email.trim().to_lowercase(),
successful,
reason: reason.map(str::to_string),
ip: req.ip(),
user_agent: req.header("user-agent").map(|agent| agent.chars().take(180).collect()),
..Default::default()
};
attempt.insert(db).await
}
pub fn for_user(user_id: i64) -> QueryBuilder {
LoginAttempt::query().filter("user_id", user_id).latest("id")
}
pub fn recent_failures(user_id: i64, since: &str) -> QueryBuilder {
LoginAttempt::query()
.filter("user_id", user_id)
.filter("successful", false)
.filter_op("created_at", ">", since)
}
}