From f30af57934a48743f77a15520d5559522ea760cf Mon Sep 17 00:00:00 2001 From: code002lover Date: Tue, 2 Dec 2025 20:30:10 +0100 Subject: [PATCH] feat: Implement game opinion functionality, update authentication to store username in token, and protect user list with a mutex. --- backend/src/auth.rs | 17 +++++++++---- backend/src/main.rs | 58 +++++++++++++++++++++++++++++++++++++++----- protobuf/items.proto | 7 +++++- 3 files changed, 70 insertions(+), 12 deletions(-) diff --git a/backend/src/auth.rs b/backend/src/auth.rs index 7246c14..7ee6957 100644 --- a/backend/src/auth.rs +++ b/backend/src/auth.rs @@ -20,7 +20,10 @@ impl AuthState { #[derive(Debug)] #[allow(dead_code)] -pub struct Token(pub String); +pub struct Token { + pub token: String, + pub username: String, +} #[rocket::async_trait] impl<'r> rocket::request::FromRequest<'r> for Token { @@ -38,8 +41,11 @@ impl<'r> rocket::request::FromRequest<'r> for Token { let state = request.guard::<&State>().await.unwrap(); let tokens = state.tokens.lock().unwrap(); - if tokens.contains_key(token) { - return rocket::request::Outcome::Success(Token(token.to_string())); + if let Some(username) = tokens.get(token) { + return rocket::request::Outcome::Success(Token { + token: token.to_string(), + username: username.clone(), + }); } } @@ -53,12 +59,13 @@ impl<'r> rocket::request::FromRequest<'r> for Token { #[post("/login", data = "")] pub fn login( state: &State, - user_list: &State>, + user_list: &State>>, request: Proto, ) -> items::LoginResponse { let req = request.into_inner(); + let users = user_list.lock().unwrap(); - if let Some(user) = user_list.iter().find(|u| u.name == req.username) + if let Some(user) = users.iter().find(|u| u.person.name == req.username) && bcrypt::verify(&req.password, &user.password_hash).unwrap_or(false) { let token = Uuid::new_v4().to_string(); diff --git a/backend/src/main.rs b/backend/src/main.rs index 4e28c71..7565938 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -1,4 +1,5 @@ use rocket::fs::FileServer; +use std::sync::Mutex; use crate::items::Game; @@ -29,19 +30,63 @@ impl std::ops::Deref for User { #[get("/")] fn get_user( _token: auth::Token, - user_list: &rocket::State>, + user_list: &rocket::State>>, name: String, ) -> Option { - user_list + let users = user_list.lock().unwrap(); + users .iter() .find(|user| user.person.name == name) .map(|u| u.person.clone()) } #[get("/")] -fn get_users(_token: auth::Token, user_list: &rocket::State>) -> items::PersonList { +fn get_users( + _token: auth::Token, + user_list: &rocket::State>>, +) -> items::PersonList { + let users = user_list.lock().unwrap(); items::PersonList { - person: user_list.inner().iter().map(|u| u.person.clone()).collect(), + person: users.iter().map(|u| u.person.clone()).collect(), + } +} + +#[get("/game/")] +fn get_game( + _token: auth::Token, + game_list: &rocket::State<Vec<Game>>, + title: String, +) -> Option<items::Game> { + game_list.iter().find(|g| g.title == title).cloned() +} + +#[post("/opinion", data = "<req>")] +fn add_opinion( + token: auth::Token, + user_list: &rocket::State<Mutex<Vec<User>>>, + req: proto_utils::Proto<items::AddOpinionRequest>, +) -> Option<items::Person> { + let mut users = user_list.lock().unwrap(); + if let Some(user) = users.iter_mut().find(|u| u.person.name == token.username) { + let req = req.into_inner(); + let opinion = items::Opinion { + title: req.game_title.clone(), + would_play: req.would_play, + }; + + if let Some(existing) = user + .person + .opinion + .iter_mut() + .find(|o| o.title == req.game_title) + { + existing.would_play = req.would_play; + } else { + user.person.opinion.push(opinion); + } + Some(user.person.clone()) + } else { + None } } @@ -84,9 +129,10 @@ fn rocket() -> _ { }); rocket::build() - .manage(user_list) + .manage(Mutex::new(user_list)) .manage(auth::AuthState::new()) - .mount("/api", routes![get_users, get_user]) + .manage(game_list) + .mount("/api", routes![get_users, get_user, get_game, add_opinion]) .mount( "/auth", routes![auth::login, auth::logout, auth::get_auth_status], diff --git a/protobuf/items.proto b/protobuf/items.proto index 239b5a3..c4c68b7 100644 --- a/protobuf/items.proto +++ b/protobuf/items.proto @@ -64,7 +64,12 @@ service AuthService { message GameRequest { string title = 1; } +message AddOpinionRequest { + string game_title = 1; + bool would_play = 2; +} + service MainService { rpc GetGame(GameRequest) returns (Game); - rpc AddOpinion(GameRequest) returns (Person); + rpc AddOpinion(AddOpinionRequest) returns (Person); } \ No newline at end of file