feat: Implement game opinion functionality, update authentication to store username in token, and protect user list with a mutex.
This commit is contained in:
parent
3ecc971e8f
commit
f30af57934
@ -20,7 +20,10 @@ impl AuthState {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct Token(pub String);
|
pub struct Token {
|
||||||
|
pub token: String,
|
||||||
|
pub username: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[rocket::async_trait]
|
#[rocket::async_trait]
|
||||||
impl<'r> rocket::request::FromRequest<'r> for Token {
|
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<AuthState>>().await.unwrap();
|
let state = request.guard::<&State<AuthState>>().await.unwrap();
|
||||||
let tokens = state.tokens.lock().unwrap();
|
let tokens = state.tokens.lock().unwrap();
|
||||||
|
|
||||||
if tokens.contains_key(token) {
|
if let Some(username) = tokens.get(token) {
|
||||||
return rocket::request::Outcome::Success(Token(token.to_string()));
|
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 = "<request>")]
|
#[post("/login", data = "<request>")]
|
||||||
pub fn login(
|
pub fn login(
|
||||||
state: &State<AuthState>,
|
state: &State<AuthState>,
|
||||||
user_list: &State<Vec<crate::User>>,
|
user_list: &State<Mutex<Vec<crate::User>>>,
|
||||||
request: Proto<items::LoginRequest>,
|
request: Proto<items::LoginRequest>,
|
||||||
) -> items::LoginResponse {
|
) -> items::LoginResponse {
|
||||||
let req = request.into_inner();
|
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)
|
&& bcrypt::verify(&req.password, &user.password_hash).unwrap_or(false)
|
||||||
{
|
{
|
||||||
let token = Uuid::new_v4().to_string();
|
let token = Uuid::new_v4().to_string();
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use rocket::fs::FileServer;
|
use rocket::fs::FileServer;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use crate::items::Game;
|
use crate::items::Game;
|
||||||
|
|
||||||
@ -29,19 +30,63 @@ impl std::ops::Deref for User {
|
|||||||
#[get("/<name>")]
|
#[get("/<name>")]
|
||||||
fn get_user(
|
fn get_user(
|
||||||
_token: auth::Token,
|
_token: auth::Token,
|
||||||
user_list: &rocket::State<Vec<User>>,
|
user_list: &rocket::State<Mutex<Vec<User>>>,
|
||||||
name: String,
|
name: String,
|
||||||
) -> Option<items::Person> {
|
) -> Option<items::Person> {
|
||||||
user_list
|
let users = user_list.lock().unwrap();
|
||||||
|
users
|
||||||
.iter()
|
.iter()
|
||||||
.find(|user| user.person.name == name)
|
.find(|user| user.person.name == name)
|
||||||
.map(|u| u.person.clone())
|
.map(|u| u.person.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
fn get_users(_token: auth::Token, user_list: &rocket::State<Vec<User>>) -> items::PersonList {
|
fn get_users(
|
||||||
|
_token: auth::Token,
|
||||||
|
user_list: &rocket::State<Mutex<Vec<User>>>,
|
||||||
|
) -> items::PersonList {
|
||||||
|
let users = user_list.lock().unwrap();
|
||||||
items::PersonList {
|
items::PersonList {
|
||||||
person: user_list.inner().iter().map(|u| u.person.clone()).collect(),
|
person: users.iter().map(|u| u.person.clone()).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/game/<title>")]
|
||||||
|
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()
|
rocket::build()
|
||||||
.manage(user_list)
|
.manage(Mutex::new(user_list))
|
||||||
.manage(auth::AuthState::new())
|
.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(
|
.mount(
|
||||||
"/auth",
|
"/auth",
|
||||||
routes![auth::login, auth::logout, auth::get_auth_status],
|
routes![auth::login, auth::logout, auth::get_auth_status],
|
||||||
|
|||||||
@ -64,7 +64,12 @@ service AuthService {
|
|||||||
|
|
||||||
message GameRequest { string title = 1; }
|
message GameRequest { string title = 1; }
|
||||||
|
|
||||||
|
message AddOpinionRequest {
|
||||||
|
string game_title = 1;
|
||||||
|
bool would_play = 2;
|
||||||
|
}
|
||||||
|
|
||||||
service MainService {
|
service MainService {
|
||||||
rpc GetGame(GameRequest) returns (Game);
|
rpc GetGame(GameRequest) returns (Game);
|
||||||
rpc AddOpinion(GameRequest) returns (Person);
|
rpc AddOpinion(AddOpinionRequest) returns (Person);
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user