systemprompt_traits/
auth.rs1use async_trait::async_trait;
7use std::sync::Arc;
8use systemprompt_identifiers::UserId;
9
10pub type AuthResult<T> = Result<T, AuthProviderError>;
11
12#[derive(Debug, thiserror::Error)]
13#[non_exhaustive]
14pub enum AuthProviderError {
15 #[error("Invalid credentials")]
16 InvalidCredentials,
17
18 #[error("User not found")]
19 UserNotFound,
20
21 #[error("Invalid token")]
22 InvalidToken,
23
24 #[error("Token expired")]
25 TokenExpired,
26
27 #[error("Insufficient permissions")]
28 InsufficientPermissions,
29
30 #[error("Internal error: {0}")]
31 Internal(String),
32}
33
34#[derive(Debug, Clone)]
35pub struct AuthUser {
36 pub id: UserId,
37 pub name: String,
38 pub email: String,
39 pub roles: Vec<String>,
40 pub is_active: bool,
41}
42
43#[derive(Debug, Clone, Default)]
50pub struct FederatedIdentityClaims {
51 pub email: Option<String>,
52 pub email_verified: bool,
57 pub name: Option<String>,
58 pub preferred_username: Option<String>,
59 pub roles: Vec<String>,
60}
61
62#[async_trait]
63pub trait UserProvider: Send + Sync {
64 async fn find_by_id(&self, id: &UserId) -> AuthResult<Option<AuthUser>>;
65 async fn find_by_email(&self, email: &str) -> AuthResult<Option<AuthUser>>;
66 async fn find_by_name(&self, name: &str) -> AuthResult<Option<AuthUser>>;
67 async fn create_user(
68 &self,
69 name: &str,
70 email: &str,
71 full_name: Option<&str>,
72 ) -> AuthResult<AuthUser>;
73 async fn create_anonymous(&self, fingerprint: &str) -> AuthResult<AuthUser>;
74 async fn assign_roles(&self, user_id: &UserId, roles: &[String]) -> AuthResult<()>;
75
76 async fn find_or_create_federated(
82 &self,
83 issuer: &str,
84 external_sub: &str,
85 claims: &FederatedIdentityClaims,
86 ) -> AuthResult<UserId>;
87}
88
89#[async_trait]
90pub trait RoleProvider: Send + Sync {
91 async fn get_roles(&self, user_id: &UserId) -> AuthResult<Vec<String>>;
92 async fn assign_role(&self, user_id: &UserId, role: &str) -> AuthResult<()>;
93 async fn revoke_role(&self, user_id: &UserId, role: &str) -> AuthResult<()>;
94 async fn list_users_by_role(&self, role: &str) -> AuthResult<Vec<AuthUser>>;
95}
96
97pub type DynUserProvider = Arc<dyn UserProvider>;
98pub type DynRoleProvider = Arc<dyn RoleProvider>;