use crate::{DbExecutor, DbResult};
use serde::{Deserialize, Serialize};
use sqlx::prelude::FromRow;
use uuid::Uuid;
pub type TenantId = Uuid;
use crate::utils::update_if_some;
#[derive(Debug, Clone, FromRow, Serialize, PartialEq, Eq)]
pub struct Tenant {
pub id: TenantId,
pub name: String,
pub db_name: String,
pub db_secret_name: Option<String>,
#[sqlx(default)]
pub db_iam_user_name: Option<String>,
pub s3_name: String,
pub os_index_name: String,
pub env: String,
pub event_queue_url: Option<String>,
}
pub struct CreateTenant {
pub id: TenantId,
pub name: String,
pub db_name: String,
pub db_iam_user_name: Option<String>,
pub db_secret_name: Option<String>,
pub s3_name: String,
pub os_index_name: String,
pub event_queue_url: Option<String>,
pub env: String,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct UpdateTenant {
pub id: Option<TenantId>,
pub name: Option<String>,
pub db_name: Option<String>,
pub db_secret_name: Option<Option<String>>,
pub db_iam_user_name: Option<Option<String>>,
pub s3_name: Option<String>,
pub os_index_name: Option<String>,
pub env: Option<String>,
pub event_queue_url: Option<Option<String>>,
}
impl Tenant {
pub async fn create(db: impl DbExecutor<'_>, create: CreateTenant) -> DbResult<Tenant> {
sqlx::query(
r#"
INSERT INTO "docbox_tenants" (
"id",
"name",
"db_name",
"db_iam_user_name",
"db_secret_name",
"s3_name",
"os_index_name",
"env",
"event_queue_url"
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
"#,
)
.bind(create.id)
.bind(create.name.as_str())
.bind(create.db_name.as_str())
.bind(create.db_iam_user_name.clone())
.bind(create.db_secret_name.clone())
.bind(create.s3_name.as_str())
.bind(create.os_index_name.as_str())
.bind(create.env.as_str())
.bind(create.event_queue_url.as_ref())
.execute(db)
.await?;
Ok(Tenant {
id: create.id,
name: create.name,
db_name: create.db_name,
db_iam_user_name: create.db_iam_user_name,
db_secret_name: create.db_secret_name,
s3_name: create.s3_name,
os_index_name: create.os_index_name,
env: create.env,
event_queue_url: create.event_queue_url,
})
}
pub async fn update(
&mut self,
db: impl DbExecutor<'_>,
UpdateTenant {
id,
name,
db_name,
db_secret_name,
db_iam_user_name,
s3_name,
os_index_name,
env,
event_queue_url,
}: UpdateTenant,
) -> DbResult<()> {
sqlx::query(
r#"
UPDATE "docbox_tenants"
SET
"id" = COALESCE($3, "id"),
"name" = COALESCE($4, "name"),
"db_name" = COALESCE($5, "db_name"),
"db_secret_name" = COALESCE($6, "db_secret_name"),
"db_iam_user_name" = COALESCE($7, "db_iam_user_name"),
"s3_name" = COALESCE($8, "s3_name"),
"os_index_name" = COALESCE($9, "os_index_name"),
"env" = COALESCE($10, "env"),
"event_queue_url" = COALESCE($11, "event_queue_url")
WHERE "id" = $1 AND "env" = $2
"#,
)
.bind(self.id)
.bind(self.env.clone())
.bind(id)
.bind(name.clone())
.bind(db_name.clone())
.bind(db_secret_name.clone())
.bind(db_iam_user_name.clone())
.bind(s3_name.clone())
.bind(os_index_name.clone())
.bind(env.clone())
.bind(event_queue_url.clone())
.fetch_optional(db)
.await?;
update_if_some!(
self,
id,
name,
db_name,
db_secret_name,
db_iam_user_name,
s3_name,
os_index_name,
env,
event_queue_url,
);
Ok(())
}
pub async fn find_by_id(
db: impl DbExecutor<'_>,
id: TenantId,
env: &str,
) -> DbResult<Option<Tenant>> {
sqlx::query_as(r#"SELECT * FROM "docbox_tenants" WHERE "id" = $1 AND "env" = $2"#)
.bind(id)
.bind(env)
.fetch_optional(db)
.await
}
pub async fn find_by_bucket(db: impl DbExecutor<'_>, bucket: &str) -> DbResult<Option<Tenant>> {
sqlx::query_as(r#"SELECT * FROM "docbox_tenants" WHERE "s3_name" = $1"#)
.bind(bucket)
.fetch_optional(db)
.await
}
pub async fn find_by_env(db: impl DbExecutor<'_>, env: &str) -> DbResult<Vec<Tenant>> {
sqlx::query_as(r#"SELECT * FROM "docbox_tenants" WHERE "env" = $1 ORDER BY "name""#)
.bind(env)
.fetch_all(db)
.await
}
pub async fn all(db: impl DbExecutor<'_>) -> DbResult<Vec<Tenant>> {
sqlx::query_as(r#"SELECT * FROM "docbox_tenants" ORDER BY "name""#)
.fetch_all(db)
.await
}
pub async fn delete(self, db: impl DbExecutor<'_>) -> DbResult<()> {
sqlx::query(r#"DELETE FROM "docbox_tenants" WHERE "id" = $1 AND "env" = $2"#)
.bind(self.id)
.bind(&self.env)
.execute(db)
.await?;
Ok(())
}
}