Fix backend for resolution notes via mobile app (#2117)
# What this PR does Add first internal api error code and add "resolution_note" param to resolve endpoint ## Which issue(s) this PR fixes It fixes resolving alert groups via mobile app when resolution note is required ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [ ] Documentation added (or `pr:no public docs` PR label added if not required) - [ ] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not required)
This commit is contained in:
parent
68605029e4
commit
a865ae1378
3 changed files with 84 additions and 5 deletions
18
engine/apps/api/errors.py
Normal file
18
engine/apps/api/errors.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
"""errors contains business-logic error codes for internal api.
|
||||
|
||||
It's expected that error codes will use 1000-9999 codes range, where first two digits are for entity:
|
||||
11xx - AlertGroup, 12xx - AlertReceiveChannel, etc.
|
||||
10xx are saved for non-entity related errors.
|
||||
"""
|
||||
# TODO: this package is WIP. It requires validation of code ranges.
|
||||
from enum import Enum, unique
|
||||
|
||||
|
||||
@unique
|
||||
class AlertGroupAPIError(Enum):
|
||||
"""
|
||||
Error codes for alert group.
|
||||
Range is 1100-1199
|
||||
"""
|
||||
|
||||
RESOLUTION_NOTE_REQUIRED = 1101
|
||||
|
|
@ -9,6 +9,7 @@ from rest_framework.response import Response
|
|||
from rest_framework.test import APIClient
|
||||
|
||||
from apps.alerts.models import AlertGroup, AlertGroupLogRecord, AlertReceiveChannel
|
||||
from apps.api.errors import AlertGroupAPIError
|
||||
from apps.api.permissions import LegacyAccessControlRole
|
||||
from apps.base.models import UserNotificationPolicyLogRecord
|
||||
|
||||
|
|
@ -1805,3 +1806,42 @@ def test_direct_paging_integration_treated_as_deleted(
|
|||
|
||||
response = client.get(url, format="json", **make_user_auth_headers(user, token))
|
||||
assert response.json()["alert_receive_channel"]["deleted"] is True
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_alert_group_resolve_resolution_note(
|
||||
make_organization_and_user_with_plugin_token,
|
||||
make_alert_receive_channel,
|
||||
make_channel_filter,
|
||||
make_alert_group,
|
||||
make_alert,
|
||||
make_user_auth_headers,
|
||||
):
|
||||
organization, user, token = make_organization_and_user_with_plugin_token()
|
||||
alert_receive_channel = make_alert_receive_channel(organization)
|
||||
channel_filter = make_channel_filter(alert_receive_channel, is_default=True)
|
||||
new_alert_group = make_alert_group(alert_receive_channel, channel_filter=channel_filter)
|
||||
make_alert(alert_group=new_alert_group, raw_request_data=alert_raw_request_data)
|
||||
|
||||
organization.is_resolution_note_required = True
|
||||
organization.save()
|
||||
|
||||
client = APIClient()
|
||||
url = reverse("api-internal:alertgroup-resolve", kwargs={"pk": new_alert_group.public_primary_key})
|
||||
|
||||
response = client.post(url, format="json", **make_user_auth_headers(user, token))
|
||||
# check that resolution note is required
|
||||
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
||||
assert response.json()["code"] == AlertGroupAPIError.RESOLUTION_NOTE_REQUIRED.value
|
||||
|
||||
with patch(
|
||||
"apps.alerts.tasks.send_update_resolution_note_signal.send_update_resolution_note_signal.apply_async"
|
||||
) as mock_signal:
|
||||
url = reverse("api-internal:alertgroup-resolve", kwargs={"pk": new_alert_group.public_primary_key})
|
||||
response = client.post(
|
||||
url, format="json", data={"resolution_note": "hi"}, **make_user_auth_headers(user, token)
|
||||
)
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
assert new_alert_group.has_resolution_notes
|
||||
assert mock_signal.called
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ from rest_framework.permissions import IsAuthenticated
|
|||
from rest_framework.response import Response
|
||||
|
||||
from apps.alerts.constants import ActionSource
|
||||
from apps.alerts.models import Alert, AlertGroup, AlertReceiveChannel, EscalationChain
|
||||
from apps.alerts.models import Alert, AlertGroup, AlertReceiveChannel, EscalationChain, ResolutionNote
|
||||
from apps.alerts.paging import unpage_user
|
||||
from apps.alerts.tasks import send_update_resolution_note_signal
|
||||
from apps.api.errors import AlertGroupAPIError
|
||||
from apps.api.permissions import RBACPermission
|
||||
from apps.api.serializers.alert_group import AlertGroupListSerializer, AlertGroupSerializer
|
||||
from apps.api.serializers.team import TeamSerializer
|
||||
|
|
@ -456,11 +458,30 @@ class AlertGroupView(
|
|||
if alert_group.is_maintenance_incident:
|
||||
alert_group.stop_maintenance(self.request.user)
|
||||
else:
|
||||
if organization.is_resolution_note_required and not alert_group.has_resolution_notes:
|
||||
return Response(
|
||||
data="Alert group without resolution note cannot be resolved due to organization settings.",
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
resolution_note_text = request.data.get("resolution_note")
|
||||
if resolution_note_text:
|
||||
rn = ResolutionNote.objects.create(
|
||||
alert_group=alert_group,
|
||||
author=self.request.user,
|
||||
source=ResolutionNote.Source.WEB,
|
||||
message_text=resolution_note_text[:3000], # trim text to fit in the db field
|
||||
)
|
||||
send_update_resolution_note_signal.apply_async(
|
||||
kwargs={
|
||||
"alert_group_pk": alert_group.pk,
|
||||
"resolution_note_pk": rn.pk,
|
||||
}
|
||||
)
|
||||
else:
|
||||
# Check resolution note required setting only if resolution_note_text was not provided.
|
||||
if organization.is_resolution_note_required and not alert_group.has_resolution_notes:
|
||||
return Response(
|
||||
data={
|
||||
"code": AlertGroupAPIError.RESOLUTION_NOTE_REQUIRED.value,
|
||||
"detail": "Alert group without resolution note cannot be resolved due to organization settings",
|
||||
},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
alert_group.resolve_by_user(self.request.user, action_source=ActionSource.WEB)
|
||||
return Response(AlertGroupSerializer(alert_group, context={"request": self.request}).data)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue