use serde::{Deserialize, Serialize};
#[derive(Debug, thiserror::Error)]
pub enum AuthError {
#[error("Invalid credentials")]
InvalidCredentials,
#[error("Token generation failed: {0}")]
TokenGeneration(String),
#[error("Invalid token")]
InvalidToken,
#[error("Token expired")]
TokenExpired,
#[error("User not found: {0}")]
UserNotFound(String),
#[error("Password hash failed: {0}")]
PasswordHash(String),
}
pub type AuthResult<T> = Result<T, AuthError>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User {
pub id: String,
pub username: String,
pub password_hash: String,
pub role: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthCredentials {
pub username: String,
pub password: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum TokenType {
Access,
Refresh,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JwtClaims {
pub sub: String,
pub username: String,
pub role: String,
pub exp: usize,
pub iat: usize,
pub token_type: TokenType,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_auth_error_display() {
let err = AuthError::InvalidCredentials;
assert_eq!(format!("{}", err), "Invalid credentials");
}
#[test]
fn test_user_serialization() {
let user = User {
id: "123".to_string(),
username: "test_user".to_string(),
password_hash: "hash".to_string(),
role: "admin".to_string(),
email: Some("test@example.com".to_string()),
created_at: None,
};
let json = serde_json::to_string(&user).unwrap();
assert!(json.contains("test_user"));
assert!(json.contains("password_hash"));
}
}