add initial crates and apps

This commit is contained in:
Evan Carroll 2026-01-12 15:34:40 -06:00
parent 5c87ba3519
commit 1ca300098f
113 changed files with 28169 additions and 0 deletions

View file

@ -0,0 +1,84 @@
//! Database connection pool and RLS context management.
use std::time::Duration;
use sqlx::{postgres::PgPoolOptions, PgPool};
use uuid::Uuid;
use chattyness_error::AppError;
/// Create a new database connection pool for the owner interface.
///
/// Uses the `chattyness_owner` role which has full database access.
pub async fn create_owner_pool(database_url: &str) -> Result<PgPool, AppError> {
let pool = PgPoolOptions::new()
.max_connections(5)
.acquire_timeout(Duration::from_secs(5))
.connect(database_url)
.await?;
Ok(pool)
}
/// Create a new database connection pool for the public app.
///
/// Uses the `chattyness_app` role which has Row-Level Security (RLS) policies.
pub async fn create_app_pool(database_url: &str) -> Result<PgPool, AppError> {
let pool = PgPoolOptions::new()
.max_connections(10)
.acquire_timeout(Duration::from_secs(5))
.connect(database_url)
.await?;
Ok(pool)
}
/// Set the current user context for Row-Level Security.
///
/// This should be called at the start of each request to enable RLS policies
/// that depend on the current user ID.
pub async fn set_user_context(pool: &PgPool, user_id: Option<Uuid>) -> Result<(), AppError> {
if let Some(id) = user_id {
sqlx::query("SELECT public.set_current_user_id($1)")
.bind(id)
.execute(pool)
.await?;
} else {
// Clear the user context for anonymous requests
sqlx::query("SELECT public.clear_current_user_id()")
.execute(pool)
.await?;
}
Ok(())
}
/// Clear the current user context.
///
/// Called at the end of a request to ensure the connection is clean
/// before returning to the pool.
pub async fn clear_user_context(pool: &PgPool) -> Result<(), AppError> {
sqlx::query("SELECT public.clear_current_user_id()")
.execute(pool)
.await?;
Ok(())
}
/// Set the current guest session context for Row-Level Security.
///
/// This should be called for guest users to enable RLS policies
/// that depend on the current guest session ID.
pub async fn set_guest_context(pool: &PgPool, guest_session_id: Uuid) -> Result<(), AppError> {
sqlx::query("SELECT public.set_current_guest_session_id($1)")
.bind(guest_session_id)
.execute(pool)
.await?;
Ok(())
}
/// Clear the current guest session context.
pub async fn clear_guest_context(pool: &PgPool) -> Result<(), AppError> {
sqlx::query("SELECT public.set_current_guest_session_id(NULL)")
.execute(pool)
.await?;
Ok(())
}