60 lines
1.7 KiB
Rust
60 lines
1.7 KiB
Rust
use crate::db::{Dao, TenebrousDbConn};
|
|
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, sqlx::FromRow)]
|
|
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)
|
|
}
|
|
}
|
|
|
|
async fn attempt_load_user<'a>(db: &'a TenebrousDbConn<'a>, id: i32) -> Option<User> {
|
|
db.load_user_by_id(id).await.ok().flatten()
|
|
}
|
|
|
|
/// Trait implementation to get the logged in user.
|
|
#[rocket::async_trait]
|
|
impl<'a, 'r> FromRequest<'a, 'r> for &'a User {
|
|
type Error = ();
|
|
|
|
async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, ()> {
|
|
let db = try_outcome!(request.guard::<TenebrousDbConn>().await);
|
|
let user_id: Option<i32> = request
|
|
.cookies()
|
|
.get_private("user_id")
|
|
.and_then(|cookie| cookie.value().parse().ok());
|
|
|
|
let user: &Option<User> = request
|
|
.local_cache_async(async {
|
|
match user_id {
|
|
Some(id) => attempt_load_user(&db, id).await,
|
|
_ => None,
|
|
}
|
|
})
|
|
.await;
|
|
|
|
user.as_ref().or_forward(())
|
|
}
|
|
}
|
|
|
|
pub struct NewUser<'a> {
|
|
pub username: &'a str,
|
|
pub password: &'a str,
|
|
}
|