lan-party-backend/src/api/user.rs

161 lines
3.7 KiB
Rust

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 = "<name>")]
pub async fn add_user(
_api_key: ApiKey,
mut db: Connection<Db>,
name: Json<&str>,
) -> Result<status::Created<Json<User>>, 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("/<id>")]
pub async fn delete_user(
_api_key: ApiKey,
mut db: Connection<Db>,
id: i64,
) -> Result<Status, PartyError> {
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("/<id>")]
pub async fn get_user(
_api_key: ApiKey,
mut db: Connection<Db>,
id: i64,
) -> Result<Json<User>, 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("/?<sort>&<order>")]
pub async fn get_all_users(
_api_key: ApiKey,
mut db: Connection<Db>,
sort: Option<UserSort>,
order: Option<Ordering>,
) -> Result<Json<Vec<User>>, 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("/<id>/score", data = "<score>")]
pub async fn set_score(
_api_key: ApiKey,
mut db: Connection<Db>,
id: i64,
score: Json<i64>,
) -> Result<Status, PartyError> {
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("/<id>/score")]
pub async fn get_score(
_api_key: ApiKey,
mut db: Connection<Db>,
id: i64,
) -> Result<Json<i64>, PartyError> {
let score = sqlx::query_scalar!("SELECT score FROM users WHERE id = ?", id)
.fetch_one(&mut *db)
.await?;
Ok(Json(score))
}