use derive_builder::Builder; use redact::Secret; use sqlx::query_as; use uuid::Uuid; use crate::{client::AppDbClient, macros::with_id_query}; /// Information pertaining to a `LOGIN` role used to grant direct PostgreSQL /// access to a backing database. #[derive(Clone, Debug)] pub struct ServiceCred { /// Primary key (defaults to UUIDv7). pub id: Uuid, /// ID of the database cluster on which this role exists. pub cluster_id: Uuid, /// ID of the user for whom this role was created. pub owner_id: Uuid, /// Postgres role name. pub rolname: String, /// Postgres password. pub password: Secret, } with_id_query!( ServiceCred, sql = "select * from service_creds where id = $1" ); impl ServiceCred { /// Build an insert statement to save information about a new service /// credential role. pub fn insert() -> InsertBuilder { Default::default() } /// Query by ID of the user who owns the credential(s). pub fn belonging_to_user(owner_id: Uuid) -> BelongingToQuery { BelongingToQuery { owner_id } } } #[derive(Builder, Clone, Debug)] pub struct Insert { cluster_id: Uuid, owner_id: Uuid, rolname: String, password: Secret, } impl Insert { pub async fn execute(self, app_db: &mut AppDbClient) -> sqlx::Result { query_as!( ServiceCred, r#" insert into service_creds ( cluster_id, owner_id, rolname, password ) values ($1, $2, $3, $4) returning * "#, self.cluster_id, self.owner_id, self.rolname, self.password.expose_secret(), ) .fetch_one(app_db.get_conn()) .await } } #[derive(Clone, Copy, Debug)] pub struct BelongingToQuery { owner_id: Uuid, } impl BelongingToQuery { pub async fn fetch_all(&self, app_db: &mut AppDbClient) -> sqlx::Result> { query_as!( ServiceCred, "select * from service_creds where owner_id = $1", self.owner_id ) .fetch_all(app_db.get_conn()) .await } }