use derive_builder::Builder; use redact::Secret; use sqlx::query_as; use url::Url; use uuid::Uuid; use crate::client::AppDbClient; /// A workspace is 1:1 with a Postgres "database". #[derive(Clone, Debug)] pub struct Workspace { /// Primary key (defaults to UUIDv7). pub id: Uuid, /// Human friendly name for the workspace. pub name: String, /// `postgresql://` URL of the instance and database hosting this workspace. // TODO: Encrypt values in Postgres using `pgp_sym_encrypt()`. pub url: Secret, /// ID of the user account that created this workspace. pub owner_id: Uuid, } impl Workspace { /// Build an insert statement to create a new workspace. pub fn insert() -> InsertBuilder { InsertBuilder::default() } /// Build a single-field query by workspace ID. pub fn with_id(id: Uuid) -> WithIdQuery { WithIdQuery { id } } } pub struct WithIdQuery { id: Uuid, } impl WithIdQuery { pub async fn fetch_optional( self, app_db: &mut AppDbClient, ) -> Result, sqlx::Error> { query_as!( Workspace, "select * from workspaces where id = $1", &self.id ) .fetch_optional(&mut *app_db.conn) .await } pub async fn fetch_one(self, app_db: &mut AppDbClient) -> Result { query_as!( Workspace, "select * from workspaces where id = $1", &self.id ) .fetch_one(&mut *app_db.conn) .await } } #[derive(Builder)] pub struct Insert { url: Url, owner_id: Uuid, } impl Insert { pub async fn insert(self, app_db: &mut AppDbClient) -> Result { query_as!( Workspace, " insert into workspaces (url, owner_id) values ($1, $2) returning * ", self.url.to_string(), self.owner_id ) .fetch_one(&mut *app_db.conn) .await } }