Skip to main content

systemprompt_traits/
auth.rs

1use 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>;