pub enum AuthorizationDecision<AllowedReason = (), ForbiddenReason = ()> {
Allowed {
reason: AllowedReason,
},
Forbidden {
reason: ForbiddenReason,
},
}Expand description
§AuthorizationDecision
Output type for authorizers.
It is an enum designating whether an action is permitted
(Allowed) or denied (Forbidden). Both variants of the enum may carry a
user-defined and accessible “reason” payload for logic branching, API error messages,
metrics and analytics, etc.
Both reason types default to unit, and you can have both typed, just one, or neither. Often forbidden reasons are used heavily, but allowed reasons are not unless there’s particular compliance or audit/logging required for sensitive resources.
They are simple enums with no references to the inputs of the authorizer or anything like this, so feel free to store and pass them around if needed, pass them down from middleware to core logic, create them for unit tests, etc.
§Constructors
| Method | Description |
|---|---|
allowed() / forbidden() | Create a decision without a reason. |
allowed_with(reason) / forbidden_with(reason) | Create a decision with an attached reason. |
§Utilities
Predicates: is_allowed(), is_forbidden()
Result conversion:
into_result() → Result<AllowedReason, ForbiddenReason>
ok_or(err) / ok_or_else(f) → convert to Result<(), E>
Assertions / unwraps: expect_allowed(msg), expect_forbidden(msg),
unwrap_allowed(), unwrap_forbidden()
Inspection: inspect_allowed(|r| …), inspect_forbidden(|r| …)
(executes the closure for side effects, returns self unchanged)
§Examples
§1 – Minimal check without reasons
use traitgate::AuthorizationDecision;
let dec: AuthorizationDecision<(), ()> = AuthorizationDecision::allowed();
assert!(dec.is_allowed());§2 – Custom deny reason
use traitgate::AuthorizationDecision;
#[derive(Debug, PartialEq)]
enum PostDeny { NotAuthor, RateLimited }
let denied = AuthorizationDecision::<(), PostDeny>::forbidden_with(PostDeny::RateLimited);
assert_eq!(denied.into_result(), Err(PostDeny::RateLimited));§3 – Logging an allow reason
use traitgate::AuthorizationDecision;
let decision = AuthorizationDecision::<&str, ()>::allowed_with("scope=admin");
decision
.inspect_allowed(|r| println!("granted via {}", r))
.expect_allowed("expected to be allowed");Variants§
Allowed
The authorization is allowed, with an optional reason.
Fields
reason: AllowedReasonForbidden
The authorization is forbidden, with an optional reason.
Fields
reason: ForbiddenReasonImplementations§
Source§impl<F> AuthorizationDecision<(), F>
impl<F> AuthorizationDecision<(), F>
Source§impl<A> AuthorizationDecision<A, ()>
impl<A> AuthorizationDecision<A, ()>
Source§impl<A, F> AuthorizationDecision<A, F>
impl<A, F> AuthorizationDecision<A, F>
Sourcepub fn allowed_with(reason: A) -> Self
pub fn allowed_with(reason: A) -> Self
Create Allowed { reason } with your custom allow-reason.
use traitgate::prelude::*;
struct NewPostAllowed { is_author: bool }
AuthorizationDecision::<NewPostAllowed, ()>::allowed_with(NewPostAllowed { is_author: true });Sourcepub fn forbidden_with(reason: F) -> Self
pub fn forbidden_with(reason: F) -> Self
Create Forbidden { reason } with your custom deny-reason.
use traitgate::prelude::*;
enum OrderModifyForbiddenReason {
OrderIsHaunted,
NotOwner
}
let dec = AuthorizationDecision::<(), OrderModifyForbiddenReason>::forbidden_with(OrderModifyForbiddenReason::NotOwner);Sourcepub fn is_allowed(&self) -> bool
pub fn is_allowed(&self) -> bool
Return true if the decision is Allowed
Sourcepub fn is_forbidden(&self) -> bool
pub fn is_forbidden(&self) -> bool
Return true if the decision is Forbidden
Sourcepub fn ok_or<E>(self, err: E) -> Result<(), E>
pub fn ok_or<E>(self, err: E) -> Result<(), E>
Convert into Result<(), E>, using err when forbidden.
use traitgate::prelude::*;
let dec = AuthorizationDecision::<(),()>::allowed();
let res: Result<(), &str> = dec.ok_or("access denied");Sourcepub fn ok_or_else<E, G>(self, err_fn: G) -> Result<(), E>where
G: FnOnce(F) -> E,
pub fn ok_or_else<E, G>(self, err_fn: G) -> Result<(), E>where
G: FnOnce(F) -> E,
Like ok_or, but builds the error from the forbidden reason.
Sourcepub fn into_result(self) -> Result<A, F>
pub fn into_result(self) -> Result<A, F>
Convert into Result<AllowedReason, ForbiddenReason>.
Sourcepub fn expect_allowed(self, msg: &str) -> A
pub fn expect_allowed(self, msg: &str) -> A
Panic with msg if forbidden; otherwise return the allowed reason.
// panics if decision is forbidden
use traitgate::prelude::*;
let dec = AuthorizationDecision::<(),()>::allowed();
let reason = dec.expect_allowed("must be allowed");Sourcepub fn expect_forbidden(self, msg: &str) -> F
pub fn expect_forbidden(self, msg: &str) -> F
Panic with msg if allowed; otherwise return the forbidden reason.
// panics if decision is forbidden
use traitgate::prelude::*;
let dec = AuthorizationDecision::<(),()>::forbidden();
let reason = dec.expect_forbidden("must be forbidden");Sourcepub fn unwrap_forbidden(self) -> F
pub fn unwrap_forbidden(self) -> F
Panic if allowed; otherwise return the forbidden reason.
// panics if decision is allowed
use traitgate::prelude::*;
let dec = AuthorizationDecision::<(),()>::forbidden();
let reason = dec.unwrap_forbidden();Sourcepub fn unwrap_allowed(self) -> A
pub fn unwrap_allowed(self) -> A
Panic if forbidden; otherwise return the allowed reason.
// panics if decision is forbidden
use traitgate::prelude::*;
let dec = AuthorizationDecision::<(),()>::allowed();
let reason = dec.unwrap_allowed();Sourcepub fn inspect_forbidden<G: FnOnce(&F)>(self, inspect_fn: G) -> Self
pub fn inspect_forbidden<G: FnOnce(&F)>(self, inspect_fn: G) -> Self
If this decision is Forbidden, runs inspect_fn(&reason)as a side‐effect,
then returns the original decision unchanged.
§Example
let dec = AuthorizationDecision::<(), &str>::forbidden_with("not owner");
dec.inspect_forbidden(|reason| println!("Denied because {}", reason));Sourcepub fn inspect_allowed<G: FnOnce(&A)>(self, inspect_fn: G) -> Self
pub fn inspect_allowed<G: FnOnce(&A)>(self, inspect_fn: G) -> Self
If this decision is Forbidden, runs inspect_fn(&reason) for a side‐effect,
then returns the original decision unchanged.
§Example
let dec = AuthorizationDecision::<&str,()>::allowed_with("admin");
dec.inspect_allowed(|reason| println!("Granted because {}", reason));Trait Implementations§
Source§impl<AllowedReason: Clone, ForbiddenReason: Clone> Clone for AuthorizationDecision<AllowedReason, ForbiddenReason>
impl<AllowedReason: Clone, ForbiddenReason: Clone> Clone for AuthorizationDecision<AllowedReason, ForbiddenReason>
Source§fn clone(&self) -> AuthorizationDecision<AllowedReason, ForbiddenReason>
fn clone(&self) -> AuthorizationDecision<AllowedReason, ForbiddenReason>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<AllowedReason: Debug, ForbiddenReason: Debug> Debug for AuthorizationDecision<AllowedReason, ForbiddenReason>
impl<AllowedReason: Debug, ForbiddenReason: Debug> Debug for AuthorizationDecision<AllowedReason, ForbiddenReason>
Source§impl<A, F> Display for AuthorizationDecision<A, F>
impl<A, F> Display for AuthorizationDecision<A, F>
Source§impl<AllowedReason: Hash, ForbiddenReason: Hash> Hash for AuthorizationDecision<AllowedReason, ForbiddenReason>
impl<AllowedReason: Hash, ForbiddenReason: Hash> Hash for AuthorizationDecision<AllowedReason, ForbiddenReason>
Source§impl<AllowedReason: Ord, ForbiddenReason: Ord> Ord for AuthorizationDecision<AllowedReason, ForbiddenReason>
impl<AllowedReason: Ord, ForbiddenReason: Ord> Ord for AuthorizationDecision<AllowedReason, ForbiddenReason>
Source§fn cmp(
&self,
other: &AuthorizationDecision<AllowedReason, ForbiddenReason>,
) -> Ordering
fn cmp( &self, other: &AuthorizationDecision<AllowedReason, ForbiddenReason>, ) -> Ordering
1.21.0 · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl<AllowedReason: PartialEq, ForbiddenReason: PartialEq> PartialEq for AuthorizationDecision<AllowedReason, ForbiddenReason>
impl<AllowedReason: PartialEq, ForbiddenReason: PartialEq> PartialEq for AuthorizationDecision<AllowedReason, ForbiddenReason>
Source§fn eq(
&self,
other: &AuthorizationDecision<AllowedReason, ForbiddenReason>,
) -> bool
fn eq( &self, other: &AuthorizationDecision<AllowedReason, ForbiddenReason>, ) -> bool
self and other values to be equal, and is used by ==.