Files
aviation/api/src/account/mod.rs
2025-05-23 09:20:08 -04:00

79 lines
1.7 KiB
Rust

use argon2::{
Argon2, PasswordHash, PasswordHasher, PasswordVerifier,
password_hash::{SaltString, rand_core::OsRng},
};
use rand::distr::Alphanumeric;
use rand::prelude::*;
use rand_chacha::ChaCha20Rng;
mod auth;
mod email_token;
mod model;
mod routes;
mod session;
pub use auth::*;
pub use routes::init_routes;
pub use session::*;
use crate::error::{ApiResult, Error};
pub fn csprng(take: usize) -> String {
// Generate a CSPRNG 128-bit (16 byte) ID using alphanumeric characters (a-z, A-Z, 0-9)
let rng = ChaCha20Rng::from_os_rng();
rng
.sample_iter(Alphanumeric)
.take(take)
.map(char::from)
.collect()
}
pub fn hash(string: &str) -> ApiResult<String> {
let salt = SaltString::generate(&mut OsRng);
let hash = Argon2::default()
.hash_password(string.as_bytes(), &salt)?
.to_string();
Ok(hash)
}
pub fn verify_hash(string: &str, hashed_string: &str) -> bool {
let bytes = string.as_bytes();
let parsed_hash = match PasswordHash::new(hashed_string) {
Ok(h) => h,
Err(err) => {
log::error!(
"Failed to construct PasswordHash from '{}': {}",
hashed_string,
err
);
return false;
}
};
Argon2::default()
.verify_password(bytes, &parsed_hash)
.is_ok()
}
pub fn verify_role(auth: &Auth, role: &str) -> ApiResult<()> {
if auth.user.role == role {
Ok(())
} else {
Err(Error {
status: 403,
details: "User does not have permission to perform this action.".to_string(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hash() {
let password = hash("password").unwrap();
assert!(!verify_hash(&password, "bad_password"));
assert!(verify_hash("password", &password));
}
}