diff --git a/Cargo.lock b/Cargo.lock index f560ef0..bca33e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -517,6 +517,8 @@ dependencies = [ name = "fossil" version = "0.1.0" dependencies = [ + "rand", + "rand_hc", "rocket", "rocket_db_pools", "sha256", @@ -1341,6 +1343,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_hc" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b363d4f6370f88d62bf586c80405657bde0f0e1b8945d47d2ad59b906cb4f54" +dependencies = [ + "rand_core", +] + [[package]] name = "redox_syscall" version = "0.4.1" diff --git a/Cargo.toml b/Cargo.toml index f8e70cb..4183880 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +rand = "0.8.5" +rand_hc = "0.3.2" rocket = {version="0.5.0",features=["secrets","json"]} rocket_db_pools = {version="0.1.0",features=["sqlx_postgres"]} sha256 = "1.5.0" diff --git a/src/main.rs b/src/main.rs index bbfb6a0..71b00e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -74,38 +74,66 @@ async fn getuser(db: Connection, username: String) -> String { let user = User::get_by_username(db, &username).await; match user { Some(user) => format!( - "{}\n{}\n{}\n{}", + "id: {}\nusername: {}\nhashed password: {}\ntoken: {}", user.id, user.username, user.password, - user.token.is_some() + match user.token { + Some(t) => t, + None => "no token".to_string() + } ), None => format!("User {} doesn't exist.", &username), } } -#[post("/login", data = "")] -async fn login(db: Connection, info: Json, cookies: &CookieJar<'_>) -> &'static str { +#[get("/account")] +async fn account(db: Connection, cookies: &CookieJar<'_>) -> String { let token = cookies.get_private("token"); match token { Some(t) => { - if t.value_trimmed() == "skyetoken" { - "logged in with token" + let user = User::get_by_token(db, t.to_string().split("=").collect::>()[1].to_string() /*GOD I LOVE RUST*/).await; + format!("Username: {}", user.username) + }, + None => { + format!("Not logged in") + } + } +} + +#[post("/login", data = "")] +async fn login(db: Connection, db2: Connection, info: Json, cookies: &CookieJar<'_>) -> String { + let token = cookies.get_private("token"); + match token { + Some(t) => { + if User::get_by_token(db, t.to_string()).await.exists() /*god i fucking love rust, this function literally just returns true*/ { + "logged in with token".to_string() } else { - "unknown token" + "unknown token".to_string() } } None => { - // just to be clear this is Not A Good Implementation of this - // the same token for everyone is a Bad Fucking Idea - // but i'm just doing this to make sure that it. like. works. - // and it does!!! - let user = User::get_by_username(db, &info.username).await; - if user.is_some() && user.expect("actually how").password == sha256::digest(&info.password) { - cookies.add_private(("token", "skyetoken")); - "logged in!" - } else { - "invalid login info :(" + match User::get_by_username(db, &info.username).await { + Some(user) => { + if user.password == sha256::digest(&info.password) { + match user.token { + Some(t) => {cookies.add_private(("token", t)); "Logged in".to_string()}, + None => { + match user.set_new_token(db2).await { + Ok(t) => { + cookies.add_private(("token", t)); + "logged in".to_string() + }, + Err(why) => why, + } + } + } + } else { + String::from("Invalid username or password (to those whining about why it doesn't tell you if the username or password is incorrect, security)") + } + } + None => + String::from("Invalid username or password (to those whining about why it doesn't tell you if the username or password is incorrect, security)"), } } } @@ -186,7 +214,7 @@ async fn main() { .attach(AdHoc::on_ignite("DB Migrations", migrate)) .mount( "/", - routes![hello, get_book, delay, login, logout, dbtest, dbcreate, createuser, getuser], + routes![hello, get_book, delay, login, logout, dbtest, dbcreate, createuser, getuser, account], ) .register("/", catchers![default_catcher]) .mount("/login", FileServer::from("/srv/web")) diff --git a/src/tables.rs b/src/tables.rs index cbf3bc2..a5b4919 100644 --- a/src/tables.rs +++ b/src/tables.rs @@ -1,3 +1,4 @@ +use rand::{SeedableRng, RngCore}; use rocket_db_pools::sqlx::Executor; use rocket_db_pools::Connection; use sqlx::FromRow; @@ -97,6 +98,7 @@ impl User { let res = db .fetch_one(sqlx::query("SELECT * FROM users WHERE token = $1;").bind(token)) .await + // TODO: this errors sometimes i dont know why .unwrap(); User { id: res.get::("id"), @@ -120,4 +122,20 @@ impl User { Err(_) => None, } } + pub async fn set_new_token(&self, mut db: Connection) -> Result { + let token_end = rand_hc::Hc128Rng::from_entropy().next_u64(); + let token_start = sha256::digest(&self.username); + + let token = sha256::digest(format!("{token_start}-{token_end}")); + + match db.fetch_one(sqlx::query("UPDATE users SET token = $1 WHERE id = $2").bind(&token).bind(self.id)).await { + Ok(_) => Ok(token), + Err(why) => Err(why.to_string()) + } + } + + // god i fucking love rust + pub fn exists(&self) -> bool { + true + } }