- Database schema: users, permissions, client_access tables - Auth: JWT tokens with Argon2 password hashing - API: login, user CRUD, permission management - Dashboard: login required, admin Users tab - Auto-creates initial admin user on first run
58 lines
1.7 KiB
Rust
58 lines
1.7 KiB
Rust
//! Password hashing using Argon2id
|
|
|
|
use anyhow::{anyhow, Result};
|
|
use argon2::{
|
|
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
|
|
Argon2,
|
|
};
|
|
|
|
/// Hash a password using Argon2id
|
|
pub fn hash_password(password: &str) -> Result<String> {
|
|
let salt = SaltString::generate(&mut OsRng);
|
|
let argon2 = Argon2::default();
|
|
let hash = argon2
|
|
.hash_password(password.as_bytes(), &salt)
|
|
.map_err(|e| anyhow!("Failed to hash password: {}", e))?;
|
|
Ok(hash.to_string())
|
|
}
|
|
|
|
/// Verify a password against a stored hash
|
|
pub fn verify_password(password: &str, hash: &str) -> Result<bool> {
|
|
let parsed_hash = PasswordHash::new(hash)
|
|
.map_err(|e| anyhow!("Invalid password hash format: {}", e))?;
|
|
let argon2 = Argon2::default();
|
|
Ok(argon2.verify_password(password.as_bytes(), &parsed_hash).is_ok())
|
|
}
|
|
|
|
/// Generate a random password (for initial admin)
|
|
pub fn generate_random_password(length: usize) -> String {
|
|
use rand::Rng;
|
|
const CHARSET: &[u8] = b"ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789!@#$%";
|
|
let mut rng = rand::thread_rng();
|
|
(0..length)
|
|
.map(|_| {
|
|
let idx = rng.gen_range(0..CHARSET.len());
|
|
CHARSET[idx] as char
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_hash_and_verify() {
|
|
let password = "test_password_123";
|
|
let hash = hash_password(password).unwrap();
|
|
assert!(verify_password(password, &hash).unwrap());
|
|
assert!(!verify_password("wrong_password", &hash).unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_random_password() {
|
|
let password = generate_random_password(16);
|
|
assert_eq!(password.len(), 16);
|
|
}
|
|
}
|