token cookie, register

This commit is contained in:
2024-09-25 23:13:15 +02:00
parent 8b09406339
commit bcf3000bcc
2 changed files with 50 additions and 8 deletions

View File

@@ -4,5 +4,6 @@ id INTEGER PRIMARY KEY NOT NULL,
username TEXT NOT NULL, username TEXT NOT NULL,
saltyhash text NOT NULL, saltyhash text NOT NULL,
permissions INTEGER DEFAULT 0, permissions INTEGER DEFAULT 0,
token TEXT NOT NULL token TEXT NOT NULL,
UNIQUE(id, username)
) )

View File

@@ -1,6 +1,6 @@
use bytes::Buf; use bytes::Buf;
use bytes::Bytes; use bytes::Bytes;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Days, Utc};
use futures; use futures;
use http_body_util::{BodyExt, Full}; use http_body_util::{BodyExt, Full};
use hyper::body::{Body, Incoming}; use hyper::body::{Body, Incoming};
@@ -20,7 +20,7 @@ use std::str::FromStr;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::SystemTime; use std::time::SystemTime;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use rand::distributions::Standard; use rand::distributions::{DistString, Alphanumeric};
use argon2::{ use argon2::{
password_hash::{ password_hash::{
rand_core::OsRng, rand_core::OsRng,
@@ -206,7 +206,7 @@ async fn post(req: Request<Incoming>, db: Arc<Mutex<SqlitePool>>) -> Result<Resp
login(req, db).await login(req, db).await
}, },
"/register" => { "/register" => {
not_found().await register(req, db).await
}, },
_ => { _ => {
not_found().await not_found().await
@@ -247,6 +247,9 @@ async fn login(req: Request<Incoming>, db: Arc<Mutex<SqlitePool>>) -> Result<Res
return Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request"))).unwrap()); return Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request"))).unwrap());
} }
let data = data.unwrap(); let data = data.unwrap();
if !check_username(&data.username) {
return Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request"))).unwrap());
}
let pool = db.clone().lock().unwrap().clone(); let pool = db.clone().lock().unwrap().clone();
let mut conn = pool.acquire().await.unwrap(); 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; let result = sqlx::query!(r#"SELECT * FROM users WHERE username=?1"#, data.username).fetch_optional(&mut *conn).await;
@@ -256,7 +259,10 @@ async fn login(req: Request<Incoming>, db: Arc<Mutex<SqlitePool>>) -> Result<Res
let hash = PasswordHash::new(&user.saltyhash).unwrap(); let hash = PasswordHash::new(&user.saltyhash).unwrap();
match argon.verify_password(data.password.as_bytes(), &hash) { match argon.verify_password(data.password.as_bytes(), &hash) {
Ok(()) => { Ok(()) => {
Ok(Response::builder().header("Set-Cookie", format!("token={}", user.token)).body(Full::new(Bytes::from("Ok"))).unwrap()) let date: DateTime<Utc> = DateTime::from(SystemTime::now());
let date = date.checked_add_days(Days::new(7)).unwrap();
println!("{}", date.to_rfc2822());
Ok(Response::builder().header("Set-Cookie", format!("token={}; Expires={}; Secure; HttpOnly; SameSite=Strict", user.token, date.to_rfc2822())).body(Full::new(Bytes::from("Ok"))).unwrap())
}, },
Err(_) => { Err(_) => {
Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request"))).unwrap()) Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request"))).unwrap())
@@ -266,12 +272,47 @@ async fn login(req: Request<Incoming>, db: Arc<Mutex<SqlitePool>>) -> Result<Res
Ok(None) => { Ok(None) => {
Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request"))).unwrap()) 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()) } Err(_) => { Ok(Response::builder().status(StatusCode::INTERNAL_SERVER_ERROR).body(Full::new(Bytes::from("Server Error"))).unwrap()) }
} }
} }
async fn register(req: Request<Incoming>, db: Arc<Mutex<SqlitePool>>) -> Result<Response<Full<Bytes>>, Error> { async fn register(req: Request<Incoming>, db: Arc<Mutex<SqlitePool>>) -> Result<Response<Full<Bytes>>, Error> {
todo!() 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();
if !check_username(&data.username) {
return Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request"))).unwrap());
}
let pool = db.clone().lock().unwrap().clone();
let mut conn = pool.acquire().await.unwrap();
let exists = sqlx::query!(r#"SELECT id FROM users WHERE username=?1"#, data.username).fetch_optional(&mut *conn).await;
if exists.unwrap().is_some() {
return Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Full::new(Bytes::from("Bad Request"))).unwrap());
}
let argon2 = Argon2::default();
let hash = argon2.hash_password(data.password.as_bytes(), &SaltString::generate(&mut OsRng)).unwrap().to_string();
let token = Alphanumeric.sample_string(&mut OsRng, 256);
println!("{}", token);
let result = sqlx::query!(r#"INSERT INTO users ( username, saltyhash, permissions, token) VALUES ( ?1, ?2, ?3, ?4 )"#, data.username, hash, 0, token).execute(&mut *conn).await;
match result {
Ok(_) => Ok(Response::builder().body(Full::new(Bytes::from(""))).unwrap()),
Err(_) => { Ok(Response::builder().status(StatusCode::INTERNAL_SERVER_ERROR).body(Full::new(Bytes::from("Server Error"))).unwrap()) }
}
}
fn check_username(username: &String) -> bool {
if username.len() > 21 {
return false;
}
for x in username.chars() {
if !x.is_ascii_alphanumeric() {
return false;
}
}
true
} }
async fn not_found() -> Result<Response<Full<Bytes>>, Error> { async fn not_found() -> Result<Response<Full<Bytes>>, Error> {