systemprompt_traits/
auth.rs1use async_trait::async_trait;
2use std::sync::Arc;
3
4pub type AuthResult<T> = Result<T, AuthProviderError>;
5
6#[derive(Debug, thiserror::Error)]
7#[non_exhaustive]
8pub enum AuthProviderError {
9 #[error("Invalid credentials")]
10 InvalidCredentials,
11
12 #[error("User not found")]
13 UserNotFound,
14
15 #[error("Invalid token")]
16 InvalidToken,
17
18 #[error("Token expired")]
19 TokenExpired,
20
21 #[error("Insufficient permissions")]
22 InsufficientPermissions,
23
24 #[error("Internal error: {0}")]
25 Internal(String),
26}
27
28impl From<anyhow::Error> for AuthProviderError {
29 fn from(err: anyhow::Error) -> Self {
30 Self::Internal(err.to_string())
31 }
32}
33
34#[derive(Debug, Clone)]
35pub struct TokenPair {
36 pub access_token: String,
37 pub refresh_token: Option<String>,
38 pub expires_in: i64,
39 pub token_type: String,
40}
41
42impl TokenPair {
43 #[must_use]
44 pub fn new(access_token: String, refresh_token: Option<String>, expires_in: i64) -> Self {
45 Self {
46 access_token,
47 refresh_token,
48 expires_in,
49 token_type: "Bearer".to_string(),
50 }
51 }
52}
53
54#[derive(Debug, Clone)]
55pub struct TokenClaims {
56 pub subject: String,
57 pub username: String,
58 pub email: Option<String>,
59 pub audiences: Vec<String>,
60 pub permissions: Vec<String>,
61 pub expires_at: i64,
62 pub issued_at: i64,
63}
64
65#[async_trait]
66pub trait AuthProvider: Send + Sync {
67 async fn validate_token(&self, token: &str) -> AuthResult<TokenClaims>;
68 async fn refresh_token(&self, refresh_token: &str) -> AuthResult<TokenPair>;
69 async fn revoke_token(&self, token: &str) -> AuthResult<()>;
70}
71
72#[derive(Debug, Clone, PartialEq, Eq)]
73#[non_exhaustive]
74pub enum AuthAction {
75 Read,
76 Write,
77 Delete,
78 Admin,
79 Custom(String),
80}
81
82impl AuthAction {
83 #[must_use]
84 pub fn as_str(&self) -> &str {
85 match self {
86 Self::Read => "read",
87 Self::Write => "write",
88 Self::Delete => "delete",
89 Self::Admin => "admin",
90 Self::Custom(s) => s.as_str(),
91 }
92 }
93}
94
95#[derive(Debug, Clone, PartialEq, Eq)]
96pub struct AuthPermission {
97 pub resource: String,
98 pub action: AuthAction,
99}
100
101impl AuthPermission {
102 #[must_use]
103 pub fn new(resource: impl Into<String>, action: AuthAction) -> Self {
104 Self {
105 resource: resource.into(),
106 action,
107 }
108 }
109}
110
111#[async_trait]
112pub trait AuthorizationProvider: Send + Sync {
113 async fn authorize(
114 &self,
115 user_id: &str,
116 resource: &str,
117 action: &AuthAction,
118 ) -> AuthResult<bool>;
119 async fn get_permissions(&self, user_id: &str) -> AuthResult<Vec<AuthPermission>>;
120 async fn has_audience(&self, token: &str, audience: &str) -> AuthResult<bool>;
121}
122
123#[derive(Debug, Clone)]
124pub struct AuthUser {
125 pub id: String,
126 pub name: String,
127 pub email: String,
128 pub roles: Vec<String>,
129 pub is_active: bool,
130}
131
132#[async_trait]
133pub trait UserProvider: Send + Sync {
134 async fn find_by_id(&self, id: &str) -> AuthResult<Option<AuthUser>>;
135 async fn find_by_email(&self, email: &str) -> AuthResult<Option<AuthUser>>;
136 async fn find_by_name(&self, name: &str) -> AuthResult<Option<AuthUser>>;
137 async fn create_user(
138 &self,
139 name: &str,
140 email: &str,
141 full_name: Option<&str>,
142 ) -> AuthResult<AuthUser>;
143 async fn create_anonymous(&self, fingerprint: &str) -> AuthResult<AuthUser>;
144 async fn assign_roles(&self, user_id: &str, roles: &[String]) -> AuthResult<()>;
145}
146
147#[async_trait]
148pub trait RoleProvider: Send + Sync {
149 async fn get_roles(&self, user_id: &str) -> AuthResult<Vec<String>>;
150 async fn assign_role(&self, user_id: &str, role: &str) -> AuthResult<()>;
151 async fn revoke_role(&self, user_id: &str, role: &str) -> AuthResult<()>;
152 async fn list_users_by_role(&self, role: &str) -> AuthResult<Vec<AuthUser>>;
153}
154
155pub type DynAuthProvider = Arc<dyn AuthProvider>;
156pub type DynAuthorizationProvider = Arc<dyn AuthorizationProvider>;
157pub type DynUserProvider = Arc<dyn UserProvider>;
158pub type DynRoleProvider = Arc<dyn RoleProvider>;