/ auth_models.py
auth_models.py
  1  from pydantic import BaseModel, Field, EmailStr, validator
  2  from typing import Optional, List, Dict, Any
  3  from datetime import datetime
  4  from enum import Enum
  5  import uuid
  6  
  7  class ApiKeyLevel(str, Enum):
  8      FREE = "free"
  9      BASIC = "basic"
 10      PREMIUM = "premium"
 11      ENTERPRISE = "enterprise"
 12  
 13  class UsageLimit(BaseModel):
 14      """Usage limits for different API levels"""
 15      daily_requests: int = Field(..., description="Maximum number of requests per day")
 16      monthly_requests: int = Field(..., description="Maximum number of requests per month")
 17      max_tokens_per_request: int = Field(..., description="Maximum number of tokens per request")
 18      max_text_length: int = Field(..., description="Maximum text length in characters")
 19      batch_processing: bool = Field(..., description="Access to batch processing")
 20      max_concurrent_requests: int = Field(..., description="Maximum number of concurrent requests")
 21      advanced_models: bool = Field(..., description="Access to advanced models")
 22  
 23  # Define User before UserInDB
 24  class User(BaseModel):
 25      """Model for users"""
 26      id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique user ID")
 27      username: str = Field(..., description="Username")
 28      email: EmailStr = Field(..., description="User email")
 29      hashed_password: str = Field(..., description="Hashed password")
 30      full_name: Optional[str] = Field(None, description="Full name")
 31      disabled: bool = Field(default=False, description="Whether the account is disabled")
 32      roles: List[str] = Field(default_factory=lambda: ["user"], description="User roles")
 33      created_at: datetime = Field(default_factory=datetime.utcnow, description="Creation date")
 34      subscription: ApiKeyLevel = Field(default=ApiKeyLevel.FREE, description="Subscription level")
 35      
 36      class Config:
 37          json_encoders = {
 38              datetime: lambda v: v.isoformat()
 39          }
 40  
 41  class UserCreate(BaseModel):
 42      """Model for user creation"""
 43      username: str = Field(..., description="Username", min_length=3, max_length=50)
 44      email: EmailStr = Field(..., description="User email")
 45      password: str = Field(..., description="Password", min_length=8)
 46      full_name: Optional[str] = Field(None, description="Full name")
 47      
 48      @validator('username')
 49      def username_alphanumeric(cls, v):
 50          if not v.isalnum():
 51              raise ValueError('Username must be alphanumeric')
 52          return v
 53  
 54  # Now UserInDB can inherit from User
 55  class UserInDB(User):
 56      """User model for database with hashed password."""
 57      hashed_password: str
 58      is_active: bool = True
 59      is_admin: bool = False  
 60      subscription_level: str = "free"
 61      last_login: Optional[datetime] = None
 62      stripe_customer_id: Optional[str] = None
 63      
 64  class ApiKey(BaseModel):
 65      """Model for API keys"""
 66      id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique API key ID")
 67      key: str = Field(..., description="API key (hashed in the database)")
 68      name: str = Field(..., description="Descriptive name for the key")
 69      user_id: str = Field(..., description="ID of the user who owns the key")
 70      level: ApiKeyLevel = Field(default=ApiKeyLevel.FREE, description="Access level")
 71      created_at: datetime = Field(default_factory=datetime.utcnow, description="Creation date")
 72      last_used_at: Optional[datetime] = Field(None, description="Last used date")
 73      expires_at: Optional[datetime] = Field(None, description="Expiration date")
 74      is_active: bool = Field(default=True, description="Whether the key is active")
 75      usage: Dict[str, int] = Field(default_factory=dict, description="Usage statistics")
 76      
 77      class Config:
 78          json_encoders = {
 79              datetime: lambda v: v.isoformat()
 80          }
 81  
 82  class TokenData(BaseModel):
 83      """Data contained in the JWT token"""
 84      sub: str = Field(..., description="User ID")
 85      name: Optional[str] = Field(None, description="User name")
 86      email: Optional[str] = Field(None, description="User email")
 87      roles: List[str] = Field(default_factory=list, description="User roles")
 88      api_level: ApiKeyLevel = Field(default=ApiKeyLevel.FREE, description="API level")
 89      exp: Optional[int] = Field(None, description="Token expiration (timestamp)")
 90  
 91  class UserResponse(BaseModel):
 92      """Model for user response (without sensitive data)"""
 93      id: str
 94      username: str
 95      email: EmailStr
 96      full_name: Optional[str]
 97      roles: List[str]
 98      created_at: datetime
 99      subscription: ApiKeyLevel
100      
101      class Config:
102          json_encoders = {
103              datetime: lambda v: v.isoformat()
104          }
105  
106  class Token(BaseModel):
107      """Model for authentication token"""
108      access_token: str
109      token_type: str = "bearer"
110      expires_at: int
111      user: UserResponse
112  
113  class ApiKeyCreate(BaseModel):
114      """Model for API key creation"""
115      name: str = Field(..., description="Descriptive name for the key", min_length=3, max_length=50)
116      level: Optional[ApiKeyLevel] = Field(None, description="Access level (admin only)")
117      expires_at: Optional[datetime] = Field(None, description="Expiration date (optional)")
118  
119  class ApiKeyResponse(BaseModel):
120      """Model for API key response"""
121      id: str
122      key: str
123      name: str
124      level: ApiKeyLevel
125      created_at: datetime
126      expires_at: Optional[datetime]
127      is_active: bool
128      
129      class Config:
130          json_encoders = {
131              datetime: lambda v: v.isoformat()
132          }
133  
134  class UsageRecord(BaseModel):
135      """Model for usage recording"""
136      user_id: str
137      api_key_id: str
138      request_path: str
139      request_method: str
140      tokens_input: int = 0
141      tokens_output: int = 0
142      processing_time: float
143      status_code: int
144      timestamp: datetime = Field(default_factory=datetime.utcnow)
145      
146      class Config:
147          json_encoders = {
148              datetime: lambda v: v.isoformat()
149          }