extern crate bcrypt;
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use core::MedalError;
use db_objects::SessionUser;
pub fn make_ambiguous_code(len: usize) -> String { thread_rng().sample_iter(&Alphanumeric).take(len).collect() }
pub fn make_unambiguous_code(len: usize) -> String {
thread_rng().sample_iter(&Alphanumeric)
.filter(|x| {
let x = *x;
!(x == 'l' || x == 'I' || x == '1' || x == 'O' || x == 'o' || x == '0')
})
.take(len)
.collect()
}
pub fn make_unambiguous_code_prefix(len: usize, prefix: &str) -> String {
let mut code = prefix.to_owned();
code.push_str(&make_unambiguous_code(len));
code
}
pub fn make_session_token() -> String { make_ambiguous_code(10) }
pub fn make_csrf_token() -> String { make_ambiguous_code(10) }
pub fn make_salt() -> String { make_ambiguous_code(10) }
pub fn make_filename_secret() -> String { make_ambiguous_code(10) }
pub fn make_group_code() -> String { make_unambiguous_code_prefix(6, "g") }
pub fn make_login_code() -> String { make_unambiguous_code_prefix(8, "u") }
pub fn hash_password(password: &str, salt: &str) -> Result<String, MedalError> {
let password_and_salt = [password, salt].concat();
match bcrypt::hash(password_and_salt, 5) {
Ok(result) => Ok(result),
Err(_) => Err(MedalError::PasswordHashingError),
}
}
pub fn verify_password(password: &str, salt: &str, password_hash: &str) -> bool {
let password_and_salt = [password, salt].concat();
match bcrypt::verify(password_and_salt, password_hash) {
Ok(result) => result,
_ => false,
}
}
pub trait SetPassword {
fn set_password(&mut self, &str) -> Option<()>;
}
impl SetPassword for SessionUser {
fn set_password(&mut self, password: &str) -> Option<()> {
let salt: String = thread_rng().sample_iter(&Alphanumeric).take(10).collect();
let hash = hash_password(password, &salt).ok()?;
self.password = Some(hash);
self.salt = Some(salt);
Some(())
}
}