diff --git a/engine/apps/public_api/serializers/resolution_notes.py b/engine/apps/public_api/serializers/resolution_notes.py index b48f3fa63..6a7749f1f 100644 --- a/engine/apps/public_api/serializers/resolution_notes.py +++ b/engine/apps/public_api/serializers/resolution_notes.py @@ -1,6 +1,7 @@ from rest_framework import serializers from apps.alerts.models import AlertGroup, ResolutionNote +from apps.user_management.models import ServiceAccountUser from common.api_helpers.custom_fields import OrganizationFilteredPrimaryKeyRelatedField, UserIdField from common.api_helpers.exceptions import BadRequest from common.api_helpers.mixins import EagerLoadingMixin @@ -34,8 +35,9 @@ class Meta: SELECT_RELATED = ["alert_group", "resolution_note_slack_message", "author"] def create(self, validated_data): - if self.context["request"].user.pk: - validated_data["author"] = self.context["request"].user + user = self.context["request"].user + if not isinstance(user, ServiceAccountUser) and user.pk: + validated_data["author"] = user validated_data["source"] = ResolutionNote.Source.WEB return super().create(validated_data) diff --git a/engine/apps/public_api/tests/test_resolution_notes.py b/engine/apps/public_api/tests/test_resolution_notes.py index 7a730e18c..a98abac53 100644 --- a/engine/apps/public_api/tests/test_resolution_notes.py +++ b/engine/apps/public_api/tests/test_resolution_notes.py @@ -1,13 +1,16 @@ from unittest.mock import patch +import httpretty import pytest from django.urls import reverse from rest_framework import status from rest_framework.test import APIClient from apps.alerts.models import ResolutionNote +from apps.api import permissions from apps.auth_token.auth import ApiTokenAuthentication, GrafanaServiceAccountAuthentication from apps.auth_token.models import ApiAuthToken, ServiceAccountToken +from apps.auth_token.tests.helpers import setup_service_account_api_mocks @pytest.mark.django_db @@ -146,6 +149,53 @@ def test_create_resolution_note( mock_send_update_resolution_note_signal.assert_called_once() +@pytest.mark.django_db +@httpretty.activate(verbose=True, allow_net_connect=False) +@patch("apps.alerts.tasks.send_update_resolution_note_signal.send_update_resolution_note_signal.apply_async") +def test_create_resolution_note_via_service_account( + mock_send_update_resolution_note_signal, + make_organization, + make_service_account_for_organization, + make_token_for_service_account, + make_alert_receive_channel, + make_alert_group, +): + organization = make_organization(grafana_url="http://grafana.test") + service_account = make_service_account_for_organization(organization) + token_string = "glsa_token" + make_token_for_service_account(service_account, token_string) + + perms = { + permissions.RBACPermission.Permissions.ALERT_GROUPS_WRITE.value: ["*"], + } + setup_service_account_api_mocks(organization, perms) + + alert_receive_channel = make_alert_receive_channel(organization) + alert_group = make_alert_group(alert_receive_channel) + data = { + "alert_group_id": alert_group.public_primary_key, + "text": "Test Resolution Note Message", + } + url = reverse("api-public:resolution_notes-list") + client = APIClient() + response = client.post( + url, + data=data, + format="json", + HTTP_AUTHORIZATION=f"{token_string}", + HTTP_X_GRAFANA_URL=organization.grafana_url, + ) + if not organization.is_rbac_permissions_enabled: + assert response.status_code == status.HTTP_403_FORBIDDEN + else: + assert response.status_code == status.HTTP_201_CREATED + mock_send_update_resolution_note_signal.assert_called_once() + resolution_note = ResolutionNote.objects.get(public_primary_key=response.data["id"]) + assert resolution_note.author is None + assert resolution_note.text == data["text"] + assert resolution_note.alert_group == alert_group + + @pytest.mark.django_db def test_create_resolution_note_invalid_text( make_organization_and_user_with_token,