143 lines
3.5 KiB
Rust
143 lines
3.5 KiB
Rust
use rocket::fs::FileServer;
|
|
use std::sync::Mutex;
|
|
|
|
use crate::items::Game;
|
|
|
|
#[macro_use]
|
|
extern crate rocket;
|
|
|
|
pub mod items {
|
|
include!(concat!(env!("OUT_DIR"), "/items.rs"));
|
|
}
|
|
|
|
mod auth;
|
|
mod proto_utils;
|
|
|
|
#[derive(Clone)]
|
|
pub struct User {
|
|
pub person: items::Person,
|
|
pub password_hash: String,
|
|
}
|
|
|
|
impl std::ops::Deref for User {
|
|
type Target = items::Person;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.person
|
|
}
|
|
}
|
|
|
|
#[get("/<name>")]
|
|
fn get_user(
|
|
_token: auth::Token,
|
|
user_list: &rocket::State<Mutex<Vec<User>>>,
|
|
name: String,
|
|
) -> Option<items::Person> {
|
|
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<Mutex<Vec<User>>>,
|
|
) -> items::PersonList {
|
|
let users = user_list.lock().unwrap();
|
|
items::PersonList {
|
|
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
|
|
}
|
|
}
|
|
|
|
#[get("/<_..>", rank = 20)]
|
|
async fn index_fallback() -> Option<rocket::fs::NamedFile> {
|
|
// Try multiple paths for robustness
|
|
let paths = ["../frontend/dist/index.html", "frontend/dist/index.html"];
|
|
for path in paths {
|
|
if let Ok(file) = rocket::fs::NamedFile::open(path).await {
|
|
return Some(file);
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
#[launch]
|
|
fn rocket() -> _ {
|
|
let mut game_list: Vec<Game> = Vec::new();
|
|
let mut user_list: Vec<User> = Vec::new();
|
|
|
|
game_list.push(Game {
|
|
title: "Naramo Nuclear Plant V2".to_string(),
|
|
source: items::Source::Roblox.into(),
|
|
multiplayer: true,
|
|
min_players: 1,
|
|
max_players: 90,
|
|
price: 0,
|
|
remote_id: 0,
|
|
});
|
|
|
|
user_list.push(User {
|
|
person: items::Person {
|
|
name: "John".to_string(),
|
|
opinion: vec![items::Opinion {
|
|
title: "Naramo Nuclear Plant V2".to_string(),
|
|
would_play: true,
|
|
}],
|
|
},
|
|
password_hash: bcrypt::hash("password123", bcrypt::DEFAULT_COST).unwrap(),
|
|
});
|
|
|
|
rocket::build()
|
|
.manage(Mutex::new(user_list))
|
|
.manage(auth::AuthState::new())
|
|
.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],
|
|
)
|
|
.mount("/", routes![index_fallback])
|
|
.mount("/", FileServer::new("frontend/dist"))
|
|
}
|