All checks were successful
Mostovik Backend CI/CD / Tests and lint (push) Successful in 3m12s
Mostovik Backend CI/CD / Build linux/amd64 release images (push) Successful in 4m0s
Mostovik Backend CI/CD / Deploy and verify internal main (push) Has been skipped
Mostovik Backend CI/CD / Deploy customer main (push) Has been skipped
Mostovik Backend CI/CD / Deploy dev (push) Successful in 2m44s
120 lines
4.2 KiB
Python
120 lines
4.2 KiB
Python
"""Explicit dev collection does not fabricate upstream approval or perform HTTP."""
|
|
|
|
from importlib import import_module
|
|
from unittest.mock import Mock, patch
|
|
from uuid import UUID
|
|
|
|
import pytest
|
|
from apps.core.exceptions import ConflictError
|
|
from apps.core.models import BackgroundJob, JobStatus
|
|
from apps.parsers.sro_http import SroHttpClient, require_sro_access_approved
|
|
from core.celery import app as celery_app
|
|
from django.core.cache import cache
|
|
from rest_framework.test import APIClient
|
|
|
|
from tests.apps.user.factories import UserFactory
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def closed_sro_gate(settings):
|
|
settings.SRO_DEV_COLLECTION_ENABLED = False
|
|
settings.SRO_UPSTREAM_ACCESS_APPROVED = False
|
|
settings.SRO_UPSTREAM_APPROVAL_REFERENCE = ""
|
|
|
|
|
|
@pytest.fixture
|
|
def admin_client(db):
|
|
cache.clear()
|
|
client = APIClient()
|
|
client.force_authenticate(UserFactory.create_user(is_staff=True))
|
|
return client
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"dev_enabled,approved,reference,allowed",
|
|
(
|
|
(False, False, "", False),
|
|
(False, True, "", False),
|
|
(False, False, "written approval", False),
|
|
(False, True, "written approval", True),
|
|
(True, False, "", True),
|
|
(True, True, "", True),
|
|
),
|
|
)
|
|
def test_gate_keeps_dev_override_separate_from_upstream_approval(
|
|
settings, dev_enabled, approved, reference, allowed
|
|
):
|
|
settings.SRO_DEV_COLLECTION_ENABLED = dev_enabled
|
|
settings.SRO_UPSTREAM_ACCESS_APPROVED = approved
|
|
settings.SRO_UPSTREAM_APPROVAL_REFERENCE = reference
|
|
if allowed:
|
|
require_sro_access_approved()
|
|
else:
|
|
with pytest.raises(ConflictError) as error:
|
|
require_sro_access_approved()
|
|
assert error.value.code == "upstream_access_not_approved"
|
|
assert settings.SRO_UPSTREAM_ACCESS_APPROVED is approved
|
|
assert reference == settings.SRO_UPSTREAM_APPROVAL_REFERENCE
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"url",
|
|
(
|
|
"/api/v1/sources/sro-membership-check/refresh/",
|
|
"/api/v1/parsers/run/sro_membership_check/",
|
|
),
|
|
)
|
|
@pytest.mark.parametrize("enabled", (False, True))
|
|
def test_dev_refresh_entrypoints_enqueue_only_with_explicit_opt_in(
|
|
admin_client, settings, url, enabled
|
|
):
|
|
settings.SRO_DEV_COLLECTION_ENABLED = enabled
|
|
import_module("apps.parsers.tasks")
|
|
task = celery_app.tasks["parsers.sro_membership_check.refresh"]
|
|
with (
|
|
patch.object(task, "apply_async") as dispatch,
|
|
patch("apps.parsers.sro_http.requests.Session") as http_session,
|
|
):
|
|
response = admin_client.post(url, {}, format="json")
|
|
http_session.assert_not_called()
|
|
if not enabled:
|
|
assert response.status_code == 409
|
|
assert response.data["errors"][0]["code"] == "upstream_access_not_approved"
|
|
assert not BackgroundJob.objects.exists()
|
|
dispatch.assert_not_called()
|
|
return
|
|
assert response.status_code == 202
|
|
payload = response.data.get("data", response.data)
|
|
assert payload["status"] == "queued"
|
|
assert payload["task_ids"] == [payload["task_id"]]
|
|
assert str(UUID(payload["task_id"])) == payload["task_id"]
|
|
job = BackgroundJob.objects.get(task_id=payload["task_id"])
|
|
assert job.status == JobStatus.PENDING
|
|
assert job.task_name == "parsers.sro_membership_check.refresh"
|
|
dispatch.assert_called_once()
|
|
assert settings.SRO_UPSTREAM_ACCESS_APPROVED is False
|
|
assert settings.SRO_UPSTREAM_APPROVAL_REFERENCE == ""
|
|
|
|
|
|
def test_dev_http_client_uses_neutral_user_agent(settings):
|
|
settings.SRO_DEV_COLLECTION_ENABLED = True
|
|
session = Mock(headers={})
|
|
with patch("apps.parsers.sro_http.requests.Session", return_value=session):
|
|
client = SroHttpClient()
|
|
client.close()
|
|
assert session.headers["User-Agent"] == "Mostovik SRO integration"
|
|
assert session.trust_env is False
|
|
session.get.assert_not_called()
|
|
session.close.assert_called_once()
|
|
|
|
|
|
def test_revoking_dev_override_stops_before_http(settings):
|
|
settings.SRO_DEV_COLLECTION_ENABLED = True
|
|
session = Mock()
|
|
client = SroHttpClient(session=session)
|
|
settings.SRO_DEV_COLLECTION_ENABLED = False
|
|
with pytest.raises(ConflictError) as error:
|
|
client.get("https://reestr-sro.ru/")
|
|
assert error.value.code == "upstream_access_not_approved"
|
|
session.get.assert_not_called()
|