1use std::collections::HashMap;
2
3#[derive(Debug, Default, serde::Serialize, serde::Deserialize, Eq, PartialEq, Clone)]
4pub struct Claims {
5 pub sub: String,
6 pub exp: u64,
7 pub role: Role,
8 pub custom: HashMap<String, String>,
9}
10
11#[derive(Debug, Clone, Copy, serde::Deserialize, serde::Serialize, Default, Eq, PartialEq)]
12#[cfg_attr(feature = "server", derive(schemars::JsonSchema, aide::OperationIo))]
13#[serde(rename_all = "snake_case")]
14pub enum Role {
15 Admin = 0,
16 #[default]
17 User = 1,
18 Guest = 10,
20}
21
22impl TryFrom<i32> for Role {
23 type Error = String;
24
25 fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
26 match value {
27 0 => Ok(Role::Admin),
28 1 => Ok(Role::User),
29 10 => Ok(Role::Guest),
30 _ => Err(format!("Invalid Role: {}", value)),
31 }
32 }
33}
34
35impl Into<i32> for Role {
36 fn into(self) -> i32 {
37 self as i32
38 }
39}
40
41#[cfg(feature = "server")]
42impl sqlx::Type<sqlx::Postgres> for Role {
43 fn type_info() -> sqlx::postgres::PgTypeInfo {
44 <i32 as sqlx::Type<sqlx::Postgres>>::type_info()
45 }
46}
47
48#[cfg(feature = "server")]
49impl sqlx::Encode<'_, sqlx::Postgres> for Role {
50 fn encode_by_ref(
51 &self,
52 buf: &mut sqlx::postgres::PgArgumentBuffer,
53 ) -> std::result::Result<sqlx::encode::IsNull, sqlx::error::BoxDynError> {
54 let value: i32 = (*self).clone().into();
55 <i32 as sqlx::Encode<sqlx::Postgres>>::encode_by_ref(&value, buf)
56 }
57}
58
59#[cfg(feature = "server")]
60impl<'r> sqlx::Decode<'r, sqlx::Postgres> for Role {
61 fn decode(
62 value: sqlx::postgres::PgValueRef<'r>,
63 ) -> std::result::Result<Self, sqlx::error::BoxDynError> {
64 let int_value: i32 = <i32 as sqlx::Decode<sqlx::Postgres>>::decode(value)?;
65 Role::try_from(int_value)
66 .map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::InvalidData, e)).into())
67 }
68}