Skip to main content

AllowlistAspect

Struct AllowlistAspect 

Source
pub struct AllowlistAspect { /* private fields */ }
Expand description

Identity-based allowlist aspect.

Admits a call when the supplied identity string is present in a configured allowlist, optionally honoring a wildcard entry ("*") and an optional normalization hook for identity comparison.

This shape recurs across messaging-channel integrations in real codebases: each channel maintains its own list of who is permitted to talk to the bot. The classical role-based AuthorizationAspect does not fit because there are no roles — there is a set of literal identity strings and a yes/no decision.

§Example

use aspect_std::AllowlistAspect;

let policy = AllowlistAspect::new(["user_a".to_string(), "user_b".to_string()]);
assert!(policy.is_allowed("user_a"));
assert!(!policy.is_allowed("intruder"));

// Wildcard.
let open = AllowlistAspect::new(["*".to_string()]);
assert!(open.is_allowed("anyone"));

// Empty list = deny everyone.
let closed = AllowlistAspect::new(Vec::<String>::new());
assert!(!closed.is_allowed("user_a"));

§Normalization

Some identity spaces require canonicalization before comparison: phone numbers (E.164), emails (case-insensitive), Telegram usernames (@-stripped), Matrix MXIDs (case-insensitive). Pass a normalization function via AllowlistAspect::with_normalizer.

§Mutability

The allowlist is stored behind an RwLock and can be amended at runtime via AllowlistAspect::add / AllowlistAspect::set. This matches runtime-pairing flows where new identities are added without restart.

Implementations§

Source§

impl AllowlistAspect

Source

pub fn new<I, S>(entries: I) -> Self
where I: IntoIterator<Item = S>, S: Into<String>,

Build an allowlist aspect from an initial set of entries.

The wildcard entry "*" admits everyone. An empty list denies everyone (fail-closed). Identity comparison is byte-equal by default; see AllowlistAspect::with_normalizer for case- insensitive or canonicalized comparison.

Source

pub fn with_normalizer<F>(self, normalizer: F) -> Self
where F: Fn(&str) -> String + Send + Sync + 'static,

Attach a normalization function applied to both the allowlist entries and the queried identity before comparison.

Consumes and returns self. The normalizer must be deterministic and referentially transparent: calling it twice on the same input must produce identical output.

Mutually exclusive with AllowlistAspect::with_matcher: if a matcher is installed, the normalizer is bypassed because the matcher owns the entry-vs-identity comparison end-to-end.

Source

pub fn with_matcher<F>(self, matcher: F) -> Self
where F: Fn(&str, &str) -> bool + Send + Sync + 'static,

Attach a custom match predicate (entry, identity) -> bool that replaces the default byte-equal (or normalized-equal) comparison.

Consumes and returns self. The wildcard "*" and empty-list short-circuits still apply before the matcher runs — the matcher is only consulted for non-"*" entries against a non-empty list. The matcher must be referentially transparent.

Use this when entries and identities are not directly comparable — e.g. allowlist entries that describe a class of identity ("@example.com" matches any user at that domain) rather than a single literal one. When a matcher is set the normalizer is bypassed; the matcher owns the comparison.

Source

pub fn is_allowed(&self, identity: &str) -> bool

Returns true if identity is admitted by the allowlist.

Semantics: empty list ⇒ deny; "*" present ⇒ admit; otherwise admit iff the (possibly normalized) identity equals some (possibly normalized) entry.

Source

pub fn add(&self, identity: impl Into<String>)

Append identity to the allowlist if absent. No-op when identity is already present (byte-equal, not normalized).

Source

pub fn set<I, S>(&self, entries: I)
where I: IntoIterator<Item = S>, S: Into<String>,

Replace the entire allowlist atomically.

Source

pub fn snapshot(&self) -> Vec<String>

Snapshot the current allowlist as an owned Vec. Order-preserving relative to insertion / construction.

Source

pub fn len(&self) -> usize

Number of entries currently in the list (including the wildcard entry if present).

Source

pub fn is_empty(&self) -> bool

Returns true when the allowlist is empty (i.e. denies everyone).

Trait Implementations§

Source§

impl Aspect for AllowlistAspect

Source§

fn before(&self, _ctx: &JoinPoint)

Advice executed before the target function runs. Read more
Source§

fn around( &self, pjp: ProceedingJoinPoint<'_>, ) -> Result<Box<dyn Any>, AspectError>

Advice that wraps the entire target function execution. Read more
Source§

fn after(&self, _ctx: &JoinPoint, _result: &(dyn Any + 'static))

Advice executed after the target function completes successfully. Read more
Source§

fn after_error(&self, _ctx: &JoinPoint, _error: &AspectError)

Advice executed when the target function encounters an error. Read more
Source§

impl Clone for AllowlistAspect

Source§

fn clone(&self) -> AllowlistAspect

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.