Serialize History and expose to API
This commit is contained in:
parent
73362b69c6
commit
ce4602018b
|
@ -131,10 +131,11 @@ class MetaInfo(models.Model):
|
|||
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')
|
||||
history = GenericForeignKey('content_type', 'object_id')
|
||||
|
||||
owner_id = models.PositiveIntegerField()
|
||||
owner_name = models.TextField()
|
||||
object_name = models.TextField()
|
||||
history_user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
|
||||
history_date = models.DateTimeField()
|
||||
history_type = models.TextField()
|
||||
|
|
|
@ -41,6 +41,13 @@ class ReadOnly(BasePermission):
|
|||
def has_object_permission(self, request, view, obj):
|
||||
return bool(request.method in SAFE_METHODS)
|
||||
|
||||
class IsAdmin(BasePermission):
|
||||
def has_permission(self, request, view):
|
||||
return bool(
|
||||
request.user
|
||||
and is_admin_director(request.user)
|
||||
)
|
||||
|
||||
class IsAdminOrReadOnly(BasePermission):
|
||||
def has_permission(self, request, view):
|
||||
return bool(
|
||||
|
|
|
@ -396,3 +396,17 @@ class MyPasswordChangeSerializer(PasswordChangeSerializer):
|
|||
raise ValidationError(dict(non_field_errors='Problem connecting to LDAP server: set.'))
|
||||
|
||||
super().save()
|
||||
|
||||
|
||||
class HistoryChangeSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = models.HistoryChange
|
||||
fields = ['field', 'old', 'new']
|
||||
|
||||
class HistorySerializer(serializers.ModelSerializer):
|
||||
changes = HistoryChangeSerializer(many=True)
|
||||
history_user = serializers.StringRelatedField()
|
||||
|
||||
class Meta:
|
||||
model = models.HistoryIndex
|
||||
fields = '__all__'
|
||||
|
|
|
@ -10,6 +10,9 @@ from .permissions import is_admin_director
|
|||
def get_object_owner(obj):
|
||||
full_name = lambda member: member.first_name + ' ' + member.last_name
|
||||
|
||||
if obj.__class__.__name__ == 'Member':
|
||||
return full_name(obj), obj.id
|
||||
|
||||
if getattr(obj, 'user', False):
|
||||
return full_name(obj.user.member), obj.user.member.id
|
||||
|
||||
|
@ -35,27 +38,45 @@ def post_create_historical_record_callback(
|
|||
using,
|
||||
**kwargs):
|
||||
|
||||
changes = history_instance.diff_against(history_instance.prev_record).changes
|
||||
history_type = history_instance.get_history_type_display()
|
||||
object_name = instance.__class__.__name__
|
||||
|
||||
if changes:
|
||||
if object_name in ['User']: return
|
||||
|
||||
if history_type == 'Changed':
|
||||
changes = history_instance.diff_against(history_instance.prev_record).changes
|
||||
else:
|
||||
changes = []
|
||||
|
||||
# it's possible for changes to be empty if model saved with no diff
|
||||
if changes or history_type in ['Created', 'Deleted']:
|
||||
owner = get_object_owner(instance)
|
||||
|
||||
index = models.HistoryIndex.objects.create(
|
||||
content_object=history_instance,
|
||||
owner_name=owner[0],
|
||||
history=history_instance,
|
||||
owner_id=owner[1],
|
||||
owner_name=owner[0],
|
||||
object_name=object_name,
|
||||
history_user=history_user,
|
||||
history_date=history_instance.history_date,
|
||||
history_type=history_instance.get_history_type_display(),
|
||||
history_type=history_type,
|
||||
revert_url=history_instance.revert_url(),
|
||||
is_system=bool(history_user == None),
|
||||
is_admin=is_admin_director(history_user),
|
||||
)
|
||||
|
||||
change_old = change.old or ''
|
||||
change_new = change.new or ''
|
||||
|
||||
if len(change_old) > 200:
|
||||
change_old = change_old[:200] + '... [truncated]'
|
||||
if len(change_new) > 200:
|
||||
change_new = change_new[:200] + '... [truncated]'
|
||||
|
||||
for change in changes:
|
||||
models.HistoryChange.objects.create(
|
||||
index=index,
|
||||
field=change.field,
|
||||
old=change.old,
|
||||
new=change.new,
|
||||
old=change_old,
|
||||
new=change_new,
|
||||
)
|
||||
|
|
|
@ -23,6 +23,7 @@ from .permissions import (
|
|||
IsObjOwnerOrAdmin,
|
||||
IsSessionInstructorOrAdmin,
|
||||
ReadOnly,
|
||||
IsAdmin,
|
||||
IsAdminOrReadOnly,
|
||||
IsInstructorOrReadOnly
|
||||
)
|
||||
|
@ -413,6 +414,12 @@ class PasteView(views.APIView):
|
|||
raise exceptions.ValidationError(dict(paste='This field is required.'))
|
||||
|
||||
|
||||
class HistoryViewSet(Base, List, Retrieve):
|
||||
permission_classes = [AllowMetadata | IsAdmin]
|
||||
serializer_class = serializers.HistorySerializer
|
||||
queryset = models.HistoryIndex.objects.order_by('-history_date')
|
||||
|
||||
|
||||
class RegistrationView(RegisterView):
|
||||
serializer_class = serializers.MyRegisterSerializer
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ router.register(r'stats', views.StatsViewSet, basename='stats')
|
|||
router.register(r'search', views.SearchViewSet, basename='search')
|
||||
router.register(r'members', views.MemberViewSet, basename='members')
|
||||
router.register(r'courses', views.CourseViewSet, basename='course')
|
||||
router.register(r'history', views.HistoryViewSet, basename='history')
|
||||
router.register(r'sessions', views.SessionViewSet, basename='session')
|
||||
router.register(r'training', views.TrainingViewSet, basename='training')
|
||||
router.register(r'transactions', views.TransactionViewSet, basename='transaction')
|
||||
|
|
Loading…
Reference in New Issue
Block a user