mirror of
https://github.com/complexcaresolutions/dak.c2s.git
synced 2026-03-17 23:03:41 +00:00
Add core security layer: - security.py: password hashing (bcrypt), JWT access/refresh tokens, SHA-256 token hashing, TOTP MFA (generate, verify, provisioning URI), plus passlib/bcrypt 5.x compatibility patch - dependencies.py: FastAPI deps for get_current_user (Bearer JWT) and require_admin (role check) - exceptions.py: domain-specific HTTP exceptions (CaseNotFound, DuplicateCase, InvalidImportFile, ICDValidation, AccountLocked, InvalidCredentials) - test_security.py: 9 tests covering all security functions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
49 lines
1.7 KiB
Python
49 lines
1.7 KiB
Python
"""Domain-specific HTTP exceptions for the DAK Zweitmeinungs-Portal."""
|
|
|
|
from fastapi import HTTPException, status
|
|
|
|
|
|
class CaseNotFoundError(HTTPException):
|
|
"""Raised when a requested case does not exist (404)."""
|
|
|
|
def __init__(self, detail: str = "Case not found") -> None:
|
|
super().__init__(status_code=status.HTTP_404_NOT_FOUND, detail=detail)
|
|
|
|
|
|
class DuplicateCaseError(HTTPException):
|
|
"""Raised when a case with the same identifier already exists (409)."""
|
|
|
|
def __init__(self, detail: str = "Case already exists") -> None:
|
|
super().__init__(status_code=status.HTTP_409_CONFLICT, detail=detail)
|
|
|
|
|
|
class InvalidImportFileError(HTTPException):
|
|
"""Raised when an uploaded import file is malformed or invalid (400)."""
|
|
|
|
def __init__(self, detail: str = "Invalid import file") -> None:
|
|
super().__init__(status_code=status.HTTP_400_BAD_REQUEST, detail=detail)
|
|
|
|
|
|
class ICDValidationError(HTTPException):
|
|
"""Raised when ICD code validation fails (422)."""
|
|
|
|
def __init__(self, detail: str = "ICD code validation failed") -> None:
|
|
super().__init__(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=detail
|
|
)
|
|
|
|
|
|
class AccountLockedError(HTTPException):
|
|
"""Raised when a user account is temporarily locked (423)."""
|
|
|
|
def __init__(self, detail: str = "Account is locked") -> None:
|
|
super().__init__(status_code=status.HTTP_423_LOCKED, detail=detail)
|
|
|
|
|
|
class InvalidCredentialsError(HTTPException):
|
|
"""Raised when login credentials are incorrect (401)."""
|
|
|
|
def __init__(self, detail: str = "Invalid credentials") -> None:
|
|
super().__init__(
|
|
status_code=status.HTTP_401_UNAUTHORIZED, detail=detail
|
|
)
|