diff --git a/backend/app/models/config.py b/backend/app/models/config.py index 0aba7be..96890d7 100644 --- a/backend/app/models/config.py +++ b/backend/app/models/config.py @@ -1001,8 +1001,7 @@ class ServiceStatusResponse(BaseModel): model_config = ConfigDict(strict=True) online: bool = Field(..., description="Whether fail2ban is reachable via its socket.") - version: str | None = Field(default=None, description="fail2ban version string, or None when offline.") - bangui_version: str = Field(..., description="BanGUI application version.") + version: str | None = Field(default=None, description="BanGUI application version (or None when offline).") jail_count: int = Field(default=0, ge=0, description="Number of currently active jails.") total_bans: int = Field(default=0, ge=0, description="Aggregated current ban count across all jails.") total_failures: int = Field(default=0, ge=0, description="Aggregated current failure count across all jails.") diff --git a/backend/app/models/server.py b/backend/app/models/server.py index 9ebcb36..0e572a0 100644 --- a/backend/app/models/server.py +++ b/backend/app/models/server.py @@ -24,7 +24,6 @@ class ServerStatusResponse(BaseModel): model_config = ConfigDict(strict=True) status: ServerStatus - bangui_version: str = Field(..., description="BanGUI application version.") class ServerSettings(BaseModel): diff --git a/backend/app/routers/dashboard.py b/backend/app/routers/dashboard.py index 50492ac..56c3437 100644 --- a/backend/app/routers/dashboard.py +++ b/backend/app/routers/dashboard.py @@ -70,7 +70,8 @@ async def get_server_status( "server_status", ServerStatus(online=False), ) - return ServerStatusResponse(status=cached, bangui_version=__version__) + cached.version = __version__ + return ServerStatusResponse(status=cached) @router.get( diff --git a/backend/app/services/config_service.py b/backend/app/services/config_service.py index 6e8e86c..492b154 100644 --- a/backend/app/services/config_service.py +++ b/backend/app/services/config_service.py @@ -819,8 +819,7 @@ async def get_service_status( return ServiceStatusResponse( online=server_status.online, - version=server_status.version, - bangui_version=__version__, + version=__version__, jail_count=server_status.active_jails, total_bans=server_status.total_bans, total_failures=server_status.total_failures, diff --git a/backend/tests/test_regression_500s.py b/backend/tests/test_regression_500s.py index 18e995e..079e7fe 100644 --- a/backend/tests/test_regression_500s.py +++ b/backend/tests/test_regression_500s.py @@ -221,8 +221,8 @@ class TestFilterConfigImports: class TestServiceStatusBanguiVersion: - """Bug 4: ``get_service_status`` must include ``bangui_version`` - in the ``ServiceStatusResponse`` it returns.""" + """Bug 4: ``get_service_status`` must include application version + in the ``version`` field of the ``ServiceStatusResponse``.""" async def test_online_response_contains_bangui_version(self) -> None: """The returned model must contain the ``bangui_version`` field.""" @@ -256,11 +256,9 @@ class TestServiceStatusBanguiVersion: probe_fn=AsyncMock(return_value=online_status), ) - assert hasattr(result, "bangui_version"), ( - "ServiceStatusResponse is missing bangui_version — " - "Pydantic will raise ValidationError → 500" + assert result.version == app.__version__, ( + "ServiceStatusResponse must expose BanGUI version in version field" ) - assert result.bangui_version == app.__version__ async def test_offline_response_contains_bangui_version(self) -> None: """Even when fail2ban is offline, ``bangui_version`` must be present.""" @@ -275,4 +273,4 @@ class TestServiceStatusBanguiVersion: probe_fn=AsyncMock(return_value=offline_status), ) - assert result.bangui_version == app.__version__ + assert result.version == app.__version__ diff --git a/backend/tests/test_routers/test_config.py b/backend/tests/test_routers/test_config.py index 62ce95e..06a7255 100644 --- a/backend/tests/test_routers/test_config.py +++ b/backend/tests/test_routers/test_config.py @@ -2001,8 +2001,7 @@ class TestGetServiceStatus: def _mock_status(self, online: bool = True) -> ServiceStatusResponse: return ServiceStatusResponse( online=online, - version="1.0.0" if online else None, - bangui_version=app.__version__, + version=app.__version__, jail_count=2 if online else 0, total_bans=10 if online else 0, total_failures=3 if online else 0, @@ -2021,7 +2020,7 @@ class TestGetServiceStatus: assert resp.status_code == 200 data = resp.json() assert data["online"] is True - assert data["bangui_version"] == app.__version__ + assert data["version"] == app.__version__ assert data["jail_count"] == 2 assert data["log_level"] == "INFO" @@ -2035,7 +2034,7 @@ class TestGetServiceStatus: assert resp.status_code == 200 data = resp.json() - assert data["bangui_version"] == app.__version__ + assert data["version"] == app.__version__ assert data["online"] is False assert data["log_level"] == "UNKNOWN" diff --git a/backend/tests/test_routers/test_dashboard.py b/backend/tests/test_routers/test_dashboard.py index 33b3c93..1353bf8 100644 --- a/backend/tests/test_routers/test_dashboard.py +++ b/backend/tests/test_routers/test_dashboard.py @@ -153,8 +153,6 @@ class TestDashboardStatus: body = response.json() assert "status" in body - assert "bangui_version" in body - assert body["bangui_version"] == app.__version__ status = body["status"] assert "online" in status @@ -171,9 +169,8 @@ class TestDashboardStatus: body = response.json() status = body["status"] - assert body["bangui_version"] == app.__version__ assert status["online"] is True - assert status["version"] == "1.0.2" + assert status["version"] == app.__version__ assert status["active_jails"] == 2 assert status["total_bans"] == 10 assert status["total_failures"] == 5 @@ -187,9 +184,8 @@ class TestDashboardStatus: body = response.json() status = body["status"] - assert body["bangui_version"] == app.__version__ assert status["online"] is False - assert status["version"] is None + assert status["version"] == app.__version__ assert status["active_jails"] == 0 assert status["total_bans"] == 0 assert status["total_failures"] == 0 diff --git a/backend/tests/test_services/test_config_service.py b/backend/tests/test_services/test_config_service.py index 167d9d0..521bf47 100644 --- a/backend/tests/test_services/test_config_service.py +++ b/backend/tests/test_services/test_config_service.py @@ -752,8 +752,7 @@ class TestGetServiceStatus: from app import __version__ assert result.online is True - assert result.version == "1.0.0" - assert result.bangui_version == __version__ + assert result.version == __version__ assert result.jail_count == 2 assert result.total_bans == 5 assert result.total_failures == 3 diff --git a/frontend/src/components/ServerStatusBar.tsx b/frontend/src/components/ServerStatusBar.tsx index aca04bf..df96b87 100644 --- a/frontend/src/components/ServerStatusBar.tsx +++ b/frontend/src/components/ServerStatusBar.tsx @@ -70,7 +70,7 @@ const useStyles = makeStyles({ */ export function ServerStatusBar(): React.JSX.Element { const styles = useStyles(); - const { status, banguiVersion, loading, error, refresh } = useServerStatus(); + const { status, loading, error, refresh } = useServerStatus(); const cardStyles = useCardStyles(); @@ -98,21 +98,13 @@ export function ServerStatusBar(): React.JSX.Element { {/* Version */} {/* ---------------------------------------------------------------- */} {status?.version != null && ( - + v{status.version} )} - {banguiVersion != null && ( - - - BanGUI v{banguiVersion} - - - )} - {/* ---------------------------------------------------------------- */} {/* Stats (only when online) */} {/* ---------------------------------------------------------------- */} diff --git a/frontend/src/components/__tests__/ServerStatusBar.test.tsx b/frontend/src/components/__tests__/ServerStatusBar.test.tsx index a70ab47..9f3fb38 100644 --- a/frontend/src/components/__tests__/ServerStatusBar.test.tsx +++ b/frontend/src/components/__tests__/ServerStatusBar.test.tsx @@ -41,7 +41,6 @@ describe("ServerStatusBar", () => { it("shows a spinner while the initial load is in progress", () => { mockedUseServerStatus.mockReturnValue({ status: null, - banguiVersion: null, loading: true, error: null, refresh: vi.fn(), @@ -60,7 +59,6 @@ describe("ServerStatusBar", () => { total_bans: 10, total_failures: 5, }, - banguiVersion: "1.1.0", loading: false, error: null, refresh: vi.fn(), @@ -78,7 +76,6 @@ describe("ServerStatusBar", () => { total_bans: 0, total_failures: 0, }, - banguiVersion: "1.1.0", loading: false, error: null, refresh: vi.fn(), @@ -96,7 +93,6 @@ describe("ServerStatusBar", () => { total_bans: 0, total_failures: 0, }, - banguiVersion: "1.2.3", loading: false, error: null, refresh: vi.fn(), @@ -105,7 +101,7 @@ describe("ServerStatusBar", () => { expect(screen.getByText("v1.2.3")).toBeInTheDocument(); }); - it("renders a BanGUI version badge", () => { + it("does not render a separate BanGUI version badge", () => { mockedUseServerStatus.mockReturnValue({ status: { online: true, @@ -114,13 +110,12 @@ describe("ServerStatusBar", () => { total_bans: 0, total_failures: 0, }, - banguiVersion: "9.9.9", loading: false, error: null, refresh: vi.fn(), }); renderBar(); - expect(screen.getByText("BanGUI v9.9.9")).toBeInTheDocument(); + expect(screen.queryByText("BanGUI v9.9.9")).toBeNull(); }); it("does not render the version element when version is null", () => { @@ -132,7 +127,6 @@ describe("ServerStatusBar", () => { total_bans: 0, total_failures: 0, }, - banguiVersion: "1.2.3", loading: false, error: null, refresh: vi.fn(), @@ -151,7 +145,6 @@ describe("ServerStatusBar", () => { total_bans: 21, total_failures: 99, }, - banguiVersion: "1.0.0", loading: false, error: null, refresh: vi.fn(), @@ -167,7 +160,6 @@ describe("ServerStatusBar", () => { it("renders an error message when the status fetch fails", () => { mockedUseServerStatus.mockReturnValue({ status: null, - banguiVersion: null, loading: false, error: "Network error", refresh: vi.fn(), diff --git a/frontend/src/components/config/ServerHealthSection.tsx b/frontend/src/components/config/ServerHealthSection.tsx index 039ac0d..65c352e 100644 --- a/frontend/src/components/config/ServerHealthSection.tsx +++ b/frontend/src/components/config/ServerHealthSection.tsx @@ -352,12 +352,6 @@ export function ServerHealthSection(): React.JSX.Element { {status.version} )} - {status.bangui_version && ( -
- BanGUI - {status.bangui_version} -
- )}
Active Jails {status.jail_count} diff --git a/frontend/src/components/config/__tests__/ServerHealthSection.test.tsx b/frontend/src/components/config/__tests__/ServerHealthSection.test.tsx index 45575c9..4faedd9 100644 --- a/frontend/src/components/config/__tests__/ServerHealthSection.test.tsx +++ b/frontend/src/components/config/__tests__/ServerHealthSection.test.tsx @@ -15,11 +15,10 @@ describe("ServerHealthSection", () => { vi.clearAllMocks(); }); - it("shows the BanGUI version in the service health panel", async () => { + it("shows the version in the service health panel", async () => { mockedFetchServiceStatus.mockResolvedValue({ online: true, version: "1.2.3", - bangui_version: "1.2.3", jail_count: 2, total_bans: 5, total_failures: 1, @@ -41,11 +40,11 @@ describe("ServerHealthSection", () => { , ); - // The service health panel should render and include the BanGUI version. - const banGuiLabel = await screen.findByText("BanGUI"); - expect(banGuiLabel).toBeInTheDocument(); + // The service health panel should render and include the version. + const versionLabel = await screen.findByText("Version"); + expect(versionLabel).toBeInTheDocument(); - const banGuiCard = banGuiLabel.closest("div"); - expect(banGuiCard).toHaveTextContent("1.2.3"); + const versionCard = versionLabel.closest("div"); + expect(versionCard).toHaveTextContent("1.2.3"); }); }); diff --git a/frontend/src/hooks/useServerStatus.ts b/frontend/src/hooks/useServerStatus.ts index 826ccf9..8e2470b 100644 --- a/frontend/src/hooks/useServerStatus.ts +++ b/frontend/src/hooks/useServerStatus.ts @@ -18,8 +18,6 @@ const POLL_INTERVAL_MS = 30_000; export interface UseServerStatusResult { /** The most recent server status snapshot, or `null` before the first fetch. */ status: ServerStatus | null; - /** BanGUI application version string. */ - banguiVersion: string | null; /** Whether a fetch is currently in flight. */ loading: boolean; /** Error message string when the last fetch failed, otherwise `null`. */ @@ -35,7 +33,6 @@ export interface UseServerStatusResult { */ export function useServerStatus(): UseServerStatusResult { const [status, setStatus] = useState(null); - const [banguiVersion, setBanguiVersion] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -47,7 +44,6 @@ export function useServerStatus(): UseServerStatusResult { try { const data = await fetchServerStatus(); setStatus(data.status); - setBanguiVersion(data.bangui_version); setError(null); } catch (err: unknown) { handleFetchError(err, setError, "Failed to fetch server status"); @@ -82,5 +78,5 @@ export function useServerStatus(): UseServerStatusResult { void doFetch().catch((): void => undefined); }, [doFetch]); - return { status, banguiVersion, loading, error, refresh }; + return { status, loading, error, refresh }; } diff --git a/frontend/src/types/config.ts b/frontend/src/types/config.ts index ec47f65..0fa796c 100644 --- a/frontend/src/types/config.ts +++ b/frontend/src/types/config.ts @@ -659,10 +659,8 @@ export interface Fail2BanLogResponse { export interface ServiceStatusResponse { /** Whether fail2ban is reachable via its socket. */ online: boolean; - /** fail2ban version string, or null when offline. */ + /** BanGUI application version (or null when offline). */ version: string | null; - /** BanGUI application version (from the API). */ - bangui_version: string; /** Number of currently active jails. */ jail_count: number; /** Aggregated current ban count across all jails. */ diff --git a/frontend/src/types/server.ts b/frontend/src/types/server.ts index 272c538..7c9525f 100644 --- a/frontend/src/types/server.ts +++ b/frontend/src/types/server.ts @@ -21,6 +21,4 @@ export interface ServerStatus { /** Response shape for ``GET /api/dashboard/status``. */ export interface ServerStatusResponse { status: ServerStatus; - /** BanGUI application version (from the API). */ - bangui_version: string; }