Files
movies-diary/crates/domain/src/models/user.rs
Gabriel Kaszewski 6e21ec115d
Some checks failed
CI / Check / Test (push) Has been cancelled
fmt
2026-06-10 03:24:17 +02:00

180 lines
4.0 KiB
Rust

use crate::value_objects::{Email, PasswordHash, UserId, Username};
#[derive(Clone, Debug, Default)]
pub enum UserRole {
#[default]
Standard,
Admin,
}
impl UserRole {
pub fn as_str(&self) -> &'static str {
match self {
Self::Standard => "standard",
Self::Admin => "admin",
}
}
}
#[derive(Debug, Clone)]
pub struct ProfileField {
pub name: String,
pub value: String,
}
#[derive(Clone, Debug, Default)]
pub struct UserProfile {
pub display_name: Option<String>,
pub bio: Option<String>,
pub avatar_path: Option<String>,
pub banner_path: Option<String>,
pub also_known_as: Option<String>,
pub profile_fields: Vec<ProfileField>,
}
impl UserProfile {
pub const MAX_CUSTOM_FIELDS: usize = 4;
pub fn validate_custom_fields(
fields: &[ProfileField],
) -> Result<(), crate::errors::DomainError> {
if fields.len() > Self::MAX_CUSTOM_FIELDS {
Err(crate::errors::DomainError::ValidationError(
"Maximum 4 profile fields allowed".into(),
))
} else {
Ok(())
}
}
}
#[derive(Clone, Debug)]
pub struct User {
id: UserId,
email: Email,
username: Username,
password_hash: PasswordHash,
role: UserRole,
profile: UserProfile,
}
impl User {
pub fn new(
email: Email,
username: Username,
password_hash: PasswordHash,
role: UserRole,
) -> Self {
Self {
id: UserId::generate(),
email,
username,
password_hash,
role,
profile: UserProfile::default(),
}
}
pub fn from_persistence(
id: UserId,
email: Email,
username: Username,
password_hash: PasswordHash,
role: UserRole,
profile: UserProfile,
) -> Self {
Self {
id,
email,
username,
password_hash,
role,
profile,
}
}
pub fn update_password(&mut self, new_hash: PasswordHash) {
self.password_hash = new_hash;
}
pub fn update_profile(&mut self, profile: UserProfile) {
self.profile = profile;
}
pub fn email(&self) -> &Email {
&self.email
}
pub fn username(&self) -> &Username {
&self.username
}
pub fn id(&self) -> &UserId {
&self.id
}
pub fn password_hash(&self) -> &PasswordHash {
&self.password_hash
}
pub fn role(&self) -> &UserRole {
&self.role
}
pub fn display_name(&self) -> Option<&str> {
self.profile.display_name.as_deref()
}
pub fn bio(&self) -> Option<&str> {
self.profile.bio.as_deref()
}
pub fn avatar_path(&self) -> Option<&str> {
self.profile.avatar_path.as_deref()
}
pub fn banner_path(&self) -> Option<&str> {
self.profile.banner_path.as_deref()
}
pub fn also_known_as(&self) -> Option<&str> {
self.profile.also_known_as.as_deref()
}
pub fn profile_fields(&self) -> &[ProfileField] {
&self.profile.profile_fields
}
}
#[derive(Clone, Debug)]
pub struct UserSummary {
pub user_id: UserId,
email: Email,
username: Username,
display_name: Option<String>,
pub total_movies: i64,
pub avg_rating: Option<f64>,
pub avatar_path: Option<String>,
}
impl UserSummary {
pub fn new(
user_id: UserId,
email: Email,
username: Username,
display_name: Option<String>,
total_movies: i64,
avg_rating: Option<f64>,
avatar_path: Option<String>,
) -> Self {
Self {
user_id,
email,
username,
display_name,
total_movies,
avg_rating,
avatar_path,
}
}
pub fn email(&self) -> &str {
self.email.value()
}
pub fn username(&self) -> &str {
self.username.value()
}
pub fn display_name(&self) -> Option<&str> {
self.display_name.as_deref()
}
}