import json from unittest.mock import patch import pytest from django.urls import reverse from django.utils import timezone from rest_framework import status from rest_framework.response import Response from rest_framework.test import APIClient from apps.api.permissions import LegacyAccessControlRole from apps.heartbeat.models import IntegrationHeartBeat MOCK_LAST_HEARTBEAT_TIME_VERBAL = "a moment" @pytest.fixture() def integration_heartbeat_internal_api_setup( make_organization_and_user_with_plugin_token, make_alert_receive_channel, make_integration_heartbeat ): organization, user, token = make_organization_and_user_with_plugin_token() alert_receive_channel = make_alert_receive_channel(organization) now = timezone.now() integration_heartbeat = make_integration_heartbeat(alert_receive_channel, last_heartbeat_time=now) return user, token, alert_receive_channel, integration_heartbeat @pytest.mark.django_db @patch( "apps.api.serializers.integration_heartbeat.IntegrationHeartBeatSerializer.get_instruction", return_value="

Grafana instruction

", ) @patch( "apps.api.serializers.integration_heartbeat.IntegrationHeartBeatSerializer._last_heartbeat_time_verbal", return_value=MOCK_LAST_HEARTBEAT_TIME_VERBAL, ) def test_get_list_integration_heartbeat( mocked_verbal, mocked_instruction, integration_heartbeat_internal_api_setup, make_user_auth_headers, ): user, token, alert_receive_channel, integration_heartbeat = integration_heartbeat_internal_api_setup client = APIClient() url = reverse("api-internal:integration_heartbeat-list") expected_payload = [ { "id": integration_heartbeat.public_primary_key, "last_heartbeat_time_verbal": mocked_verbal.return_value, "alert_receive_channel": alert_receive_channel.public_primary_key, "link": integration_heartbeat.link, "timeout_seconds": 60, "status": True, "instruction": mocked_instruction.return_value, } ] response = client.get(url, format="json", **make_user_auth_headers(user, token)) assert response.status_code == status.HTTP_200_OK assert response.json() == expected_payload @pytest.mark.django_db @patch( "apps.api.serializers.integration_heartbeat.IntegrationHeartBeatSerializer.get_instruction", return_value="

Grafana instruction

", ) @patch( "apps.api.serializers.integration_heartbeat.IntegrationHeartBeatSerializer._last_heartbeat_time_verbal", return_value=MOCK_LAST_HEARTBEAT_TIME_VERBAL, ) def test_get_detail_integration_heartbeat( mocked_verbal, mocked_instruction, integration_heartbeat_internal_api_setup, make_user_auth_headers, ): user, token, alert_receive_channel, integration_heartbeat = integration_heartbeat_internal_api_setup client = APIClient() url = reverse("api-internal:integration_heartbeat-detail", kwargs={"pk": integration_heartbeat.public_primary_key}) expected_payload = { "id": integration_heartbeat.public_primary_key, "last_heartbeat_time_verbal": mocked_verbal.return_value, "alert_receive_channel": alert_receive_channel.public_primary_key, "link": integration_heartbeat.link, "timeout_seconds": 60, "status": True, "instruction": mocked_instruction.return_value, } response = client.get(url, format="json", **make_user_auth_headers(user, token)) assert response.status_code == status.HTTP_200_OK assert response.json() == expected_payload @pytest.mark.django_db @patch( "apps.api.serializers.integration_heartbeat.IntegrationHeartBeatSerializer.get_instruction", return_value="

Grafana instruction

", ) def test_create_integration_heartbeat( mocked_instruction, make_organization_and_user_with_plugin_token, make_alert_receive_channel, make_user_auth_headers, ): organization, user, token = make_organization_and_user_with_plugin_token() alert_receive_channel = make_alert_receive_channel(organization) client = APIClient() url = reverse("api-internal:integration_heartbeat-list") data_for_create = {"alert_receive_channel": alert_receive_channel.public_primary_key, "timeout_seconds": 60} response = client.post(url, data_for_create, format="json", **make_user_auth_headers(user, token)) integration_heartbeat = IntegrationHeartBeat.objects.get(public_primary_key=response.data["id"]) expected_payload = { "id": integration_heartbeat.public_primary_key, "alert_receive_channel": alert_receive_channel.public_primary_key, "last_heartbeat_time_verbal": None, "timeout_seconds": 60, "link": integration_heartbeat.link, "status": False, "instruction": mocked_instruction.return_value, } assert response.status_code == status.HTTP_201_CREATED assert response.json() == expected_payload @pytest.mark.django_db def test_create_invalid_timeout_integration_heartbeat( make_organization_and_user_with_plugin_token, make_alert_receive_channel, make_user_auth_headers, ): organization, user, token = make_organization_and_user_with_plugin_token() alert_receive_channel = make_alert_receive_channel(organization) client = APIClient() url = reverse("api-internal:integration_heartbeat-list") data_for_create = {"alert_receive_channel": alert_receive_channel.public_primary_key, "timeout_seconds": 71} response = client.post(url, data_for_create, format="json", **make_user_auth_headers(user, token)) assert response.status_code == status.HTTP_400_BAD_REQUEST @pytest.mark.django_db def test_create_empty_alert_receive_channel_integration_heartbeat( integration_heartbeat_internal_api_setup, make_user_auth_headers, ): user, token, _, _ = integration_heartbeat_internal_api_setup client = APIClient() url = reverse("api-internal:integration_heartbeat-list") data_for_create = {"timeout_seconds": 60} response = client.post(url, data_for_create, format="json", **make_user_auth_headers(user, token)) assert response.status_code == status.HTTP_400_BAD_REQUEST @pytest.mark.django_db def test_update_integration_heartbeat( integration_heartbeat_internal_api_setup, make_user_auth_headers, ): user, token, alert_receive_channel, integration_heartbeat = integration_heartbeat_internal_api_setup client = APIClient() url = reverse("api-internal:integration_heartbeat-detail", kwargs={"pk": integration_heartbeat.public_primary_key}) data = { "alert_receive_channel": alert_receive_channel.public_primary_key, "timeout_seconds": 600, } response = client.put( url, data=json.dumps(data), content_type="application/json", **make_user_auth_headers(user, token) ) updated_instance = IntegrationHeartBeat.objects.get(public_primary_key=integration_heartbeat.public_primary_key) assert response.status_code == status.HTTP_200_OK assert updated_instance.timeout_seconds == 600 @pytest.mark.django_db def test_reset_integration_heartbeat( integration_heartbeat_internal_api_setup, make_user_auth_headers, ): user, token, alert_receive_channel, integration_heartbeat = integration_heartbeat_internal_api_setup last_updated = timezone.now() integration_heartbeat.last_heartbeat_time = last_updated integration_heartbeat.save() heartbeat_before_reset = IntegrationHeartBeat.objects.get( public_primary_key=integration_heartbeat.public_primary_key ) assert heartbeat_before_reset.last_heartbeat_time == last_updated client = APIClient() url = reverse("api-internal:integration_heartbeat-reset", kwargs={"pk": integration_heartbeat.public_primary_key}) response = client.post(url, **make_user_auth_headers(user, token)) reset_instance = IntegrationHeartBeat.objects.get(public_primary_key=integration_heartbeat.public_primary_key) assert response.status_code == status.HTTP_204_NO_CONTENT assert reset_instance.last_heartbeat_time is None @pytest.mark.django_db @pytest.mark.parametrize( "role,expected_status", [ (LegacyAccessControlRole.ADMIN, status.HTTP_200_OK), (LegacyAccessControlRole.EDITOR, status.HTTP_403_FORBIDDEN), (LegacyAccessControlRole.VIEWER, status.HTTP_403_FORBIDDEN), (LegacyAccessControlRole.NONE, status.HTTP_403_FORBIDDEN), ], ) def test_integration_heartbeat_create_permissions( make_organization_and_user_with_plugin_token, make_user_auth_headers, role, expected_status, ): _, user, token = make_organization_and_user_with_plugin_token(role) client = APIClient() url = reverse("api-internal:integration_heartbeat-list") with patch( "apps.api.views.integration_heartbeat.IntegrationHeartBeatView.create", return_value=Response( status=status.HTTP_200_OK, ), ): response = client.post(url, format="json", **make_user_auth_headers(user, token)) assert response.status_code == expected_status @pytest.mark.django_db @pytest.mark.parametrize( "role,expected_status", [ (LegacyAccessControlRole.ADMIN, status.HTTP_200_OK), (LegacyAccessControlRole.EDITOR, status.HTTP_403_FORBIDDEN), (LegacyAccessControlRole.VIEWER, status.HTTP_403_FORBIDDEN), (LegacyAccessControlRole.NONE, status.HTTP_403_FORBIDDEN), ], ) def test_integration_heartbeat_update_permissions( make_organization_and_user_with_plugin_token, make_alert_receive_channel, make_integration_heartbeat, make_user_auth_headers, role, expected_status, ): organization, user, token = make_organization_and_user_with_plugin_token(role) alert_receive_channel = make_alert_receive_channel(organization) integration_heartbeat = make_integration_heartbeat(alert_receive_channel) client = APIClient() url = reverse("api-internal:integration_heartbeat-detail", kwargs={"pk": integration_heartbeat.public_primary_key}) with patch( "apps.api.views.integration_heartbeat.IntegrationHeartBeatView.update", return_value=Response( status=status.HTTP_200_OK, ), ): response = client.put(url, format="json", **make_user_auth_headers(user, token)) assert response.status_code == expected_status response = client.patch(url, format="json", **make_user_auth_headers(user, token)) assert response.status_code == expected_status @pytest.mark.django_db @pytest.mark.parametrize( "role,expected_status", [ (LegacyAccessControlRole.ADMIN, status.HTTP_200_OK), (LegacyAccessControlRole.EDITOR, status.HTTP_200_OK), (LegacyAccessControlRole.VIEWER, status.HTTP_200_OK), (LegacyAccessControlRole.NONE, status.HTTP_403_FORBIDDEN), ], ) def test_integration_heartbeat_list_permissions( make_organization_and_user_with_plugin_token, make_alert_receive_channel, make_integration_heartbeat, make_user_auth_headers, role, expected_status, ): organization, user, token = make_organization_and_user_with_plugin_token(role) alert_receive_channel = make_alert_receive_channel(organization) make_integration_heartbeat(alert_receive_channel) client = APIClient() url = reverse("api-internal:integration_heartbeat-list") with patch( "apps.api.views.integration_heartbeat.IntegrationHeartBeatView.list", return_value=Response( status=status.HTTP_200_OK, ), ): response = client.get(url, format="json", **make_user_auth_headers(user, token)) assert response.status_code == expected_status @pytest.mark.django_db @pytest.mark.parametrize( "role,expected_status", [ (LegacyAccessControlRole.ADMIN, status.HTTP_200_OK), (LegacyAccessControlRole.EDITOR, status.HTTP_200_OK), (LegacyAccessControlRole.VIEWER, status.HTTP_200_OK), (LegacyAccessControlRole.NONE, status.HTTP_403_FORBIDDEN), ], ) def test_integration_heartbeat_timeout_options_permissions( make_organization_and_user_with_plugin_token, make_user_auth_headers, role, expected_status, ): _, user, token = make_organization_and_user_with_plugin_token(role) client = APIClient() url = reverse("api-internal:integration_heartbeat-timeout-options") with patch( "apps.api.views.integration_heartbeat.IntegrationHeartBeatView.timeout_options", return_value=Response( status=status.HTTP_200_OK, ), ): response = client.get(url, format="json", **make_user_auth_headers(user, token)) assert response.status_code == expected_status @pytest.mark.django_db @pytest.mark.parametrize( "role,expected_status", [ (LegacyAccessControlRole.ADMIN, status.HTTP_200_OK), (LegacyAccessControlRole.EDITOR, status.HTTP_200_OK), (LegacyAccessControlRole.VIEWER, status.HTTP_200_OK), (LegacyAccessControlRole.NONE, status.HTTP_403_FORBIDDEN), ], ) def test_integration_heartbeat_retrieve_permissions( make_organization_and_user_with_plugin_token, make_alert_receive_channel, make_integration_heartbeat, make_user_auth_headers, role, expected_status, ): organization, user, token = make_organization_and_user_with_plugin_token(role) alert_receive_channel = make_alert_receive_channel(organization) integration_heartbeat = make_integration_heartbeat(alert_receive_channel) client = APIClient() url = reverse("api-internal:integration_heartbeat-detail", kwargs={"pk": integration_heartbeat.public_primary_key}) with patch( "apps.api.views.integration_heartbeat.IntegrationHeartBeatView.retrieve", return_value=Response( status=status.HTTP_200_OK, ), ): response = client.get(url, format="json", **make_user_auth_headers(user, token)) assert response.status_code == expected_status