Coverage for sm/views_audit.py: 93%

45 statements  

« prev     ^ index     » next       coverage.py v7.17.0, created at 2026-10-24 19:06 +0000

1from django.contrib.auth.mixins import LoginRequiredMixin 

2from django.db.models import Q 

3from django.views.generic import ListView 

4from typing import Any 

5 

6from .utils_permissions import APP_MODELS 

7 

8 

9class AuditLogView(LoginRequiredMixin, ListView): 

10 """ 

11 Per-tenant audit log: lists history records across all core models, 

12 filtered by the user's groups (or a specific selected group). 

13 """ 

14 

15 template_name = "audit_log.html" 

16 context_object_name = "entries" 

17 paginate_by = 50 

18 

19 def get_group(self): 

20 group_id = self.request.GET.get("group") 

21 if not group_id or not group_id.isdigit(): 

22 return None 

23 return int(group_id) 

24 

25 def get_queryset(self): 

26 user = self.request.user 

27 group_filter = self.get_group() 

28 

29 entries = [] 

30 for app_label, _model_name in APP_MODELS: 

31 try: 

32 from django.apps import apps 

33 

34 model = apps.get_model(app_label, "Model") 

35 except LookupError: 

36 continue 

37 if not hasattr(model, "history"): 

38 continue 

39 

40 qs = model.history.all() 

41 if not user.is_superuser: 

42 user_groups = user.groups.all() 

43 qs = qs.filter(Q(group_id__in=user_groups) | Q(group_id__isnull=True)) 

44 if group_filter: 

45 qs = qs.filter(group_id=group_filter) 

46 

47 for record in qs.select_related("history_user")[:100]: 

48 entries.append( 

49 { 

50 "date": record.history_date, 

51 "user": ( 

52 record.history_user 

53 if getattr(record, "history_user_id", None) 

54 else None 

55 ), 

56 "user_id": getattr(record, "history_user_id", None), 

57 "action": record.history_type, 

58 "model": model._meta.verbose_name, 

59 "object": record, 

60 "group_id": getattr(record, "group_id", None), 

61 "group_name": ( 

62 record.group.name 

63 if getattr(record, "group_id", None) and record.group_id 

64 else None 

65 ), 

66 } 

67 ) 

68 

69 entries.sort(key=lambda e: e["date"], reverse=True) 

70 return entries 

71 

72 def get_context_data(self, **kwargs: Any) -> Any: 

73 context = super().get_context_data(**kwargs) 

74 user = self.request.user 

75 if user.is_superuser: 

76 from django.contrib.auth.models import Group 

77 

78 context["groups"] = Group.objects.all() 

79 else: 

80 context["groups"] = user.groups.all() 

81 context["selected_group"] = self.get_group() 

82 return context