stormchaser_api/db/
storage.rs1use crate::UpdateStorageBackendRequest;
2use serde_json::Value;
3use sqlx::{PgPool, Postgres, Transaction};
4use stormchaser_model::BackendId;
5
6use stormchaser_model::storage;
7
8pub async fn unset_default_sfs(tx: &mut Transaction<'_, Postgres>) -> Result<(), sqlx::Error> {
11 sqlx::query("UPDATE storage_backends SET is_default_sfs = FALSE WHERE is_default_sfs = TRUE")
12 .execute(&mut **tx)
13 .await?;
14 Ok(())
15}
16
17#[allow(clippy::too_many_arguments)]
20pub async fn create_storage_backend(
21 tx: &mut Transaction<'_, Postgres>,
22 id: BackendId,
23 name: &str,
24 description: &Option<String>,
25 backend_type: &storage::BackendType,
26 config: &Value,
27 aws_assume_role_arn: &Option<String>,
28 is_default_sfs: bool,
29) -> Result<(), sqlx::Error> {
30 sqlx::query(
31 r#"
32 INSERT INTO storage_backends (id, name, description, backend_type, config, aws_assume_role_arn, is_default_sfs)
33 VALUES ($1, $2, $3, $4, $5, $6, $7)
34 "#,
35 )
36 .bind(id)
37 .bind(name)
38 .bind(description)
39 .bind(backend_type)
40 .bind(config)
41 .bind(aws_assume_role_arn)
42 .bind(is_default_sfs)
43 .execute(&mut **tx)
44 .await?;
45 Ok(())
46}
47
48pub async fn list_storage_backends(
51 pool: &PgPool,
52) -> Result<Vec<storage::StorageBackend>, sqlx::Error> {
53 sqlx::query_as("SELECT * FROM storage_backends ORDER BY name ASC")
54 .fetch_all(pool)
55 .await
56}
57
58pub async fn get_storage_backend(
61 pool: &PgPool,
62 id: BackendId,
63) -> Result<Option<storage::StorageBackend>, sqlx::Error> {
64 sqlx::query_as("SELECT * FROM storage_backends WHERE id = $1")
65 .bind(id)
66 .fetch_optional(pool)
67 .await
68}
69
70pub async fn update_storage_backend(
73 tx: &mut Transaction<'_, Postgres>,
74 id: BackendId,
75 payload: &UpdateStorageBackendRequest,
76) -> Result<(), sqlx::Error> {
77 let mut query = sqlx::QueryBuilder::new("UPDATE storage_backends SET ");
78 let mut separated = query.separated(", ");
79
80 if let Some(name) = &payload.name {
81 separated.push("name = ").push_bind_unseparated(name);
82 }
83 if let Some(desc) = &payload.description {
84 separated.push("description = ").push_bind_unseparated(desc);
85 }
86 if let Some(bt) = &payload.backend_type {
87 separated.push("backend_type = ").push_bind_unseparated(bt);
88 }
89 if let Some(cfg) = &payload.config {
90 separated.push("config = ").push_bind_unseparated(cfg);
91 }
92 if let Some(role) = &payload.aws_assume_role_arn {
93 let value: Option<&str> = if role.is_empty() {
95 None
96 } else {
97 Some(role.as_str())
98 };
99 separated
100 .push("aws_assume_role_arn = ")
101 .push_bind_unseparated(value);
102 }
103 if let Some(is_default) = payload.is_default_sfs {
104 separated
105 .push("is_default_sfs = ")
106 .push_bind_unseparated(is_default);
107 }
108
109 query.push(" WHERE id = ").push_bind(id);
110
111 query.build().execute(&mut **tx).await?;
112 Ok(())
113}
114
115pub async fn delete_storage_backend(pool: &PgPool, id: BackendId) -> Result<(), sqlx::Error> {
118 sqlx::query("DELETE FROM storage_backends WHERE id = $1")
119 .bind(id)
120 .execute(pool)
121 .await?;
122 Ok(())
123}