1use sqlx::Row;
2use std::fmt::Debug;
3use supp_macro::command;
4
5use super::{CmdError, CmdResult};
6use crate::{
7 config::{ConfigError, ConfigOption, config, set_config},
8 db::get_connection,
9};
10command! {
11 GetConfig {
12 #[required]
13 name: String,
14 } => {
15 Ok(config(&name).await?.map(|v| match v {
16 ConfigOption::String(s) => CmdResult::String(s),
17 ConfigOption::Blob(b) => CmdResult::Data(b),
18 }))
19 }
20}
21
22command! {
23 GetVersion {
24 } => {
25 const HASH: &str = env!("GIT_HASH");
26 Ok(Some(CmdResult::String(HASH.to_string())))
27 }
28}
29
30command! {
31 GetBuildDate {
32 } => {
33 const BUILD: &str = env!("BUILD_DATE");
34 Ok(Some(CmdResult::String(BUILD.to_string())))
35 }
36}
37
38command! {
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
50command! {
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 {field}::text FROM {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)]
74mod 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 static CONTEXT: OnceCell<()> = OnceCell::const_new();
83 static USER: OnceCell<User> = OnceCell::const_new();
84
85 async fn setup() {
86 CONTEXT
87 .get_or_init(|| async {
88 #[cfg(feature = "testlog")]
89 let _ = env_logger::builder()
90 .is_test(true)
91 .filter_level(log::LevelFilter::Trace)
92 .try_init();
93 })
94 .await;
95 USER.get_or_init(|| async { User { id: Uuid::new_v4() } })
96 .await;
97 }
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}