1use sqlx::Row;
2use sqlx::types::Uuid;
3use std::fmt::Debug;
4use supp_macro::command;
5
6use super::{CmdError, CmdResult};
7use crate::{
8 config::{ConfigError, ConfigOption},
9 db::get_connection,
10 user::User,
11};
12command! {
13 GetConfig {
14 #[required]
15 user_id: Uuid,
16 #[required]
17 name: String,
18 } => {
19 let user = User { id: user_id };
20 Ok(user.config(&name).await?.map(|v| match v {
21 ConfigOption::String(s) => CmdResult::String(s),
22 ConfigOption::Blob(b) => CmdResult::Data(b),
23 }))
24 }
25}
26
27command! {
28 GetVersion {
29 } => {
30 const HASH: &str = env!("GIT_HASH");
31 Ok(Some(CmdResult::String(HASH.to_string())))
32 }
33}
34
35command! {
36 GetBuildDate {
37 } => {
38 const BUILD: &str = env!("BUILD_DATE");
39 Ok(Some(CmdResult::String(BUILD.to_string())))
40 }
41}
42
43command! {
44 SetConfig {
45 #[required]
46 user_id: Uuid,
47 #[required]
48 name: String,
49 #[required]
50 value: String,
51 } => {
52 let user = User { id: user_id };
53 user.set_config(&name, ConfigOption::String(value)).await?;
54 Ok(None)
55 }
56}
57
58command! {
59 SelectColumn {
60 #[required]
61 field: String,
62 #[required]
63 table: String,
64 } => {
65 let mut conn = get_connection().await.map_err(|err| {
66 log::error!("{}", t!("Database error: %{err}", err = err : {:?}));
67 ConfigError::DB
68 })?;
69
70 let values: Vec<String> = sqlx::query(&format!("SELECT {field}::text FROM {table}"))
71 .fetch_all(&mut *conn)
72 .await?
73 .into_iter()
74 .map(|row| row.get::<Option<String>, _>(0).unwrap_or_default())
75 .collect();
76
77 Ok(Some(CmdResult::Lines(values)))
78 }
79}
80
81#[cfg(test)]
82mod command_config_tests {
83 use super::*;
84 use crate::{db::DB_POOL, user::User};
85 use sqlx::{PgPool, types::Uuid};
86 use supp_macro::local_db_sqlx_test;
87 use tokio::sync::OnceCell;
88
89 static CONTEXT: OnceCell<()> = OnceCell::const_new();
91 static USER: OnceCell<User> = OnceCell::const_new();
92
93 async fn setup() {
94 CONTEXT
95 .get_or_init(|| async {
96 #[cfg(feature = "testlog")]
97 let _ = env_logger::builder()
98 .is_test(true)
99 .filter_level(log::LevelFilter::Trace)
100 .try_init();
101 })
102 .await;
103 USER.get_or_init(|| async { User { id: Uuid::new_v4() } })
104 .await;
105 }
106
107 #[local_db_sqlx_test]
108 async fn set_then_get_config_round_trips_per_user(pool: PgPool) -> anyhow::Result<()> {
109 let user_id = Uuid::new_v4();
110 SetConfig::new()
111 .user_id(user_id)
112 .name("testfield".to_string())
113 .value("testval".to_string())
114 .run()
115 .await?;
116
117 let val = GetConfig::new()
118 .user_id(user_id)
119 .name("testfield".to_string())
120 .run()
121 .await?
122 .unwrap();
123 assert_eq!(val.to_string(), "testval");
124 }
125}