Skip to content

Commit 39e133f

Browse files
committed
Allow non-superuser DREF3 queries also + unit test chg
1 parent 5991b9d commit 39e133f

File tree

2 files changed

+72
-9
lines changed

2 files changed

+72
-9
lines changed

dref/test_views.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1806,4 +1806,6 @@ def test_superuser_can_access_list(self):
18061806
def test_normal_user_cannot_access_list(self):
18071807
self.client.force_authenticate(user=self.user)
18081808
response = self.client.get(self.url)
1809-
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
1809+
# self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
1810+
# New decision: normal users can access but see fewer records
1811+
self.assertEqual(response.status_code, status.HTTP_200_OK)

dref/views.py

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import django.utils.timezone as timezone
2+
from django.apps import apps
23
from django.contrib.auth.models import Permission
34
from django.db import models
45
from django.templatetags.static import static
@@ -41,7 +42,7 @@
4142
DrefShareUserSerializer,
4243
MiniDrefSerializer,
4344
)
44-
from main.permissions import DenyGuestUserPermission, UseBySuperAdminOnly
45+
from main.permissions import DenyGuestUserPermission
4546

4647

4748
def filter_dref_queryset_by_user_access(user, queryset):
@@ -284,15 +285,32 @@ def get_queryset(self):
284285

285286

286287
class Dref3ViewSet(RevisionMixin, viewsets.ModelViewSet):
287-
permission_classes = [permissions.IsAuthenticated, DenyGuestUserPermission, UseBySuperAdminOnly]
288-
# serializer_class = DrefSerializer
289-
# filterset_class = DrefFilter
288+
# Allow unauthenticated access; we'll filter published-only for anonymous users below
289+
permission_classes = [permissions.AllowAny]
290+
# Previous: [permissions.IsAuthenticated, DenyGuestUserPermission, UseBySuperAdminOnly]
290291
lookup_field = "appeal_code"
291292

292293
def get_queryset(self):
293294
# just to give something to rest_framework/generics.py:63 – not used in retrieve
294295
return Dref.objects.none()
295296

297+
def get_nonsuperusers_excluded_codes(self):
298+
"""Return a set of appeal_codes that should be hidden from non-superusers.
299+
Accepts CSV values in AppealFilter.value like "MDRXX019,MDRYY036".
300+
"""
301+
try:
302+
AppealFilter = apps.get_model("api", "AppealFilter")
303+
codes = list(AppealFilter.objects.values_list("value", flat=True))
304+
except Exception:
305+
# If model/app not available, fail open (no extra exclusions)
306+
return set()
307+
excluded = set()
308+
for code in codes:
309+
c = code.strip().upper()
310+
if c:
311+
excluded.add(c)
312+
return excluded
313+
296314
def list(self, request):
297315
# === First approach – would be nice to work like this, but recent definitons are more complex than that:
298316
# # Aggregate all appeal-codes from the three models
@@ -335,11 +353,21 @@ def list(self, request):
335353

336354
codes = list(codes_qs)
337355

356+
# Exclude codes for non-superusers
357+
if not getattr(self.request.user, "is_superuser", False):
358+
excluded_codes = self.get_nonsuperusers_excluded_codes()
359+
if excluded_codes:
360+
codes = [c for c in codes if c and c.upper() not in excluded_codes]
361+
338362
data = []
339363
old_kwargs = getattr(self, "kwargs", {}).copy()
340364
for code in codes:
341365
self.kwargs = {self.lookup_field: code}
342-
resp = self.retrieve(request)
366+
try:
367+
resp = self.retrieve(request)
368+
except NotFound:
369+
# Skip codes that have no visible records for this user
370+
continue
343371
if resp.status_code == 200:
344372
for item in resp.data if isinstance(resp.data, list) else [resp.data]:
345373
data.append(item)
@@ -356,6 +384,42 @@ def get_serializer_class(self):
356384
def get_objects_by_appeal_code(self, appeal_code):
357385
results = []
358386
user = self.request.user
387+
388+
if not getattr(user, "is_superuser", False):
389+
# If code is in the excluded list, return no results for anonymous users
390+
excluded_codes = self.get_nonsuperusers_excluded_codes()
391+
if appeal_code and appeal_code.upper() in excluded_codes:
392+
return []
393+
# Light users: only published records are visible
394+
drefs = (
395+
Dref.objects.filter(appeal_code=appeal_code, is_published=True)
396+
.prefetch_related("planned_interventions", "needs_identified", "national_society_actions", "users")
397+
.order_by("created_at")
398+
.distinct()
399+
)
400+
if drefs.exists():
401+
results.extend(drefs)
402+
403+
operational_updates = (
404+
DrefOperationalUpdate.objects.filter(appeal_code=appeal_code, is_published=True)
405+
.prefetch_related("planned_interventions", "needs_identified", "national_society_actions", "users")
406+
.order_by("created_at")
407+
.distinct()
408+
)
409+
if operational_updates.exists():
410+
results.extend(operational_updates)
411+
412+
final_reports = (
413+
DrefFinalReport.objects.filter(appeal_code=appeal_code, is_published=True)
414+
.prefetch_related("planned_interventions", "needs_identified", "national_society_actions", "users")
415+
.order_by("created_at")
416+
.distinct()
417+
)
418+
if final_reports.exists():
419+
results.extend(final_reports)
420+
return results
421+
422+
# Strong users: allow more access
359423
drefs = (
360424
Dref.objects.filter(appeal_code=appeal_code)
361425
.prefetch_related("planned_interventions", "needs_identified", "national_society_actions", "users")
@@ -366,7 +430,6 @@ def get_objects_by_appeal_code(self, appeal_code):
366430
if drefs.exists():
367431
results.extend(drefs)
368432

369-
# Code duplication of the previous "drefs" for "operational_updates" and "final_reports" until ¤¤¤:
370433
operational_updates = (
371434
DrefOperationalUpdate.objects.filter(appeal_code=appeal_code)
372435
.prefetch_related("planned_interventions", "needs_identified", "national_society_actions", "users")
@@ -386,8 +449,6 @@ def get_objects_by_appeal_code(self, appeal_code):
386449
final_reports = filter_dref_queryset_by_user_access(user, final_reports)
387450
if final_reports.exists():
388451
results.extend(final_reports)
389-
# ¤¤¤
390-
391452
return results
392453

393454
def retrieve(self, request, *args, **kwargs):

0 commit comments

Comments
 (0)