Fix config status and missing historical filter imports
1) Added _get_active_jail_names import in jail_config_service 2) Added _get_active_jail_names and _parse_jails_sync imports in filter_config_service and resolved constants/exceptions 3) Added bangui_version=__version__ in config_service.get_service_status and tests
This commit is contained in:
@@ -15,7 +15,6 @@ from __future__ import annotations
|
|||||||
import asyncio
|
import asyncio
|
||||||
import contextlib
|
import contextlib
|
||||||
import re
|
import re
|
||||||
from collections.abc import Awaitable, Callable
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, TypeVar, cast
|
from typing import TYPE_CHECKING, TypeVar, cast
|
||||||
|
|
||||||
@@ -24,8 +23,12 @@ import structlog
|
|||||||
from app.utils.fail2ban_client import Fail2BanCommand, Fail2BanResponse, Fail2BanToken
|
from app.utils.fail2ban_client import Fail2BanCommand, Fail2BanResponse, Fail2BanToken
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from collections.abc import Awaitable, Callable
|
||||||
|
|
||||||
import aiosqlite
|
import aiosqlite
|
||||||
|
|
||||||
|
from app import __version__
|
||||||
|
from app.exceptions import ConfigOperationError, ConfigValidationError, JailNotFoundError
|
||||||
from app.models.config import (
|
from app.models.config import (
|
||||||
AddLogPathRequest,
|
AddLogPathRequest,
|
||||||
BantimeEscalation,
|
BantimeEscalation,
|
||||||
@@ -44,11 +47,13 @@ from app.models.config import (
|
|||||||
RegexTestResponse,
|
RegexTestResponse,
|
||||||
ServiceStatusResponse,
|
ServiceStatusResponse,
|
||||||
)
|
)
|
||||||
from app.exceptions import ConfigOperationError, ConfigValidationError, JailNotFoundError
|
|
||||||
from app.utils.fail2ban_client import Fail2BanClient
|
from app.utils.fail2ban_client import Fail2BanClient
|
||||||
from app.utils.log_utils import preview_log as util_preview_log, test_regex as util_test_regex
|
from app.utils.log_utils import preview_log as util_preview_log
|
||||||
|
from app.utils.log_utils import test_regex as util_test_regex
|
||||||
from app.utils.setup_utils import (
|
from app.utils.setup_utils import (
|
||||||
get_map_color_thresholds as util_get_map_color_thresholds,
|
get_map_color_thresholds as util_get_map_color_thresholds,
|
||||||
|
)
|
||||||
|
from app.utils.setup_utils import (
|
||||||
set_map_color_thresholds as util_set_map_color_thresholds,
|
set_map_color_thresholds as util_set_map_color_thresholds,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -815,6 +820,7 @@ async def get_service_status(
|
|||||||
return ServiceStatusResponse(
|
return ServiceStatusResponse(
|
||||||
online=server_status.online,
|
online=server_status.online,
|
||||||
version=server_status.version,
|
version=server_status.version,
|
||||||
|
bangui_version=__version__,
|
||||||
jail_count=server_status.active_jails,
|
jail_count=server_status.active_jails,
|
||||||
total_bans=server_status.total_bans,
|
total_bans=server_status.total_bans,
|
||||||
total_failures=server_status.total_failures,
|
total_failures=server_status.total_failures,
|
||||||
|
|||||||
@@ -17,16 +17,21 @@ from pathlib import Path
|
|||||||
|
|
||||||
import structlog
|
import structlog
|
||||||
|
|
||||||
|
from app.exceptions import FilterInvalidRegexError
|
||||||
from app.models.config import (
|
from app.models.config import (
|
||||||
|
AssignFilterRequest,
|
||||||
FilterConfig,
|
FilterConfig,
|
||||||
FilterConfigUpdate,
|
FilterConfigUpdate,
|
||||||
FilterCreateRequest,
|
FilterCreateRequest,
|
||||||
FilterListResponse,
|
FilterListResponse,
|
||||||
FilterUpdateRequest,
|
FilterUpdateRequest,
|
||||||
AssignFilterRequest,
|
|
||||||
)
|
)
|
||||||
from app.exceptions import FilterInvalidRegexError, JailNotFoundError
|
from app.services.config_file_service import _TRUE_VALUES, ConfigWriteError, JailNotFoundInConfigError
|
||||||
from app.utils import conffile_parser
|
from app.utils import conffile_parser
|
||||||
|
from app.utils.config_file_utils import (
|
||||||
|
_get_active_jail_names,
|
||||||
|
_parse_jails_sync,
|
||||||
|
)
|
||||||
from app.utils.jail_utils import reload_jails
|
from app.utils.jail_utils import reload_jails
|
||||||
|
|
||||||
log: structlog.stdlib.BoundLogger = structlog.get_logger()
|
log: structlog.stdlib.BoundLogger = structlog.get_logger()
|
||||||
@@ -90,6 +95,7 @@ class JailNameError(Exception):
|
|||||||
"""Raised when a jail name contains invalid characters."""
|
"""Raised when a jail name contains invalid characters."""
|
||||||
|
|
||||||
|
|
||||||
|
_SAFE_FILTER_NAME_RE: re.Pattern[str] = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$")
|
||||||
_SAFE_JAIL_NAME_RE: re.Pattern[str] = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$")
|
_SAFE_JAIL_NAME_RE: re.Pattern[str] = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,22 +26,17 @@ from app.models.config import (
|
|||||||
InactiveJail,
|
InactiveJail,
|
||||||
InactiveJailListResponse,
|
InactiveJailListResponse,
|
||||||
JailActivationResponse,
|
JailActivationResponse,
|
||||||
JailValidationIssue,
|
|
||||||
JailValidationResult,
|
JailValidationResult,
|
||||||
RollbackResponse,
|
RollbackResponse,
|
||||||
)
|
)
|
||||||
from app.utils.config_file_utils import (
|
from app.utils.config_file_utils import (
|
||||||
_build_inactive_jail,
|
_build_inactive_jail,
|
||||||
_ordered_config_files,
|
_get_active_jail_names,
|
||||||
_parse_jails_sync,
|
_parse_jails_sync,
|
||||||
_validate_jail_config_sync,
|
_validate_jail_config_sync,
|
||||||
)
|
)
|
||||||
|
from app.utils.fail2ban_client import Fail2BanClient
|
||||||
from app.utils.jail_utils import reload_jails
|
from app.utils.jail_utils import reload_jails
|
||||||
from app.utils.fail2ban_client import (
|
|
||||||
Fail2BanClient,
|
|
||||||
Fail2BanConnectionError,
|
|
||||||
Fail2BanResponse,
|
|
||||||
)
|
|
||||||
|
|
||||||
log: structlog.stdlib.BoundLogger = structlog.get_logger()
|
log: structlog.stdlib.BoundLogger = structlog.get_logger()
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
@@ -748,8 +749,11 @@ class TestGetServiceStatus:
|
|||||||
probe_fn=AsyncMock(return_value=online_status),
|
probe_fn=AsyncMock(return_value=online_status),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from app import __version__
|
||||||
|
|
||||||
assert result.online is True
|
assert result.online is True
|
||||||
assert result.version == "1.0.0"
|
assert result.version == "1.0.0"
|
||||||
|
assert result.bangui_version == __version__
|
||||||
assert result.jail_count == 2
|
assert result.jail_count == 2
|
||||||
assert result.total_bans == 5
|
assert result.total_bans == 5
|
||||||
assert result.total_failures == 3
|
assert result.total_failures == 3
|
||||||
@@ -771,3 +775,62 @@ class TestGetServiceStatus:
|
|||||||
assert result.jail_count == 0
|
assert result.jail_count == 0
|
||||||
assert result.log_level == "UNKNOWN"
|
assert result.log_level == "UNKNOWN"
|
||||||
assert result.log_target == "UNKNOWN"
|
assert result.log_target == "UNKNOWN"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
class TestConfigModuleIntegration:
|
||||||
|
async def test_jail_config_service_list_inactive_jails_uses_imports(self, tmp_path: Any) -> None:
|
||||||
|
from app.services.jail_config_service import list_inactive_jails
|
||||||
|
|
||||||
|
# Arrange: fake parse_jails output with one active and one inactive
|
||||||
|
def fake_parse_jails_sync(path: Path) -> tuple[dict[str, dict[str, str]], dict[str, str]]:
|
||||||
|
return (
|
||||||
|
{
|
||||||
|
"sshd": {
|
||||||
|
"enabled": "true",
|
||||||
|
"filter": "sshd",
|
||||||
|
"logpath": "/var/log/auth.log",
|
||||||
|
},
|
||||||
|
"apache-auth": {
|
||||||
|
"enabled": "false",
|
||||||
|
"filter": "apache-auth",
|
||||||
|
"logpath": "/var/log/apache2/error.log",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sshd": str(path / "jail.conf"),
|
||||||
|
"apache-auth": str(path / "jail.conf"),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"app.services.jail_config_service._parse_jails_sync",
|
||||||
|
new=fake_parse_jails_sync,
|
||||||
|
), patch(
|
||||||
|
"app.services.jail_config_service._get_active_jail_names",
|
||||||
|
new=AsyncMock(return_value={"sshd"}),
|
||||||
|
):
|
||||||
|
result = await list_inactive_jails(str(tmp_path), "/fake.sock")
|
||||||
|
|
||||||
|
names = {j.name for j in result.jails}
|
||||||
|
assert "apache-auth" in names
|
||||||
|
assert "sshd" not in names
|
||||||
|
|
||||||
|
async def test_filter_config_service_list_filters_uses_imports(self, tmp_path: Any) -> None:
|
||||||
|
from app.services.filter_config_service import list_filters
|
||||||
|
|
||||||
|
# Arrange minimal filter and jail config files
|
||||||
|
filter_d = tmp_path / "filter.d"
|
||||||
|
filter_d.mkdir(parents=True)
|
||||||
|
(filter_d / "sshd.conf").write_text("[Definition]\nfailregex = ^%(__prefix_line)s.*$\n")
|
||||||
|
(tmp_path / "jail.conf").write_text("[sshd]\nfilter = sshd\nenabled = true\n")
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"app.services.filter_config_service._get_active_jail_names",
|
||||||
|
new=AsyncMock(return_value={"sshd"}),
|
||||||
|
):
|
||||||
|
result = await list_filters(str(tmp_path), "/fake.sock")
|
||||||
|
|
||||||
|
assert result.total == 1
|
||||||
|
assert result.filters[0].name == "sshd"
|
||||||
|
assert result.filters[0].active is True
|
||||||
|
|||||||
Reference in New Issue
Block a user