1use chrono::{DateTime, Utc};
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11pub enum UserRole {
12 Admin,
14 Blocked,
16}
17
18impl UserRole {
19 #[cfg(feature = "server")]
21 pub fn from_str(s: &str) -> Option<Self> {
22 match s {
23 "admin" => Some(UserRole::Admin),
24 "blocked" => Some(UserRole::Blocked),
25 _ => None,
26 }
27 }
28}
29
30#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
32pub struct SessionUser {
33 pub id: i32,
35 pub username: String,
37 pub email: String,
39 pub role: UserRole,
41 pub created_at: DateTime<Utc>,
43 pub session_generation: i32,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct PublicUser {
50 pub id: i32,
52 pub username: String,
54 pub email: String,
56 pub role: UserRole,
58 pub created_at: DateTime<Utc>,
60}
61
62impl From<SessionUser> for PublicUser {
63 fn from(u: SessionUser) -> Self {
65 PublicUser {
66 id: u.id,
67 username: u.username,
68 email: u.email,
69 role: u.role,
70 created_at: u.created_at,
71 }
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use chrono::{TimeZone, Utc};
79
80 fn sample_user() -> SessionUser {
81 SessionUser {
82 id: 1,
83 username: "admin".to_string(),
84 email: "admin@test.com".to_string(),
85 role: UserRole::Admin,
86 created_at: Utc.with_ymd_and_hms(2024, 1, 1, 0, 0, 0).unwrap(),
87 session_generation: 0,
88 }
89 }
90
91 #[test]
92 #[cfg(feature = "server")]
93 fn user_role_from_str() {
94 assert_eq!(UserRole::from_str("admin"), Some(UserRole::Admin));
95 assert_eq!(UserRole::from_str("blocked"), Some(UserRole::Blocked));
96 assert_eq!(UserRole::from_str("unknown"), None);
97 assert_eq!(UserRole::from_str(""), None);
98 }
99
100 #[test]
101 fn user_role_serde_roundtrip() {
102 let json = serde_json::to_string(&UserRole::Admin).unwrap();
103 assert_eq!(
104 serde_json::from_str::<UserRole>(&json).unwrap(),
105 UserRole::Admin
106 );
107 }
108
109 #[test]
110 fn session_user_to_public_user_conversion() {
111 let session = sample_user();
114 let public: PublicUser = session.clone().into();
115 assert_eq!(public.id, session.id);
116 assert_eq!(public.username, session.username);
117 assert_eq!(public.email, session.email);
118 assert_eq!(public.role, session.role);
119 assert_eq!(public.created_at, session.created_at);
120 }
121
122 #[test]
123 fn public_user_excludes_session_generation() {
124 let session = sample_user();
126 let public: PublicUser = session.into();
127 let json = serde_json::to_string(&public).unwrap();
128 assert!(!json.contains("session_generation"));
129 }
130}