Skip to main content

modkit_db/secure/
mod.rs

1//! Secure ORM layer for scoped database access.
2//!
3//! This module provides a type-safe wrapper around `SeaORM` that enforces
4//! access control scoping at compile time using the typestate pattern.
5//!
6//! # Basic Example
7//!
8//! Creating and using access scopes:
9//!
10//! ```rust
11//! use modkit_db::secure::{AccessScope, pep_properties};
12//! use uuid::Uuid;
13//!
14//! // Create an empty scope (deny-all)
15//! let deny_scope = AccessScope::default();
16//! assert!(deny_scope.is_deny_all());
17//!
18//! // Create a tenant-scoped access
19//! let tenant_id = Uuid::new_v4();
20//! let scope = AccessScope::for_tenant(tenant_id);
21//! assert!(scope.has_property(pep_properties::OWNER_TENANT_ID));
22//! assert!(!scope.is_deny_all());
23//!
24//! // Create a resource-scoped access
25//! let resource_id = Uuid::new_v4();
26//! let resource_scope = AccessScope::for_resource(resource_id);
27//! assert!(resource_scope.has_property(pep_properties::RESOURCE_ID));
28//! ```
29//!
30//! # Quick Start with `SeaORM`
31//!
32//! ```rust,ignore
33//! use modkit_db::secure::{AccessScope, SecureEntityExt, Scopable};
34//! use sea_orm::entity::prelude::*;
35//!
36//! // 1. Derive Scopable for your entity (or implement manually)
37//! #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Scopable)]
38//! #[sea_orm(table_name = "users")]
39//! #[secure(
40//!     tenant_col = "tenant_id",
41//!     resource_col = "id",
42//!     no_owner,
43//!     no_type
44//! )]
45//! pub struct Model {
46//!     #[sea_orm(primary_key)]
47//!     pub id: Uuid,
48//!     pub tenant_id: Uuid,
49//!     pub email: String,
50//! }
51//!
52//! // 2. Create an access scope
53//! let scope = AccessScope::for_tenants(vec![tenant_id]);
54//!
55//! // 3. Execute scoped queries
56//! let users = Entity::find()
57//!     .secure()
58//!     .scope_with(&scope)?
59//!     .all(conn)
60//!     .await?;
61//! ```
62//!
63//! # Manual Implementation
64//!
65//! If you prefer not to use the derive macro:
66//!
67//! ```rust,ignore
68//! use modkit_db::secure::ScopableEntity;
69//!
70//! impl ScopableEntity for Entity {
71//!     fn tenant_col() -> Option<Self::Column> {
72//!         Some(Column::TenantId)
73//!     }
74//!     fn resource_col() -> Option<Self::Column> {
75//!         Some(Column::Id)
76//!     }
77//!     fn owner_col() -> Option<Self::Column> {
78//!         None
79//!     }
80//!     fn type_col() -> Option<Self::Column> {
81//!         None
82//!     }
83//! }
84//! ```
85//!
86//! # Features
87//!
88//! - **Typestate enforcement**: Prevents unscoped queries at compile time
89//! - **Implicit policy**: Automatic deny-all for empty scopes
90//! - **Multi-tenant support**: Enforces tenant isolation when applicable
91//! - **Resource-level access**: Fine-grained control via explicit IDs
92//! - **Zero runtime overhead**: All checks at compile/build time
93//!
94//! # Policy
95//!
96//! | Scope | Behavior |
97//! |-------|----------|
98//! | Empty | Deny all (`WHERE 1=0`) |
99//! | Tenants only | Filter by tenant column |
100//! | Resources only | Filter by ID column |
101//! | Both | AND them together |
102//!
103//! See the [docs module](docs) for comprehensive examples and usage patterns.
104
105// Module declarations
106mod cond;
107mod db;
108mod db_ops;
109pub mod docs;
110#[allow(clippy::module_inception)]
111mod entity_traits;
112mod error;
113pub mod provider;
114mod runner;
115mod secure_conn;
116mod select;
117mod tests;
118mod tx_config;
119mod tx_error;
120
121// Public API re-exports
122
123// Core types
124pub use entity_traits::ScopableEntity;
125pub use error::ScopeError;
126
127// Security types from modkit-security
128pub use modkit_security::{
129    AccessScope, EqScopeFilter, InScopeFilter, ScopeConstraint, ScopeFilter, ScopeValue,
130    pep_properties,
131};
132
133// Ergonomic secure connection API (no raw SeaORM types leaked)
134pub use secure_conn::{SecureConn, SecureTx};
135
136// Hidden runner capability used by repositories.
137#[doc(hidden)]
138pub use runner::DBRunner;
139
140pub(crate) use runner::{DBRunnerInternal, SeaOrmRunner};
141
142// Primary database types (new secure API)
143pub use db::{Db, DbConn, DbTx};
144
145// Transaction error types (no SeaORM types leaked)
146pub use tx_error::{InfraError, TxError};
147
148// Transaction configuration (no SeaORM types leaked)
149pub use tx_config::{TxAccessMode, TxConfig, TxIsolationLevel};
150
151// Select operations
152pub use select::{
153    Scoped, SecureEntityExt, SecureFindRelatedExt, SecureSelect, SecureSelectTwo,
154    SecureSelectTwoMany, Unscoped,
155};
156
157// Update/Delete/Insert operations
158pub use db_ops::{
159    SecureDeleteExt, SecureDeleteMany, SecureInsertExt, SecureInsertOne, SecureOnConflict,
160    SecureUpdateExt, SecureUpdateMany, secure_insert, secure_update_with_scope,
161    validate_tenant_in_scope,
162};
163
164// Provider pattern for advanced tenant filtering
165pub use provider::{SimpleTenantFilter, TenantFilterProvider};
166
167pub use modkit_db_macros::Scopable;