11import django .utils .timezone as timezone
2+ from django .apps import apps
23from django .contrib .auth .models import Permission
34from django .db import models
45from django .templatetags .static import static
4142 DrefShareUserSerializer ,
4243 MiniDrefSerializer ,
4344)
44- from main .permissions import DenyGuestUserPermission , UseBySuperAdminOnly
45+ from main .permissions import DenyGuestUserPermission
4546
4647
4748def filter_dref_queryset_by_user_access (user , queryset ):
@@ -284,15 +285,32 @@ def get_queryset(self):
284285
285286
286287class 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