pub struct SecureSelect<E: EntityTrait, S> { /* private fields */ }Expand description
A type-safe wrapper around SeaORM’s Select that enforces scoping.
This wrapper uses the typestate pattern to ensure that queries cannot
be executed without first applying access control via .scope_with().
§Type Parameters
E: TheSeaORMentity typeS: The typestate (UnscopedorScoped)
§Example
use modkit_db::secure::{AccessScope, SecureEntityExt};
let scope = AccessScope::tenants_only(vec![tenant_id]);
let users = user::Entity::find()
.secure() // Returns SecureSelect<E, Unscoped>
.scope_with(&scope)? // Returns SecureSelect<E, Scoped>
.all(conn) // Now can execute
.await?;Implementations§
Source§impl<E> SecureSelect<E, Unscoped>
impl<E> SecureSelect<E, Unscoped>
Sourcepub fn scope_with(self, scope: &AccessScope) -> SecureSelect<E, Scoped>
pub fn scope_with(self, scope: &AccessScope) -> SecureSelect<E, Scoped>
Apply access control scope to this query, transitioning to the Scoped state.
This applies the implicit policy:
- Empty scope → deny all
- Tenants only → filter by tenant
- Resources only → filter by resource IDs
- Both → AND them together
Source§impl<E> SecureSelect<E, Scoped>where
E: EntityTrait,
impl<E> SecureSelect<E, Scoped>where
E: EntityTrait,
Sourcepub async fn all<C>(self, conn: &C) -> Result<Vec<E::Model>, ScopeError>
pub async fn all<C>(self, conn: &C) -> Result<Vec<E::Model>, ScopeError>
Execute the query and return all matching results.
§Errors
Returns ScopeError::Db if the database query fails.
Sourcepub async fn one<C>(self, conn: &C) -> Result<Option<E::Model>, ScopeError>
pub async fn one<C>(self, conn: &C) -> Result<Option<E::Model>, ScopeError>
Execute the query and return at most one result.
§Errors
Returns ScopeError::Db if the database query fails.
Sourcepub async fn count<C>(self, conn: &C) -> Result<u64, ScopeError>
pub async fn count<C>(self, conn: &C) -> Result<u64, ScopeError>
Execute the query and return the number of matching results.
§Errors
Returns ScopeError::Db if the database query fails.
Sourcepub fn and_id(self, id: Uuid) -> Result<Self, ScopeError>
pub fn and_id(self, id: Uuid) -> Result<Self, ScopeError>
Add an additional filter for a specific resource ID.
This is useful when you want to further narrow a scoped query to a single resource.
§Example
let user = User::find()
.secure()
.scope_with(&scope)?
.and_id(user_id)
.one(conn)
.await?;§Errors
Returns ScopeError::Invalid if the entity doesn’t have a resource column.
Sourcepub fn into_inner(self) -> Select<E>
pub fn into_inner(self) -> Select<E>
Unwrap the inner SeaORM Select for advanced use cases.
This is an escape hatch if you need to add additional filters, joins, or ordering after scoping has been applied.
§Safety
The caller must ensure they don’t remove or bypass the security
conditions that were applied during .scope_with().
Source§impl<E> SecureSelect<E, Scoped>where
E: EntityTrait,
impl<E> SecureSelect<E, Scoped>where
E: EntityTrait,
Sourcepub fn filter(self, filter: Condition) -> Self
pub fn filter(self, filter: Condition) -> Self
Add additional filters to the scoped query. The scope conditions remain in place.
Sourcepub fn order_by<C>(self, col: C, order: Order) -> Selfwhere
C: IntoSimpleExpr,
pub fn order_by<C>(self, col: C, order: Order) -> Selfwhere
C: IntoSimpleExpr,
Add ordering to the scoped query.
Sourcepub fn and_scope_for<J>(self, scope: &AccessScope) -> Self
pub fn and_scope_for<J>(self, scope: &AccessScope) -> Self
Sourcepub fn scope_via_exists<J>(self, scope: &AccessScope) -> Self
pub fn scope_via_exists<J>(self, scope: &AccessScope) -> Self
Apply scoping via EXISTS subquery on a related entity.
This is particularly useful when the base entity doesn’t have a tenant column but is related to one that does.
§Note
This is a simplified version that filters by tenant on the joined entity.
For complex join predicates, use into_inner() and build custom EXISTS clauses.
§Example
// Find settings that exist in a tenant-scoped relationship
GlobalSetting::find()
.secure()
.scope_with(&AccessScope::resources_only(vec![]))?
.scope_via_exists::<TenantSetting>(&scope)
.all(conn)
.await?Trait Implementations§
Source§impl<E: Clone + EntityTrait, S: Clone> Clone for SecureSelect<E, S>
impl<E: Clone + EntityTrait, S: Clone> Clone for SecureSelect<E, S>
Source§fn clone(&self) -> SecureSelect<E, S>
fn clone(&self) -> SecureSelect<E, S>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl<E, S> Freeze for SecureSelect<E, S>
impl<E, S> !RefUnwindSafe for SecureSelect<E, S>
impl<E, S> Send for SecureSelect<E, S>where
S: Send,
impl<E, S> Sync for SecureSelect<E, S>where
S: Sync,
impl<E, S> Unpin for SecureSelect<E, S>
impl<E, S> !UnwindSafe for SecureSelect<E, S>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi Quirk value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);