//! Print the permission model's schema as a plain `.sql` migration. //! //! A consumer whose migrations are files rather than a Rust `open()` //! call — Supabase, sqlx, plain psql — needs the same DDL as text. //! Emitting it from the same constants the library applies is the point: //! two hand-maintained copies of an authorisation schema will diverge, //! and the divergence will be discovered by something going wrong. //! //! ```text //! cargo run -p trusty-policy-postgres --example emit_ddl > 0001_permission_model.sql //! ``` //! //! Pass a table and its scope column to additionally emit the policies //! that put that table under enforcement: //! //! ```text //! cargo run -p trusty-policy-postgres --example emit_ddl -- public.calendar resource_scope //! ``` use trusty_policy_postgres::permits::DDL_FUNCTIONS; use trusty_policy_postgres::schema::{DDL_SCHEMA_VERSION_UPSERT, DDL_V1, SCHEMA_VERSION}; use trusty_policy_postgres::store::policy_statements; fn main() { println!("-- Generated by `cargo run -p trusty-policy-postgres --example emit_ddl`."); println!("-- Source of truth is trusty-policy-postgres; edit there, regenerate here."); println!("-- Applying this by hand and by GrantStore::open must agree, so do not"); println!("-- edit this file directly."); println!(); for stmt in DDL_V1 { println!("{};", stmt.trim()); println!(); } for stmt in DDL_FUNCTIONS { println!("{};", stmt.trim()); println!(); } // The library upserts this with a bind parameter; a file has no // parameters, so the version is inlined. It is a constant, not // input. println!( "{};", DDL_SCHEMA_VERSION_UPSERT .trim() .replace("$1", &format!("'{SCHEMA_VERSION}'")) ); println!(); let args: Vec = std::env::args().skip(1).collect(); match args.as_slice() { [] => { println!("-- No table given, so no policies were emitted."); println!("-- Installing this schema protects nothing on its own: a table is"); println!("-- guarded only once it has ENABLE + FORCE ROW LEVEL SECURITY and the"); println!("-- four policies. Re-run with a table and its scope column, e.g."); println!("-- ... --example emit_ddl -- public.calendar resource_scope"); } [table, column] => match policy_statements(table, column) { Ok(stmts) => { println!("-- Enforcement for {table}({column})."); for stmt in stmts { println!("{stmt}"); } } Err(e) => { eprintln!("error: {e}"); std::process::exit(1); } }, _ => { eprintln!("usage: emit_ddl [ ]"); std::process::exit(2); } } }