This commit is contained in:
2024-09-24 22:19:55 +02:00
parent 70d4e9ca20
commit 8b09406339
5 changed files with 81 additions and 11 deletions

View File

@@ -3,7 +3,7 @@ use bytes::Bytes;
use chrono::{DateTime, Utc};
use futures;
use http_body_util::{BodyExt, Full};
use hyper::body::Incoming;
use hyper::body::{Body, Incoming};
use hyper::server::conn::http1;
use hyper::service::service_fn;
use hyper::{Error, Method, Request, Response, StatusCode};
@@ -20,7 +20,14 @@ use std::str::FromStr;
use std::sync::{Arc, Mutex};
use std::time::SystemTime;
use tokio::net::TcpListener;
use rand::distributions::Standard;
use argon2::{
password_hash::{
rand_core::OsRng,
PasswordHash, PasswordHasher, PasswordVerifier, SaltString
},
Argon2
};
#[cfg(target_os = "linux")]
use daemonize::Daemonize;
#[derive(Serialize, Deserialize)]
@@ -29,7 +36,7 @@ struct Player {
name: String,
}
#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize)]
struct Vote {
plus_player_id: i64,
plus_nickname: String,
@@ -39,6 +46,19 @@ struct Vote {
minus_reason: String,
}
#[derive(Serialize, Deserialize)]
struct User {
username: String,
saltyhash: String,
permissions: i64,
token: String
}
#[derive(Serialize, Deserialize)]
struct Login {
username: String,
password: String
}
#[derive(Serialize, Deserialize)]
struct Settings {
database_url: String,
@@ -178,13 +198,27 @@ async fn get_votes(req: &Request<Incoming>, db: Arc<Mutex<SqlitePool>>) -> Vec<V
async fn post(req: Request<Incoming>, db: Arc<Mutex<SqlitePool>>) -> Result<Response<Full<Bytes>>, Error> {
let path = req.uri().path();
if path != "/post" {
return Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request (Bad Route)"))).unwrap());
match path {
"/vote" => {
post_vote(req, db).await
},
"/login" => {
login(req, db).await
},
"/register" => {
not_found().await
},
_ => {
not_found().await
}
}
}
async fn post_vote(req: Request<Incoming>, db: Arc<Mutex<SqlitePool>>) -> Result<Response<Full<Bytes>>, Error> {
let body = req.into_body().collect().await?;
let data: Result<Vote, serde_json::Error> = from_reader(body.aggregate().reader());
if data.is_err() {
return Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request (Bad Data)"))).unwrap());
return Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request"))).unwrap());
}
let vote = data.unwrap();
let timestamp: DateTime<Utc> = DateTime::from(SystemTime::now());
@@ -206,6 +240,40 @@ async fn post(req: Request<Incoming>, db: Arc<Mutex<SqlitePool>>) -> Result<Resp
Ok(Response::builder().body(Full::new(Bytes::new())).unwrap())
}
async fn login(req: Request<Incoming>, db: Arc<Mutex<SqlitePool>>) -> Result<Response<Full<Bytes>>, Error> {
let body = req.into_body().collect().await;
let data: Result<Login, serde_json::Error> = from_reader(body?.aggregate().reader());
if data.is_err() {
return Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request"))).unwrap());
}
let data = data.unwrap();
let pool = db.clone().lock().unwrap().clone();
let mut conn = pool.acquire().await.unwrap();
let result = sqlx::query!(r#"SELECT * FROM users WHERE username=?1"#, data.username).fetch_optional(&mut *conn).await;
match result {
Ok(Some(user)) => {
let argon = Argon2::default();
let hash = PasswordHash::new(&user.saltyhash).unwrap();
match argon.verify_password(data.password.as_bytes(), &hash) {
Ok(()) => {
Ok(Response::builder().header("Set-Cookie", format!("token={}", user.token)).body(Full::new(Bytes::from("Ok"))).unwrap())
},
Err(_) => {
Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request"))).unwrap())
}
}
},
Ok(None) => {
Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request"))).unwrap())
}
Err(e) => { Ok(Response::builder().status(StatusCode::INTERNAL_SERVER_ERROR).body(Full::new(Bytes::from("Bad Request"))).unwrap()) }
}
}
async fn register(req: Request<Incoming>, db: Arc<Mutex<SqlitePool>>) -> Result<Response<Full<Bytes>>, Error> {
todo!()
}
async fn not_found() -> Result<Response<Full<Bytes>>, Error> {
let mut file_path = env::current_dir().expect("Could not get app directory.");
file_path.push("static/html/404.html");