Skip to content

Commit

Permalink
Prevent exposing Django Admin features referencing media tables in pr…
Browse files Browse the repository at this point in the history
…od (#4349)
  • Loading branch information
AetherUnbound committed May 17, 2024
1 parent bc457c0 commit 0dbe130
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 6 deletions.
6 changes: 4 additions & 2 deletions api/api/admin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.conf import settings
from django.contrib import admin
from django.contrib.auth.admin import GroupAdmin, UserAdmin
from django.contrib.auth.models import Group, User
Expand Down Expand Up @@ -55,8 +56,9 @@
admin.site.register(klass, MediaSubreportAdmin)

# Temporary addition of model admin for decisions while this view gets built
admin.site.register(ImageDecision, admin.ModelAdmin)
admin.site.register(AudioDecision, admin.ModelAdmin)
if settings.ENVIRONMENT != "production":
admin.site.register(ImageDecision, admin.ModelAdmin)
admin.site.register(AudioDecision, admin.ModelAdmin)


@admin.register(ContentProvider)
Expand Down
23 changes: 19 additions & 4 deletions api/api/admin/media_report.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Sequence

from django.conf import settings
from django.contrib import admin
from django.contrib.admin.views.main import ChangeList
Expand All @@ -17,6 +19,20 @@
logger = structlog.get_logger(__name__)


def _production_deferred(*values: str) -> Sequence[str]:
"""
Define a sequence in all environment except production.
The autocomplete/search queries in Django are woefully unoptimized for massive
tables, and so enabling certain utility features in production will often incur
a significant performance hit or outage. This will return the input values except
when the environment is production, in which case it will return an empty sequence.
"""
if settings.ENVIRONMENT == "production":
return ()
return values


class PredeterminedOrderChangelist(ChangeList):
"""
ChangeList class which does not apply any default ordering to the items.
Expand Down Expand Up @@ -65,8 +81,7 @@ class MediaListAdmin(admin.ModelAdmin):
list_filter = (PendingRecordCountFilter,)
# Disable link display for images
list_display_links = None
# Allow autocomplete to work from other referenced fields
search_fields = ("identifier",)
search_fields = _production_deferred("identifier")
media_type = None
# Ordering is not set here, see get_queryset

Expand Down Expand Up @@ -128,8 +143,8 @@ class MediaReportAdmin(admin.ModelAdmin):
)
list_display_links = ("id",)
list_select_related = ("media_obj",)
search_fields = ("description", "media_obj__identifier")
autocomplete_fields = ("media_obj",)
search_fields = _production_deferred("description", "media_obj__identifier")
autocomplete_fields = _production_deferred("media_obj")
actions = None
media_type = None

Expand Down
21 changes: 21 additions & 0 deletions api/test/unit/admin/test_media_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from unittest import mock

import pytest

from api.admin.media_report import _production_deferred


@pytest.mark.parametrize(
"values, environment, expected",
[
([1, 2, 3], "local", (1, 2, 3)),
([1, 2, 3], "production", ()),
([], "local", ()),
([], "production", ()),
],
)
def test_production_deferred(values, environment, expected):
with mock.patch("api.admin.media_report.settings") as mock_settings:
mock_settings.ENVIRONMENT = environment
actual = _production_deferred(*values)
assert actual == expected

0 comments on commit 0dbe130

Please sign in to comment.