tallyweb_backend/
types.rs

1use super::*;
2use sqlx::{query, query_as, PgPool};
3
4#[derive(Debug, Clone, sqlx::Type)]
5#[sqlx(type_name = "hunttype")]
6pub enum Hunttype {
7    OldOdds,
8    NewOdds,
9    SOS,
10    DexNav,
11    MasudaGenIV,
12    MasudaGenV,
13    MasudaGenVI,
14}
15
16impl From<String> for Hunttype {
17    fn from(value: String) -> Self {
18        match value.as_str() {
19            "OldOdds" => Self::OldOdds,
20            "NewOdds" => Self::NewOdds,
21            "SOS" => Self::SOS,
22            "DexNav" => Self::DexNav,
23            "MasudaGenIV" => Self::MasudaGenIV,
24            "MasudaGenV" => Self::MasudaGenV,
25            "MasudaGenVI" => Self::MasudaGenVI,
26            _ => Self::NewOdds,
27        }
28    }
29}
30
31#[derive(Debug, sqlx::FromRow)]
32pub struct DbCounter {
33    pub uuid: uuid::Uuid,
34    pub owner_uuid: uuid::Uuid,
35    pub name: String,
36    pub created_at: chrono::NaiveDateTime,
37    pub last_edit: chrono::NaiveDateTime,
38    pub is_deleted: bool,
39}
40
41#[derive(Debug, sqlx::FromRow)]
42pub struct DbPhase {
43    pub uuid: uuid::Uuid,
44    pub owner_uuid: uuid::Uuid,
45    pub parent_uuid: uuid::Uuid,
46    pub name: String,
47    pub count: i32,
48    pub time: i64,
49    pub hunt_type: Hunttype,
50    pub has_charm: bool,
51    pub dexnav_encounters: Option<i32>,
52    pub success: bool,
53    pub created_at: chrono::NaiveDateTime,
54    pub last_edit: chrono::NaiveDateTime,
55    pub is_deleted: bool,
56}
57
58#[derive(Debug)]
59pub struct DbUser {
60    pub uuid: uuid::Uuid,
61    pub username: String,
62    pub token: Option<uuid::Uuid>,
63    pub token_expire: chrono::NaiveDateTime,
64    pub email: Option<String>,
65}
66
67impl DbUser {
68    pub async fn get_token(&self, pool: &PgPool) -> Result<DbAuthToken, sqlx::error::Error> {
69        let token = query_as!(
70            DbAuthToken,
71            r#"
72            select * from auth_tokens
73            where uuid = $1 AND user_uuid = $2
74            "#,
75            self.token,
76            self.uuid,
77        )
78        .fetch_one(pool)
79        .await?;
80        Ok(token)
81    }
82
83    pub async fn token_status(&self, pool: &PgPool) -> TokenStatus {
84        if let Ok(token) = self.get_token(pool).await {
85            if token.expire_on.and_utc() > chrono::Utc::now() {
86                TokenStatus::Valid
87            } else {
88                TokenStatus::Expired
89            }
90        } else {
91            TokenStatus::Invalid
92        }
93    }
94
95    pub async fn get_counters(&self, pool: &PgPool) -> Result<Vec<DbCounter>, AuthorizationError> {
96        let data = query_as!(
97            DbCounter,
98            r#"
99            select * from counters
100            where owner_uuid = $1
101            "#,
102            self.uuid
103        )
104        .fetch_all(pool)
105        .await
106        .map_err(|err| AuthorizationError::Internal(err.to_string()))?;
107
108        Ok(data)
109    }
110}
111
112pub struct DbAuthToken {
113    pub uuid: uuid::Uuid,
114    pub user_uuid: uuid::Uuid,
115    pub expire_on: chrono::NaiveDateTime,
116}
117
118#[derive(Debug, Clone, PartialEq, Eq)]
119pub enum TokenStatus {
120    Valid,
121    Invalid,
122    Expired,
123}
124
125pub struct DbPreferences {
126    pub user_uuid: uuid::Uuid,
127    pub use_default_accent_color: bool,
128    pub accent_color: Option<String>,
129    pub show_separator: bool,
130    pub multi_select: bool,
131    pub save_on_pause: bool,
132}
133
134impl DbPreferences {
135    pub async fn db_get(pool: &PgPool, user_uuid: uuid::Uuid) -> Result<Self, BackendError> {
136        let data = match query_as!(
137            DbPreferences,
138            r#"
139            select * from preferences
140            where user_uuid = $1
141            "#,
142            user_uuid,
143        )
144        .fetch_one(pool)
145        .await
146        {
147            Ok(data) => data,
148            Err(sqlx::Error::RowNotFound) => {
149                Err(BackendError::DataNotFound(String::from("preferences")))?
150            }
151            Err(err) => Err(err)?,
152        };
153
154        Ok(data)
155    }
156
157    pub async fn db_set(
158        self,
159        pool: &PgPool,
160        username: &str,
161        token: uuid::Uuid,
162    ) -> Result<(), BackendError> {
163        let user = auth::get_user(pool, username, token).await?;
164        query!(
165            r#"
166            INSERT INTO preferences (
167                user_uuid,
168                use_default_accent_color,
169                accent_color,
170                show_separator,
171                multi_select,
172                save_on_pause
173            )
174            VALUES ($1, $2, $3, $4, $5, $6)
175            ON CONFLICT (user_uuid) DO UPDATE
176                SET use_default_accent_color = $2,
177                    accent_color = $3,
178                    show_separator = $4,
179                    multi_select = $5,
180                    save_on_pause = $6
181            "#,
182            user.uuid,
183            self.use_default_accent_color,
184            self.accent_color,
185            self.show_separator,
186            self.multi_select,
187            self.save_on_pause,
188        )
189        .execute(pool)
190        .await?;
191
192        Ok(())
193    }
194}