Merge of dev-auth #1

Merged
AINDUSTRIES merged 28 commits from dev-auth into main 2024-10-05 13:58:45 +00:00
5 changed files with 81 additions and 11 deletions
Showing only changes of commit 8b09406339 - Show all commits

View File

@@ -22,6 +22,7 @@ chrono = { version = "0.4.38", features = ["alloc"]}
futures-util = "0.3.30"
h2 = "0.4.6"
argon2 = "0.5.3"
rand = "0.8.1"
[target.'cfg(unix)'.dependencies]
daemonize = "0.5.0"

View File

@@ -2,8 +2,7 @@ CREATE TABLE IF NOT EXISTS users
(
id INTEGER PRIMARY KEY NOT NULL,
username TEXT NOT NULL,
salt text NOT NULL,
hash TEXT NOT NULL,
saltyhash text NOT NULL,
permissions INTEGER DEFAULT 0,
token TEXT
token TEXT NOT NULL
)

View File

@@ -2,5 +2,7 @@
"/": "static/html/index.html",
"/results": "static/html/results.html",
"/archives": "static/html/archives.html",
"/favicon.ico": "static/img/favicon.ico"
"/favicon.ico": "static/img/favicon.ico",
"/login": "static/html/login.html",
"/register": "static/html/register.html"
}

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");

View File

@@ -59,7 +59,7 @@ async function main() {
true, "warning");
return;
}
if (await fetch("/post", {
if (await fetch("/vote", {
method: "post", body: JSON.stringify(vote)
})
.then(r => r.status) === 200) {