diff --git a/backend/app/services/mobile_notify.py b/backend/app/services/mobile_notify.py index 1d85c46..f5bb27d 100644 --- a/backend/app/services/mobile_notify.py +++ b/backend/app/services/mobile_notify.py @@ -141,13 +141,16 @@ def _send_fcm_data( } errors: list[str] = [] + # Data-only: Android always calls SeacaMessagingService.onMessageReceived so the app + # can honour per-device notification mode (sound / silent / off). + message_data = {**data, "title": title, "body": body} + with httpx.Client(timeout=12.0) as client: for token in tokens: payload = { "message": { "token": token, - "notification": {"title": title, "body": body}, - "data": data, + "data": message_data, "android": {"priority": "high"}, } } diff --git a/backend/app/version.py b/backend/app/version.py index 39ad46f..8fb610f 100644 --- a/backend/app/version.py +++ b/backend/app/version.py @@ -1,5 +1,5 @@ """Единый источник версии SAC (API, health, логи, OpenAPI).""" APP_NAME = "Security Alert Center" -APP_VERSION = "0.9.4" +APP_VERSION = "0.9.6" APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}" diff --git a/backend/tests/test_mobile_notify.py b/backend/tests/test_mobile_notify.py index 95ddf1c..9a0f7d1 100644 --- a/backend/tests/test_mobile_notify.py +++ b/backend/tests/test_mobile_notify.py @@ -1,6 +1,6 @@ """FCM push must not break event ingest.""" -from unittest.mock import patch +from unittest.mock import MagicMock, patch import pytest @@ -40,3 +40,37 @@ def test_send_fcm_data_raises_token_errors_when_required(): body="b", require_success=True, ) + + +def test_send_fcm_data_payload_is_data_only(): + posted: list[dict] = [] + + def capture_post(_url, *, headers, json): + posted.append(json) + response = MagicMock() + response.raise_for_status.return_value = None + return response + + with patch("app.services.mobile_notify._fcm_access_token", return_value="token"): + with patch("app.services.mobile_notify.get_effective_fcm_config") as mock_cfg: + mock_cfg.return_value.enabled = True + mock_cfg.return_value.project_id = "proj" + mock_cfg.return_value.service_account_path = "/etc/fcm.json" + mock_cfg.return_value.configured = True + mock_cfg.return_value.active = True + with patch("httpx.Client") as mock_client: + mock_client.return_value.__enter__.return_value.post = capture_post + _send_fcm_data( + ["device-token"], + {"kind": "event", "id": "42", "severity": "high"}, + title="Alert", + body="Summary text", + ) + + assert len(posted) == 1 + message = posted[0]["message"] + assert "notification" not in message + assert message["data"]["title"] == "Alert" + assert message["data"]["body"] == "Summary text" + assert message["data"]["kind"] == "event" + assert message["data"]["id"] == "42" diff --git a/frontend/src/version.ts b/frontend/src/version.ts index b1432df..a245fa9 100644 --- a/frontend/src/version.ts +++ b/frontend/src/version.ts @@ -1,4 +1,4 @@ /** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */ export const APP_NAME = "Security Alert Center"; -export const APP_VERSION = "0.9.4"; +export const APP_VERSION = "0.9.6"; export const APP_VERSION_LABEL = `${APP_NAME} v.${APP_VERSION}`;