Add ban management features and update documentation

- Implement ban model, service, and router endpoints in backend
- Add ban table component and dashboard integration in frontend
- Update ban-related types and API endpoints
- Add comprehensive tests for ban service and dashboard router
- Update documentation (Features, Tasks, Architecture, Web-Design)
- Clean up old fail2ban configuration files
- Update Makefile with new commands
This commit is contained in:
2026-03-06 20:33:42 +01:00
parent 06738dbfa5
commit cbad4ea706
20 changed files with 58 additions and 760 deletions

View File

@@ -1,4 +1,4 @@
"""Tests for ban_service.list_bans() and ban_service.list_accesses()."""
"""Tests for ban_service.list_bans()."""
from __future__ import annotations
@@ -299,61 +299,3 @@ class TestListBansPagination:
result = await ban_service.list_bans("/fake/sock", "7d", page_size=1)
assert result.total == 3 # All three bans are within 7d.
# ---------------------------------------------------------------------------
# list_accesses
# ---------------------------------------------------------------------------
class TestListAccesses:
"""Verify ban_service.list_accesses()."""
async def test_expands_matches_into_rows(self, f2b_db_path: str) -> None:
"""Each element in ``data.matches`` becomes a separate row."""
with patch(
"app.services.ban_service._get_fail2ban_db_path",
new=AsyncMock(return_value=f2b_db_path),
):
result = await ban_service.list_accesses("/fake/sock", "24h")
# Two bans in last 24h: sshd (1 match) + nginx (1 match) = 2 rows.
assert result.total == 2
assert len(result.items) == 2
async def test_access_item_has_line_field(self, f2b_db_path: str) -> None:
"""Each access item contains the raw matched log line."""
with patch(
"app.services.ban_service._get_fail2ban_db_path",
new=AsyncMock(return_value=f2b_db_path),
):
result = await ban_service.list_accesses("/fake/sock", "24h")
for item in result.items:
assert item.line
async def test_ban_with_no_matches_produces_no_access_rows(
self, f2b_db_path: str
) -> None:
"""Bans with empty matches list do not contribute rows."""
with patch(
"app.services.ban_service._get_fail2ban_db_path",
new=AsyncMock(return_value=f2b_db_path),
):
result = await ban_service.list_accesses("/fake/sock", "7d")
# Third ban (9.10.11.12) has no matches, so only 2 rows total.
assert result.total == 2
async def test_empty_db_returns_zero_accesses(
self, empty_f2b_db_path: str
) -> None:
"""Returns empty result when no bans exist."""
with patch(
"app.services.ban_service._get_fail2ban_db_path",
new=AsyncMock(return_value=empty_f2b_db_path),
):
result = await ban_service.list_accesses("/fake/sock", "24h")
assert result.total == 0
assert result.items == []