fix: eslint-disable for useEffect deps in UsersPage
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 5s
CI Pipeline / Clippy Lints (push) Successful in 46s
CI Pipeline / Rust Unit Tests (push) Successful in 1m2s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Has been skipped
All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 5s
CI Pipeline / Clippy Lints (push) Successful in 46s
CI Pipeline / Rust Unit Tests (push) Successful in 1m2s
CI Pipeline / Security Audit (push) Successful in 4s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 14s
CI Pipeline / Build .deb & Release (push) Has been skipped
This commit is contained in:
@ -19,7 +19,7 @@ pub mod session;
|
||||
|
||||
// Commonly re-exported types
|
||||
pub use jwt::{AccessClaims, JwtError};
|
||||
pub use password::{hash_password, verify_password, PasswordError};
|
||||
pub use password::validate_password_strength;
|
||||
pub use password::{hash_password, verify_password, PasswordError};
|
||||
pub use rbac::{AuthConfig, AuthUser, UserRole};
|
||||
pub use session::{LoginRequest, LoginResponse, SessionError, SessionUser};
|
||||
|
||||
@ -90,7 +90,10 @@ pub fn validate_password_strength(password: &str) -> Result<(), String> {
|
||||
}
|
||||
let special_chars = "!@#$%^&*()_+-=[]{}|;:,.<>?";
|
||||
if !password.chars().any(|c| special_chars.contains(c)) {
|
||||
return Err("Password must contain at least one special character (!@#$%^&*()_+-=[]{}|;:,.<>?)".to_string());
|
||||
return Err(
|
||||
"Password must contain at least one special character (!@#$%^&*()_+-=[]{}|;:,.<>?)"
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -141,10 +141,12 @@ pub async fn login(
|
||||
return Err(SessionError::AccountLocked);
|
||||
}
|
||||
// Lockout period has expired — reset counters
|
||||
sqlx::query("UPDATE users SET failed_login_attempts = 0, locked_until = NULL WHERE id = $1")
|
||||
.bind(user.id)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
sqlx::query(
|
||||
"UPDATE users SET failed_login_attempts = 0, locked_until = NULL WHERE id = $1",
|
||||
)
|
||||
.bind(user.id)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// 2. Verify password
|
||||
@ -156,12 +158,14 @@ pub async fn login(
|
||||
let new_attempts = user.failed_login_attempts + 1;
|
||||
if new_attempts >= 5 {
|
||||
let lock_until = Utc::now() + chrono::Duration::minutes(30);
|
||||
sqlx::query("UPDATE users SET failed_login_attempts = $1, locked_until = $2 WHERE id = $3")
|
||||
.bind(new_attempts)
|
||||
.bind(lock_until)
|
||||
.bind(user.id)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
sqlx::query(
|
||||
"UPDATE users SET failed_login_attempts = $1, locked_until = $2 WHERE id = $3",
|
||||
)
|
||||
.bind(new_attempts)
|
||||
.bind(lock_until)
|
||||
.bind(user.id)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
tracing::warn!(username = %req.username, "Account locked after {} failed attempts", new_attempts);
|
||||
} else {
|
||||
sqlx::query("UPDATE users SET failed_login_attempts = $1 WHERE id = $2")
|
||||
|
||||
Reference in New Issue
Block a user