Consolidate domain exceptions into app.exceptions
Move all shared domain exception classes to backend/app/exceptions.py and update services/routers to import the canonical exceptions. Update docs to reflect the shared exceptions source.
This commit is contained in:
@@ -9,7 +9,6 @@ overrides in jail.d/*.local files.
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from app.utils.async_utils import run_blocking
|
||||
import configparser
|
||||
import contextlib
|
||||
import io
|
||||
@@ -21,7 +20,14 @@ from typing import TYPE_CHECKING, cast
|
||||
|
||||
import structlog
|
||||
|
||||
from app.exceptions import JailNotFoundError
|
||||
from app.exceptions import (
|
||||
ConfigWriteError,
|
||||
JailAlreadyActiveError,
|
||||
JailAlreadyInactiveError,
|
||||
JailNameError,
|
||||
JailNotFoundError,
|
||||
JailNotFoundInConfigError,
|
||||
)
|
||||
from app.helpers.config_file_helpers import (
|
||||
_build_inactive_jail,
|
||||
_get_active_jail_names,
|
||||
@@ -38,6 +44,7 @@ from app.models.config import (
|
||||
RollbackResponse,
|
||||
)
|
||||
from app.tasks.health_check import run_probe
|
||||
from app.utils.async_utils import run_blocking
|
||||
from app.utils.fail2ban_client import Fail2BanClient
|
||||
from app.utils.runtime_state import (
|
||||
clear_activation_record,
|
||||
@@ -76,58 +83,6 @@ _POST_RELOAD_PROBE_INTERVAL: float = 2.0
|
||||
_POST_RELOAD_MAX_ATTEMPTS: int = 4
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Custom exceptions
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class JailNotFoundInConfigError(Exception):
|
||||
"""Raised when the requested jail name is not defined in any config file."""
|
||||
|
||||
def __init__(self, name: str) -> None:
|
||||
"""Initialise with the jail name that was not found.
|
||||
|
||||
Args:
|
||||
name: The jail name that could not be located.
|
||||
"""
|
||||
self.name: str = name
|
||||
super().__init__(f"Jail not found in config files: {name!r}")
|
||||
|
||||
|
||||
class JailAlreadyActiveError(Exception):
|
||||
"""Raised when trying to activate a jail that is already active."""
|
||||
|
||||
def __init__(self, name: str) -> None:
|
||||
"""Initialise with the jail name.
|
||||
|
||||
Args:
|
||||
name: The jail that is already active.
|
||||
"""
|
||||
self.name: str = name
|
||||
super().__init__(f"Jail is already active: {name!r}")
|
||||
|
||||
|
||||
class JailAlreadyInactiveError(Exception):
|
||||
"""Raised when trying to deactivate a jail that is already inactive."""
|
||||
|
||||
def __init__(self, name: str) -> None:
|
||||
"""Initialise with the jail name.
|
||||
|
||||
Args:
|
||||
name: The jail that is already inactive.
|
||||
"""
|
||||
self.name: str = name
|
||||
super().__init__(f"Jail is already inactive: {name!r}")
|
||||
|
||||
|
||||
class JailNameError(Exception):
|
||||
"""Raised when a jail name contains invalid characters."""
|
||||
|
||||
|
||||
class ConfigWriteError(Exception):
|
||||
"""Raised when writing a ``.local`` override file fails."""
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Internal helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -502,8 +457,9 @@ async def list_inactive_jails(
|
||||
:class:`~app.models.config.InactiveJailListResponse` with all
|
||||
inactive jails.
|
||||
"""
|
||||
loop = asyncio.get_event_loop()
|
||||
parsed_result: tuple[dict[str, dict[str, str]], dict[str, str]] = await run_blocking(_parse_jails_sync, Path(config_dir)
|
||||
parsed_result: tuple[dict[str, dict[str, str]], dict[str, str]] = await run_blocking(
|
||||
_parse_jails_sync,
|
||||
Path(config_dir),
|
||||
)
|
||||
all_jails, source_files = parsed_result
|
||||
active_names: set[str] = await _get_active_jail_names(socket_path)
|
||||
@@ -587,7 +543,6 @@ async def _activate_jail(
|
||||
"""
|
||||
_safe_jail_name(name)
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
all_jails, _source_files = await run_blocking( _parse_jails_sync, Path(config_dir))
|
||||
|
||||
if name not in all_jails:
|
||||
@@ -639,7 +594,8 @@ async def _activate_jail(
|
||||
# we can restore it if activation fails. #
|
||||
# ---------------------------------------------------------------------- #
|
||||
local_path = Path(config_dir) / "jail.d" / f"{name}.local"
|
||||
original_content: bytes | None = await run_blocking(lambda: local_path.read_bytes() if local_path.exists() else None,
|
||||
original_content: bytes | None = await run_blocking(
|
||||
lambda: local_path.read_bytes() if local_path.exists() else None,
|
||||
)
|
||||
|
||||
await run_blocking(_write_local_override_sync,
|
||||
@@ -783,7 +739,6 @@ async def _rollback_activation_async(
|
||||
``True`` if fail2ban is responsive again after the rollback, ``False``
|
||||
if recovery also failed.
|
||||
"""
|
||||
loop = asyncio.get_event_loop()
|
||||
local_path = Path(config_dir) / "jail.d" / f"{name}.local"
|
||||
|
||||
# Step 1 — restore original file (or delete it).
|
||||
@@ -860,7 +815,6 @@ async def _deactivate_jail(
|
||||
"""
|
||||
_safe_jail_name(name)
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
all_jails, _source_files = await run_blocking( _parse_jails_sync, Path(config_dir))
|
||||
|
||||
if name not in all_jails:
|
||||
@@ -916,7 +870,6 @@ async def delete_jail_local_override(
|
||||
"""
|
||||
_safe_jail_name(name)
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
all_jails, _source_files = await run_blocking( _parse_jails_sync, Path(config_dir))
|
||||
|
||||
if name not in all_jails:
|
||||
@@ -956,7 +909,6 @@ async def validate_jail_config(
|
||||
JailNameError: If *name* contains invalid characters.
|
||||
"""
|
||||
_safe_jail_name(name)
|
||||
loop = asyncio.get_event_loop()
|
||||
return await run_blocking(_validate_jail_config_sync,
|
||||
Path(config_dir),
|
||||
name,
|
||||
@@ -1008,7 +960,6 @@ async def _rollback_jail(
|
||||
"""
|
||||
_safe_jail_name(name)
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
# Write enabled=false — this must succeed even when fail2ban is down.
|
||||
await run_blocking(_write_local_override_sync,
|
||||
|
||||
Reference in New Issue
Block a user