#[macro_use] extern crate rocket; use rocket::{http::Status, serde::json::Json, State}; use serde::{Deserialize, Serialize}; mod uid; use tokio::sync::Mutex; use uid::UID; mod db; use db::DB; use db::User; use db::Config; #[get("/")] async fn index() -> &'static str { "This is a POKO server" } #[derive(Serialize)] struct UserOut { name: String, id: String, } impl Into for User { fn into(self) -> UserOut { UserOut { name: self.get_name(), id: self.hex_id() } } } #[get("/")] async fn get_user(user: &str, db: &State>) -> (Status, Result, Json>) { let mut db = db.lock().await; match db.get_user(user).await { Ok(n) => (Status::Ok, Ok(Json(n.clone().into()))), Err(n) => (Status::NotFound, Err(n.into())) } } #[get("/by_name/")] async fn get_users_by_name(user: &str, db: &State>) -> (Status, Result>, Json>) { let db = db.lock().await; match db.get_user_by_name(user).await { Ok(n) => (Status::Ok, Ok(Json(n.into_iter().map(|v| v.into()).collect()))), Err(n) => (Status::NotFound, Err(n.into())) } } #[get("/all")] async fn get_all_users(db: &State>) -> (Status, Result>, Json>) { let db = db.lock().await; match db.get_all_users().await { Ok(n) => (Status::Ok, Ok(Json(n.into_iter().map(|v| v.into()).collect()))), //Nothing found Err(n) => (Status::NotFound, Err(n.into())), } } fn default_id() -> String { "random".into() } #[derive(Deserialize)] struct UserForm { name: String, password: String, #[serde(default = "default_id")] id: String, } #[post("/register", data="", format="json")] async fn new_user(data: Json, db: &State>) -> (Status, Result<(), Json>) { let mut db = db.lock().await; let id; if data.id == "random".to_string() { match db.uid_generator.new_uid() { // Gotten a new UID to make a new user with Ok(n) => id = Some(n), // Did not get a new UID Err(n) => return (Status::InternalServerError, Err(n.clone().into())), }; } else { match UID::from(data.id.clone()) { // Could not make UID from input Err(n) => return (Status::BadRequest, Err(n.into())), // Made a UID Ok(n) => { if db.uid_generator.is_taken(n) { // UID is taken return (Status::BadRequest, Err("UID is taken".to_string().into())); } else { // UID is not taken match db.uid_generator.add_uid(n) { // Could not add UID for some reason Err(n) => return (Status::InternalServerError, Err(n.into())), // Made Ok(n) => id = Some(n), }; } }, }; } match id { None => return (Status::InternalServerError, Err("".to_string().into())), Some(n) => { match db.new_user(data.name.clone(), data.password.clone(), n).await { // User has been created Ok(_) => return (Status::Created, Ok(())), // Could not create user Err(n) => return (Status::InternalServerError, Err(n.into())), } } } } #[derive(Deserialize)] struct LoginForm { id: String, password: String, clientid: String, } #[post("/", data="", format="json")] async fn login(data: Json, db: &State>) -> (Status, Json) { let mut db = db.lock().await; match db.login(&data.id, &data.password, &data.clientid).await { Ok(n) => (Status::Ok, n.into()), Err(n) => (Status::Unauthorized, n.into()), } } #[derive(Deserialize)] struct LogoutForm { id: String, sessionhash: String, } #[post("/logout", data="", format="json")] async fn logout(data: Json, db: &State>) -> (Status, Result<(), String>) { let mut db = db.lock().await; match db.logout(&data.id, &data.sessionhash).await { Ok(_) => (Status::Ok, Ok(())), Err(n) => (Status::Unauthorized, Err(n)), } } #[launch] fn rocket() -> _ { rocket::build().manage(Mutex::new(DB::load(Config::new()))) .mount("/", routes![index]) .mount("/user", routes![login, get_users_by_name, get_user, new_user, get_all_users, logout]) }