Files
BanGUI/backend/app/models/jail.py

101 lines
3.9 KiB
Python

"""Jail management Pydantic models.
Request, response, and domain models used by the jails router and service.
"""
from pydantic import Field
from app.models.config import BantimeEscalation
from app.models.response import BanGuiBaseModel, CommandResponse, CollectionResponse
class JailStatus(BanGuiBaseModel):
"""Runtime metrics for a single jail."""
currently_banned: int = Field(..., ge=0)
total_banned: int = Field(..., ge=0)
currently_failed: int = Field(..., ge=0)
total_failed: int = Field(..., ge=0)
class Jail(BanGuiBaseModel):
"""Domain model for a single fail2ban jail with its full configuration."""
name: str = Field(..., description="Jail name as configured in fail2ban.")
enabled: bool = Field(..., description="Whether the jail is currently active.")
running: bool = Field(..., description="Whether the jail backend is running.")
idle: bool = Field(default=False, description="Whether the jail is in idle mode.")
backend: str = Field(..., description="Log monitoring backend (e.g. polling, systemd).")
log_paths: list[str] = Field(default_factory=list, description="Monitored log files.")
fail_regex: list[str] = Field(default_factory=list, description="Failure detection regex patterns.")
ignore_regex: list[str] = Field(default_factory=list, description="Regex patterns that bypass the ban logic.")
ignore_ips: list[str] = Field(default_factory=list, description="IP addresses or CIDRs on the ignore list.")
date_pattern: str | None = Field(default=None, description="Custom date pattern for log parsing.")
log_encoding: str = Field(default="UTF-8", description="Log file encoding.")
find_time: int = Field(..., description="Time window (seconds) for counting failures.")
ban_time: int = Field(..., description="Duration (seconds) of a ban. -1 means permanent.")
max_retry: int = Field(..., description="Number of failures before a ban is issued.")
actions: list[str] = Field(default_factory=list, description="Names of actions attached to this jail.")
bantime_escalation: BantimeEscalation | None = Field(
default=None,
description="Incremental ban-time escalation settings, or None if not configured.",
)
status: JailStatus | None = Field(default=None, description="Runtime counters.")
class JailSummary(BanGuiBaseModel):
"""Lightweight jail entry for the overview list."""
name: str
enabled: bool
running: bool
idle: bool
backend: str
find_time: int
ban_time: int
max_retry: int
status: JailStatus | None = None
class JailListResponse(CollectionResponse[JailSummary]):
"""Response for ``GET /api/jails``.
Returns a non-paginated collection of jail summaries with their current status.
"""
pass
class IgnoreListResponse(CollectionResponse[str]):
"""Response for ``GET /api/jails/{name}/ignoreip``.
Returns the jailed ignore list as a standard collection response.
"""
pass
class JailDetailResponse(BanGuiBaseModel):
"""Response for ``GET /api/jails/{name}``.
Includes the primary jail object together with supplemental metadata
required by the UI.
"""
jail: Jail
ignore_list: list[str] = Field(
default_factory=list,
description="List of IP addresses and networks currently ignored by the jail.",
)
ignore_self: bool = Field(
default=False,
description="Whether the jail ignores the server's own IP addresses.",
)
class JailCommandResponse(CommandResponse):
"""Generic response for jail control commands (start, stop, reload, idle).
Extends the base CommandResponse with a jail field to identify the target.
"""
jail: str = Field(..., description="Target jail name, or '*' for operations on all jails.")
class IgnoreIpRequest(BanGuiBaseModel):
"""Payload for adding an IP or network to a jail's ignore list."""
ip: str = Field(..., description="IP address or CIDR network to ignore.")