use backbone_orm::company_scope::with_request_scope;
use backbone_orm::org_scope::{with_org_request_scope_and_audit, OrgScope};
use backbone_orm::RequestAuditContext;
use sqlx::postgres::PgPoolOptions;
use sqlx::PgPool;
use std::time::Duration;
use uuid::Uuid;
fn admin_dsn() -> Option<String> {
std::env::var("BACKBONE_ORM_RLS_DSN").ok()
}
async fn single_connection_pool(dsn: &str) -> PgPool {
PgPoolOptions::new()
.max_connections(1)
.acquire_timeout(Duration::from_secs(5))
.connect(dsn)
.await
.expect("connect")
}
async fn settings_on_next_borrow(pool: &PgPool) -> Vec<(String, String)> {
let mut conn = pool
.acquire()
.await
.expect("the cancelled scope's connection comes back");
let mut out = Vec::new();
for var in [
"app.company_id",
"app.scope_unit_ids",
"app.acting_unit_id",
"app.actor",
"app.correlation_id",
] {
let value: Option<String> = sqlx::query_scalar("SELECT current_setting($1, true)")
.bind(var)
.fetch_one(&mut *conn)
.await
.unwrap();
out.push((var.to_string(), value.unwrap_or_default()));
}
out
}
fn assert_clean(settings: &[(String, String)]) {
let dirty: Vec<_> = settings.iter().filter(|(_, v)| !v.is_empty()).collect();
assert!(
dirty.is_empty(),
"a cancelled request scope returned its connection still scoped: {dirty:?}"
);
}
#[tokio::test]
async fn a_cancelled_org_scope_returns_a_clean_connection() {
let Some(dsn) = admin_dsn() else {
eprintln!("skipping: BACKBONE_ORM_RLS_DSN not set");
return;
};
let pool = single_connection_pool(&dsn).await;
let unit = Uuid::new_v4();
let mut audit = RequestAuditContext::new("cancelled-actor");
audit.correlation_id = "corr-1".into();
let outcome = tokio::time::timeout(
Duration::from_millis(200),
with_org_request_scope_and_audit(&pool, OrgScope::for_company_unit(unit), audit, async {
tokio::time::sleep(Duration::from_secs(30)).await;
}),
)
.await;
assert!(outcome.is_err(), "the scope must have been cancelled");
assert_clean(&settings_on_next_borrow(&pool).await);
}
#[tokio::test]
async fn a_cancelled_company_scope_returns_a_clean_connection() {
let Some(dsn) = admin_dsn() else {
eprintln!("skipping: BACKBONE_ORM_RLS_DSN not set");
return;
};
let pool = single_connection_pool(&dsn).await;
let outcome = tokio::time::timeout(
Duration::from_millis(200),
with_request_scope(&pool, Uuid::new_v4(), async {
tokio::time::sleep(Duration::from_secs(30)).await;
}),
)
.await;
assert!(outcome.is_err(), "the scope must have been cancelled");
assert_clean(&settings_on_next_borrow(&pool).await);
}
#[tokio::test]
async fn a_completed_scope_still_resets_before_returning() {
let Some(dsn) = admin_dsn() else {
eprintln!("skipping: BACKBONE_ORM_RLS_DSN not set");
return;
};
let pool = single_connection_pool(&dsn).await;
let unit = Uuid::new_v4();
with_org_request_scope_and_audit(
&pool,
OrgScope::for_company_unit(unit),
RequestAuditContext::new("done-actor"),
async {},
)
.await
.unwrap();
assert_clean(&settings_on_next_borrow(&pool).await);
}
#[tokio::test]
async fn the_legacy_company_is_the_nearest_company_ancestor() {
let Some(dsn) = admin_dsn() else {
eprintln!("skipping: BACKBONE_ORM_RLS_DSN not set");
return;
};
let pool = single_connection_pool(&dsn).await;
let mut conn = pool.acquire().await.unwrap();
let mut tx = sqlx::Connection::begin(&mut *conn).await.unwrap();
sqlx::raw_sql(
"DROP SCHEMA IF EXISTS organization CASCADE; \
CREATE SCHEMA organization; \
CREATE TABLE organization.org_units ( \
id uuid PRIMARY KEY, parent_id uuid, kind text NOT NULL); \
CREATE FUNCTION organization.org_unit_subtree(roots uuid[]) \
RETURNS SETOF uuid LANGUAGE sql AS $$ \
WITH RECURSIVE d AS ( \
SELECT id FROM organization.org_units WHERE id = ANY(roots) \
UNION SELECT o.id FROM organization.org_units o JOIN d ON o.parent_id = d.id) \
SELECT id FROM d $$; \
CREATE FUNCTION organization.org_unit_root() RETURNS uuid LANGUAGE sql AS $$ \
SELECT id FROM organization.org_units WHERE parent_id IS NULL LIMIT 1 $$;",
)
.execute(&mut *tx)
.await
.unwrap();
let root = Uuid::parse_str("00000000-0000-0000-0000-0000000000f0").unwrap();
let parent = Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap();
let subsidiary = Uuid::parse_str("ffffffff-0000-0000-0000-000000000002").unwrap();
let branch = Uuid::parse_str("00000000-0000-0000-0000-0000000000b0").unwrap();
for (id, parent_id, kind) in [
(root, None, "root"),
(parent, Some(root), "company"),
(subsidiary, Some(parent), "company"),
(branch, Some(subsidiary), "branch"),
] {
sqlx::query("INSERT INTO organization.org_units (id, parent_id, kind) VALUES ($1, $2, $3)")
.bind(id)
.bind(parent_id)
.bind(kind)
.execute(&mut *tx)
.await
.unwrap();
}
let scope = backbone_orm::org_scope::resolve_org_scope(&mut tx, branch, &[])
.await
.unwrap();
let subsidiary_scope = backbone_orm::org_scope::resolve_org_scope(&mut tx, subsidiary, &[])
.await
.unwrap();
tx.rollback().await.unwrap();
assert_eq!(
scope.legacy_company_id(),
Some(subsidiary),
"a branch acts as its own company"
);
assert_eq!(
subsidiary_scope.legacy_company_id(),
Some(subsidiary),
"a company is its own"
);
}