1
use crate::config::{ConfigError, ConfigOption, config_on, set_config_on};
2
use crate::db::DBError;
3
use cfg_if::cfg_if;
4
use sqlx::Postgres;
5
use sqlx::pool::PoolConnection;
6
use sqlx::types::Uuid;
7

            
8
// `userpool` is the production per-user routing path. Compile it whenever we
9
// are NOT inside server's own `cfg(test)` runs. That keeps the module
10
// available to external test consumers (the workspace `tests-integration`
11
// crate, web's integration tests under `--all-features`, etc.) so they can
12
// fall back to userpool when the test-pool override is absent.
13
#[cfg(not(test))]
14
mod userpool;
15

            
16
pub struct User {
17
    pub id: Uuid,
18
}
19

            
20
impl User {
21
    cfg_if! {
22
        if #[cfg(test)] {
23
1191
        pub async fn get_connection(&self) -> Result<PoolConnection<Postgres>, DBError> {
24
1191
            crate::db::get_connection().await
25
1191
        }
26
        } else if #[cfg(feature = "test-utils")] {
27
6885
        pub async fn get_connection(&self) -> Result<PoolConnection<Postgres>, DBError> {
28
6885
            if crate::db::test_pool_is_set() {
29
5535
                crate::db::get_connection().await
30
            } else {
31
1350
                userpool::get_connection(self.id).await
32
            }
33
6885
        }
34
        } else {
35
        pub async fn get_connection(&self) -> Result<PoolConnection<Postgres>, DBError> {
36
            userpool::get_connection(self.id).await
37
        }
38
        }
39
    }
40

            
41
    /// Reads a config field from THIS user's database. Per-user config is
42
    /// isolated to the user's own DB (distinct from server-wide
43
    /// [`crate::config::system_config`]).
44
    ///
45
    /// # Errors
46
    /// [`ConfigError::DB`] on a connection or query error.
47
136
    pub async fn config(&self, field: &str) -> Result<Option<ConfigOption>, ConfigError> {
48
57
        let mut conn = self.get_connection().await.map_err(|_| ConfigError::DB)?;
49
57
        config_on(&mut conn, field).await
50
57
    }
51

            
52
    /// Writes a config field to THIS user's database.
53
    ///
54
    /// # Errors
55
    /// [`ConfigError::DB`] on a connection or query error.
56
136
    pub async fn set_config(&self, field: &str, contents: ConfigOption) -> Result<(), ConfigError> {
57
40
        let mut conn = self.get_connection().await.map_err(|_| ConfigError::DB)?;
58
40
        set_config_on(&mut conn, field, contents).await
59
40
    }
60
}
61

            
62
#[cfg(test)]
63
impl User {
64
121
    pub async fn commit(&self) -> Result<(), sqlx::Error> {
65
121
        let mut conn = self.get_connection().await.unwrap();
66

            
67
121
        sqlx::query!(
68
            "INSERT INTO users (
69
                id, user_name, email, photo, verified, user_password, user_role, db_name, created_at
70
            ) VALUES (
71
                $1, 'Test User', 'test@example.com', 'default.png',
72
                FALSE, 'password123', 'user', 'database', NOW()
73
            )",
74
            self.id,
75
        )
76
121
        .execute(&mut *conn)
77
121
        .await?;
78

            
79
121
        Ok(())
80
121
    }
81
}