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, 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, #[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, #[serde(with = "serde_big_decimal")] pub price: BigDecimal, pub confirmed: bool, pub created_by: Option, } /// 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, #[serde(with = "serde_big_decimal")] pub price: BigDecimal, pub created_by: Option, } /// 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, } #[derive( sqlx::Type, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, )] pub struct ReportEntry { pub username: String, pub grade: i32, pub points: Option, pub event_titles: Vec, pub event_points: Vec, pub event_discriptions: Vec, pub event_types: Vec, } /// 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(date: &OffsetDateTime, serializer: S) -> Result where S: Serializer, { let timestamp = date.unix_timestamp(); serializer.serialize_i64(timestamp) } pub fn deserialize<'de, D>(deserializer: D) -> Result 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(dt: &NaiveDateTime, serializer: S) -> Result where S: Serializer, { serializer.serialize_str(&dt.to_string()) } pub fn deserialize<'de, D: Deserializer<'de>>( deserializer: D, ) -> Result { let str = ::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(bd: &BigDecimal, serializer: S) -> Result where S: Serializer, { serializer.serialize_f32(bd.to_string().parse::().unwrap()) } pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result { let float = f32::deserialize(deserializer)?; BigDecimal::try_from(float).map_err(serde::de::Error::custom) } }