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;
12//! use uuid::Uuid;
13//!
14//! // Create an empty scope (deny-all)
15//! let deny_scope = AccessScope::default();
16//! assert!(deny_scope.is_empty());
17//!
18//! // Create a tenant-scoped access
19//! let tenant_id = Uuid::new_v4();
20//! let scope = AccessScope::tenant(tenant_id);
21//! assert!(scope.has_tenants());
22//! assert!(!scope.is_empty());
23//!
24//! // Create a resource-scoped access
25//! let resource_id = Uuid::new_v4();
26//! let resource_scope = AccessScope::resource(resource_id);
27//! assert!(resource_scope.has_resources());
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::tenants_only(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::AccessScope;
129
130// Ergonomic secure connection API (no raw SeaORM types leaked)
131pub use secure_conn::{SecureConn, SecureTx};
132
133// Hidden runner capability used by repositories.
134#[doc(hidden)]
135pub use runner::DBRunner;
136
137pub(crate) use runner::{DBRunnerInternal, SeaOrmRunner};
138
139// Primary database types (new secure API)
140pub use db::{Db, DbConn, DbTx};
141
142// Transaction error types (no SeaORM types leaked)
143pub use tx_error::{InfraError, TxError};
144
145// Transaction configuration (no SeaORM types leaked)
146pub use tx_config::{TxAccessMode, TxConfig, TxIsolationLevel};
147
148// Select operations
149pub use select::{
150    Scoped, SecureEntityExt, SecureFindRelatedExt, SecureSelect, SecureSelectTwo,
151    SecureSelectTwoMany, Unscoped,
152};
153
154// Update/Delete/Insert operations
155pub use db_ops::{
156    SecureDeleteExt, SecureDeleteMany, SecureInsertExt, SecureInsertOne, SecureOnConflict,
157    SecureUpdateExt, SecureUpdateMany, secure_insert, secure_update_with_scope,
158    validate_tenant_in_scope,
159};
160
161// Provider pattern for advanced tenant filtering
162pub use provider::{SimpleTenantFilter, TenantFilterProvider};
163
164pub use modkit_db_macros::Scopable;