use crate::jwt::token_factory; use crate::types::{NewPost, Post}; use crate::ServerState; use actix_web::web::{Data, Path}; use actix_web::{get, post, web::Json, HttpResponse, Responder, Result}; use argon2::password_hash::rand_core::OsRng; use argon2::password_hash::SaltString; use argon2::password_hash::*; use argon2::Argon2; use argon2::PasswordHasher; use argon2::PasswordVerifier; use log::*; use serde::{Deserialize, Serialize}; use uuid::Uuid; #[derive(Debug, Serialize, Deserialize)] pub struct RegisterData { username: String, password: String, captcha: String, } #[post("/register")] pub async fn register( data: Json, state: Data, ) -> Result { let q = "SELECT password FROM users WHERE username = ?"; let query = sqlx::query(q).bind(&data.username); let result = query.fetch_one(&state.pool).await.ok(); if result.is_some() { info!("User \"{}\" already exists", data.username); return Ok(HttpResponse::BadRequest().json("Error")); } let password = data.password.clone(); let salt = SaltString::generate(&mut OsRng); let phc_hash = Argon2::default().hash_password(password.as_bytes(), &salt); if let Ok(phc_hash) = phc_hash { info!("User: {} registered", data.username); let phc_hash = phc_hash.to_string(); let q = "INSERT INTO users (username, password) VALUES (?, ?)"; let query = sqlx::query(q).bind(&data.username).bind(&phc_hash); query.execute(&state.pool).await.unwrap(); } else { return Ok(HttpResponse::BadRequest().json("Error")); } Ok(HttpResponse::Ok().json("User registered")) } #[derive(Debug, Serialize, Deserialize)] pub struct LoginData { username: String, password: String, } use sqlx::Row; #[derive(Debug, Serialize, Deserialize)] struct LoginResponse { username: String, token: String, } #[post("/login")] pub async fn login(data: Json, state: Data) -> Result { let q = "SELECT password FROM users WHERE username = ?"; let query = sqlx::query(q).bind(&data.username); let result = query.fetch_one(&state.pool).await.ok(); if let Some(row) = result { let phc_from_db = row.get::("password"); let pwhash = PasswordHash::new(&phc_from_db).unwrap_or_else(|_| { warn!( "Invalid hash for user {} fetched from database (not a valid PHC string)", data.username ); panic!(); }); match Argon2::default().verify_password(data.password.as_bytes(), &pwhash) { Ok(_) => { info!("User {} logged in", data.username); let token = token_factory(&data.username).unwrap(); println!("{:?}", token); return Ok(HttpResponse::Ok().json(LoginResponse { username: data.username.clone(), token: token, })); } Err(_) => { info!("User \"{}\" failed to log in", data.username); return Ok(HttpResponse::BadRequest().json("Error")); } } } Ok(HttpResponse::Ok().json("What happens here???")) }