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