Skip to main content

docbox_database/models/
user.rs

1use crate::{DbExecutor, DbResult, models::shared::CountResult};
2use serde::Serialize;
3use sqlx::{postgres::PgQueryResult, prelude::FromRow};
4use utoipa::ToSchema;
5
6pub type UserId = String;
7
8#[derive(Debug, Clone, Serialize, FromRow, ToSchema, sqlx::Type, PartialEq, Eq)]
9#[sqlx(type_name = "docbox_user")]
10pub struct User {
11    /// Unique ID of the user
12    pub id: String,
13    /// Last saved name for the user
14    pub name: Option<String>,
15    /// Last saved image ID for the user
16    pub image_id: Option<String>,
17}
18
19impl User {
20    /// Stores / updates the stored user data, returns back the user ID
21    pub async fn store(
22        db: impl DbExecutor<'_>,
23        id: UserId,
24        name: Option<String>,
25        image_id: Option<String>,
26    ) -> DbResult<User> {
27        sqlx::query(
28            r#"
29            INSERT INTO "docbox_users" ("id", "name", "image_id")
30            VALUES ($1, $2, $3)
31            ON CONFLICT ("id")
32            DO UPDATE SET "name" = EXCLUDED."name", "image_id" = EXCLUDED."image_id"
33        "#,
34        )
35        .bind(id.as_str())
36        .bind(name.as_ref())
37        .bind(image_id.as_ref())
38        .execute(db)
39        .await?;
40
41        Ok(User { id, name, image_id })
42    }
43
44    /// Find a user by ID
45    pub async fn find(db: impl DbExecutor<'_>, id: &str) -> DbResult<Option<User>> {
46        sqlx::query_as(r#"SELECT * FROM "docbox_users" WHERE "id" = $1"#)
47            .bind(id)
48            .fetch_optional(db)
49            .await
50    }
51
52    /// Get a page from the users list
53    pub async fn query(db: impl DbExecutor<'_>, offset: u64, limit: u64) -> DbResult<Vec<User>> {
54        sqlx::query_as(
55            r#"
56            SELECT * FROM "docbox_users"
57            ORDER BY "id" DESC
58            OFFSET $1 LIMIT $2"#,
59        )
60        .bind(offset as i64)
61        .bind(limit as i64)
62        .fetch_all(db)
63        .await
64    }
65
66    /// Get the total number of users
67    pub async fn total(db: impl DbExecutor<'_>) -> DbResult<i64> {
68        let result: CountResult =
69            sqlx::query_as(r#"SELECT COUNT(*) as "count" FROM "docbox_users""#)
70                .fetch_one(db)
71                .await?;
72
73        Ok(result.count)
74    }
75
76    /// Delete a user
77    pub async fn delete(self, db: impl DbExecutor<'_>) -> DbResult<PgQueryResult> {
78        sqlx::query(r#"DELETE FROM "docbox_users" WHERE "id" = $1"#)
79            .bind(self.id)
80            .execute(db)
81            .await
82    }
83}