From 73362b69c6dd276a2c672976dd50fd6a3b0484b2 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Mon, 24 Feb 2020 23:49:14 +0000 Subject: [PATCH] Create an index of all history changes --- apiserver/apiserver/api/__init__.py | 1 + apiserver/apiserver/api/apps.py | 5 ++- apiserver/apiserver/api/models.py | 24 ++++++++++ apiserver/apiserver/api/permissions.py | 3 ++ apiserver/apiserver/api/signals.py | 61 ++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 apiserver/apiserver/api/signals.py diff --git a/apiserver/apiserver/api/__init__.py b/apiserver/apiserver/api/__init__.py index e69de29..1e78b81 100644 --- a/apiserver/apiserver/api/__init__.py +++ b/apiserver/apiserver/api/__init__.py @@ -0,0 +1 @@ +default_app_config = 'apiserver.api.apps.ApiConfig' diff --git a/apiserver/apiserver/api/apps.py b/apiserver/apiserver/api/apps.py index d87006d..1f1ea97 100644 --- a/apiserver/apiserver/api/apps.py +++ b/apiserver/apiserver/api/apps.py @@ -2,4 +2,7 @@ from django.apps import AppConfig class ApiConfig(AppConfig): - name = 'api' + name = 'apiserver.api' + + def ready(self): + from . import signals diff --git a/apiserver/apiserver/api/models.py b/apiserver/apiserver/api/models.py index be46722..5508a91 100644 --- a/apiserver/apiserver/api/models.py +++ b/apiserver/apiserver/api/models.py @@ -1,6 +1,8 @@ from datetime import date, datetime from django.db import models from django.contrib.auth.models import User +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType from django.utils.timezone import now, pytz from simple_history.models import HistoricalRecords from simple_history import register @@ -125,3 +127,25 @@ class Training(models.Model): class MetaInfo(models.Model): backup_id = models.TextField() + +class HistoryIndex(models.Model): + content_type = models.ForeignKey(ContentType, null=True, on_delete=models.SET_NULL) + object_id = models.PositiveIntegerField() + content_object = GenericForeignKey('content_type', 'object_id') + + owner_id = models.PositiveIntegerField() + owner_name = models.TextField() + history_user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL) + history_date = models.DateTimeField() + history_type = models.TextField() + revert_url = models.TextField() + + is_system = models.BooleanField() + is_admin = models.BooleanField() + +class HistoryChange(models.Model): + index = models.ForeignKey(HistoryIndex, related_name='changes', null=True, on_delete=models.SET_NULL) + + field = models.TextField() + old = models.TextField() + new = models.TextField() diff --git a/apiserver/apiserver/api/permissions.py b/apiserver/apiserver/api/permissions.py index bde5278..452c865 100644 --- a/apiserver/apiserver/api/permissions.py +++ b/apiserver/apiserver/api/permissions.py @@ -5,6 +5,9 @@ class AllowMetadata(BasePermission): return request.method in ['OPTIONS', 'HEAD'] def is_admin_director(user): + if not user: + return False + if user.is_staff: return True diff --git a/apiserver/apiserver/api/signals.py b/apiserver/apiserver/api/signals.py new file mode 100644 index 0000000..11f9ad1 --- /dev/null +++ b/apiserver/apiserver/api/signals.py @@ -0,0 +1,61 @@ +from django.dispatch import receiver +from simple_history.signals import ( + pre_create_historical_record, + post_create_historical_record +) + +from . import models +from .permissions import is_admin_director + +def get_object_owner(obj): + full_name = lambda member: member.first_name + ' ' + member.last_name + + if getattr(obj, 'user', False): + return full_name(obj.user.member), obj.user.member.id + + if getattr(obj, 'instructor', False): + return full_name(obj.instructor.member), obj.instructor.member.id + + if getattr(obj, 'member_id', False): + try: + member = models.Member.objects.get(id=obj.member_id) + return full_name(member), member.id + except models.Member.DoesNotExist: + pass + + return 'Protospace', 0 + +@receiver(post_create_historical_record, dispatch_uid='create_hist') +def post_create_historical_record_callback( + sender, + instance, + history_instance, + history_change_reason, + history_user, + using, + **kwargs): + + changes = history_instance.diff_against(history_instance.prev_record).changes + + if changes: + owner = get_object_owner(instance) + + index = models.HistoryIndex.objects.create( + content_object=history_instance, + owner_name=owner[0], + owner_id=owner[1], + history_user=history_user, + history_date=history_instance.history_date, + history_type=history_instance.get_history_type_display(), + revert_url=history_instance.revert_url(), + is_system=bool(history_user == None), + is_admin=is_admin_director(history_user), + ) + + for change in changes: + models.HistoryChange.objects.create( + index=index, + field=change.field, + old=change.old, + new=change.new, + )