Skip to main content

systemprompt_models/auth/
enums.rs

1use serde::{Deserialize, Serialize};
2use std::fmt;
3use std::str::FromStr;
4
5use super::permission::Permission;
6use crate::errors::ParseEnumError;
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, schemars::JsonSchema)]
9#[serde(rename_all = "lowercase")]
10pub enum JwtAudience {
11    Web,
12    Api,
13    A2a,
14    Mcp,
15    Internal,
16    Bridge,
17    Hook,
18    #[serde(untagged)]
19    Resource(String),
20}
21
22impl JwtAudience {
23    pub fn as_str(&self) -> &str {
24        match self {
25            Self::Web => "web",
26            Self::Api => "api",
27            Self::A2a => "a2a",
28            Self::Mcp => "mcp",
29            Self::Internal => "internal",
30            Self::Bridge => "bridge",
31            Self::Hook => "hook",
32            Self::Resource(s) => s.as_str(),
33        }
34    }
35
36    pub fn standard() -> Vec<Self> {
37        vec![Self::Web, Self::Api, Self::A2a, Self::Mcp]
38    }
39
40    pub fn service() -> Vec<Self> {
41        vec![Self::Api, Self::Mcp, Self::A2a, Self::Internal]
42    }
43}
44
45impl fmt::Display for JwtAudience {
46    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47        write!(f, "{}", self.as_str())
48    }
49}
50
51impl FromStr for JwtAudience {
52    type Err = ParseEnumError;
53    fn from_str(s: &str) -> Result<Self, Self::Err> {
54        match s {
55            "web" => Ok(Self::Web),
56            "api" => Ok(Self::Api),
57            "a2a" => Ok(Self::A2a),
58            "mcp" => Ok(Self::Mcp),
59            "internal" => Ok(Self::Internal),
60            "bridge" => Ok(Self::Bridge),
61            "hook" => Ok(Self::Hook),
62            _ => Ok(Self::Resource(s.to_owned())),
63        }
64    }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
68#[serde(rename_all = "lowercase")]
69pub enum UserType {
70    Admin,
71    User,
72    A2a,
73    Mcp,
74    Service,
75    Anon,
76    Unknown,
77}
78
79impl UserType {
80    /// Derives the caller type from a permission set, the single source of
81    /// truth for the permission → type mapping. The precedence is
82    /// privilege-descending (`Admin` wins over `User`, etc.); the hook scopes
83    /// resolve to `Service` so a hook principal is never silently downgraded
84    /// to `Anon`.
85    pub fn from_permissions(permissions: &[Permission]) -> Self {
86        let has = |p: Permission| permissions.contains(&p);
87        if has(Permission::Admin) {
88            Self::Admin
89        } else if has(Permission::User) {
90            Self::User
91        } else if has(Permission::A2a) {
92            Self::A2a
93        } else if has(Permission::Mcp) {
94            Self::Mcp
95        } else if has(Permission::Service)
96            || has(Permission::HookGovern)
97            || has(Permission::HookTrack)
98        {
99            Self::Service
100        } else {
101            Self::Anon
102        }
103    }
104
105    pub const fn as_str(&self) -> &'static str {
106        match self {
107            Self::Admin => "admin",
108            Self::User => "user",
109            Self::A2a => "a2a",
110            Self::Mcp => "mcp",
111            Self::Service => "service",
112            Self::Anon => "anon",
113            Self::Unknown => "unknown",
114        }
115    }
116
117    pub const fn rate_tier(&self) -> RateLimitTier {
118        match self {
119            Self::Admin => RateLimitTier::Admin,
120            Self::User => RateLimitTier::User,
121            Self::A2a => RateLimitTier::A2a,
122            Self::Mcp => RateLimitTier::Mcp,
123            Self::Service => RateLimitTier::Service,
124            Self::Anon | Self::Unknown => RateLimitTier::Anon,
125        }
126    }
127}
128
129impl fmt::Display for UserType {
130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131        write!(f, "{}", self.as_str())
132    }
133}
134
135impl FromStr for UserType {
136    type Err = ParseEnumError;
137    fn from_str(s: &str) -> Result<Self, Self::Err> {
138        match s {
139            "admin" => Ok(Self::Admin),
140            "user" => Ok(Self::User),
141            "a2a" => Ok(Self::A2a),
142            "mcp" => Ok(Self::Mcp),
143            "service" => Ok(Self::Service),
144            "anon" => Ok(Self::Anon),
145            "unknown" => Ok(Self::Unknown),
146            _ => Err(ParseEnumError::new("user_type", s)),
147        }
148    }
149}
150
151#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
152pub enum TokenType {
153    #[default]
154    Bearer,
155}
156
157impl TokenType {
158    pub const fn as_str(self) -> &'static str {
159        match self {
160            Self::Bearer => "Bearer",
161        }
162    }
163}
164
165impl fmt::Display for TokenType {
166    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167        write!(f, "Bearer")
168    }
169}
170
171#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
172#[serde(rename_all = "lowercase")]
173pub enum RateLimitTier {
174    Admin,
175    User,
176    A2a,
177    Mcp,
178    Service,
179    Anon,
180}
181
182impl RateLimitTier {
183    pub const fn as_str(&self) -> &'static str {
184        match self {
185            Self::Admin => "admin",
186            Self::User => "user",
187            Self::A2a => "a2a",
188            Self::Mcp => "mcp",
189            Self::Service => "service",
190            Self::Anon => "anon",
191        }
192    }
193}
194
195impl fmt::Display for RateLimitTier {
196    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197        write!(f, "{}", self.as_str())
198    }
199}
200
201impl FromStr for RateLimitTier {
202    type Err = ParseEnumError;
203    fn from_str(s: &str) -> Result<Self, Self::Err> {
204        match s {
205            "admin" => Ok(Self::Admin),
206            "user" => Ok(Self::User),
207            "a2a" => Ok(Self::A2a),
208            "mcp" => Ok(Self::Mcp),
209            "service" => Ok(Self::Service),
210            "anon" => Ok(Self::Anon),
211            _ => Err(ParseEnumError::new("rate_limit_tier", s)),
212        }
213    }
214}
215
216#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
217#[serde(rename_all = "lowercase")]
218pub enum UserRole {
219    Admin,
220    User,
221    Anonymous,
222}
223
224impl UserRole {
225    pub const fn as_str(&self) -> &'static str {
226        match self {
227            Self::Admin => "admin",
228            Self::User => "user",
229            Self::Anonymous => "anonymous",
230        }
231    }
232}
233
234impl fmt::Display for UserRole {
235    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
236        write!(f, "{}", self.as_str())
237    }
238}
239
240impl FromStr for UserRole {
241    type Err = ParseEnumError;
242    fn from_str(s: &str) -> Result<Self, Self::Err> {
243        match s {
244            "admin" => Ok(Self::Admin),
245            "user" => Ok(Self::User),
246            "anonymous" => Ok(Self::Anonymous),
247            _ => Err(ParseEnumError::new("user_role", s)),
248        }
249    }
250}
251
252#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
253#[serde(rename_all = "lowercase")]
254pub enum UserStatus {
255    Active,
256    Inactive,
257    Suspended,
258    Pending,
259    Deleted,
260    Temporary,
261}
262
263impl UserStatus {
264    pub const fn as_str(&self) -> &'static str {
265        match self {
266            Self::Active => "active",
267            Self::Inactive => "inactive",
268            Self::Suspended => "suspended",
269            Self::Pending => "pending",
270            Self::Deleted => "deleted",
271            Self::Temporary => "temporary",
272        }
273    }
274
275    pub const fn is_active(&self) -> bool {
276        matches!(self, Self::Active)
277    }
278}
279
280impl fmt::Display for UserStatus {
281    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
282        write!(f, "{}", self.as_str())
283    }
284}
285
286impl FromStr for UserStatus {
287    type Err = ParseEnumError;
288    fn from_str(s: &str) -> Result<Self, Self::Err> {
289        match s {
290            "active" => Ok(Self::Active),
291            "inactive" => Ok(Self::Inactive),
292            "suspended" => Ok(Self::Suspended),
293            "pending" => Ok(Self::Pending),
294            "deleted" => Ok(Self::Deleted),
295            "temporary" => Ok(Self::Temporary),
296            _ => Err(ParseEnumError::new("user_status", s)),
297        }
298    }
299}