1
use sqlx::Row;
2
use std::fmt::Debug;
3
use supp_macro::command;
4

            
5
use super::{CmdError, CmdResult};
6
use crate::{
7
    config::{ConfigError, ConfigOption, config, set_config},
8
    db::get_connection,
9
};
10
command! {
11
    GetConfig {
12
        #[required]
13
        name: String,
14
    } => {
15
2
        Ok(config(&name).await?.map(|v| match v {
16
2
            ConfigOption::String(s) => CmdResult::String(s),
17
            ConfigOption::Blob(b) => CmdResult::Data(b),
18
2
        }))
19
    }
20
6
}
21

            
22
command! {
23
    GetVersion {
24
    } => {
25
        const HASH: &str = env!("GIT_HASH");
26
        Ok(Some(CmdResult::String(HASH.to_string())))
27
    }
28
16
}
29

            
30
command! {
31
    GetBuildDate {
32
    } => {
33
    const BUILD: &str = env!("BUILD_DATE");
34
        Ok(Some(CmdResult::String(BUILD.to_string())))
35
    }
36
16
}
37

            
38
command! {
39
    SetConfig {
40
        #[required]
41
        name: String,
42
        #[required]
43
        value: String,
44
    } => {
45
        set_config(&name, ConfigOption::String(value)).await?;
46
        Ok(None)
47
    }
48
}
49

            
50
command! {
51
    SelectColumn {
52
        #[required]
53
        field: String,
54
        #[required]
55
        table: String,
56
    } => {
57
        let mut conn = get_connection().await.map_err(|err| {
58
            log::error!("{}", t!("Database error: %{err}", err = err : {:?}));
59
            ConfigError::DB
60
        })?;
61

            
62
        let values: Vec<String> = sqlx::query(&format!("SELECT {}::text FROM {}", field, table))
63
            .fetch_all(&mut *conn)
64
            .await?
65
            .into_iter()
66
            .map(|row| row.get::<Option<String>, _>(0).unwrap_or_default())
67
            .collect();
68

            
69
        Ok(Some(CmdResult::Lines(values)))
70
    }
71
}
72

            
73
#[cfg(test)]
74
mod command_config_tests {
75
    use super::*;
76
    use crate::{db::DB_POOL, user::User};
77
    use sqlx::{PgPool, types::Uuid};
78
    use supp_macro::local_db_sqlx_test;
79
    use tokio::sync::OnceCell;
80

            
81
    /// Context for keeping environment intact
82
    static CONTEXT: OnceCell<()> = OnceCell::const_new();
83
    static USER: OnceCell<User> = OnceCell::const_new();
84

            
85
3
    async fn setup() {
86
2
        CONTEXT
87
2
            .get_or_init(|| async {
88
                #[cfg(feature = "testlog")]
89
2
                let _ = env_logger::builder()
90
2
                    .is_test(true)
91
2
                    .filter_level(log::LevelFilter::Trace)
92
2
                    .try_init();
93
4
            })
94
2
            .await;
95
4
        USER.get_or_init(|| async { User { id: Uuid::new_v4() } })
96
2
            .await;
97
2
    }
98

            
99
    #[local_db_sqlx_test]
100
    async fn test_config_string(pool: PgPool) -> anyhow::Result<()> {
101
        let opt = ConfigOption::String("testval".to_string());
102
        crate::config::set_config("testfield", opt.clone())
103
            .await
104
            .unwrap();
105

            
106
        let val = GetConfig::new()
107
            .name("testfield".to_string())
108
            .run()
109
            .await?
110
            .unwrap();
111
        assert_eq!(opt.to_string(), val.to_string());
112
    }
113
}