Skip to main content

systemprompt_users/services/user/
provider.rs

1use std::str::FromStr;
2
3use async_trait::async_trait;
4use systemprompt_identifiers::UserId;
5use systemprompt_traits::auth::{
6    AuthProviderError, AuthResult, AuthUser, FederatedIdentityClaims, RoleProvider, UserProvider,
7};
8
9use super::UserService;
10use crate::models::{User, UserRole};
11
12impl From<User> for AuthUser {
13    fn from(user: User) -> Self {
14        let is_active = user.is_active();
15        Self {
16            id: user.id,
17            name: user.name,
18            email: user.email,
19            roles: user.roles,
20            is_active,
21        }
22    }
23}
24
25#[async_trait]
26impl UserProvider for UserService {
27    async fn find_by_id(&self, id: &UserId) -> AuthResult<Option<AuthUser>> {
28        self.find_by_id(id)
29            .await
30            .map(|opt| opt.map(AuthUser::from))
31            .map_err(|e| AuthProviderError::Internal(e.to_string()))
32    }
33
34    async fn find_by_email(&self, email: &str) -> AuthResult<Option<AuthUser>> {
35        Self::find_by_email(self, email)
36            .await
37            .map(|opt| opt.map(AuthUser::from))
38            .map_err(|e| AuthProviderError::Internal(e.to_string()))
39    }
40
41    async fn find_by_name(&self, name: &str) -> AuthResult<Option<AuthUser>> {
42        Self::find_by_name(self, name)
43            .await
44            .map(|opt| opt.map(AuthUser::from))
45            .map_err(|e| AuthProviderError::Internal(e.to_string()))
46    }
47
48    async fn create_user(
49        &self,
50        name: &str,
51        email: &str,
52        full_name: Option<&str>,
53    ) -> AuthResult<AuthUser> {
54        Self::create(self, name, email, full_name, full_name)
55            .await
56            .map(AuthUser::from)
57            .map_err(|e| AuthProviderError::Internal(e.to_string()))
58    }
59
60    async fn create_anonymous(&self, fingerprint: &str) -> AuthResult<AuthUser> {
61        Self::create_anonymous(self, fingerprint)
62            .await
63            .map(AuthUser::from)
64            .map_err(|e| AuthProviderError::Internal(e.to_string()))
65    }
66
67    async fn assign_roles(&self, user_id: &UserId, roles: &[String]) -> AuthResult<()> {
68        Self::assign_roles(self, user_id, roles)
69            .await
70            .map(|_| ())
71            .map_err(|e| AuthProviderError::Internal(e.to_string()))
72    }
73
74    async fn find_or_create_federated(
75        &self,
76        issuer: &str,
77        external_sub: &str,
78        claims: &FederatedIdentityClaims,
79    ) -> AuthResult<UserId> {
80        Self::find_or_create_federated(self, issuer, external_sub, claims)
81            .await
82            .map(|u| u.id)
83            .map_err(|e| AuthProviderError::Internal(e.to_string()))
84    }
85}
86
87#[async_trait]
88impl RoleProvider for UserService {
89    async fn get_roles(&self, user_id: &UserId) -> AuthResult<Vec<String>> {
90        match Self::find_by_id(self, user_id).await {
91            Ok(Some(user)) => Ok(user.roles),
92            Ok(None) => Err(AuthProviderError::UserNotFound),
93            Err(e) => Err(AuthProviderError::Internal(e.to_string())),
94        }
95    }
96
97    async fn assign_role(&self, user_id: &UserId, role: &str) -> AuthResult<()> {
98        let user = match Self::find_by_id(self, user_id).await {
99            Ok(Some(u)) => u,
100            Ok(None) => return Err(AuthProviderError::UserNotFound),
101            Err(e) => return Err(AuthProviderError::Internal(e.to_string())),
102        };
103
104        let mut roles = user.roles;
105        let role_str = role.to_owned();
106        if !roles.contains(&role_str) {
107            roles.push(role_str);
108        }
109
110        Self::assign_roles(self, user_id, &roles)
111            .await
112            .map(|_| ())
113            .map_err(|e| AuthProviderError::Internal(e.to_string()))
114    }
115
116    async fn revoke_role(&self, user_id: &UserId, role: &str) -> AuthResult<()> {
117        let user = match Self::find_by_id(self, user_id).await {
118            Ok(Some(u)) => u,
119            Ok(None) => return Err(AuthProviderError::UserNotFound),
120            Err(e) => return Err(AuthProviderError::Internal(e.to_string())),
121        };
122
123        let roles: Vec<String> = user.roles.into_iter().filter(|r| r != role).collect();
124
125        Self::assign_roles(self, user_id, &roles)
126            .await
127            .map(|_| ())
128            .map_err(|e| AuthProviderError::Internal(e.to_string()))
129    }
130
131    async fn list_users_by_role(&self, role: &str) -> AuthResult<Vec<AuthUser>> {
132        let Ok(user_role) = UserRole::from_str(role) else {
133            return Ok(vec![]);
134        };
135
136        Self::find_by_role(self, user_role)
137            .await
138            .map(|users| users.into_iter().map(AuthUser::from).collect())
139            .map_err(|e| AuthProviderError::Internal(e.to_string()))
140    }
141}