forked from cardosofelipe/fast-next-template
- Added reusable validation functions (`validate_password_strength`, `validate_phone_number`, etc.) to centralize schema validation in `validators.py`. - Updated `schemas/users.py` to use shared validators, simplifying and unifying validation logic. - Introduced new error codes (`AUTH_007`, `SYS_005`) for enhanced error specificity. - Refactored exception handling in admin routes to use more appropriate error types (`AuthorizationError`, `DuplicateError`). - Improved organization query performance by replacing N+1 queries with optimized methods for member counts and data aggregation. - Strengthened security in JWT decoding to prevent algorithm confusion attacks, with strict validation of required claims and algorithm enforcement.
88 lines
2.5 KiB
Python
88 lines
2.5 KiB
Python
"""
|
|
Error schemas for standardized API error responses.
|
|
"""
|
|
from enum import Enum
|
|
from typing import List, Optional
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class ErrorCode(str, Enum):
|
|
"""Standard error codes for the API."""
|
|
|
|
# Authentication errors (AUTH_xxx)
|
|
INVALID_CREDENTIALS = "AUTH_001"
|
|
TOKEN_EXPIRED = "AUTH_002"
|
|
TOKEN_INVALID = "AUTH_003"
|
|
INSUFFICIENT_PERMISSIONS = "AUTH_004"
|
|
USER_INACTIVE = "AUTH_005"
|
|
AUTHENTICATION_REQUIRED = "AUTH_006"
|
|
OPERATION_FORBIDDEN = "AUTH_007" # Operation not allowed for this user/role
|
|
|
|
# User errors (USER_xxx)
|
|
USER_NOT_FOUND = "USER_001"
|
|
USER_ALREADY_EXISTS = "USER_002"
|
|
USER_CREATION_FAILED = "USER_003"
|
|
USER_UPDATE_FAILED = "USER_004"
|
|
USER_DELETION_FAILED = "USER_005"
|
|
|
|
# Validation errors (VAL_xxx)
|
|
VALIDATION_ERROR = "VAL_001"
|
|
INVALID_PASSWORD = "VAL_002"
|
|
INVALID_EMAIL = "VAL_003"
|
|
INVALID_PHONE_NUMBER = "VAL_004"
|
|
INVALID_UUID = "VAL_005"
|
|
INVALID_INPUT = "VAL_006"
|
|
|
|
# Database errors (DB_xxx)
|
|
DATABASE_ERROR = "DB_001"
|
|
DUPLICATE_ENTRY = "DB_002"
|
|
FOREIGN_KEY_VIOLATION = "DB_003"
|
|
RECORD_NOT_FOUND = "DB_004"
|
|
|
|
# Generic errors (SYS_xxx)
|
|
INTERNAL_ERROR = "SYS_001"
|
|
NOT_FOUND = "SYS_002"
|
|
METHOD_NOT_ALLOWED = "SYS_003"
|
|
RATE_LIMIT_EXCEEDED = "SYS_004"
|
|
ALREADY_EXISTS = "SYS_005" # Generic resource already exists error
|
|
|
|
|
|
class ErrorDetail(BaseModel):
|
|
"""Detailed information about a single error."""
|
|
|
|
code: ErrorCode = Field(..., description="Machine-readable error code")
|
|
message: str = Field(..., description="Human-readable error message")
|
|
field: Optional[str] = Field(None, description="Field name if error is field-specific")
|
|
|
|
model_config = {
|
|
"json_schema_extra": {
|
|
"example": {
|
|
"code": "VAL_002",
|
|
"message": "Password must be at least 8 characters long",
|
|
"field": "password"
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class ErrorResponse(BaseModel):
|
|
"""Standardized error response format."""
|
|
|
|
success: bool = Field(default=False, description="Always false for error responses")
|
|
errors: List[ErrorDetail] = Field(..., description="List of errors that occurred")
|
|
|
|
model_config = {
|
|
"json_schema_extra": {
|
|
"example": {
|
|
"success": False,
|
|
"errors": [
|
|
{
|
|
"code": "AUTH_001",
|
|
"message": "Invalid email or password",
|
|
"field": None
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|