systemprompt_models/auth/
claims.rs1use serde::{Deserialize, Serialize};
2use std::str::FromStr;
3
4use super::{
5 parse_permissions, permissions_to_string, JwtAudience, Permission, RateLimitTier, TokenType,
6 UserType,
7};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct JwtClaims {
11 pub sub: String,
12 pub iat: i64,
13 pub exp: i64,
14 pub iss: String,
15 #[serde(
16 serialize_with = "serialize_audiences",
17 deserialize_with = "deserialize_audiences"
18 )]
19 pub aud: Vec<JwtAudience>,
20 pub jti: String,
21
22 #[serde(
23 serialize_with = "serialize_scope",
24 deserialize_with = "deserialize_scope"
25 )]
26 pub scope: Vec<Permission>,
27
28 pub username: String,
29 pub email: String,
30 pub user_type: UserType,
31
32 #[serde(default, skip_serializing_if = "Vec::is_empty")]
33 pub roles: Vec<String>,
34
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub client_id: Option<String>,
37 pub token_type: TokenType,
38 pub auth_time: i64,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 pub session_id: Option<String>,
41
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub rate_limit_tier: Option<RateLimitTier>,
44}
45
46fn serialize_audiences<S>(auds: &[JwtAudience], s: S) -> Result<S::Ok, S::Error>
47where
48 S: serde::Serializer,
49{
50 use serde::ser::SerializeSeq;
51 let mut seq = s.serialize_seq(Some(auds.len()))?;
52 for aud in auds {
53 seq.serialize_element(aud.as_str())?;
54 }
55 seq.end()
56}
57
58fn deserialize_audiences<'de, D>(d: D) -> Result<Vec<JwtAudience>, D::Error>
59where
60 D: serde::Deserializer<'de>,
61{
62 let strings: Vec<String> = Vec::deserialize(d)?;
63 strings
64 .iter()
65 .map(|s| JwtAudience::from_str(s).map_err(serde::de::Error::custom))
66 .collect()
67}
68
69fn serialize_scope<S>(permissions: &[Permission], s: S) -> Result<S::Ok, S::Error>
70where
71 S: serde::Serializer,
72{
73 s.serialize_str(&permissions_to_string(permissions))
74}
75
76fn deserialize_scope<'de, D>(d: D) -> Result<Vec<Permission>, D::Error>
77where
78 D: serde::Deserializer<'de>,
79{
80 let scope_string: String = String::deserialize(d)?;
81 parse_permissions(&scope_string).map_err(serde::de::Error::custom)
82}
83
84impl JwtClaims {
85 pub fn has_permission(&self, permission: Permission) -> bool {
86 self.scope.contains(&permission)
87 }
88
89 pub fn permissions(&self) -> &[Permission] {
90 &self.scope
91 }
92
93 pub fn get_permissions(&self) -> Vec<Permission> {
94 self.scope.clone()
95 }
96
97 pub fn get_scopes(&self) -> Vec<String> {
98 self.scope.iter().map(ToString::to_string).collect()
99 }
100
101 pub fn is_admin(&self) -> bool {
102 self.has_permission(Permission::Admin)
103 }
104
105 pub fn is_registered_user(&self) -> bool {
106 self.has_permission(Permission::User)
107 }
108
109 pub fn is_anonymous(&self) -> bool {
110 self.has_permission(Permission::Anonymous)
111 }
112
113 pub fn has_audience(&self, aud: JwtAudience) -> bool {
114 self.aud.contains(&aud)
115 }
116
117 pub fn has_role(&self, role: &str) -> bool {
118 self.roles.iter().any(|r| r == role)
119 }
120
121 pub fn roles(&self) -> &[String] {
122 &self.roles
123 }
124}