shared/models/
server_variable.rs

1use crate::prelude::*;
2use serde::{Deserialize, Serialize};
3use sqlx::{Row, postgres::PgRow};
4use std::collections::BTreeMap;
5use utoipa::ToSchema;
6
7#[derive(Serialize, Deserialize)]
8pub struct ServerVariable {
9    pub variable: super::nest_egg_variable::NestEggVariable,
10
11    pub value: String,
12
13    pub created: chrono::NaiveDateTime,
14}
15
16impl BaseModel for ServerVariable {
17    const NAME: &'static str = "server_variable";
18
19    #[inline]
20    fn columns(prefix: Option<&str>) -> BTreeMap<&'static str, compact_str::CompactString> {
21        let prefix = prefix.unwrap_or_default();
22
23        let mut columns = BTreeMap::from([
24            (
25                "server_variables.value",
26                compact_str::format_compact!("{prefix}value"),
27            ),
28            (
29                "server_variables.created",
30                compact_str::format_compact!("{prefix}created"),
31            ),
32        ]);
33
34        columns.extend(super::nest_egg_variable::NestEggVariable::columns(Some(
35            "variable_",
36        )));
37
38        columns
39    }
40
41    #[inline]
42    fn map(prefix: Option<&str>, row: &PgRow) -> Result<Self, crate::database::DatabaseError> {
43        let prefix = prefix.unwrap_or_default();
44
45        let variable = super::nest_egg_variable::NestEggVariable::map(Some("variable_"), row)?;
46        let value = row
47            .try_get(compact_str::format_compact!("{prefix}value").as_str())
48            .unwrap_or_else(|_| {
49                variable
50                    .default_value
51                    .clone()
52                    .unwrap_or_else(|| "".to_string())
53            });
54
55        Ok(Self {
56            variable,
57            value,
58            created: row
59                .try_get(compact_str::format_compact!("{prefix}created").as_str())
60                .unwrap_or_else(|_| chrono::Utc::now().naive_utc()),
61        })
62    }
63}
64
65impl ServerVariable {
66    pub async fn create(
67        database: &crate::database::Database,
68        server_uuid: uuid::Uuid,
69        variable_uuid: uuid::Uuid,
70        value: &str,
71    ) -> Result<(), crate::database::DatabaseError> {
72        sqlx::query(
73            r#"
74            INSERT INTO server_variables (server_uuid, variable_uuid, value)
75            VALUES ($1, $2, $3)
76            ON CONFLICT (server_uuid, variable_uuid) DO UPDATE SET value = EXCLUDED.value
77            "#,
78        )
79        .bind(server_uuid)
80        .bind(variable_uuid)
81        .bind(value)
82        .execute(database.write())
83        .await?;
84
85        Ok(())
86    }
87
88    pub async fn all_by_server_uuid_egg_uuid(
89        database: &crate::database::Database,
90        server_uuid: uuid::Uuid,
91        egg_uuid: uuid::Uuid,
92    ) -> Result<Vec<Self>, crate::database::DatabaseError> {
93        let rows = sqlx::query(&format!(
94            r#"
95            SELECT {}
96            FROM nest_egg_variables
97            LEFT JOIN server_variables ON server_variables.variable_uuid = nest_egg_variables.uuid AND server_variables.server_uuid = $1
98            WHERE nest_egg_variables.egg_uuid = $2
99            ORDER BY nest_egg_variables.order_, nest_egg_variables.created
100            "#,
101            Self::columns_sql(None)
102        ))
103        .bind(server_uuid)
104        .bind(egg_uuid)
105        .fetch_all(database.read())
106        .await?;
107
108        rows.into_iter()
109            .map(|row| Self::map(None, &row))
110            .try_collect_vec()
111    }
112
113    #[inline]
114    pub fn into_api_object(self) -> ApiServerVariable {
115        ApiServerVariable {
116            name: self.variable.name,
117            description: self.variable.description,
118            env_variable: self.variable.env_variable,
119            default_value: self.variable.default_value,
120            value: self.value,
121            is_editable: self.variable.user_editable,
122            is_secret: self.variable.secret,
123            rules: self.variable.rules,
124            created: self.created.and_utc(),
125        }
126    }
127}
128
129#[derive(ToSchema, Serialize)]
130#[schema(title = "ServerVariable")]
131pub struct ApiServerVariable {
132    pub name: compact_str::CompactString,
133    pub description: Option<compact_str::CompactString>,
134
135    pub env_variable: compact_str::CompactString,
136    pub default_value: Option<String>,
137    pub value: String,
138    pub is_editable: bool,
139    pub is_secret: bool,
140    pub rules: Vec<compact_str::CompactString>,
141
142    pub created: chrono::DateTime<chrono::Utc>,
143}