Skip to content

Commit a464390

Browse files
authored
chore(audit): date filtering for audit logs endpoint (#93470)
1 parent cbbdf2c commit a464390

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

src/sentry/api/endpoints/organization_auditlogs.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from sentry.api.bases.organization import OrganizationAuditPermission
1111
from sentry.api.paginator import DateTimePaginator
1212
from sentry.api.serializers import serialize
13+
from sentry.api.utils import get_date_range_from_stats_period
1314
from sentry.audit_log.manager import AuditLogEventNotRegistered
1415
from sentry.db.models.fields.bounded import BoundedIntegerField
1516
from sentry.models.auditlogentry import AuditLogEntry
@@ -20,9 +21,11 @@
2021

2122

2223
class AuditLogQueryParamSerializer(serializers.Serializer):
23-
2424
event = serializers.CharField(required=False)
2525
actor = serializers.IntegerField(required=False, max_value=BoundedIntegerField.MAX_VALUE)
26+
start = serializers.DateTimeField(required=False)
27+
end = serializers.DateTimeField(required=False)
28+
statsPeriod = serializers.CharField(required=False)
2629

2730
def validate_event(self, event):
2831
try:
@@ -65,6 +68,11 @@ def get(
6568
else:
6669
queryset = queryset.filter(event=query["event"])
6770

71+
# Handle date filtering
72+
start, end = get_date_range_from_stats_period(request.GET, optional=True)
73+
if start and end:
74+
queryset = queryset.filter(datetime__range=(start, end))
75+
6876
response = self.paginate(
6977
request=request,
7078
queryset=queryset,

tests/sentry/api/endpoints/test_organization_auditlogs.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,59 @@ def test_superuser_read_write_can_see_audit_logs(self):
196196

197197
self.add_user_permission(superuser, "superuser.write")
198198
self.get_success_response(self.organization.slug)
199+
200+
def test_filter_by_date(self):
201+
now = timezone.now()
202+
203+
entry1 = AuditLogEntry.objects.create(
204+
organization_id=self.organization.id,
205+
event=audit_log.get_event_id("ORG_EDIT"),
206+
actor=self.user,
207+
datetime=now - timedelta(days=1),
208+
)
209+
AuditLogEntry.objects.create(
210+
organization_id=self.organization.id,
211+
event=audit_log.get_event_id("ORG_ADD"),
212+
actor=self.user,
213+
datetime=now,
214+
)
215+
216+
start_time = now - timedelta(days=1)
217+
end_time = now - timedelta(hours=1)
218+
219+
response = self.get_success_response(
220+
self.organization.slug,
221+
qs_params={
222+
"event": "org.edit",
223+
"start": start_time.isoformat(),
224+
"end": end_time.isoformat(),
225+
},
226+
)
227+
assert len(response.data["rows"]) == 1
228+
assert response.data["rows"][0]["id"] == str(entry1.id)
229+
230+
def test_filter_by_stats_period(self):
231+
now = timezone.now()
232+
233+
# old entry
234+
AuditLogEntry.objects.create(
235+
organization_id=self.organization.id,
236+
event=audit_log.get_event_id("ORG_EDIT"),
237+
actor=self.user,
238+
datetime=now - timedelta(days=2),
239+
)
240+
241+
recent_entry = AuditLogEntry.objects.create(
242+
organization_id=self.organization.id,
243+
event=audit_log.get_event_id("ORG_ADD"),
244+
actor=self.user,
245+
datetime=now - timedelta(hours=12),
246+
)
247+
248+
response = self.get_success_response(
249+
self.organization.slug, qs_params={"statsPeriod": "1d"}
250+
)
251+
252+
# Should only return the recent entry, not the old one
253+
assert len(response.data["rows"]) == 1
254+
assert response.data["rows"][0]["id"] == str(recent_entry.id)

0 commit comments

Comments
 (0)