use nomifun_common::TimestampMs; use serde::{Deserialize, Serialize}; /// User role enum for RBAC #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)] #[serde(rename_all = "lowercase")] pub enum UserRole { #[default] User, Admin, } impl UserRole { pub fn as_str(&self) -> &'static str { match self { UserRole::User => "user", UserRole::Admin => "admin", } } pub fn from_str(s: &str) -> Self { match s.to_lowercase().as_str() { "admin" => UserRole::Admin, _ => UserRole::User, } } pub fn is_admin(&self) -> bool { matches!(self, UserRole::Admin) } } /// Row mapping for the `users` table. /// /// All fields match the SQLite column names and types exactly. /// Optional fields correspond to nullable columns. #[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)] pub struct User { pub id: String, pub username: String, pub email: Option, pub password_hash: String, pub role: String, // 'admin' or 'user' pub avatar_path: Option, pub jwt_secret: Option, pub created_at: TimestampMs, pub updated_at: TimestampMs, pub last_login: Option, } impl User { /// Get the parsed role pub fn role(&self) -> UserRole { UserRole::from_str(&self.role) } /// Check if user is admin pub fn is_admin(&self) -> bool { self.role().is_admin() } }