use anyhow::Error; use giterated_models::repository::Repository; use giterated_models::settings::AnySetting; use giterated_models::user::User; use sqlx::PgPool; use super::MetadataBackend; pub struct DatabaseSettings { pub pg_pool: PgPool, } #[async_trait::async_trait] impl MetadataBackend for DatabaseSettings { async fn user_get(&mut self, user: &User, name: &str) -> Result { let row = sqlx::query_as!( UserSettingRow, "SELECT * FROM user_settings WHERE username = $1 AND name = $2", user.username, name ) .fetch_one(&self.pg_pool) .await?; let setting = serde_json::from_str(&row.value)?; Ok(setting) } async fn user_write( &mut self, user: &User, name: &str, value: AnySetting, ) -> Result<(), Error> { sqlx::query!("INSERT INTO user_settings VALUES ($1, $2, $3) ON CONFLICT (username, name) DO UPDATE SET value = $3", user.username, name, serde_json::to_string(&value)?) .execute(&self.pg_pool).await?; Ok(()) } async fn repository_get( &mut self, repository: &Repository, name: &str, ) -> Result { let row = sqlx::query_as!( RepositorySettingRow, "SELECT * FROM repository_settings WHERE repository = $1 AND name = $2", repository.to_string(), name ) .fetch_one(&self.pg_pool) .await?; let setting = serde_json::from_str(&row.value)?; Ok(setting) } async fn repository_write( &mut self, repository: &Repository, name: &str, value: AnySetting, ) -> Result<(), Error> { sqlx::query!("INSERT INTO repository_settings VALUES ($1, $2, $3) ON CONFLICT (repository, name) DO UPDATE SET value = $3", repository.to_string(), name, serde_json::to_string(&value)?) .execute(&self.pg_pool).await?; Ok(()) } } #[allow(unused)] #[derive(Debug, sqlx::FromRow)] struct UserSettingRow { pub username: String, pub name: String, pub value: String, } #[allow(unused)] #[derive(Debug, sqlx::FromRow)] struct RepositorySettingRow { pub repository: String, pub name: String, pub value: String, }