tenebrous-sheets/src/models/users.rs

57 lines
1.6 KiB
Rust

use crate::db::{Dao, TenebrousDbConn};
use crate::schema::users;
use argon2::{self, Config, Error as ArgonError};
use rand::Rng;
use rocket::outcome::IntoOutcome;
use rocket::request::{self, FromRequest, Request};
use serde_derive::Serialize;
pub(crate) fn hash_password(raw_password: &str) -> Result<String, ArgonError> {
let salt = rand::thread_rng().gen::<[u8; 16]>();
let config = Config::default();
argon2::hash_encoded(raw_password.as_bytes(), &salt, &config)
}
#[derive(Eq, PartialEq, Serialize, Debug, Queryable)]
pub struct User {
pub id: i32,
pub username: String,
pub password: String,
}
impl User {
pub fn verify_password(&self, raw_password: &str) -> bool {
argon2::verify_encoded(&self.password, raw_password.as_bytes()).unwrap_or(false)
}
}
impl<'a, 'r> FromRequest<'a, 'r> for &'a User {
type Error = !;
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, !> {
let user: &Option<User> = request.local_cache(|| {
let attempt_load_user = |id| -> Option<User> {
TenebrousDbConn::from_request(request)
.map(|conn| conn.load_user_by_id(id).ok().flatten())
.succeeded()
.flatten()
};
request
.cookies()
.get_private("user_id")
.and_then(|cookie| cookie.value().parse().ok())
.and_then(attempt_load_user)
});
user.as_ref().or_forward(())
}
}
#[derive(Insertable)]
#[table_name = "users"]
pub struct NewUser<'a> {
pub username: &'a str,
pub password: &'a str,
}