Skip to content

Commit 5890a1c

Browse files
authored
feat(issues): add audit log for deletions (#68198)
Adds an audit log event for issue deletion. We were already sending an audit log, but it would only log, not appear in the UI as no event was registered. I think this is a good change as it is helpful to know who deleted issues. Fixes getsentry/sentry#68162
1 parent 8f0b6bf commit 5890a1c

File tree

4 files changed

+39
-5
lines changed

4 files changed

+39
-5
lines changed

src/sentry/api/helpers/group_index/delete.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from rest_framework.request import Request
88
from rest_framework.response import Response
99

10-
from sentry import eventstream
10+
from sentry import audit_log, eventstream
1111
from sentry.api.base import audit_logger
1212
from sentry.issues.grouptype import GroupCategory
1313
from sentry.models.group import Group, GroupStatus
@@ -73,6 +73,11 @@ def delete_group_list(
7373
logger=audit_logger,
7474
organization_id=project.organization_id,
7575
target_object=group.id,
76+
event=audit_log.get_event_id("ISSUE_DELETE"),
77+
data={
78+
"issue_id": group.id,
79+
"project_slug": project.slug,
80+
},
7681
)
7782

7883
delete_logger.info(

src/sentry/audit_log/register.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,3 +458,11 @@
458458
template="unblocked {tags} tags of metric {metric_mri} for project {project_slug}",
459459
)
460460
)
461+
default_manager.add(
462+
AuditLogEvent(
463+
event_id=186,
464+
name="ISSUE_DELETE",
465+
api_name="issue.delete",
466+
template="Deleted issue {issue_id} for project {project_slug}",
467+
)
468+
)

tests/sentry/api/endpoints/test_group_details.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
from django.test import override_settings
55
from django.utils import timezone
66

7-
from sentry import buffer, tsdb
7+
from sentry import audit_log, buffer, tsdb
88
from sentry.buffer.redis import RedisBuffer
99
from sentry.issues.grouptype import PerformanceSlowDBQueryGroupType
1010
from sentry.models.activity import Activity
1111
from sentry.models.apikey import ApiKey
12+
from sentry.models.auditlogentry import AuditLogEntry
1213
from sentry.models.environment import Environment
1314
from sentry.models.group import Group, GroupStatus
1415
from sentry.models.groupassignee import GroupAssignee
@@ -24,9 +25,11 @@
2425
from sentry.notifications.types import GroupSubscriptionReason
2526
from sentry.plugins.base import plugins
2627
from sentry.silo import SiloMode
28+
from sentry.tasks.deletion.hybrid_cloud import schedule_hybrid_cloud_foreign_key_jobs
2729
from sentry.testutils.cases import APITestCase, SnubaTestCase
2830
from sentry.testutils.helpers.datetime import freeze_time
2931
from sentry.testutils.helpers.features import with_feature
32+
from sentry.testutils.outbox import outbox_runner
3033
from sentry.testutils.silo import assume_test_silo_mode
3134
from sentry.testutils.skips import requires_snuba
3235
from sentry.types.activity import ActivityType
@@ -274,8 +277,9 @@ def test_count_with_buffer(self):
274277
self.login_as(user=self.user)
275278

276279
redis_buffer = RedisBuffer()
277-
with mock.patch("sentry.buffer.backend.get", redis_buffer.get), mock.patch(
278-
"sentry.buffer.backend.incr", redis_buffer.incr
280+
with (
281+
mock.patch("sentry.buffer.backend.get", redis_buffer.get),
282+
mock.patch("sentry.buffer.backend.incr", redis_buffer.incr),
279283
):
280284
event = self.store_event(
281285
data={"message": "testing", "fingerprint": ["group-1"]}, project_id=self.project.id
@@ -660,7 +664,7 @@ def test_ratelimit(self):
660664

661665

662666
class GroupDeleteTest(APITestCase):
663-
def test_delete(self):
667+
def test_delete_deferred(self):
664668
self.login_as(user=self.user)
665669

666670
group = self.create_group()
@@ -679,6 +683,13 @@ def test_delete(self):
679683

680684
Group.objects.filter(id=group.id).update(status=GroupStatus.UNRESOLVED)
681685

686+
def test_delete_and_tasks_run(self):
687+
self.login_as(user=self.user)
688+
689+
group = self.create_group()
690+
hash = "x" * 32
691+
GroupHash.objects.create(project=group.project, hash=hash, group=group)
692+
682693
url = f"/api/0/issues/{group.id}/"
683694

684695
with self.tasks():
@@ -689,6 +700,15 @@ def test_delete(self):
689700
# Now we killed everything with fire
690701
assert not Group.objects.filter(id=group.id).exists()
691702
assert not GroupHash.objects.filter(group_id=group.id).exists()
703+
with self.tasks(), outbox_runner():
704+
schedule_hybrid_cloud_foreign_key_jobs()
705+
with assume_test_silo_mode(SiloMode.CONTROL):
706+
assert (
707+
AuditLogEntry.objects.get(
708+
event=audit_log.get_event_id("ISSUE_DELETE"),
709+
).data["issue_id"]
710+
== group.id
711+
)
692712

693713
def test_delete_performance_issue(self):
694714
"""Test that a performance issue cannot be deleted"""

tests/sentry/audit_log/test_register.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ def test_get_api_names(self):
8888
"org-auth-token.remove",
8989
"project-team.remove",
9090
"project-team.add",
91+
"issue.delete",
9192
]
9293

9394
assert set(audit_log.get_api_names()) == set(audit_log_api_name_list)

0 commit comments

Comments
 (0)