#[non_exhaustive]pub enum ScopeFilter {
Eq(EqScopeFilter),
In(InScopeFilter),
InGroup(InGroupScopeFilter),
InGroupSubtree(InGroupSubtreeScopeFilter),
InTenantSubtree(InTenantSubtreeScopeFilter),
}Expand description
A single scope filter — a typed predicate on a named resource property.
The property name (e.g., "owner_tenant_id", "id") is an authorization
concept. Mapping to DB columns is done by ScopableEntity::resolve_property().
Variants mirror the predicate types from the PDP response:
ScopeFilter::Eq— equality (property = value)ScopeFilter::In— set membership (property IN (values))ScopeFilter::InGroup— group membership subqueryScopeFilter::InGroupSubtree— group subtree subqueryScopeFilter::InTenantSubtree— tenant subtree subquery ontenant_closure
#[non_exhaustive]: this mirrors the PDP’s predicate set, which has already
grown to five variants and will grow again. Without it, every new predicate
is a breaking change for every downstream match. With it, a consumer must
write a wildcard arm — and that arm must fail closed: a filter this build
does not understand is a restriction it cannot apply, so treating it as
“nothing to do” silently drops a narrowing term and widens the grant.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Eq(EqScopeFilter)
Equality: property = value.
In(InScopeFilter)
Set membership: property IN (values).
InGroup(InGroupScopeFilter)
Group membership: property IN (SELECT resource_id FROM membership WHERE group_id IN (group_ids)).
InGroupSubtree(InGroupSubtreeScopeFilter)
Group subtree: property IN (SELECT resource_id FROM membership WHERE group_id IN (SELECT descendant_id FROM closure WHERE ancestor_id IN (ancestor_ids))).
InTenantSubtree(InTenantSubtreeScopeFilter)
Tenant subtree: property IN (SELECT descendant_id FROM tenant_closure WHERE ancestor_id = root_tenant_id).
Implementations§
Source§impl ScopeFilter
impl ScopeFilter
Sourcepub fn eq(property: impl Into<String>, value: impl Into<ScopeValue>) -> Self
pub fn eq(property: impl Into<String>, value: impl Into<ScopeValue>) -> Self
Create an equality filter (property = value).
Sourcepub fn in(property: impl Into<String>, values: Vec<ScopeValue>) -> Self
pub fn in(property: impl Into<String>, values: Vec<ScopeValue>) -> Self
Create a set membership filter (property IN (values)).
Sourcepub fn in_uuids(property: impl Into<String>, uuids: Vec<Uuid>) -> Self
pub fn in_uuids(property: impl Into<String>, uuids: Vec<Uuid>) -> Self
Create a set membership filter from UUID values (convenience).
Sourcepub fn in_group(property: impl Into<String>, group_ids: Vec<ScopeValue>) -> Self
pub fn in_group(property: impl Into<String>, group_ids: Vec<ScopeValue>) -> Self
Create a group membership filter.
Sourcepub fn in_group_subtree(
property: impl Into<String>,
ancestor_ids: Vec<ScopeValue>,
) -> Self
pub fn in_group_subtree( property: impl Into<String>, ancestor_ids: Vec<ScopeValue>, ) -> Self
Create a group subtree filter.
Sourcepub fn in_tenant_subtree(
property: impl Into<String>,
root_tenant_id: impl Into<ScopeValue>,
respect_barriers: bool,
descendant_status: Vec<ScopeValue>,
) -> Self
pub fn in_tenant_subtree( property: impl Into<String>, root_tenant_id: impl Into<ScopeValue>, respect_barriers: bool, descendant_status: Vec<ScopeValue>, ) -> Self
Create a tenant subtree filter rooted at a single ancestor tenant.
descendant_status is a (possibly empty) list of SMALLINT-encoded
tenant statuses (see tenant_resolver_sdk::TenantStatus::as_smallint);
when non-empty, the SQL adds AND descendant_status IN (...) to
the closure subquery. Pass Vec::new() for “no status filter”.
Sourcepub fn values(&self) -> ScopeFilterValues<'_>
pub fn values(&self) -> ScopeFilterValues<'_>
Collect direct-match values as a slice-like view for iteration.
For Eq, returns a single-element slice; for In, returns the values slice.
For InGroup/InGroupSubtree/InTenantSubtree, returns empty — those
are subquery parameters, not resource property values. The actual
matching happens in SQL via [secure::scope_to_condition].
Write-path limitation: Because InTenantSubtree returns an empty
slice here, in-memory helpers such as AccessScope::contains_uuid and
AccessScope::all_uuid_values_for always return negative/empty results
for this filter variant. Secure-insert paths that validate scope membership
via these helpers cannot use InTenantSubtree as a substitute for
allow_all() without an additional DB-backed tenant-membership check.
Sourcepub fn is_representable_in_memory(&self) -> bool
pub fn is_representable_in_memory(&self) -> bool
Whether this filter can be decided from its values alone.
false for the three subquery variants, whose matching happens in SQL.
ScopeFilter::values returns an empty view for those, which is
indistinguishable from an In filter that genuinely has no values — so
a caller deciding membership in memory reads “no match” for a filter
that does grant access.
Check this first: a filter that is not representable in memory has to be resolved against the database, not treated as a negative.
Sourcepub fn uuid_values(&self) -> Vec<Uuid>
pub fn uuid_values(&self) -> Vec<Uuid>
Extract filter values as UUIDs, skipping non-UUID entries.
Useful when the caller knows the property holds UUID values
(e.g., owner_tenant_id, id).
Trait Implementations§
Source§impl Clone for ScopeFilter
impl Clone for ScopeFilter
Source§fn clone(&self) -> ScopeFilter
fn clone(&self) -> ScopeFilter
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more