cf7c29639c
Backend: config/db/security/logging core, SQLAlchemy models (Server, Credential, UpdateJob, UpdateLog, AuditLog, User), services (winrm, ssh, cau, audit, job_runner), REST API (auth, servers, updates, audit), Socket.io WebSocket layer. Frontend: Vue 3 + TS + Pinia + Tailwind, Views (Dashboard, Servers, Updates, Audit, Login), axios + socket.io-client, nginx prod config.
67 lines
1.4 KiB
Python
67 lines
1.4 KiB
Python
"""Custom application exceptions, mapped to HTTP responses in main.py."""
|
|
|
|
|
|
class AppError(Exception):
|
|
"""Base class for application errors."""
|
|
|
|
status_code: int = 500
|
|
detail: str = "Internal server error"
|
|
|
|
def __init__(self, detail: str | None = None) -> None:
|
|
super().__init__(detail or self.detail)
|
|
if detail:
|
|
self.detail = detail
|
|
|
|
|
|
class NotFoundError(AppError):
|
|
status_code = 404
|
|
detail = "Resource not found"
|
|
|
|
|
|
class ConflictError(AppError):
|
|
status_code = 409
|
|
detail = "Resource conflict"
|
|
|
|
|
|
class UnauthorizedError(AppError):
|
|
status_code = 401
|
|
detail = "Authentication required"
|
|
|
|
|
|
class ForbiddenError(AppError):
|
|
status_code = 403
|
|
detail = "Permission denied"
|
|
|
|
|
|
class InvalidTokenError(UnauthorizedError):
|
|
detail = "Token is invalid or expired"
|
|
|
|
|
|
class CredentialDecryptionError(AppError):
|
|
status_code = 500
|
|
detail = "Stored credential cannot be decrypted"
|
|
|
|
|
|
class ConnectionTestError(AppError):
|
|
status_code = 502
|
|
detail = "Connection test failed"
|
|
|
|
|
|
class WinRMError(AppError):
|
|
status_code = 502
|
|
detail = "WinRM operation failed"
|
|
|
|
|
|
class SSHError(AppError):
|
|
status_code = 502
|
|
detail = "SSH operation failed"
|
|
|
|
|
|
class CAUError(AppError):
|
|
status_code = 502
|
|
detail = "Cluster-Aware Updating operation failed"
|
|
|
|
|
|
class JobNotCancellableError(ConflictError):
|
|
detail = "Job cannot be cancelled in its current state"
|