|
@@ -1,5 +1,13 @@
|
|
|
|
|
+use actix_web::cookie::{Cookie, SameSite, time::Duration};
|
|
|
use uuid::Uuid;
|
|
use uuid::Uuid;
|
|
|
use serde::{Serialize, Deserialize};
|
|
use serde::{Serialize, Deserialize};
|
|
|
|
|
+use argon2::{
|
|
|
|
|
+ Argon2,
|
|
|
|
|
+ password_hash::{
|
|
|
|
|
+ PasswordHash,
|
|
|
|
|
+ PasswordVerifier
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
use std::{fs, io::Write, path::Path};
|
|
use std::{fs, io::Write, path::Path};
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
@@ -76,4 +84,32 @@ impl User {
|
|
|
fs::rename(&tmp_path, path)
|
|
fs::rename(&tmp_path, path)
|
|
|
.expect("Failed to replace users file");
|
|
.expect("Failed to replace users file");
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ pub fn find_by_email(users: Vec<User>, email: String) -> Option<Self> {
|
|
|
|
|
+ users
|
|
|
|
|
+ .iter()
|
|
|
|
|
+ .find(|u| u.email == email).cloned()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub fn verify_password(self, password: &String) -> Option<Self> {
|
|
|
|
|
+ let parsed_hash = match PasswordHash::new(&self.pass_hash) {
|
|
|
|
|
+ Ok(p) => p,
|
|
|
|
|
+ Err(_) => { return None }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ match Argon2::default().verify_password(password.as_bytes(), &parsed_hash) {
|
|
|
|
|
+ Ok(_) => Some(self),
|
|
|
|
|
+ Err(_) => None
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub fn create_auth_cookie(&self) -> Cookie<'static> {
|
|
|
|
|
+ Cookie::build("user", self.id.to_string())
|
|
|
|
|
+ .path("/")
|
|
|
|
|
+ .http_only(true)
|
|
|
|
|
+ .same_site(SameSite::Lax)
|
|
|
|
|
+ .secure(true)
|
|
|
|
|
+ .max_age(Duration::days(90))
|
|
|
|
|
+ .finish()
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|