Refactor backend to use request-scoped SQLite connections

This commit is contained in:
2026-04-05 23:14:46 +02:00
parent fde4c480fa
commit 42c030c706
13 changed files with 250 additions and 116 deletions

View File

@@ -17,7 +17,7 @@ if TYPE_CHECKING:
from fastapi import APIRouter, HTTPException, Request, status
from app.dependencies import AuthDep
from app.dependencies import AuthDep, DbDep
from app.models.ban import ActiveBanListResponse, BanRequest, UnbanAllResponse, UnbanRequest
from app.models.jail import JailCommandResponse
from app.services import geo_service, jail_service
@@ -50,6 +50,7 @@ def _bad_gateway(exc: Exception) -> HTTPException:
async def get_active_bans(
request: Request,
_auth: AuthDep,
db: DbDep,
) -> ActiveBanListResponse:
"""Return every IP that is currently banned across all fail2ban jails.
@@ -68,14 +69,13 @@ async def get_active_bans(
"""
socket_path: str = request.app.state.settings.fail2ban_socket
http_session: aiohttp.ClientSession = request.app.state.http_session
app_db = request.app.state.db
try:
return await jail_service.get_active_bans(
socket_path,
geo_batch_lookup=geo_service.lookup_batch,
http_session=http_session,
app_db=app_db,
app_db=db,
)
except Fail2BanConnectionError as exc:
raise _bad_gateway(exc) from exc

View File

@@ -43,7 +43,7 @@ from typing import Annotated
import structlog
from fastapi import APIRouter, HTTPException, Path, Query, Request, status
from app.dependencies import AuthDep
from app.dependencies import AuthDep, DbDep
from app.models.config import (
ActionConfig,
ActionCreateRequest,
@@ -594,6 +594,7 @@ async def preview_log(
async def get_map_color_thresholds(
request: Request,
_auth: AuthDep,
db: DbDep,
) -> MapColorThresholdsResponse:
"""Return the configured map color thresholds.
@@ -607,7 +608,7 @@ async def get_map_color_thresholds(
"""
from app.services import setup_service
high, medium, low = await setup_service.get_map_color_thresholds(request.app.state.db)
high, medium, low = await setup_service.get_map_color_thresholds(db)
return MapColorThresholdsResponse(
threshold_high=high,
threshold_medium=medium,
@@ -623,6 +624,7 @@ async def get_map_color_thresholds(
async def update_map_color_thresholds(
request: Request,
_auth: AuthDep,
db: DbDep,
body: MapColorThresholdsUpdate,
) -> MapColorThresholdsResponse:
"""Update the map color threshold configuration.
@@ -644,7 +646,7 @@ async def update_map_color_thresholds(
try:
await setup_service.set_map_color_thresholds(
request.app.state.db,
db,
threshold_high=body.threshold_high,
threshold_medium=body.threshold_medium,
threshold_low=body.threshold_low,

View File

@@ -20,7 +20,7 @@ if TYPE_CHECKING:
from fastapi import APIRouter, Query, Request
from app import __version__
from app.dependencies import AuthDep
from app.dependencies import AuthDep, DbDep
from app.models.ban import (
BanOrigin,
BansByCountryResponse,
@@ -82,6 +82,7 @@ async def get_server_status(
async def get_dashboard_bans(
request: Request,
_auth: AuthDep,
db: DbDep,
range: TimeRange = Query(default=_DEFAULT_RANGE, description="Time-range preset."),
source: Literal["fail2ban", "archive"] = Query(
default="fail2ban",
@@ -125,7 +126,7 @@ async def get_dashboard_bans(
page=page,
page_size=page_size,
http_session=http_session,
app_db=request.app.state.db,
app_db=db,
geo_batch_lookup=geo_service.lookup_batch,
origin=origin,
)
@@ -139,6 +140,7 @@ async def get_dashboard_bans(
async def get_bans_by_country(
request: Request,
_auth: AuthDep,
db: DbDep,
range: TimeRange = Query(default=_DEFAULT_RANGE, description="Time-range preset."),
source: Literal["fail2ban", "archive"] = Query(
default="fail2ban",
@@ -181,7 +183,7 @@ async def get_bans_by_country(
http_session=http_session,
geo_cache_lookup=geo_service.lookup_cached_only,
geo_batch_lookup=geo_service.lookup_batch,
app_db=request.app.state.db,
app_db=db,
origin=origin,
country_code=country_code,
)
@@ -195,6 +197,7 @@ async def get_bans_by_country(
async def get_ban_trend(
request: Request,
_auth: AuthDep,
db: DbDep,
range: TimeRange = Query(default=_DEFAULT_RANGE, description="Time-range preset."),
source: Literal["fail2ban", "archive"] = Query(
default="fail2ban",
@@ -235,7 +238,7 @@ async def get_ban_trend(
socket_path,
range,
source=source,
app_db=request.app.state.db,
app_db=db,
origin=origin,
)
@@ -248,6 +251,7 @@ async def get_ban_trend(
async def get_bans_by_jail(
request: Request,
_auth: AuthDep,
db: DbDep,
range: TimeRange = Query(default=_DEFAULT_RANGE, description="Time-range preset."),
source: Literal["fail2ban", "archive"] = Query(
default="fail2ban",
@@ -281,6 +285,6 @@ async def get_bans_by_jail(
socket_path,
range,
source=source,
app_db=request.app.state.db,
app_db=db,
origin=origin,
)

View File

@@ -22,7 +22,7 @@ if TYPE_CHECKING:
from fastapi import APIRouter, HTTPException, Query, Request
from app.dependencies import AuthDep
from app.dependencies import AuthDep, DbDep
from app.models.ban import BanOrigin, TimeRange
from app.models.history import HistoryListResponse, IpDetailResponse
from app.services import geo_service, history_service
@@ -40,6 +40,7 @@ _DEFAULT_PAGE_SIZE: int = 100
async def get_history(
request: Request,
_auth: AuthDep,
db: DbDep,
range: TimeRange | None = Query(
default=None,
description="Optional time-range filter. Omit for all-time.",
@@ -102,7 +103,7 @@ async def get_history(
page=page,
page_size=page_size,
geo_enricher=_enricher,
db=request.app.state.db,
db=db,
)
@@ -114,6 +115,7 @@ async def get_history(
async def get_history_archive(
request: Request,
_auth: AuthDep,
db: DbDep,
range: TimeRange | None = Query(
default=None,
description="Optional time-range filter. Omit for all-time.",
@@ -138,7 +140,7 @@ async def get_history_archive(
page=page,
page_size=page_size,
geo_enricher=_enricher,
db=request.app.state.db,
db=db,
)

View File

@@ -23,7 +23,7 @@ from typing import Annotated
from fastapi import APIRouter, Body, HTTPException, Path, Request, status
from app.dependencies import AuthDep
from app.dependencies import AuthDep, DbDep
from app.models.ban import JailBannedIpsResponse
from app.models.jail import (
IgnoreIpRequest,
@@ -557,6 +557,7 @@ async def toggle_ignore_self(
async def get_jail_banned_ips(
request: Request,
_auth: AuthDep,
db: DbDep,
name: _NamePath,
page: int = 1,
page_size: int = 25,
@@ -597,7 +598,6 @@ async def get_jail_banned_ips(
socket_path: str = request.app.state.settings.fail2ban_socket
http_session = getattr(request.app.state, "http_session", None)
app_db = getattr(request.app.state, "db", None)
try:
return await jail_service.get_jail_banned_ips(
@@ -608,7 +608,7 @@ async def get_jail_banned_ips(
search=search,
geo_batch_lookup=geo_service.lookup_batch,
http_session=http_session,
app_db=app_db,
app_db=db,
)
except JailNotFoundError:
raise _not_found(name) from None