From cdaf5febb7cafbc1c20d19abb3668db471069bb3 Mon Sep 17 00:00:00 2001 From: reidlab Date: Thu, 21 Sep 2023 18:43:41 -0700 Subject: [PATCH] some type of authentication for the site --- Cargo.lock | 126 ++++++++++++++++++++++++ Cargo.toml | 4 +- public/style.css | 23 +++++ readme.md | 3 +- src/endpoints/accounts/login_account.rs | 2 +- src/helpers.rs | 3 +- src/helpers/templates.rs | 19 ++++ src/main.rs | 7 +- src/template_endpoints.rs | 2 + src/template_endpoints/login.rs | 68 +++++++++++++ src/template_endpoints/logout.rs | 11 +++ templates/login.html.hbs | 55 +++++++++++ templates/reupload.html.hbs | 2 +- 13 files changed, 318 insertions(+), 7 deletions(-) create mode 100644 src/helpers/templates.rs create mode 100644 src/template_endpoints/login.rs create mode 100644 src/template_endpoints/logout.rs create mode 100644 templates/login.html.hbs diff --git a/Cargo.lock b/Cargo.lock index 4d3039f..4d7c018 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,41 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "aho-corasick" version = "1.0.4" @@ -161,13 +196,29 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "cookie" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" dependencies = [ + "aes-gcm", + "base64", + "hkdf", "percent-encoding", + "rand", + "sha2", + "subtle", "time", "version_check", ] @@ -232,9 +283,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core", "typenum", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "deranged" version = "0.3.8" @@ -571,6 +632,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "ghash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +dependencies = [ + "opaque-debug", + "polyval", +] + [[package]] name = "glob" version = "0.3.1" @@ -628,6 +699,24 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "http" version = "0.2.9" @@ -756,6 +845,15 @@ dependencies = [ "libc", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "ipnet" version = "2.8.0" @@ -996,6 +1094,12 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "openssl" version = "0.10.57" @@ -1184,6 +1288,18 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "polyval" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2023,6 +2139,16 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "url" version = "2.4.1" diff --git a/Cargo.toml b/Cargo.toml index 5161ef9..2de4816 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,8 @@ maplit = "1.0.2" password-auth = "0.3.0" rand = "0.8.5" regex = "1.9.4" -reqwest = { version = "0.11.20", features = ["blocking"] } -rocket = "=0.5.0-rc.3" +reqwest = "0.11.20" +rocket = { version = "=0.5.0-rc.3", features = ["secrets"]} rocket_dyn_templates = { version = "0.1.0-rc.3", features = ["handlebars"] } roxmltree = "0.18.0" serde = { version = "1.0.188", features = ["derive"] } diff --git a/public/style.css b/public/style.css index f2dfc52..bee5c97 100644 --- a/public/style.css +++ b/public/style.css @@ -44,4 +44,27 @@ pre { a { color: #89b4fa; +} + +.error { + color: #f38ba8; +} + +.success { + color: #a6e3a1; +} + +.fancy-button { + outline: 0; + border: none; + background-color: #89b4fa; + color: #11111b; + font-size: 1.2rem; + padding: 0.4em 0.8em; + margin: 0.5em; + border-radius: 16px; + + cursor: pointer; + + transition: 0.1s background-color; } \ No newline at end of file diff --git a/readme.md b/readme.md index c830d85..38ed40e 100644 --- a/readme.md +++ b/readme.md @@ -38,4 +38,5 @@ i've run out of ideas. - ip actions - better song support - authentication caching (ip? redis?) -- use log instead of println \ No newline at end of file +- use log instead of println +- store everything in 1 cookie? \ No newline at end of file diff --git a/src/endpoints/accounts/login_account.rs b/src/endpoints/accounts/login_account.rs index 87a084f..822f6a8 100644 --- a/src/endpoints/accounts/login_account.rs +++ b/src/endpoints/accounts/login_account.rs @@ -45,7 +45,7 @@ pub fn login_account(input: Form) -> status::Custom<&'static s let query_result = accounts .select(id) .filter(username.eq(input.userName.clone())) - .get_result::(connection); + .get_result::(connection); match query_result { Ok(account_id_val) => { diff --git a/src/helpers.rs b/src/helpers.rs index 1c3391f..67be0d5 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -4,4 +4,5 @@ pub mod difficulty; pub mod encryption; pub mod format; pub mod levels; -pub mod reupload; \ No newline at end of file +pub mod reupload; +pub mod templates; \ No newline at end of file diff --git a/src/helpers/templates.rs b/src/helpers/templates.rs new file mode 100644 index 0000000..20eac2e --- /dev/null +++ b/src/helpers/templates.rs @@ -0,0 +1,19 @@ +macro_rules! auth { + ($cookies: expr) => { + match $cookies.get_private("blackmail_data") { + Some(cookie_val) => { + let parts = cookie_val.value().split(":").collect::>(); + + let username = parts[0].to_string(); + let account_id = parts[1].parse::().expect("account id is not an integer! this should NOT happen!"); + let user_id = parts[2].parse::().expect("user id is not an integer! this should NOT happen!"); + + (true, Some(username), Some(account_id), Some(user_id)) + } + None => { + (false, None, None, None) + } + } + } +} +pub(crate) use auth; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index f8abf9b..a0455ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -53,7 +53,12 @@ fn rocket() -> _ { template_endpoints::index::index, template_endpoints::reupload::post_reupload, - template_endpoints::reupload::get_reupload + template_endpoints::reupload::get_reupload, + + template_endpoints::login::post_login, + template_endpoints::login::get_login, + + template_endpoints::logout::logout, ]) // assets .mount("/", routes![ diff --git a/src/template_endpoints.rs b/src/template_endpoints.rs index 50567bf..89eada7 100644 --- a/src/template_endpoints.rs +++ b/src/template_endpoints.rs @@ -1,2 +1,4 @@ pub mod index; +pub mod login; +pub mod logout; pub mod reupload; \ No newline at end of file diff --git a/src/template_endpoints/login.rs b/src/template_endpoints/login.rs new file mode 100644 index 0000000..cd091ef --- /dev/null +++ b/src/template_endpoints/login.rs @@ -0,0 +1,68 @@ +use rocket::response::Redirect; + +use rocket_dyn_templates::{Template, context}; + +use rocket::form::Form; + +use rocket::http::{Cookie, CookieJar}; + +use diesel::prelude::*; + +use crate::db; +use crate::helpers; + +#[derive(FromForm)] +pub struct FormLogin { + username: String, + password: String +} + +#[post("/login", data = "")] +pub fn post_login(jar: &CookieJar<'_>, input: Form) -> Template { + let connection = &mut db::establish_connection_pg(); + + use crate::schema::accounts::dsl::*; + + let result = accounts + .select((id, username)) + .filter(username.eq(input.username.clone())) + .get_result::<(i32, String), >(connection); + + match result { + Ok(account_id_username_val) => { + match helpers::accounts::auth(account_id_username_val.0, Some(input.password.clone()), None, None) { + Ok(account_id_user_id_val) => { + jar.add_private(Cookie::build( + "blackmail_data", + format!("{}:{}:{}", account_id_username_val.1, account_id_user_id_val.0, account_id_user_id_val.1)) + .finish()); + + return Template::render("login", context! { + success: "Successfully logged in" + }) + }, + Err(_) => { + return Template::render("login", context! { + error: "Invalid password" + }) + } + } + } + Err(_) => { + return Template::render("login", context! { + error: "Invalid username or password" + }) + } + } +} + +#[get("/login")] +pub fn get_login(cookies: &CookieJar<'_>) -> Result { + let (logged_in, _username, _account_id, _user_id) = crate::helpers::templates::auth!(cookies); + + if logged_in { + Ok(Redirect::to("/")) + } else { + Err(Template::render("login", context! { })) + } +} \ No newline at end of file diff --git a/src/template_endpoints/logout.rs b/src/template_endpoints/logout.rs new file mode 100644 index 0000000..83b0a28 --- /dev/null +++ b/src/template_endpoints/logout.rs @@ -0,0 +1,11 @@ +use rocket::http::{Cookie, CookieJar}; +use rocket::response::Redirect; + +#[post("/accounts/logout")] +pub fn logout(jar: &CookieJar<'_>) -> Redirect { + jar.remove_private(Cookie::named("username")); + jar.remove_private(Cookie::named("account_id")); + jar.remove_private(Cookie::named("user_id")); + + Redirect::to("/") +} \ No newline at end of file diff --git a/templates/login.html.hbs b/templates/login.html.hbs new file mode 100644 index 0000000..127901b --- /dev/null +++ b/templates/login.html.hbs @@ -0,0 +1,55 @@ + + + + + + + + + Login + + + + +
+ +
+ + + + + + {{#if error}} +
{{error}}
+ {{/if}} + {{#if success}} +
{{success}}
+ {{/if}} + + +
+ + + \ No newline at end of file diff --git a/templates/reupload.html.hbs b/templates/reupload.html.hbs index 98da58d..282ea38 100644 --- a/templates/reupload.html.hbs +++ b/templates/reupload.html.hbs @@ -13,7 +13,7 @@

Level Reupload

{{#if error}} -
Error while uploading: {{ error }}

+
Error while uploading: {{ error }}

{{/if}} {{#if level_id}}
Uploaded successfully! Level ID: {{ level_id }}