Logging support

This commit is contained in:
Yohann D'ANELLO 2020-02-24 18:18:44 +01:00
parent c8dd41c1d7
commit fd529a53c8
11 changed files with 279 additions and 19 deletions

4
apps/api/__init__.py Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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 = [
]

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-02-21 13:50+0100\n"
"POT-Creation-Date: 2020-02-24 17:15+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -82,6 +82,46 @@ msgstr ""
msgid "guests"
msgstr ""
#: apps/api/apps.py:10
msgid "API"
msgstr ""
#: apps/logs/apps.py:10
msgid "Logs"
msgstr ""
#: apps/logs/models.py:20 apps/note/models/notes.py:105
msgid "user"
msgstr ""
#: apps/logs/models.py:27
msgid "model"
msgstr ""
#: apps/logs/models.py:34
msgid "identifier"
msgstr ""
#: apps/logs/models.py:39
msgid "previous data"
msgstr ""
#: apps/logs/models.py:44
msgid "new data"
msgstr ""
#: apps/logs/models.py:51
msgid "action"
msgstr ""
#: apps/logs/models.py:59
msgid "timestamp"
msgstr ""
#: apps/logs/models.py:63
msgid "Logs cannot be destroyed."
msgstr ""
#: apps/member/apps.py:10
msgid "member"
msgstr ""
@ -244,10 +284,6 @@ msgstr ""
msgid "This alias is already taken."
msgstr ""
#: apps/note/models/notes.py:105
msgid "user"
msgstr ""
#: apps/note/models/notes.py:109
msgid "one's note"
msgstr ""
@ -358,15 +394,19 @@ msgstr ""
msgid "Transfer money from your account to one or others"
msgstr ""
#: note_kfet/settings/base.py:148
msgid "German"
msgstr ""
#: note_kfet/settings/base.py:149
msgid "English"
#: apps/note/views.py:143
msgid "Consommations"
msgstr ""
#: note_kfet/settings/base.py:150
msgid "German"
msgstr ""
#: note_kfet/settings/base.py:151
msgid "English"
msgstr ""
#: note_kfet/settings/base.py:152
msgid "French"
msgstr ""

View File

@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-02-21 13:50+0100\n"
"POT-Creation-Date: 2020-02-24 17:15+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -77,6 +77,50 @@ msgstr "invité"
msgid "guests"
msgstr "invités"
#: apps/api/apps.py:10
msgid "API"
msgstr ""
#: apps/logs/apps.py:10
msgid "Logs"
msgstr ""
#: apps/logs/models.py:20 apps/note/models/notes.py:105
msgid "user"
msgstr "utilisateur"
#: apps/logs/models.py:27
msgid "model"
msgstr "Modèle"
#: apps/logs/models.py:34
msgid "identifier"
msgstr "Identifiant"
#: apps/logs/models.py:39
msgid "previous data"
msgstr "Données précédentes"
#: apps/logs/models.py:44
#, fuzzy
#| msgid "end date"
msgid "new data"
msgstr "Nouvelles données"
#: apps/logs/models.py:51
#, fuzzy
#| msgid "section"
msgid "action"
msgstr "Action"
#: apps/logs/models.py:59
msgid "timestamp"
msgstr "Date"
#: apps/logs/models.py:63
msgid "Logs cannot be destroyed."
msgstr "Les logs ne peuvent pas être détruits."
#: apps/member/apps.py:10
msgid "member"
msgstr "adhérent"
@ -244,10 +288,6 @@ msgstr "Note"
msgid "This alias is already taken."
msgstr "Cet alias est déjà pris."
#: apps/note/models/notes.py:105
msgid "user"
msgstr "utilisateur"
#: apps/note/models/notes.py:109
msgid "one's note"
msgstr "note d'un utilisateur"
@ -358,15 +398,21 @@ msgstr "transactions d'adhésion"
msgid "Transfer money from your account to one or others"
msgstr "Transfert d'argent de ton compte vers un ou plusieurs autres"
#: note_kfet/settings/base.py:148
#: apps/note/views.py:143
#, fuzzy
#| msgid "transactions"
msgid "Consommations"
msgstr "transactions"
#: note_kfet/settings/base.py:150
msgid "German"
msgstr ""
#: note_kfet/settings/base.py:149
#: note_kfet/settings/base.py:151
msgid "English"
msgstr ""
#: note_kfet/settings/base.py:150
#: note_kfet/settings/base.py:152
msgid "French"
msgstr ""

View File

@ -61,6 +61,7 @@ INSTALLED_APPS = [
'member',
'note',
'api',
'logs',
]
LOGIN_REDIRECT_URL = '/note/transfer/'

View File

@ -21,4 +21,6 @@ urlpatterns = [
# Include Django REST API
path('api/', include('api.urls')),
path('logs/', include('logs.urls')),
]