Skip to main content

shared/models/
system_backup_policy_location.rs

1use crate::{models::InsertQueryBuilder, prelude::*};
2use garde::Validate;
3use serde::{Deserialize, Serialize};
4use sqlx::{Row, postgres::PgRow};
5use std::{
6    collections::BTreeMap,
7    sync::{Arc, LazyLock},
8};
9use utoipa::ToSchema;
10
11#[derive(Serialize, Deserialize)]
12pub struct SystemBackupPolicyLocation {
13    pub system_backup_policy: Fetchable<super::system_backup_policy::SystemBackupPolicy>,
14    pub location: Fetchable<super::location::Location>,
15
16    pub created: chrono::NaiveDateTime,
17
18    extension_data: super::ModelExtensionData,
19}
20
21impl BaseModel for SystemBackupPolicyLocation {
22    const NAME: &'static str = "system_backup_policy_location";
23
24    fn get_extension_list() -> &'static super::ModelExtensionList {
25        static EXTENSIONS: LazyLock<super::ModelExtensionList> =
26            LazyLock::new(|| parking_lot::RwLock::new(Vec::new()));
27
28        &EXTENSIONS
29    }
30
31    fn get_extension_data(&self) -> &super::ModelExtensionData {
32        &self.extension_data
33    }
34
35    #[inline]
36    fn base_columns(prefix: Option<&str>) -> BTreeMap<&'static str, compact_str::CompactString> {
37        let prefix = prefix.unwrap_or_default();
38
39        BTreeMap::from([
40            (
41                "system_backup_policy_locations.system_backup_policy_uuid",
42                compact_str::format_compact!("{prefix}system_backup_policy_uuid"),
43            ),
44            (
45                "system_backup_policy_locations.location_uuid",
46                compact_str::format_compact!("{prefix}location_uuid"),
47            ),
48            (
49                "system_backup_policy_locations.created",
50                compact_str::format_compact!("{prefix}created"),
51            ),
52        ])
53    }
54
55    #[inline]
56    fn map(prefix: Option<&str>, row: &PgRow) -> Result<Self, crate::database::DatabaseError> {
57        let prefix = prefix.unwrap_or_default();
58
59        Ok(Self {
60            system_backup_policy: super::system_backup_policy::SystemBackupPolicy::get_fetchable(
61                row.try_get(
62                    compact_str::format_compact!("{prefix}system_backup_policy_uuid").as_str(),
63                )?,
64            ),
65            location: super::location::Location::get_fetchable(
66                row.try_get(compact_str::format_compact!("{prefix}location_uuid").as_str())?,
67            ),
68            created: row.try_get(compact_str::format_compact!("{prefix}created").as_str())?,
69            extension_data: Self::map_extensions(prefix, row)?,
70        })
71    }
72}
73
74impl SystemBackupPolicyLocation {
75    pub async fn by_system_backup_policy_uuid_location_uuid(
76        database: &crate::database::Database,
77        system_backup_policy_uuid: uuid::Uuid,
78        location_uuid: uuid::Uuid,
79    ) -> Result<Option<Self>, crate::database::DatabaseError> {
80        let row = sqlx::query(sqlx::AssertSqlSafe(format!(
81            r#"
82            SELECT {}
83            FROM system_backup_policy_locations
84            WHERE
85                system_backup_policy_locations.system_backup_policy_uuid = $1
86                AND system_backup_policy_locations.location_uuid = $2
87            "#,
88            Self::columns_sql(None)
89        )))
90        .bind(system_backup_policy_uuid)
91        .bind(location_uuid)
92        .fetch_optional(database.read())
93        .await?;
94
95        row.try_map(|row| Self::map(None, &row))
96    }
97
98    pub async fn by_system_backup_policy_uuid_with_pagination(
99        database: &crate::database::Database,
100        system_backup_policy_uuid: uuid::Uuid,
101        page: i64,
102        per_page: i64,
103        search: Option<&str>,
104    ) -> Result<super::Pagination<Self>, crate::database::DatabaseError> {
105        super::PaginatedQueryBuilder::new(
106            Self::columns_sql(None),
107            format!(
108                r#"
109                FROM system_backup_policy_locations
110                JOIN locations ON locations.uuid = system_backup_policy_locations.location_uuid
111                WHERE
112                    system_backup_policy_locations.system_backup_policy_uuid = $1
113                    AND {search}
114                "#,
115                search = super::search_sql(2, &["locations.name"], &["locations.uuid"]),
116            ),
117            "system_backup_policy_locations.created, system_backup_policy_locations.system_backup_policy_uuid, system_backup_policy_locations.location_uuid",
118        )
119        .bind(system_backup_policy_uuid)
120        .bind(search)
121        .fetch(database, page, per_page)
122        .await
123    }
124}
125
126#[async_trait::async_trait]
127impl IntoAdminApiObject for SystemBackupPolicyLocation {
128    type AdminApiObject = AdminApiSystemBackupPolicyLocation;
129    type ExtraArgs<'a> = ();
130
131    async fn into_admin_api_object<'a>(
132        self,
133        state: &crate::State,
134        _args: Self::ExtraArgs<'a>,
135    ) -> Result<Self::AdminApiObject, crate::database::DatabaseError> {
136        let api_object = AdminApiSystemBackupPolicyLocation::init_hooks(&self, state).await?;
137
138        let api_object = finish_extendible!(
139            AdminApiSystemBackupPolicyLocation {
140                location: self
141                    .location
142                    .fetch_cached(&state.database)
143                    .await?
144                    .into_admin_api_object(state, ())
145                    .await?,
146                created: self.created.and_utc(),
147            },
148            api_object,
149            state
150        )?;
151
152        Ok(api_object)
153    }
154}
155
156#[derive(ToSchema, Deserialize, Validate)]
157pub struct CreateSystemBackupPolicyLocationOptions {
158    #[garde(skip)]
159    pub system_backup_policy_uuid: uuid::Uuid,
160    #[garde(skip)]
161    pub location_uuid: uuid::Uuid,
162}
163
164#[async_trait::async_trait]
165impl CreatableModel for SystemBackupPolicyLocation {
166    type CreateOptions<'a> = CreateSystemBackupPolicyLocationOptions;
167    type CreateResult = Self;
168
169    fn get_create_handlers() -> &'static LazyLock<CreateListenerList<Self>> {
170        static CREATE_LISTENERS: LazyLock<CreateListenerList<SystemBackupPolicyLocation>> =
171            LazyLock::new(|| Arc::new(ModelHandlerList::default()));
172
173        &CREATE_LISTENERS
174    }
175
176    async fn create_with_transaction(
177        state: &crate::State,
178        mut options: Self::CreateOptions<'_>,
179        transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
180    ) -> Result<Self, crate::database::DatabaseError> {
181        options.validate()?;
182
183        super::location::Location::by_uuid_optional_cached(&state.database, options.location_uuid)
184            .await?
185            .ok_or(crate::database::InvalidRelationError("location"))?;
186
187        let mut query_builder = InsertQueryBuilder::new("system_backup_policy_locations");
188
189        Self::run_create_handlers(&mut options, &mut query_builder, state, transaction).await?;
190
191        query_builder
192            .set(
193                "system_backup_policy_uuid",
194                options.system_backup_policy_uuid,
195            )
196            .set("location_uuid", options.location_uuid);
197
198        let row = query_builder
199            .returning(&Self::columns_sql(None))
200            .fetch_one(&mut **transaction)
201            .await?;
202        let mut policy_location = Self::map(None, &row)?;
203
204        Self::run_after_create_handlers(&mut policy_location, &options, state, transaction).await?;
205
206        Ok(policy_location)
207    }
208}
209
210#[async_trait::async_trait]
211impl DeletableModel for SystemBackupPolicyLocation {
212    type DeleteOptions = ();
213
214    fn get_delete_handlers() -> &'static LazyLock<DeleteHandlerList<Self>> {
215        static DELETE_LISTENERS: LazyLock<DeleteHandlerList<SystemBackupPolicyLocation>> =
216            LazyLock::new(|| Arc::new(ModelHandlerList::default()));
217
218        &DELETE_LISTENERS
219    }
220
221    async fn delete_with_transaction(
222        &self,
223        state: &crate::State,
224        options: Self::DeleteOptions,
225        transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
226    ) -> Result<(), anyhow::Error> {
227        self.run_delete_handlers(&options, state, transaction)
228            .await?;
229
230        sqlx::query(
231            r#"
232            DELETE FROM system_backup_policy_locations
233            WHERE
234                system_backup_policy_locations.system_backup_policy_uuid = $1
235                AND system_backup_policy_locations.location_uuid = $2
236            "#,
237        )
238        .bind(self.system_backup_policy.uuid)
239        .bind(self.location.uuid)
240        .execute(&mut **transaction)
241        .await?;
242
243        self.run_after_delete_handlers(&options, state, transaction)
244            .await?;
245
246        Ok(())
247    }
248}
249
250#[schema_extension_derive::extendible]
251#[init_args(SystemBackupPolicyLocation, crate::State)]
252#[hook_args(crate::State)]
253#[derive(ToSchema, Serialize)]
254#[schema(title = "SystemBackupPolicyLocation")]
255pub struct AdminApiSystemBackupPolicyLocation {
256    pub location: super::location::AdminApiLocation,
257
258    pub created: chrono::DateTime<chrono::Utc>,
259}