Skip to main content

ScopeSet

Struct ScopeSet 

Source
pub struct ScopeSet(pub Vec<Scope>);
Expand description

A space-separated set of Scopes, as carried on a scope parameter or a token response.

Canonical by construction: ScopeSet::new sorts, dedupes, and drops any atom already admitted by another atom of its kind, so two sets built from the same members in different orders — or with redundant members — compare equal. Policy is a set of records in a repository, which has no inherent order, so a ceiling has to be a function of the rule set alone; a ScopeSet that could represent the same ceiling two different ways would let vector order silently change what a policy means, which is exactly the failure this type exists to rule out.

Tuple Fields§

§0: Vec<Scope>

Implementations§

Source§

impl ScopeSet

Source

pub fn new(atoms: Vec<Scope>) -> ScopeSet

Builds a canonical ScopeSet from a bag of atoms: sorted, deduped, and with every atom already admitted by another atom of its kind dropped. Containment among distinct atoms is a strict partial order — two distinct atoms can never admit each other — so which atom survives never depends on the input order.

Only an atom of the same kind stands in for another. A ceiling judges each kind on its own (ScopeSet::narrow), and this server never grants a transition: scope, so transition:generic does not absorb the repo: scopes asked for beside it.

Source

pub fn covers(&self, wanted: &Scope) -> bool

Whether some atom of this set admits wanted, which is what a token carrying this set may do.

Source

pub fn permits_rpc(&self, lxm: Option<&str>, aud: &str) -> bool

Whether a token carrying this set may act at another service: call lxm there through atproto-proxy, or take a token for it from com.atproto.server.getServiceAuth. aud names the service, as a DID or a DID and a service fragment.

None asks for a token bound to no method. An rpc:* scope for aud admits one, and so does transition:generic, as the reference PDS reads it.

Source

pub fn parse(s: &str) -> Result<ScopeSet, ScopeParseError>

Parses a whole scope string: OAuth2’s space-separated list of atoms.

Checks MAX_SCOPE_BYTES before reading any atom, and MAX_SCOPE_ATOMS against the scopes they name. An atom this grammar cannot read is kept as Scope::Unknown; see ScopeSet::read.

Source

pub fn read( s: &str, ) -> Result<(ScopeSet, Vec<(String, ScopeWarning)>), ScopeParseError>

Reads a scope an app asked for: the set, and each warning its atoms’ forms carry, beside the atom as the app wrote it.

Every form the permission spec defines reads without a warning. A form it does not define is read as well as it can be, with a warning saying how. An atom that names no scope this grammar reads is kept as Scope::Unknown, with a warning, rather than failing the string: a server can drop it and grant the rest. Only the bounds and a character no scope may hold fail the whole string.

Source

pub fn parse_grant(s: &str) -> Result<ScopeSet, ScopeParseError>

Parses a grant this server stored, which may be larger than any request: each include: in the request became the atoms its permission set grants.

Checks MAX_GRANT_BYTES and MAX_GRANT_ATOMS before parsing any atom.

Source

pub fn intersect(&self, ceiling: &ScopeSet) -> Result<ScopeSet, ScopeRefused>

Is every requested scope admitted by some scope in ceiling?

Returns the whole intersected grant on success. On refusal, returns the first requested scope that no ceiling scope admits at all — plan/scope-policy.md’s “refuse rather than silently narrow, and say which scope”, which needs this exact atom to build the WWW-Authenticate: Bearer error="insufficient_scope", scope="…" header.

A requested atom’s grant is the union of its overlap with every ceiling atom, not the single largest overlap: ceiling is a set with no inherent order, so a ceiling atom that grants create and one that grants delete must both survive regardless of which one this loop visits first. ScopeSet::new then collapses any overlap that one of its siblings already subsumes.

An overlap counts only in the requested atom’s own kind, as in ScopeSet::narrow: transition:generic under a repo:* ceiling is refused, not paid out as repo:*.

Source

pub fn narrow(&self, ceiling: &ScopeSet) -> (ScopeSet, ScopeSet)

The same overlap, split into what the ceiling granted and what it did not.

ScopeSet::intersect refuses the whole request the moment one atom falls outside the ceiling, which is what token and every other caller checking a grant against a ceiling wants. A consent decision wants the other answer: the grant that is available, plus the part of the request it does not cover, so the record an agent approves can name both.

Projection runs from the requested atom onto the ceiling and never the other way, and only ever within one kind: a granted atom is always a narrowing of something the request named, of that atom’s own kind. So a wide atom is never paid out in capabilities of a kind nobody asked for — transition:generic overlaps repo:* and rpc:*, and a ceiling holding those grants it nothing.

cut is every requested atom that no granted atom contains — the atoms the ceiling dropped outright and the atoms it shrank alike. The grammar has no difference operation, so an atom the ceiling narrowed (repo:*?action=create&action=delete against a ceiling holding repo:*?action=create) is named whole rather than as the sliver removed from it. An empty cut means the ceiling granted the request exactly as asked, which is the only case ScopeSet::intersect and this agree on completely.

Trait Implementations§

Source§

impl Clone for ScopeSet

Source§

fn clone(&self) -> ScopeSet

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
Source§

impl Debug for ScopeSet

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for ScopeSet

Source§

fn default() -> ScopeSet

Returns the “default value” for a type. Read more
Source§

impl Display for ScopeSet

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl PartialEq for ScopeSet

Source§

fn eq(&self, other: &ScopeSet) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for ScopeSet

Source§

impl StructuralPartialEq for ScopeSet

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
§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

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
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

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

§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

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

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T> ToCowStr for T
where T: Display + ?Sized,

§

fn to_cowstr(&self) -> CowStr<'_>

Convert to a CowStr.
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
§

impl<T> ToSmolStr for T
where T: Display + ?Sized,

§

fn to_smolstr(&self) -> SmolStr

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. 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.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,