use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User {
pub id: Uuid,
pub email: String,
pub username: String,
#[serde(skip_serializing)]
pub password_hash: String,
pub is_admin: bool,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Clone)]
pub struct NewUser {
pub email: String,
pub username: String,
pub password_hash: String,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn user_serde_excludes_password_hash_on_output() {
let user = User {
id: Uuid::now_v7(),
email: "test@example.com".to_string(),
username: "testuser".to_string(),
password_hash: "secret_hash_should_not_appear".to_string(),
is_admin: false,
created_at: Utc::now(),
updated_at: Utc::now(),
};
let _json = serde_json::to_string(&user).expect("serialize");
assert!(!_json.contains("secret_hash_should_not_appear"));
assert!(_json.contains("test@example.com"));
assert!(_json.contains("testuser"));
}
#[test]
fn user_serde_with_explicit_password_hash() {
let now = Utc::now();
let user = User {
id: Uuid::now_v7(),
email: "alice@example.com".to_string(),
username: "alice".to_string(),
password_hash: "argon2_hash".to_string(),
is_admin: true,
created_at: now,
updated_at: now,
};
let _json = serde_json::to_string(&user).expect("serialize");
assert_eq!(user.password_hash, "argon2_hash");
assert_eq!(user.email, "alice@example.com");
assert_eq!(user.username, "alice");
assert!(user.is_admin);
}
#[test]
fn newuser_basic_creation() {
let new_user = NewUser {
email: "bob@example.com".to_string(),
username: "bob".to_string(),
password_hash: "hash123".to_string(),
};
assert_eq!(new_user.email, "bob@example.com");
assert_eq!(new_user.username, "bob");
assert_eq!(new_user.password_hash, "hash123");
}
}