systemprompt_users/models/
mod.rs1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use sqlx::FromRow;
4use systemprompt_identifiers::{SessionId, UserId};
5
6pub use systemprompt_models::auth::{UserRole, UserStatus};
7
8#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
9pub struct User {
10 #[sqlx(try_from = "String")]
11 pub id: UserId,
12 pub name: String,
13 pub email: String,
14 pub full_name: Option<String>,
15 pub display_name: Option<String>,
16 pub status: Option<String>,
17 pub email_verified: Option<bool>,
18 pub roles: Vec<String>,
19 pub avatar_url: Option<String>,
20 pub is_bot: bool,
21 pub is_scanner: bool,
22 pub created_at: Option<DateTime<Utc>>,
23 pub updated_at: Option<DateTime<Utc>>,
24}
25
26impl User {
27 pub fn is_active(&self) -> bool {
28 self.status.as_deref() == Some(UserStatus::Active.as_str())
29 }
30
31 pub fn is_admin(&self) -> bool {
32 self.roles.contains(&UserRole::Admin.as_str().to_string())
33 }
34
35 pub fn has_role(&self, role: UserRole) -> bool {
36 self.roles.contains(&role.as_str().to_string())
37 }
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
41pub struct UserActivity {
42 #[sqlx(try_from = "String")]
43 pub user_id: UserId,
44 pub last_active: Option<DateTime<Utc>>,
45 pub session_count: i64,
46 pub task_count: i64,
47 pub message_count: i64,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
51pub struct UserWithSessions {
52 #[sqlx(try_from = "String")]
53 pub id: UserId,
54 pub name: String,
55 pub email: String,
56 pub full_name: Option<String>,
57 pub status: Option<String>,
58 pub roles: Vec<String>,
59 pub created_at: Option<DateTime<Utc>>,
60 pub active_sessions: i64,
61 pub last_session_at: Option<DateTime<Utc>>,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct UserSession {
66 pub session_id: SessionId,
67 pub user_id: Option<UserId>,
68 pub ip_address: Option<String>,
69 pub user_agent: Option<String>,
70 pub device_type: Option<String>,
71 pub started_at: Option<DateTime<Utc>>,
72 pub last_activity_at: Option<DateTime<Utc>>,
73 pub ended_at: Option<DateTime<Utc>>,
74}
75
76#[derive(Debug, Clone, FromRow)]
77pub(crate) struct UserSessionRow {
78 #[sqlx(try_from = "String")]
79 pub session_id: SessionId,
80 pub user_id: Option<String>,
81 pub ip_address: Option<String>,
82 pub user_agent: Option<String>,
83 pub device_type: Option<String>,
84 pub started_at: Option<DateTime<Utc>>,
85 pub last_activity_at: Option<DateTime<Utc>>,
86 pub ended_at: Option<DateTime<Utc>>,
87}
88
89impl From<UserSessionRow> for UserSession {
90 fn from(row: UserSessionRow) -> Self {
91 Self {
92 session_id: row.session_id,
93 user_id: row.user_id.map(UserId::new),
94 ip_address: row.ip_address,
95 user_agent: row.user_agent,
96 device_type: row.device_type,
97 started_at: row.started_at,
98 last_activity_at: row.last_activity_at,
99 ended_at: row.ended_at,
100 }
101 }
102}
103
104#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
105pub struct UserStats {
106 pub total: i64,
107 pub created_24h: i64,
108 pub created_7d: i64,
109 pub created_30d: i64,
110 pub active: i64,
111 pub suspended: i64,
112 pub admins: i64,
113 pub anonymous: i64,
114 pub bots: i64,
115 pub oldest_user: Option<DateTime<Utc>>,
116 pub newest_user: Option<DateTime<Utc>>,
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct UserCountBreakdown {
121 pub total: i64,
122 pub by_status: std::collections::HashMap<String, i64>,
123 pub by_role: std::collections::HashMap<String, i64>,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct UserExport {
128 pub id: String,
129 pub name: String,
130 pub email: String,
131 pub full_name: Option<String>,
132 pub display_name: Option<String>,
133 pub status: Option<String>,
134 pub email_verified: Option<bool>,
135 pub roles: Vec<String>,
136 pub is_bot: bool,
137 pub is_scanner: bool,
138 pub created_at: Option<DateTime<Utc>>,
139 pub updated_at: Option<DateTime<Utc>>,
140}
141
142impl From<User> for UserExport {
143 fn from(user: User) -> Self {
144 Self {
145 id: user.id.to_string(),
146 name: user.name,
147 email: user.email,
148 full_name: user.full_name,
149 display_name: user.display_name,
150 status: user.status,
151 email_verified: user.email_verified,
152 roles: user.roles,
153 is_bot: user.is_bot,
154 is_scanner: user.is_scanner,
155 created_at: user.created_at,
156 updated_at: user.updated_at,
157 }
158 }
159}