use super::prelude::*; use sqlx::FromRow; use util::{Ordering, PartyError}; api_routes!( add_user, get_user, get_all_users, delete_user, set_score, get_score ); /// # User /// /// A user that represents a person participating in the LAN party #[derive(Clone, Debug, FromForm, Serialize, Deserialize, JsonSchema, FromRow)] #[serde(crate = "rocket::serde")] pub struct User { /// Name of the user name: String, /// Score of the user #[serde(default)] score: i64, /// Unique identifier of the user #[serde(default)] id: i64, } /// # Create new user with the give name /// /// Returns the created user #[openapi(tag = "User")] #[post("/", data = "")] pub async fn add_user( _api_key: ApiKey, mut db: Connection, name: Json<&str>, ) -> Result>, PartyError> { let result = sqlx::query!("INSERT INTO users (name) VALUES (?)", *name) .execute(&mut *db) .await?; let user = User { id: result.last_insert_rowid(), score: 0, name: name.to_string(), }; Ok(status::Created::new("/").body(Json(user))) } /// # Delete user by id #[openapi(tag = "User")] #[delete("/")] pub async fn delete_user( _api_key: ApiKey, mut db: Connection, id: i64, ) -> Result { sqlx::query!("DELETE FROM users where (id = ?)", id) .execute(&mut *db) .await?; Ok(Status::Ok) } /// # Get user by id /// /// Returns a single user by id #[openapi(tag = "User")] #[get("/")] pub async fn get_user( _api_key: ApiKey, mut db: Connection, id: i64, ) -> Result, PartyError> { let user = sqlx::query_as!(User, "SELECT id, name, score FROM users WHERE (id = ?)", id) .fetch_one(&mut *db) .await?; Ok(Json(user)) } /// # UserSort /// /// Field used to sort users #[derive(Clone, Debug, FromFormField, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum UserSort { #[field(value = "score")] Score, #[field(value = "name")] Name, #[field(value = "id")] Id, } impl ToString for UserSort { fn to_string(&self) -> String { match self { Self::Score => "score", Self::Name => "name", Self::Id => "id", } .into() } } /// # Get all users /// /// Returns an array of all users sorted by the given sort field and ordering #[openapi(tag = "User")] #[get("/?&")] pub async fn get_all_users( _api_key: ApiKey, mut db: Connection, sort: Option, order: Option, ) -> Result>, PartyError> { let users = sqlx::query_as::<_, User>(&format!( "SELECT id, name, score FROM users ORDER BY {} {}", sort.unwrap_or(UserSort::Id).to_string(), order.unwrap_or(Ordering::Asc).to_string() )) .fetch_all(&mut *db) .await?; Ok(Json(users)) } /// # Set score of user by id #[openapi(tag = "User")] #[post("//score", data = "")] pub async fn set_score( _api_key: ApiKey, mut db: Connection, id: i64, score: Json, ) -> Result { sqlx::query!("UPDATE users SET score = ? WHERE id = ?", *score, id) .execute(&mut *db) .await?; Ok(Status::Ok) } /// # Get score of user by id /// /// Returns the score of a single user by id #[openapi(tag = "User")] #[get("//score")] pub async fn get_score( _api_key: ApiKey, mut db: Connection, id: i64, ) -> Result, PartyError> { let score = sqlx::query_scalar!("SELECT score FROM users WHERE id = ?", id) .fetch_one(&mut *db) .await?; Ok(Json(score)) }