fixed tests

This commit is contained in:
2026-05-15 20:41:05 +02:00
parent 96ce516ecf
commit 77df5d5d65
50 changed files with 1482 additions and 5089 deletions

View File

@@ -11,6 +11,13 @@ from httpx import ASGITransport, AsyncClient
from app.config import Settings
from app.db import init_db
from app.exceptions import (
ConfigDirError,
ConfigFileExistsError,
ConfigFileNameError,
ConfigFileNotFoundError,
ConfigFileWriteError,
)
from app.main import create_app
from app.models.config import (
ActionConfig,
@@ -26,20 +33,13 @@ from app.models.file_config import (
JailConfigFileContent,
JailConfigFilesResponse,
)
from app.exceptions import (
ConfigDirError,
ConfigFileExistsError,
ConfigFileNameError,
ConfigFileNotFoundError,
ConfigFileWriteError,
)
# ---------------------------------------------------------------------------
# Fixtures
# ---------------------------------------------------------------------------
_SETUP_PAYLOAD = {
"master_password": "testpassword1",
"master_password": "Testpassword1!",
"database_path": "bangui.db",
"fail2ban_socket": "/var/run/fail2ban/fail2ban.sock",
"timezone": "UTC",
@@ -50,13 +50,17 @@ _SETUP_PAYLOAD = {
@pytest.fixture
async def file_config_client(tmp_path: Path) -> AsyncClient: # type: ignore[misc]
"""Provide an authenticated ``AsyncClient`` for file_config endpoint tests."""
config_dir = tmp_path / "fail2ban"
config_dir.mkdir()
settings = Settings(
database_path=str(tmp_path / "file_config_test.db"),
fail2ban_socket="/tmp/fake.sock",
session_secret="test-file-config-secret",
fail2ban_config_dir=str(config_dir),
session_secret="test-file-config-secret-that-is-long-enough!!",
session_duration_minutes=60,
timezone="UTC",
log_level="debug",
session_cookie_secure=False,
)
app = create_app(settings=settings)
@@ -67,7 +71,7 @@ async def file_config_client(tmp_path: Path) -> AsyncClient: # type: ignore[mis
app.state.http_session = MagicMock()
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as ac:
async with AsyncClient(transport=transport, base_url="http://test", headers={"X-BanGUI-Request": "1"}) as ac:
await ac.post("/api/v1/setup", json=_SETUP_PAYLOAD)
login = await ac.post(
"/api/v1/auth/login",
@@ -108,9 +112,7 @@ def _conf_file_content(name: str = "nginx") -> ConfFileContent:
class TestListJailConfigFiles:
async def test_200_returns_file_list(
self, file_config_client: AsyncClient
) -> None:
async def test_200_returns_file_list(self, file_config_client: AsyncClient) -> None:
with patch(
"app.routers.file_config.raw_config_io_service.list_jail_config_files",
AsyncMock(return_value=_jail_files_resp()),
@@ -122,9 +124,7 @@ class TestListJailConfigFiles:
assert data["total"] == 1
assert data["files"][0]["filename"] == "sshd.conf"
async def test_503_on_config_dir_error(
self, file_config_client: AsyncClient
) -> None:
async def test_503_on_config_dir_error(self, file_config_client: AsyncClient) -> None:
with patch(
"app.routers.file_config.raw_config_io_service.list_jail_config_files",
AsyncMock(side_effect=ConfigDirError("not found")),
@@ -147,9 +147,7 @@ class TestListJailConfigFiles:
class TestGetJailConfigFile:
async def test_200_returns_content(
self, file_config_client: AsyncClient
) -> None:
async def test_200_returns_content(self, file_config_client: AsyncClient) -> None:
content = JailConfigFileContent(
name="sshd",
filename="sshd.conf",
@@ -174,9 +172,7 @@ class TestGetJailConfigFile:
assert resp.status_code == 404
async def test_400_invalid_filename(
self, file_config_client: AsyncClient
) -> None:
async def test_400_invalid_filename(self, file_config_client: AsyncClient) -> None:
with patch(
"app.routers.file_config.raw_config_io_service.get_jail_config_file",
AsyncMock(side_effect=ConfigFileNameError("bad name")),
@@ -268,7 +264,7 @@ class TestUpdateFilterFile:
assert resp.status_code == 204
async def test_400_write_error(self, file_config_client: AsyncClient) -> None:
async def test_500_write_error(self, file_config_client: AsyncClient) -> None:
with patch(
"app.routers.file_config.raw_config_io_service.write_filter_file",
AsyncMock(side_effect=ConfigFileWriteError("disk full")),
@@ -278,7 +274,7 @@ class TestUpdateFilterFile:
json={"content": "x"},
)
assert resp.status_code == 400
assert resp.status_code == 500
# ---------------------------------------------------------------------------
@@ -342,7 +338,7 @@ class TestListActionFiles:
)
resp_data = ActionListResponse(actions=[mock_action], total=1)
with patch(
"app.routers.config.action_config_service.list_actions",
"app.routers.action_config.action_config_service.list_actions",
AsyncMock(return_value=resp_data),
):
resp = await file_config_client.get("/api/v1/config/actions")
@@ -365,7 +361,7 @@ class TestCreateActionFile:
actionban="echo ban <ip>",
)
with patch(
"app.routers.config.action_config_service.create_action",
"app.routers.action_config.action_config_service.create_action",
AsyncMock(return_value=created),
):
resp = await file_config_client.post(
@@ -404,9 +400,7 @@ class TestGetActionFileRaw:
assert resp.status_code == 404
async def test_503_on_config_dir_error(
self, file_config_client: AsyncClient
) -> None:
async def test_503_on_config_dir_error(self, file_config_client: AsyncClient) -> None:
with patch(
"app.routers.file_config.raw_config_io_service.get_action_file",
AsyncMock(side_effect=ConfigDirError("no dir")),
@@ -436,7 +430,7 @@ class TestUpdateActionFileRaw:
assert resp.status_code == 204
async def test_400_write_error(self, file_config_client: AsyncClient) -> None:
async def test_500_write_error(self, file_config_client: AsyncClient) -> None:
with patch(
"app.routers.file_config.raw_config_io_service.write_action_file",
AsyncMock(side_effect=ConfigFileWriteError("disk full")),
@@ -446,7 +440,7 @@ class TestUpdateActionFileRaw:
json={"content": "x"},
)
assert resp.status_code == 400
assert resp.status_code == 500
async def test_404_not_found(self, file_config_client: AsyncClient) -> None:
with patch(
@@ -516,9 +510,7 @@ class TestCreateJailConfigFile:
assert resp.status_code == 400
async def test_503_on_config_dir_error(
self, file_config_client: AsyncClient
) -> None:
async def test_503_on_config_dir_error(self, file_config_client: AsyncClient) -> None:
with patch(
"app.routers.file_config.raw_config_io_service.create_jail_config_file",
AsyncMock(side_effect=ConfigDirError("no dir")),
@@ -537,9 +529,7 @@ class TestCreateJailConfigFile:
class TestGetParsedFilter:
async def test_200_returns_parsed_config(
self, file_config_client: AsyncClient
) -> None:
async def test_200_returns_parsed_config(self, file_config_client: AsyncClient) -> None:
cfg = FilterConfig(name="nginx", filename="nginx.conf")
with patch(
"app.routers.file_config.raw_config_io_service.get_parsed_filter_file",
@@ -557,15 +547,11 @@ class TestGetParsedFilter:
"app.routers.file_config.raw_config_io_service.get_parsed_filter_file",
AsyncMock(side_effect=ConfigFileNotFoundError("missing")),
):
resp = await file_config_client.get(
"/api/v1/config/filters/missing/parsed"
)
resp = await file_config_client.get("/api/v1/config/filters/missing/parsed")
assert resp.status_code == 404
async def test_503_on_config_dir_error(
self, file_config_client: AsyncClient
) -> None:
async def test_503_on_config_dir_error(self, file_config_client: AsyncClient) -> None:
with patch(
"app.routers.file_config.raw_config_io_service.get_parsed_filter_file",
AsyncMock(side_effect=ConfigDirError("no dir")),
@@ -605,17 +591,17 @@ class TestUpdateParsedFilter:
assert resp.status_code == 404
async def test_400_write_error(self, file_config_client: AsyncClient) -> None:
async def test_500_write_error(self, file_config_client: AsyncClient) -> None:
with patch(
"app.routers.file_config.raw_config_io_service.update_parsed_filter_file",
AsyncMock(side_effect=ConfigFileWriteError("disk full")),
):
resp = await file_config_client.put(
"/api/v1/config/filters/nginx/parsed",
json={"failregex": ["^<HOST> "]},
json={"name": "nginx", "failregex": ["^test$"]},
)
assert resp.status_code == 400
assert resp.status_code == 500
# ---------------------------------------------------------------------------
@@ -624,17 +610,13 @@ class TestUpdateParsedFilter:
class TestGetParsedAction:
async def test_200_returns_parsed_config(
self, file_config_client: AsyncClient
) -> None:
async def test_200_returns_parsed_config(self, file_config_client: AsyncClient) -> None:
cfg = ActionConfig(name="iptables", filename="iptables.conf")
with patch(
"app.routers.file_config.raw_config_io_service.get_parsed_action_file",
AsyncMock(return_value=cfg),
):
resp = await file_config_client.get(
"/api/v1/config/actions/iptables/parsed"
)
resp = await file_config_client.get("/api/v1/config/actions/iptables/parsed")
assert resp.status_code == 200
data = resp.json()
@@ -646,22 +628,16 @@ class TestGetParsedAction:
"app.routers.file_config.raw_config_io_service.get_parsed_action_file",
AsyncMock(side_effect=ConfigFileNotFoundError("missing")),
):
resp = await file_config_client.get(
"/api/v1/config/actions/missing/parsed"
)
resp = await file_config_client.get("/api/v1/config/actions/missing/parsed")
assert resp.status_code == 404
async def test_503_on_config_dir_error(
self, file_config_client: AsyncClient
) -> None:
async def test_503_on_config_dir_error(self, file_config_client: AsyncClient) -> None:
with patch(
"app.routers.file_config.raw_config_io_service.get_parsed_action_file",
AsyncMock(side_effect=ConfigDirError("no dir")),
):
resp = await file_config_client.get(
"/api/v1/config/actions/iptables/parsed"
)
resp = await file_config_client.get("/api/v1/config/actions/iptables/parsed")
assert resp.status_code == 503
@@ -696,7 +672,7 @@ class TestUpdateParsedAction:
assert resp.status_code == 404
async def test_400_write_error(self, file_config_client: AsyncClient) -> None:
async def test_500_write_error(self, file_config_client: AsyncClient) -> None:
with patch(
"app.routers.file_config.raw_config_io_service.update_parsed_action_file",
AsyncMock(side_effect=ConfigFileWriteError("disk full")),
@@ -706,7 +682,7 @@ class TestUpdateParsedAction:
json={"actionban": "iptables -I INPUT -s <ip> -j DROP"},
)
assert resp.status_code == 400
assert resp.status_code == 500
# ---------------------------------------------------------------------------
@@ -715,18 +691,14 @@ class TestUpdateParsedAction:
class TestGetParsedJailFile:
async def test_200_returns_parsed_config(
self, file_config_client: AsyncClient
) -> None:
async def test_200_returns_parsed_config(self, file_config_client: AsyncClient) -> None:
section = JailSectionConfig(enabled=True, port="ssh")
cfg = JailFileConfig(filename="sshd.conf", jails={"sshd": section})
with patch(
"app.routers.file_config.raw_config_io_service.get_parsed_jail_file",
AsyncMock(return_value=cfg),
):
resp = await file_config_client.get(
"/api/v1/config/jail-files/sshd.conf/parsed"
)
resp = await file_config_client.get("/api/v1/config/jail-files/sshd.conf/parsed")
assert resp.status_code == 200
data = resp.json()
@@ -738,22 +710,16 @@ class TestGetParsedJailFile:
"app.routers.file_config.raw_config_io_service.get_parsed_jail_file",
AsyncMock(side_effect=ConfigFileNotFoundError("missing.conf")),
):
resp = await file_config_client.get(
"/api/v1/config/jail-files/missing.conf/parsed"
)
resp = await file_config_client.get("/api/v1/config/jail-files/missing.conf/parsed")
assert resp.status_code == 404
async def test_503_on_config_dir_error(
self, file_config_client: AsyncClient
) -> None:
async def test_503_on_config_dir_error(self, file_config_client: AsyncClient) -> None:
with patch(
"app.routers.file_config.raw_config_io_service.get_parsed_jail_file",
AsyncMock(side_effect=ConfigDirError("no dir")),
):
resp = await file_config_client.get(
"/api/v1/config/jail-files/sshd.conf/parsed"
)
resp = await file_config_client.get("/api/v1/config/jail-files/sshd.conf/parsed")
assert resp.status_code == 503
@@ -788,7 +754,7 @@ class TestUpdateParsedJailFile:
assert resp.status_code == 404
async def test_400_write_error(self, file_config_client: AsyncClient) -> None:
async def test_500_write_error(self, file_config_client: AsyncClient) -> None:
with patch(
"app.routers.file_config.raw_config_io_service.update_parsed_jail_file",
AsyncMock(side_effect=ConfigFileWriteError("disk full")),
@@ -798,4 +764,4 @@ class TestUpdateParsedJailFile:
json={"jails": {"sshd": {"enabled": True}}},
)
assert resp.status_code == 400
assert resp.status_code == 500