pub enum AclScope {
Unrestricted,
Anonymous,
User {
object_id: String,
roles: Vec<String>,
},
}Expand description
Who a request is acting as, for ACL purposes.
An enum rather than an Option<String> so that “no ACL constraint at all” cannot be reached
by forgetting to set a field. acl === undefined as a master sentinel is the upstream shape
this deliberately does not copy.
Variants§
Unrestricted
Master or maintenance: no ACL constraint is applied at all.
Anonymous
A caller acting as nobody in particular.
User
A logged-in user, with the transitive closure of their roles.
Roles are bare names here, with no role: prefix. The prefix is added by
AclScope::acl_group and by AclScope::principals, so there is exactly one place
that knows the wire spelling. Construct through AclScope::user rather than by
literal, so that a role:-prefixed objectId cannot reach object_id.
Implementations§
Source§impl AclScope
impl AclScope
Sourcepub fn user(
object_id: impl Into<String>,
roles: Vec<String>,
) -> Result<Self, ParseError>
pub fn user( object_id: impl Into<String>, roles: Vec<String>, ) -> Result<Self, ParseError>
Build a user scope, refusing a role:-prefixed objectId.
A user whose objectId began with role: would be granted that role by every ACL and CLP
check, because the entity namespace is one flat string space on the wire. Upstream guards
it at two session-resolution sites with the same code and message (Auth.js:195, :237);
here the guard is at the one place a scope can be built.
pub fn is_master(&self) -> bool
pub fn user_id(&self) -> Option<&str>
Sourcepub fn has_role(&self, name: &str) -> bool
pub fn has_role(&self, name: &str) -> bool
Does the caller hold this role? The name is bare, with no role: prefix.
Sourcepub fn acl_group(&self) -> Vec<String>
pub fn acl_group(&self) -> Vec<String>
Upstream’s aclGroup: ['*'], then every role as role:<name>, then the user’s objectId
(RestWrite.js:184, RestQuery.js:427, both ['*'].concat(roles, [user.id])).
Master is the empty list, because upstream never reaches a caller that consumes an
aclGroup without first branching on isMaster.
Order matters twice over. addPointerPermissions extracts the single user id by filtering
out role: and * (DatabaseController.js:1745-1747), and the compiled $in array is
snapshot-compared.
Sourcepub fn read_constraint(&self) -> Option<Constraint>
pub fn read_constraint(&self) -> Option<Constraint>
The constraint to add to a read.
None for AclScope::Unrestricted, which is the only case where no constraint is
applied. Returning Option makes the master case explicit at every call site instead of
being the absence of a step.
UPSTREAM-QUIRK: the emitted list carries '*' twice, once seeded by addReadACL
(DatabaseController.js:88) and once already present in the aclGroup
(RestQuery.js:427). A duplicate in an $in changes nothing, and removing it would make
the compiled query differ from upstream’s for no gain.
Sourcepub fn write_constraint(&self) -> Option<Constraint>
pub fn write_constraint(&self) -> Option<Constraint>
The constraint to add to a write.
Note the asymmetry with reads: addWriteACL omits '*' from the injected list, because
getUserAndRoleACL already seeds it for every non-master caller. Reproduced rather than
unified, since the two functions are not symmetric upstream and a caller path that builds
its own list would behave differently.
Trait Implementations§
impl Eq for AclScope
impl StructuralPartialEq for AclScope
Auto Trait Implementations§
impl Freeze for AclScope
impl RefUnwindSafe for AclScope
impl Send for AclScope
impl Sync for AclScope
impl Unpin for AclScope
impl UnsafeUnpin for AclScope
impl UnwindSafe for AclScope
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.