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 { 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 { let user: &Option = request.local_cache(|| { let attempt_load_user = |id| -> Option { 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, }