systemprompt_users/services/user/
mod.rs1mod provider;
2
3use std::collections::HashMap;
4use systemprompt_database::DbPool;
5use systemprompt_identifiers::{SessionId, UserId};
6
7use crate::error::Result;
8use crate::models::{
9 User, UserActivity, UserCountBreakdown, UserRole, UserSession, UserStats, UserStatus,
10 UserWithSessions,
11};
12use crate::repository::{MergeResult, UpdateUserParams, UserRepository};
13
14#[derive(Debug, Clone)]
15pub struct UserService {
16 repository: UserRepository,
17}
18
19impl UserService {
20 pub fn new(db: &DbPool) -> anyhow::Result<Self> {
21 Ok(Self {
22 repository: UserRepository::new(db)?,
23 })
24 }
25
26 pub async fn find_by_id(&self, id: &UserId) -> Result<Option<User>> {
27 self.repository.find_by_id(id).await
28 }
29
30 pub async fn find_by_email(&self, email: &str) -> Result<Option<User>> {
31 self.repository.find_by_email(email).await
32 }
33
34 pub async fn find_by_name(&self, name: &str) -> Result<Option<User>> {
35 self.repository.find_by_name(name).await
36 }
37
38 pub async fn find_by_role(&self, role: UserRole) -> Result<Vec<User>> {
39 self.repository.find_by_role(role).await
40 }
41
42 pub async fn find_first_user(&self) -> Result<Option<User>> {
43 self.repository.find_first_user().await
44 }
45
46 pub async fn find_first_admin(&self) -> Result<Option<User>> {
47 self.repository.find_first_admin().await
48 }
49
50 pub async fn find_authenticated_user(&self, user_id: &UserId) -> Result<Option<User>> {
51 self.repository.find_authenticated_user(user_id).await
52 }
53
54 pub async fn find_with_sessions(&self, user_id: &UserId) -> Result<Option<UserWithSessions>> {
55 self.repository.find_with_sessions(user_id).await
56 }
57
58 pub async fn get_activity(&self, user_id: &UserId) -> Result<UserActivity> {
59 self.repository.get_activity(user_id).await
60 }
61
62 pub async fn list(&self, limit: i64, offset: i64) -> Result<Vec<User>> {
63 self.repository.list(limit, offset).await
64 }
65
66 pub async fn list_all(&self) -> Result<Vec<User>> {
67 self.repository.list_all().await
68 }
69
70 pub async fn search(&self, query: &str, limit: i64) -> Result<Vec<User>> {
71 self.repository.search(query, limit).await
72 }
73
74 pub async fn count(&self) -> Result<i64> {
75 self.repository.count().await
76 }
77
78 pub async fn is_temporary_anonymous(&self, id: &UserId) -> Result<bool> {
79 self.repository.is_temporary_anonymous(id).await
80 }
81
82 pub async fn list_non_anonymous_with_sessions(
83 &self,
84 limit: i64,
85 ) -> Result<Vec<UserWithSessions>> {
86 self.repository
87 .list_non_anonymous_with_sessions(limit)
88 .await
89 }
90
91 pub async fn list_sessions(&self, user_id: &UserId) -> Result<Vec<UserSession>> {
92 self.repository.list_sessions(user_id).await
93 }
94
95 pub async fn list_active_sessions(&self, user_id: &UserId) -> Result<Vec<UserSession>> {
96 self.repository.list_active_sessions(user_id).await
97 }
98
99 pub async fn list_recent_sessions(
100 &self,
101 user_id: &UserId,
102 limit: i64,
103 ) -> Result<Vec<UserSession>> {
104 self.repository.list_recent_sessions(user_id, limit).await
105 }
106
107 pub async fn end_session(&self, session_id: &SessionId) -> Result<bool> {
108 self.repository.end_session(session_id).await
109 }
110
111 pub async fn end_all_sessions(&self, user_id: &UserId) -> Result<u64> {
112 self.repository.end_all_sessions(user_id).await
113 }
114
115 pub async fn create(
116 &self,
117 name: &str,
118 email: &str,
119 full_name: Option<&str>,
120 display_name: Option<&str>,
121 ) -> Result<User> {
122 self.repository
123 .create(name, email, full_name, display_name)
124 .await
125 }
126
127 pub async fn create_anonymous(&self, fingerprint: &str) -> Result<User> {
128 self.repository.create_anonymous(fingerprint).await
129 }
130
131 pub async fn update_email(&self, id: &UserId, email: &str) -> Result<User> {
132 self.repository.update_email(id, email).await
133 }
134
135 pub async fn update_full_name(&self, id: &UserId, full_name: &str) -> Result<User> {
136 self.repository.update_full_name(id, full_name).await
137 }
138
139 pub async fn update_status(&self, id: &UserId, status: UserStatus) -> Result<User> {
140 self.repository.update_status(id, status).await
141 }
142
143 pub async fn update_email_verified(&self, id: &UserId, verified: bool) -> Result<User> {
144 self.repository.update_email_verified(id, verified).await
145 }
146
147 pub async fn update_display_name(&self, id: &UserId, display_name: &str) -> Result<User> {
148 self.repository.update_display_name(id, display_name).await
149 }
150
151 pub async fn update_all_fields(
152 &self,
153 id: &UserId,
154 params: UpdateUserParams<'_>,
155 ) -> Result<User> {
156 self.repository.update_all_fields(id, params).await
157 }
158
159 pub async fn assign_roles(&self, id: &UserId, roles: &[String]) -> Result<User> {
160 self.repository.assign_roles(id, roles).await
161 }
162
163 pub async fn delete(&self, id: &UserId) -> Result<()> {
164 self.repository.delete(id).await
165 }
166
167 pub async fn cleanup_old_anonymous(&self, days: i32) -> Result<u64> {
168 self.repository.cleanup_old_anonymous(days).await
169 }
170
171 pub async fn count_with_breakdown(&self) -> Result<UserCountBreakdown> {
172 let total = self.repository.count().await?;
173 let by_status_vec = self.repository.count_by_status().await?;
174 let by_role_vec = self.repository.count_by_role().await?;
175
176 let by_status: HashMap<String, i64> = by_status_vec.into_iter().collect();
177 let by_role: HashMap<String, i64> = by_role_vec.into_iter().collect();
178
179 Ok(UserCountBreakdown {
180 total,
181 by_status,
182 by_role,
183 })
184 }
185
186 pub async fn get_stats(&self) -> Result<UserStats> {
187 self.repository.get_stats().await
188 }
189
190 pub async fn list_by_filter(
191 &self,
192 status: Option<&str>,
193 role: Option<&str>,
194 older_than_days: Option<i64>,
195 limit: i64,
196 ) -> Result<Vec<User>> {
197 self.repository
198 .list_by_filter(status, role, older_than_days, limit)
199 .await
200 }
201
202 pub async fn bulk_update_status(&self, user_ids: &[UserId], new_status: &str) -> Result<u64> {
203 self.repository
204 .bulk_update_status(user_ids, new_status)
205 .await
206 }
207
208 pub async fn bulk_delete(&self, user_ids: &[UserId]) -> Result<u64> {
209 self.repository.bulk_delete(user_ids).await
210 }
211
212 pub async fn merge_users(&self, source_id: &UserId, target_id: &UserId) -> Result<MergeResult> {
213 self.repository.merge_users(source_id, target_id).await
214 }
215}