From d38f8891f5be40bb7512d0096a585dd89df8669c Mon Sep 17 00:00:00 2001 From: code002lover Date: Sun, 30 Nov 2025 17:54:58 +0100 Subject: [PATCH] mock auth --- backend/Cargo.lock | 73 +++++++++++++++++++++++++++++++ backend/Cargo.toml | 1 + backend/src/auth.rs | 89 ++++++++++++++++++++++++++++++++++++++ backend/src/main.rs | 9 ++++ backend/src/proto_utils.rs | 50 +++++++++++++++++++++ protobuf/items.proto | 1 + 6 files changed, 223 insertions(+) create mode 100644 backend/src/auth.rs create mode 100644 backend/src/proto_utils.rs diff --git a/backend/Cargo.lock b/backend/Cargo.lock index de82e28..84556ba 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -110,6 +110,7 @@ dependencies = [ "prost-types", "rocket", "rocket_prost_responder_derive", + "uuid", ] [[package]] @@ -124,6 +125,12 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + [[package]] name = "bytemuck" version = "1.24.0" @@ -656,6 +663,16 @@ dependencies = [ "libc", ] +[[package]] +name = "js-sys" +version = "0.3.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -1920,6 +1937,17 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "uuid" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +dependencies = [ + "getrandom 0.3.4", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "valuable" version = "0.1.1" @@ -1953,6 +1981,51 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasm-bindgen" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +dependencies = [ + "unicode-ident", +] + [[package]] name = "windows" version = "0.48.0" diff --git a/backend/Cargo.toml b/backend/Cargo.toml index c639655..04cd798 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -9,6 +9,7 @@ prost-types = "0.14.1" rocket = { git = "https://github.com/rwf2/Rocket", rev = "504efef179622df82ba1dbd37f2e0d9ed2b7c9e4" } bytes = "1" rocket_prost_responder_derive = { path = "rocket_prost_responder_derive" } +uuid = { version = "1.10.0", features = ["v4"] } [build-dependencies] prost-build = "0.14.1" diff --git a/backend/src/auth.rs b/backend/src/auth.rs new file mode 100644 index 0000000..9589cb6 --- /dev/null +++ b/backend/src/auth.rs @@ -0,0 +1,89 @@ +use rocket::State; +use std::collections::HashMap; +use std::sync::Mutex; +use uuid::Uuid; +use crate::items; +use crate::proto_utils::Proto; + +pub struct AuthState { + // Map token -> username + tokens: Mutex>, +} + +impl AuthState { + pub fn new() -> Self { + Self { + tokens: Mutex::new(HashMap::new()), + } + } +} + +#[post("/login", data = "")] +pub fn login( + state: &State, + request: Proto, +) -> items::LoginResponse { + let req = request.into_inner(); + // Simple mock authentication: allow any non-empty username/password + if !req.username.is_empty() && !req.password.is_empty() { + let token = Uuid::new_v4().to_string(); + let mut tokens = state.tokens.lock().unwrap(); + tokens.insert(token.clone(), req.username); + + items::LoginResponse { + token, + success: true, + message: "Login successful".to_string(), + } + } else { + items::LoginResponse { + token: "".to_string(), + success: false, + message: "Invalid credentials".to_string(), + } + } +} + +#[post("/logout", data = "")] +pub fn logout( + state: &State, + request: Proto, +) -> items::LogoutResponse { + let req = request.into_inner(); + let mut tokens = state.tokens.lock().unwrap(); + + if tokens.remove(&req.token).is_some() { + items::LogoutResponse { + success: true, + message: "Logged out successfully".to_string(), + } + } else { + items::LogoutResponse { + success: false, + message: "Invalid token".to_string(), + } + } +} + +#[post("/get_auth_status", data = "")] +pub fn get_auth_status( + state: &State, + request: Proto, +) -> items::AuthStatusResponse { + let req = request.into_inner(); + let tokens = state.tokens.lock().unwrap(); + + if let Some(username) = tokens.get(&req.token) { + items::AuthStatusResponse { + authenticated: true, + username: username.clone(), + message: "Authenticated".to_string(), + } + } else { + items::AuthStatusResponse { + authenticated: false, + username: "".to_string(), + message: "Not authenticated".to_string(), + } + } +} \ No newline at end of file diff --git a/backend/src/main.rs b/backend/src/main.rs index f1cd21c..2cfa4f4 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -7,6 +7,9 @@ pub mod items { include!(concat!(env!("OUT_DIR"), "/items.rs")); } +mod auth; +mod proto_utils; + #[get("/")] fn get_user(user_list: &rocket::State>, name: String) -> Option { user_list.iter().find(|user| user.name == name).cloned() @@ -53,6 +56,7 @@ fn rocket() -> _ { min_players: 1, max_players: 90, price: 0, + remote_id: 0, }), would_play: true, }], @@ -60,7 +64,12 @@ fn rocket() -> _ { rocket::build() .manage(user_list) + .manage(auth::AuthState::new()) .mount("/api", routes![get_users, get_user]) + .mount( + "/auth", + routes![auth::login, auth::logout, auth::get_auth_status], + ) .mount("/", routes![index_fallback]) .mount("/", FileServer::new("../frontend/dist")) } diff --git a/backend/src/proto_utils.rs b/backend/src/proto_utils.rs new file mode 100644 index 0000000..925b0f3 --- /dev/null +++ b/backend/src/proto_utils.rs @@ -0,0 +1,50 @@ +use rocket::data::{Data, FromData, Outcome, ToByteUnit}; +use rocket::http::{Status, ContentType}; +use rocket::Request; +use prost::Message; +use std::ops::{Deref, DerefMut}; + +pub struct Proto(pub T); + +impl Proto { + pub fn into_inner(self) -> T { + self.0 + } +} + +impl Deref for Proto { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Proto { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +#[rocket::async_trait] +impl<'r, T: Message + Default> FromData<'r> for Proto { + type Error = String; + + async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> { + if req.content_type() != Some(&ContentType::new("application", "protobuf")) { + return Outcome::Forward((data, Status::NotFound)); + } + + let limit = req.limits().get("protobuf").unwrap_or(1.mebibytes()); + let bytes = match data.open(limit).into_bytes().await { + Ok(bytes) if bytes.is_complete() => bytes.into_inner(), + Ok(_) => return Outcome::Error((Status::PayloadTooLarge, "Payload too large".into())), + Err(e) => return Outcome::Error((Status::InternalServerError, e.to_string())), + }; + + match T::decode(&bytes[..]) { + Ok(msg) => Outcome::Success(Proto(msg)), + Err(e) => Outcome::Error((Status::UnprocessableEntity, e.to_string())), + } + } +} \ No newline at end of file diff --git a/protobuf/items.proto b/protobuf/items.proto index d4fbdbe..35bd3f4 100644 --- a/protobuf/items.proto +++ b/protobuf/items.proto @@ -19,6 +19,7 @@ message Game { uint32 min_players = 4; uint32 max_players = 5; uint32 price = 6; + uint64 remote_id = 7; } enum Source {