Fix: Rename directory to remove & character causing shell issues
Renamed ebook_backend&admin_panel to ebook_backend_admin_panel The & character was being interpreted by shell as background process operator, causing 'Dockerfile not found' errors in Coolify.
This commit is contained in:
211
ebook_backend_admin_panel/admin-backend/utils/exceptions.py
Normal file
211
ebook_backend_admin_panel/admin-backend/utils/exceptions.py
Normal file
@@ -0,0 +1,211 @@
|
||||
"""
|
||||
Custom exceptions for the Ebook Coupon Management System
|
||||
Provides structured error handling with proper error codes and messages.
|
||||
"""
|
||||
from typing import Dict, Any, Optional
|
||||
from fastapi import HTTPException
|
||||
|
||||
|
||||
class APIException(HTTPException):
|
||||
"""Base API exception with structured error information"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
status_code: int,
|
||||
detail: str,
|
||||
error_code: str,
|
||||
extra_data: Optional[Dict[str, Any]] = None
|
||||
):
|
||||
super().__init__(status_code=status_code, detail=detail)
|
||||
self.error_code = error_code
|
||||
self.extra_data = extra_data or {}
|
||||
|
||||
|
||||
class AuthenticationError(APIException):
|
||||
"""Authentication related errors"""
|
||||
|
||||
def __init__(self, detail: str = "Authentication failed"):
|
||||
super().__init__(
|
||||
status_code=401,
|
||||
detail=detail,
|
||||
error_code="AUTHENTICATION_ERROR"
|
||||
)
|
||||
|
||||
|
||||
class AuthorizationError(APIException):
|
||||
"""Authorization related errors"""
|
||||
|
||||
def __init__(self, detail: str = "Access denied"):
|
||||
super().__init__(
|
||||
status_code=403,
|
||||
detail=detail,
|
||||
error_code="AUTHORIZATION_ERROR"
|
||||
)
|
||||
|
||||
|
||||
class NotFoundError(APIException):
|
||||
"""Resource not found errors"""
|
||||
|
||||
def __init__(self, resource: str, detail: Optional[str] = None):
|
||||
if detail is None:
|
||||
detail = f"{resource} not found"
|
||||
super().__init__(
|
||||
status_code=404,
|
||||
detail=detail,
|
||||
error_code="NOT_FOUND_ERROR"
|
||||
)
|
||||
|
||||
|
||||
class ValidationError(APIException):
|
||||
"""Validation related errors"""
|
||||
|
||||
def __init__(self, detail: str, field: Optional[str] = None):
|
||||
if field:
|
||||
detail = f"Validation error in field '{field}': {detail}"
|
||||
super().__init__(
|
||||
status_code=422,
|
||||
detail=detail,
|
||||
error_code="VALIDATION_ERROR"
|
||||
)
|
||||
|
||||
|
||||
class ConflictError(APIException):
|
||||
"""Resource conflict errors"""
|
||||
|
||||
def __init__(self, detail: str):
|
||||
super().__init__(
|
||||
status_code=409,
|
||||
detail=detail,
|
||||
error_code="CONFLICT_ERROR"
|
||||
)
|
||||
|
||||
|
||||
class RateLimitError(APIException):
|
||||
"""Rate limiting errors"""
|
||||
|
||||
def __init__(self, detail: str = "Rate limit exceeded"):
|
||||
super().__init__(
|
||||
status_code=429,
|
||||
detail=detail,
|
||||
error_code="RATE_LIMIT_ERROR"
|
||||
)
|
||||
|
||||
|
||||
class DatabaseError(APIException):
|
||||
"""Database related errors"""
|
||||
|
||||
def __init__(self, detail: str = "Database operation failed"):
|
||||
super().__init__(
|
||||
status_code=500,
|
||||
detail=detail,
|
||||
error_code="DATABASE_ERROR"
|
||||
)
|
||||
|
||||
|
||||
class FileUploadError(APIException):
|
||||
"""File upload related errors"""
|
||||
|
||||
def __init__(self, detail: str):
|
||||
super().__init__(
|
||||
status_code=400,
|
||||
detail=detail,
|
||||
error_code="FILE_UPLOAD_ERROR"
|
||||
)
|
||||
|
||||
|
||||
class CouponError(APIException):
|
||||
"""Coupon related errors"""
|
||||
|
||||
def __init__(self, detail: str, error_code: str = "COUPON_ERROR"):
|
||||
super().__init__(
|
||||
status_code=400,
|
||||
detail=detail,
|
||||
error_code=error_code
|
||||
)
|
||||
|
||||
|
||||
def handle_api_exception(exc: APIException, path: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Handle API exception and return structured error response
|
||||
|
||||
Args:
|
||||
exc: API exception instance
|
||||
path: Request path
|
||||
|
||||
Returns:
|
||||
Structured error response
|
||||
"""
|
||||
return {
|
||||
"success": False,
|
||||
"error": exc.detail,
|
||||
"error_code": exc.error_code,
|
||||
"timestamp": None, # Will be set by exception handler
|
||||
"path": path,
|
||||
**exc.extra_data
|
||||
}
|
||||
|
||||
|
||||
# Coupon specific exceptions
|
||||
class CouponNotFoundError(NotFoundError):
|
||||
"""Coupon not found error"""
|
||||
|
||||
def __init__(self, code: str):
|
||||
super().__init__("coupon", f"Coupon code '{code}' not found")
|
||||
|
||||
|
||||
class CouponAlreadyUsedError(CouponError):
|
||||
"""Coupon already used error"""
|
||||
|
||||
def __init__(self, code: str):
|
||||
super().__init__(
|
||||
f"Coupon code '{code}' has already been used",
|
||||
"COUPON_ALREADY_USED"
|
||||
)
|
||||
|
||||
|
||||
class CouponBlockedError(CouponError):
|
||||
"""Coupon blocked error"""
|
||||
|
||||
def __init__(self, code: str, remaining_minutes: int):
|
||||
super().__init__(
|
||||
f"Coupon code '{code}' is blocked. Try again in {remaining_minutes} minutes",
|
||||
"COUPON_BLOCKED"
|
||||
)
|
||||
|
||||
|
||||
class CouponLimitExceededError(CouponError):
|
||||
"""Coupon usage limit exceeded error"""
|
||||
|
||||
def __init__(self, code: str, limit: int):
|
||||
super().__init__(
|
||||
f"Coupon code '{code}' usage limit ({limit}) exceeded",
|
||||
"COUPON_LIMIT_EXCEEDED"
|
||||
)
|
||||
|
||||
|
||||
# File upload specific exceptions
|
||||
class FileTypeError(FileUploadError):
|
||||
"""Invalid file type error"""
|
||||
|
||||
def __init__(self, allowed_types: list):
|
||||
super().__init__(
|
||||
f"Invalid file type. Allowed types: {', '.join(allowed_types)}"
|
||||
)
|
||||
|
||||
|
||||
class FileSizeError(FileUploadError):
|
||||
"""File too large error"""
|
||||
|
||||
def __init__(self, max_size_mb: int):
|
||||
super().__init__(
|
||||
f"File too large. Maximum size: {max_size_mb}MB"
|
||||
)
|
||||
|
||||
|
||||
class FileExistsError(FileUploadError):
|
||||
"""File already exists error"""
|
||||
|
||||
def __init__(self, filename: str):
|
||||
super().__init__(
|
||||
f"File '{filename}' already exists. Please delete it first."
|
||||
)
|
||||
Reference in New Issue
Block a user