// Password authentication module use crate::models::{Role, User}; use anyhow::{Context, Result}; use bcrypt::verify; use sqlx::MySqlPool; pub async fn authenticate_password( pool: &MySqlPool, username: &str, password: &str, ) -> Result> { // Fetch user from database let user: Option = sqlx::query_as::<_, User>( r#" SELECT id, name, username, password, pin_code, login_string, role_id, email, phone, notes, active, last_login_date, created_date, password_reset_token, password_reset_expiry FROM users WHERE username = ? AND active = TRUE "#, ) .bind(username) .fetch_optional(pool) .await .context("Failed to fetch user from database")?; if let Some(user) = user { // Verify password let password_valid = verify(password, &user.password).context("Failed to verify password")?; if password_valid { // Fetch user's role let role: Role = sqlx::query_as::<_, Role>( "SELECT id, name, power, created_at FROM roles WHERE id = ?", ) .bind(user.role_id) .fetch_one(pool) .await .context("Failed to fetch user role")?; // Update last login date sqlx::query("UPDATE users SET last_login_date = NOW() WHERE id = ?") .bind(user.id) .execute(pool) .await .context("Failed to update last login date")?; Ok(Some((user, role))) } else { Ok(None) } } else { Ok(None) } }