vanitha
changed user_id as UUID
5fdb9fd
"""
System User model for authentication and authorization.
Represents a system user with login credentials and permissions.
"""
from datetime import datetime
from typing import Optional, Dict, Any, List
from uuid import UUID
from pydantic import BaseModel, Field, EmailStr
from enum import Enum
class UserStatus(str, Enum):
"""User account status options."""
ACTIVE = "active"
INACTIVE = "inactive"
SUSPENDED = "suspended"
LOCKED = "locked"
PENDING_ACTIVATION = "pending_activation"
class UserRole(str, Enum):
"""System user roles."""
SUPER_ADMIN = "super_admin"
ADMIN = "admin"
MANAGER = "manager"
USER = "user"
READ_ONLY = "read_only"
class LoginAttemptModel(BaseModel):
"""Login attempt tracking."""
timestamp: datetime = Field(default_factory=datetime.utcnow)
ip_address: Optional[str] = Field(None, description="IP address of login attempt")
user_agent: Optional[str] = Field(None, description="User agent string")
success: bool = Field(..., description="Whether login was successful")
failure_reason: Optional[str] = Field(None, description="Reason for failure if unsuccessful")
class SecuritySettingsModel(BaseModel):
"""User security settings."""
require_password_change: bool = Field(default=False, description="Force password change on next login")
password_expires_at: Optional[datetime] = Field(None, description="Password expiry date")
failed_login_attempts: int = Field(default=0, description="Count of consecutive failed login attempts")
last_failed_login: Optional[datetime] = Field(None, description="Timestamp of last failed login")
account_locked_until: Optional[datetime] = Field(None, description="Account lock expiry time")
last_password_change: Optional[datetime] = Field(None, description="Last password change timestamp")
login_attempts: List[LoginAttemptModel] = Field(default_factory=list, description="Recent login attempts (last 10)")
password_reset_token: Optional[str] = Field(None, description="Password reset token (stored securely)")
password_reset_token_created_at: Optional[datetime] = Field(None, description="When reset token was created")
class SystemUserModel(BaseModel):
"""
System User data model for authentication and authorization.
Represents the complete user document in MongoDB.
"""
user_id: UUID = Field(..., description="Unique user identifier (UUID/ULID)")
username: str = Field(..., description="Unique username (lowercase alphanumeric)")
email: EmailStr = Field(..., description="User email address")
merchant_id: str = Field(..., description="User Merchant Information")
merchant_type: Optional[str] = Field(None, description="Merchant type (ncnf, cnf, distributor, retail)")
# Authentication
password_hash: str = Field(..., description="Bcrypt hashed password")
# Personal information
first_name: Optional[str] = Field(None, description="User first name")
last_name: Optional[str] = Field(None, description="User last name")
full_name: Optional[str] = Field(None, description="User full name")
phone: Optional[str] = Field(None, description="User phone number (E.164 format)")
# Authorization
role: str = Field(default="user", alias="role_id", description="User role identifier")
permissions: Dict[str, List[str]] = Field(default_factory=dict, description="Grouped permissions by module")
# Status and security
status: UserStatus = Field(default=UserStatus.PENDING_ACTIVATION, description="Account status")
security_settings: SecuritySettingsModel = Field(
default_factory=SecuritySettingsModel,
description="Security and login settings"
)
# Session management
last_login_at: Optional[datetime] = Field(None, description="Last successful login timestamp")
last_login_ip: Optional[str] = Field(None, description="IP address of last login")
current_session_token: Optional[str] = Field(None, description="Current JWT token hash for session management")
# Profile information
profile_picture_url: Optional[str] = Field(None, description="URL to profile picture")
timezone: str = Field(default="UTC", description="User timezone")
language: str = Field(default="en", description="Preferred language code")
# Audit fields
created_by: str = Field(..., description="User ID who created this user account")
created_at: datetime = Field(default_factory=datetime.utcnow, description="Account creation timestamp")
updated_at: Optional[datetime] = Field(None, description="Last update timestamp")
updated_by: Optional[str] = Field(None, description="User ID who last updated this record")
class Config:
populate_by_name = True
json_schema_extra = {
"example": {
"user_id": "usr_01HZQX5K3N2P8R6T4V9W",
"username": "john.doe",
"email": "john.doe@company.com",
"merchant_id": "mch_retail_001",
"merchant_type": "retail",
"password_hash": "$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LeVMstdMT6jmDQrji",
"first_name": "John",
"last_name": "Doe",
"phone": "+919876543210",
"role_id": "admin",
"permissions": {
"customers": ["view", "create", "update"],
"orders": ["view", "create", "update"],
"settings": ["view", "update"]
},
"status": "active",
"security_settings": {
"require_password_change": False,
"failed_login_attempts": 0,
"login_attempts": []
},
"last_login_at": "2024-11-30T10:30:00Z",
"last_login_ip": "192.168.1.100",
"timezone": "Asia/Kolkata",
"language": "en",
"created_by": "system",
"created_at": "2024-01-15T08:00:00Z"
}
}