"""Server settings router. Provides endpoints to view and update fail2ban server-level settings and to flush log files. * ``GET /api/server/settings`` — current log level, target, and DB config * ``PUT /api/server/settings`` — update server-level settings * ``POST /api/server/flush-logs`` — flush and re-open log files """ from __future__ import annotations from fastapi import APIRouter, Request, status from app.dependencies import AuthDep, Fail2BanSocketDep from app.mappers import server_mappers from app.models.server import ServerSettingsResponse, ServerSettingsUpdate from app.services import server_service router: APIRouter = APIRouter(prefix="/api/v1/server", tags=["Server"]) # --------------------------------------------------------------------------- # Endpoints # --------------------------------------------------------------------------- @router.get( "/settings", response_model=ServerSettingsResponse, summary="Return fail2ban server-level settings", ) async def get_server_settings( request: Request, _auth: AuthDep, socket_path: Fail2BanSocketDep, ) -> ServerSettingsResponse: """Return the current fail2ban server-level settings. Includes log level, log target, syslog socket, database file path, database purge age, and maximum stored matches per record. Args: request: Incoming request (used to access ``app.state``). _auth: Validated session — enforces authentication. Returns: :class:`~app.models.server.ServerSettingsResponse`. Raises: HTTPException: 502 when fail2ban is unreachable. """ domain_result = await server_service.get_settings(socket_path) return server_mappers.map_domain_server_settings_result_to_response(domain_result) @router.put( "/settings", status_code=status.HTTP_204_NO_CONTENT, summary="Update fail2ban server-level settings", ) async def update_server_settings( request: Request, _auth: AuthDep, body: ServerSettingsUpdate, socket_path: Fail2BanSocketDep, ) -> None: """Update fail2ban server-level settings. Only non-None fields in the request body are written. Changes take effect immediately without a daemon restart. Args: request: Incoming request. _auth: Validated session. body: Partial settings update. Raises: HTTPException: 400 when a set command is rejected by fail2ban. HTTPException: 502 when fail2ban is unreachable. """ await server_service.update_settings(socket_path, body) @router.post( "/flush-logs", status_code=status.HTTP_200_OK, summary="Flush and re-open fail2ban log files", ) async def flush_logs( request: Request, _auth: AuthDep, socket_path: Fail2BanSocketDep, ) -> dict[str, str]: """Flush and re-open fail2ban log files. Useful after log rotation so the daemon writes to the newly created log file rather than continuing to append to the rotated one. Args: request: Incoming request. _auth: Validated session. Returns: ``{"message": ""}`` Raises: HTTPException: 400 when the command is rejected. HTTPException: 502 when fail2ban is unreachable. """ result = await server_service.flush_logs(socket_path) return {"message": result}