engage_earn_api/src/models.rs
2023-04-16 22:31:15 -05:00

272 lines
7.5 KiB
Rust

use serde::{Deserialize, Serialize};
use sqlx::types::{chrono::NaiveDateTime, time::OffsetDateTime, BigDecimal};
/// The model for a winner of a prize.
#[derive(
sqlx::Type, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
)]
pub struct WinnerEntry {
pub user_id: i32,
pub username: String,
pub prize_id: i32,
pub prize_name: String,
pub prize_description: String,
#[serde(with = "serde_datetime")]
pub date: NaiveDateTime,
pub claimed: bool,
}
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct PrizeQuery {
pub prize_id: Option<i32>,
pub grade: i32,
}
#[derive(Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct PrizeEntry {
pub id: i32,
pub name: String,
pub points_min: i32,
pub description: String,
pub directions_to_claim: String,
}
#[derive(Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct NewPrize {
pub name: String,
pub points_min: i32,
pub description: String,
pub directions_to_claim: String,
}
#[derive(Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct AttendingEntry {
pub user_id: i32,
pub username: String,
}
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct GetAttendingQuery {
pub event_id: i32,
}
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct WinnerQuery {
pub winner_id: i32,
}
/// The possible event types.
#[derive(
sqlx::Type, Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
)]
#[sqlx(type_name = "event_type", rename_all = "snake_case")]
pub enum EventType {
Sports,
Meetings,
Drama,
Music,
Other,
}
/// The model for the body of the create event request.
#[derive(Clone, Deserialize, Debug)]
pub struct NewEventRequestEntry {
pub title: String,
pub description: String,
#[serde(with = "serde_datetime")]
pub time_start: NaiveDateTime,
#[serde(with = "serde_datetime")]
pub time_end: NaiveDateTime,
pub event_type: EventType,
pub points: i32,
pub place: Option<String>,
#[serde(with = "serde_big_decimal")]
pub price: BigDecimal,
}
/// The model for the get event request.
#[derive(
sqlx::Type, Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
)]
pub struct GetEventQuery {
pub id: i32,
}
/// The model for an Event in the db.
#[derive(Clone, Serialize, Debug)]
pub struct EventWithConfirmed {
pub id: i32,
pub title: String,
pub description: String,
#[serde(with = "serde_datetime")]
pub time_start: NaiveDateTime,
#[serde(with = "serde_datetime")]
pub time_end: NaiveDateTime,
pub event_type: EventType,
pub points: i32,
pub place: Option<String>,
#[serde(with = "serde_big_decimal")]
pub price: BigDecimal,
pub confirmed: bool,
pub created_by: Option<i32>,
}
/// The model for an Event in the db.
#[derive(Clone, Serialize, Debug)]
pub struct Event {
pub id: i32,
pub title: String,
pub description: String,
#[serde(with = "serde_datetime")]
pub time_start: NaiveDateTime,
#[serde(with = "serde_datetime")]
pub time_end: NaiveDateTime,
pub event_type: EventType,
pub points: i32,
pub place: Option<String>,
#[serde(with = "serde_big_decimal")]
pub price: BigDecimal,
pub created_by: Option<i32>,
}
/// The model for the body of the signup request.
#[derive(Clone, Debug, Deserialize)]
pub struct Signup {
pub username: String,
pub role: Role,
pub grade: i32,
pub password: String,
}
/// The possible roles for a user.
#[derive(
sqlx::Type, Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
)]
#[sqlx(type_name = "role", rename_all = "snake_case")]
pub enum Role {
Student,
Teacher,
Admin,
}
/// The model for the signin request.
#[derive(Clone, Debug, Deserialize)]
pub struct Signin {
pub username: String,
pub password: String,
}
/// The model for the query parameters of the report request.
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ReportQuery {
pub detailed_event_view: bool,
}
/// The model for the confirm attending request.
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ConfirmAttending {
pub new_confirmed: bool,
pub event_id: i32,
pub user_id: i32,
}
/// The model for the mark attending request.
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct MarkAttending {
pub event_id: i32,
}
/// The claims for the JWT.
#[derive(Clone, Serialize, Deserialize, Debug, Hash)]
pub struct Claims {
#[serde(with = "serde_numeric_date")]
pub exp: OffsetDateTime,
pub id: i32,
pub username: String,
pub grade: i32,
pub role: Role,
}
#[derive(
sqlx::Type, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
)]
pub struct LeaderBoardEntry {
pub username: String,
pub points: Option<i64>,
}
#[derive(
sqlx::Type, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
)]
pub struct ReportEntry {
pub username: String,
pub grade: i32,
pub points: Option<i64>,
pub event_titles: Vec<String>,
pub event_points: Vec<i32>,
pub event_discriptions: Vec<String>,
pub event_types: Vec<String>,
}
/// Module for (de)serializing [OffsetDateTime] to conform with the JWT spec (RFC 7519 section 2, "Numeric Date")
mod serde_numeric_date {
use serde::{self, Deserialize, Deserializer, Serializer};
use sqlx::types::time::OffsetDateTime;
pub fn serialize<S>(date: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let timestamp = date.unix_timestamp();
serializer.serialize_i64(timestamp)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
where
D: Deserializer<'de>,
{
OffsetDateTime::from_unix_timestamp(i64::deserialize(deserializer)?)
.map_err(|_| serde::de::Error::custom("invalid Unix timestamp value"))
}
}
/// Module for (de)serializing [NaiveDateTime]
mod serde_datetime {
use std::str::FromStr;
use serde::{self, Deserialize, Deserializer, Serializer};
use sqlx::types::chrono::NaiveDateTime;
pub fn serialize<S>(dt: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&dt.to_string())
}
pub fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<NaiveDateTime, D::Error> {
let str = <String as Deserialize>::deserialize(deserializer)?;
NaiveDateTime::from_str(&str).map_err(serde::de::Error::custom)
}
}
/// Module for (de)serializing [BigDecimal]
mod serde_big_decimal {
use serde::{self, Deserialize, Deserializer, Serializer};
use sqlx::types::BigDecimal;
pub fn serialize<S>(bd: &BigDecimal, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_f32(bd.to_string().parse::<f32>().unwrap())
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<BigDecimal, D::Error> {
let float = f32::deserialize(deserializer)?;
BigDecimal::try_from(float).map_err(serde::de::Error::custom)
}
}