Skip to main content

docbox_database/models/
tenant.rs

1use crate::{DbExecutor, DbResult};
2use serde::Serialize;
3use sqlx::prelude::FromRow;
4use uuid::Uuid;
5
6pub type TenantId = Uuid;
7
8#[derive(Debug, Clone, FromRow, Serialize, PartialEq, Eq)]
9pub struct Tenant {
10    /// Unique ID for the tenant
11    pub id: TenantId,
12    /// Name for the tenant
13    pub name: String,
14    /// Name of the tenant database
15    pub db_name: String,
16    /// Name for the AWS secret used for the database user if
17    /// using secret based authentication
18    pub db_secret_name: Option<String>,
19    /// Name for the database user username if using IAM based
20    /// authentication
21    #[sqlx(default)]
22    pub db_iam_user_name: Option<String>,
23    /// Name of the tenant s3 bucket
24    pub s3_name: String,
25    /// Name of the tenant search index
26    pub os_index_name: String,
27    /// Environment for the tenant
28    pub env: String,
29    /// Optional event queue (SQS) to send docbox events to
30    pub event_queue_url: Option<String>,
31}
32
33pub struct CreateTenant {
34    pub id: TenantId,
35    pub name: String,
36    pub db_name: String,
37    pub db_iam_user_name: Option<String>,
38    pub db_secret_name: Option<String>,
39    pub s3_name: String,
40    pub os_index_name: String,
41    pub event_queue_url: Option<String>,
42    pub env: String,
43}
44
45impl Tenant {
46    /// Create a new tenant
47    pub async fn create(db: impl DbExecutor<'_>, create: CreateTenant) -> DbResult<Tenant> {
48        sqlx::query(
49            r#"
50            INSERT INTO "docbox_tenants" (
51                "id",
52                "name",
53                "db_name",
54                "db_iam_user_name",
55                "db_secret_name",
56                "s3_name",
57                "os_index_name",
58                "env",
59                "event_queue_url"
60            )
61            VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
62        "#,
63        )
64        .bind(create.id)
65        .bind(create.name.as_str())
66        .bind(create.db_name.as_str())
67        .bind(create.db_iam_user_name.clone())
68        .bind(create.db_secret_name.clone())
69        .bind(create.s3_name.as_str())
70        .bind(create.os_index_name.as_str())
71        .bind(create.env.as_str())
72        .bind(create.event_queue_url.as_ref())
73        .execute(db)
74        .await?;
75
76        Ok(Tenant {
77            id: create.id,
78            name: create.name,
79            db_name: create.db_name,
80            db_iam_user_name: create.db_iam_user_name,
81            db_secret_name: create.db_secret_name,
82            s3_name: create.s3_name,
83            os_index_name: create.os_index_name,
84            env: create.env,
85            event_queue_url: create.event_queue_url,
86        })
87    }
88
89    /// Find a tenant by `id` within a specific `env`
90    pub async fn find_by_id(
91        db: impl DbExecutor<'_>,
92        id: TenantId,
93        env: &str,
94    ) -> DbResult<Option<Tenant>> {
95        sqlx::query_as(r#"SELECT * FROM "docbox_tenants" WHERE "id" = $1 AND "env" = $2"#)
96            .bind(id)
97            .bind(env)
98            .fetch_optional(db)
99            .await
100    }
101
102    /// Find a tenant using its S3 bucket
103    pub async fn find_by_bucket(db: impl DbExecutor<'_>, bucket: &str) -> DbResult<Option<Tenant>> {
104        sqlx::query_as(r#"SELECT * FROM "docbox_tenants" WHERE "s3_name" = $1"#)
105            .bind(bucket)
106            .fetch_optional(db)
107            .await
108    }
109
110    /// Finds all tenants for the specified environment
111    pub async fn find_by_env(db: impl DbExecutor<'_>, env: &str) -> DbResult<Vec<Tenant>> {
112        sqlx::query_as(r#"SELECT * FROM "docbox_tenants" WHERE "env" = $1 ORDER BY "name""#)
113            .bind(env)
114            .fetch_all(db)
115            .await
116    }
117
118    /// Finds all tenants
119    pub async fn all(db: impl DbExecutor<'_>) -> DbResult<Vec<Tenant>> {
120        sqlx::query_as(r#"SELECT * FROM "docbox_tenants" ORDER BY "name""#)
121            .fetch_all(db)
122            .await
123    }
124
125    /// Deletes the tenant
126    pub async fn delete(self, db: impl DbExecutor<'_>) -> DbResult<()> {
127        sqlx::query(r#"DELETE FROM "docbox_tenants" WHERE "id" = $1 AND "env" = $2"#)
128            .bind(self.id)
129            .bind(&self.env)
130            .execute(db)
131            .await?;
132        Ok(())
133    }
134}