webgates_core/roles.rs
1//! Built-in hierarchical roles for authorization decisions.
2//!
3//! Use this module when the default `webgates-core` role hierarchy matches your
4//! application. If not, define your own role enum and implement
5//! [`crate::authz::access_hierarchy::AccessHierarchy`].
6//!
7//! The built-in hierarchy is ordered from least privileged to most privileged:
8//!
9//! - [`Role::User`]
10//! - [`Role::Reporter`]
11//! - [`Role::Moderator`]
12//! - [`Role::Admin`]
13//!
14//! This ordering matters because [`crate::authz::access_hierarchy::AccessHierarchy`] uses the type's
15//! total ordering to determine whether one role is the same as, or supervises,
16//! another role.
17//!
18//! # Examples
19//!
20//! ```rust
21//! use webgates_core::authz::access_policy::AccessPolicy;
22//! use webgates_core::groups::Group;
23//! use webgates_core::roles::Role;
24//!
25//! let exact_admin = AccessPolicy::<Role, Group>::require_role(Role::Admin);
26//! let moderator_or_higher =
27//! AccessPolicy::<Role, Group>::require_role_or_supervisor(Role::Moderator);
28//!
29//! assert!(!exact_admin.denies_all());
30//! assert!(!moderator_or_higher.denies_all());
31//! ```
32//!
33//! # Custom role hierarchies
34//!
35//! If your application needs a different hierarchy, define your own enum in
36//! least-privileged to most-privileged order and implement
37//! [`crate::authz::access_hierarchy::AccessHierarchy`] for it.
38//!
39//! ```rust
40//! use serde::{Deserialize, Serialize};
41//! use webgates_core::authz::access_hierarchy::AccessHierarchy;
42//!
43//! #[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
44//! enum CompanyRole {
45//! #[default]
46//! Employee,
47//! TeamLead,
48//! Manager,
49//! Director,
50//! }
51//!
52//! impl std::fmt::Display for CompanyRole {
53//! fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54//! match self {
55//! CompanyRole::Employee => write!(f, "Employee"),
56//! CompanyRole::TeamLead => write!(f, "TeamLead"),
57//! CompanyRole::Manager => write!(f, "Manager"),
58//! CompanyRole::Director => write!(f, "Director"),
59//! }
60//! }
61//! }
62//!
63//! impl AccessHierarchy for CompanyRole {}
64//! ```
65
66use crate::authz::access_hierarchy::AccessHierarchy;
67use serde::{Deserialize, Serialize};
68
69/// Built-in roles ordered from least privileged to most privileged.
70///
71/// These roles give you a ready-to-use hierarchy for common applications.
72/// When used with [`crate::authz::access_policy::AccessPolicy::<Role, crate::groups::Group>::require_role_or_supervisor`],
73/// a higher-privileged role can satisfy lower-role requirements.
74///
75/// # Example
76///
77/// ```rust
78/// use webgates_core::authz::access_policy::AccessPolicy;
79/// use webgates_core::groups::Group;
80/// use webgates_core::roles::Role;
81///
82/// let moderator_or_higher =
83/// AccessPolicy::<Role, Group>::require_role_or_supervisor(Role::Moderator);
84/// let admin_or_moderator = AccessPolicy::<Role, Group>::require_role(Role::Admin)
85/// .or_require_role(Role::Moderator);
86///
87/// assert!(!moderator_or_higher.denies_all());
88/// assert!(!admin_or_moderator.denies_all());
89/// ```
90#[derive(
91 Debug,
92 Default,
93 Clone,
94 Copy,
95 Eq,
96 PartialEq,
97 Ord,
98 PartialOrd,
99 Serialize,
100 Deserialize,
101 strum::Display,
102 strum::EnumString,
103 strum::EnumIter,
104)]
105pub enum Role {
106 /// Baseline role for regular users.
107 ///
108 /// This is the default role assigned by `Account::new(...)` when you use the
109 /// built-in [`Role`] type.
110 #[default]
111 User,
112 /// Role for users who primarily need read-heavy or reporting access.
113 Reporter,
114 /// Elevated role for moderation or operational workflows.
115 Moderator,
116 /// Highest built-in role.
117 ///
118 /// Administrators typically have full access to protected operations.
119 Admin,
120}
121
122impl AccessHierarchy for Role {}