173 lines
4.1 KiB
Rust
173 lines
4.1 KiB
Rust
use crate::{ApiKey, Db, Ordering, PartyError};
|
|
use okapi::openapi3::OpenApi;
|
|
use rocket::{
|
|
fairing::AdHoc,
|
|
http::Status,
|
|
response::status::Created,
|
|
serde::{json::Json, Deserialize, Serialize},
|
|
};
|
|
use rocket_db_pools::{sqlx, Connection};
|
|
use rocket_okapi::{
|
|
openapi, openapi_get_routes, openapi_get_routes_spec, settings::OpenApiSettings, JsonSchema,
|
|
};
|
|
use sqlx::FromRow;
|
|
|
|
/// # 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<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(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))
|
|
}
|
|
|
|
pub fn get_routes_and_docs(settings: &OpenApiSettings) -> (Vec<rocket::Route>, OpenApi) {
|
|
openapi_get_routes_spec![
|
|
settings: add_user,
|
|
get_user,
|
|
get_all_users,
|
|
delete_user,
|
|
set_score,
|
|
get_score
|
|
]
|
|
}
|