fix: FCM must not break ingest; add requests dependency (0.9.3)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -69,7 +69,12 @@ def _fcm_access_token(service_account_path: str) -> str:
|
|||||||
from google.oauth2 import service_account
|
from google.oauth2 import service_account
|
||||||
from google.auth.transport.requests import Request
|
from google.auth.transport.requests import Request
|
||||||
except ImportError as exc:
|
except ImportError as exc:
|
||||||
raise MobileNotConfiguredError("google-auth package is required for FCM") from exc
|
msg = str(exc).lower()
|
||||||
|
if "requests" in msg:
|
||||||
|
raise MobileNotConfiguredError(
|
||||||
|
"FCM: установите пакет requests (pip install requests)"
|
||||||
|
) from exc
|
||||||
|
raise MobileNotConfiguredError("FCM: установите google-auth") from exc
|
||||||
|
|
||||||
creds = service_account.Credentials.from_service_account_file(
|
creds = service_account.Credentials.from_service_account_file(
|
||||||
service_account_path,
|
service_account_path,
|
||||||
@@ -116,7 +121,19 @@ def _send_fcm_data(
|
|||||||
raise MobileNotConfiguredError("FCM не настроен на сервере")
|
raise MobileNotConfiguredError("FCM не настроен на сервере")
|
||||||
return
|
return
|
||||||
|
|
||||||
access_token = _fcm_access_token(cfg.service_account_path)
|
try:
|
||||||
|
access_token = _fcm_access_token(cfg.service_account_path)
|
||||||
|
except (MobileNotConfiguredError, MobileSendError) as exc:
|
||||||
|
logger.warning("FCM skipped: %s", exc)
|
||||||
|
if require_success:
|
||||||
|
raise
|
||||||
|
return
|
||||||
|
except Exception:
|
||||||
|
logger.exception("FCM token acquisition failed")
|
||||||
|
if require_success:
|
||||||
|
raise MobileSendError("Failed to obtain FCM access token", status_code=502)
|
||||||
|
return
|
||||||
|
|
||||||
url = f"https://fcm.googleapis.com/v1/projects/{cfg.project_id}/messages:send"
|
url = f"https://fcm.googleapis.com/v1/projects/{cfg.project_id}/messages:send"
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {access_token}",
|
"Authorization": f"Bearer {access_token}",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
"""Единый источник версии SAC (API, health, логи, OpenAPI)."""
|
"""Единый источник версии SAC (API, health, логи, OpenAPI)."""
|
||||||
|
|
||||||
APP_NAME = "Security Alert Center"
|
APP_NAME = "Security Alert Center"
|
||||||
APP_VERSION = "0.9.2"
|
APP_VERSION = "0.9.3"
|
||||||
APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}"
|
APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ passlib[bcrypt]>=1.7.4,<2
|
|||||||
python-jose[cryptography]>=3.3.0,<4
|
python-jose[cryptography]>=3.3.0,<4
|
||||||
httpx>=0.28.0,<1
|
httpx>=0.28.0,<1
|
||||||
google-auth>=2.36.0,<3
|
google-auth>=2.36.0,<3
|
||||||
|
requests>=2.32.0,<3
|
||||||
psutil>=6.1.0,<8
|
psutil>=6.1.0,<8
|
||||||
|
|
||||||
# dev
|
# dev
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
"""FCM push must not break event ingest."""
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from app.services.mobile_notify import MobileNotConfiguredError, _send_fcm_data
|
||||||
|
|
||||||
|
|
||||||
|
def test_send_fcm_data_swallows_token_errors_by_default():
|
||||||
|
with patch(
|
||||||
|
"app.services.mobile_notify._fcm_access_token",
|
||||||
|
side_effect=MobileNotConfiguredError("FCM: install requests"),
|
||||||
|
):
|
||||||
|
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
|
||||||
|
_send_fcm_data(["token"], {"kind": "test"}, title="t", body="b")
|
||||||
|
|
||||||
|
|
||||||
|
def test_send_fcm_data_raises_token_errors_when_required():
|
||||||
|
with patch(
|
||||||
|
"app.services.mobile_notify._fcm_access_token",
|
||||||
|
side_effect=MobileNotConfiguredError("FCM: install requests"),
|
||||||
|
):
|
||||||
|
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 pytest.raises(MobileNotConfiguredError):
|
||||||
|
_send_fcm_data(
|
||||||
|
["token"],
|
||||||
|
{"kind": "test"},
|
||||||
|
title="t",
|
||||||
|
body="b",
|
||||||
|
require_success=True,
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user