mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-06-21 01:48:21 +02:00
Logging support
This commit is contained in:
4
apps/api/__init__.py
Normal file
4
apps/api/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
default_app_config = 'api.apps.APIConfig'
|
10
apps/api/apps.py
Normal file
10
apps/api/apps.py
Normal file
@ -0,0 +1,10 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class APIConfig(AppConfig):
|
||||
name = 'api'
|
||||
verbose_name = _('API')
|
4
apps/logs/__init__.py
Normal file
4
apps/logs/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
default_app_config = 'logs.apps.LogsConfig'
|
14
apps/logs/apps.py
Normal file
14
apps/logs/apps.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class LogsConfig(AppConfig):
|
||||
name = 'logs'
|
||||
verbose_name = _('Logs')
|
||||
|
||||
def ready(self):
|
||||
# noinspection PyUnresolvedReferences
|
||||
import logs.signals
|
63
apps/logs/models.py
Normal file
63
apps/logs/models.py
Normal file
@ -0,0 +1,63 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Changelog(models.Model):
|
||||
"""
|
||||
Store each modification on the database (except sessions and logging),
|
||||
including creating, editing and deleting models.
|
||||
"""
|
||||
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.PROTECT,
|
||||
null=True,
|
||||
verbose_name=_('user'),
|
||||
)
|
||||
|
||||
model = models.CharField(
|
||||
max_length=255,
|
||||
null=False,
|
||||
blank=False,
|
||||
verbose_name=_('model'),
|
||||
)
|
||||
|
||||
instance_pk = models.CharField(
|
||||
max_length=255,
|
||||
null=False,
|
||||
blank=False,
|
||||
verbose_name=_('identifier'),
|
||||
)
|
||||
|
||||
previous = models.TextField(
|
||||
null=True,
|
||||
verbose_name=_('previous data'),
|
||||
)
|
||||
|
||||
data = models.TextField(
|
||||
null=True,
|
||||
verbose_name=_('new data'),
|
||||
)
|
||||
|
||||
action = models.CharField( # create, edit or delete
|
||||
max_length=16,
|
||||
null=False,
|
||||
blank=False,
|
||||
verbose_name=_('action'),
|
||||
)
|
||||
|
||||
timestamp = models.DateTimeField(
|
||||
null=False,
|
||||
blank=False,
|
||||
auto_now_add=True,
|
||||
name='timestamp',
|
||||
verbose_name=_('timestamp'),
|
||||
)
|
||||
|
||||
def delete(self, using=None, keep_parents=False):
|
||||
raise ValidationError(_("Logs cannot be destroyed."))
|
68
apps/logs/signals.py
Normal file
68
apps/logs/signals.py
Normal file
@ -0,0 +1,68 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import inspect
|
||||
|
||||
from django.core import serializers
|
||||
from django.db.models.signals import pre_save, pre_delete
|
||||
from django.dispatch import receiver
|
||||
from .models import Changelog
|
||||
|
||||
|
||||
def get_user_in_signal(sender, **kwargs):
|
||||
user = None
|
||||
for entry in reversed(inspect.stack()):
|
||||
try:
|
||||
user = entry[0].f_locals['request'].user
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
if not user:
|
||||
print("WARNING: Attempt to save " + str(sender) + " with no user")
|
||||
|
||||
return user
|
||||
|
||||
EXCLUDED = [
|
||||
'Changelog',
|
||||
'Migration',
|
||||
'Session',
|
||||
]
|
||||
|
||||
@receiver(pre_save)
|
||||
def save_object(sender, instance, **kwargs):
|
||||
model_name = sender.__name__
|
||||
if model_name in EXCLUDED:
|
||||
return
|
||||
|
||||
previous = sender.objects.filter(pk=instance.pk).all()
|
||||
|
||||
user = get_user_in_signal(sender, **kwargs)
|
||||
if previous.exists:
|
||||
previous_json = serializers.serialize('json', previous)[1:-1]
|
||||
else:
|
||||
previous_json = None
|
||||
instance_json = serializers.serialize('json', [instance, ],)[1:-1]
|
||||
Changelog.objects.create(user=user,
|
||||
model=model_name,
|
||||
instance_pk=instance.pk,
|
||||
previous=previous_json,
|
||||
data=instance_json,
|
||||
action=("edit" if previous.exists() else "create")
|
||||
)#.save()
|
||||
|
||||
@receiver(pre_delete)
|
||||
def delete_object(sender, instance, **kwargs):
|
||||
model_name = sender.__name__
|
||||
if model_name in EXCLUDED:
|
||||
return
|
||||
|
||||
user = get_user_in_signal(sender, **kwargs)
|
||||
instance_json = serializers.serialize('json', [instance, ])[1:-1]
|
||||
Changelog.objects.create(user=user,
|
||||
model=model_name,
|
||||
instance_pk=instance.pk,
|
||||
previous=instance_json,
|
||||
data=None,
|
||||
action="delete"
|
||||
).save()
|
8
apps/logs/urls.py
Normal file
8
apps/logs/urls.py
Normal file
@ -0,0 +1,8 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
app_name = 'logs'
|
||||
|
||||
# TODO User interface
|
||||
urlpatterns = [
|
||||
]
|
Reference in New Issue
Block a user