Spaces:
Running
Running
File size: 6,118 Bytes
7a5b513 5fdb9fd 7a5b513 96e0270 7a5b513 5fdb9fd 7a5b513 8cd913e d74c068 7a5b513 d990a6b 7a5b513 6939a48 7a5b513 eb862e9 7a5b513 6939a48 7a5b513 eb862e9 7a5b513 349a6d0 7a5b513 eb862e9 7a5b513 d990a6b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | """
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"
}
}
|