From 4de8dcd29affa173671f280c6e0949d1a163f43a Mon Sep 17 00:00:00 2001 From: Paul Marillonnet Date: Wed, 31 Oct 2018 16:04:36 +0100 Subject: [PATCH] WIP add journal application (#20695) --- MANIFEST.in | 2 ++ setup.py | 1 + src/authentic2/settings.py | 1 + src/authentic2_journal/__init__.py | 9 ++++++ src/authentic2_journal/admin.py | 0 src/authentic2_journal/apps.py | 8 ++++++ src/authentic2_journal/event_logger.py | 17 +++++++++++ src/authentic2_journal/kinds.py | 20 +++++++++++++ src/authentic2_journal/migrations/__init__.py | 0 src/authentic2_journal/models.py | 28 +++++++++++++++++++ src/authentic2_journal/tables.py | 12 ++++++++ .../authentic2_journal/user_events.html | 10 +++++++ src/authentic2_journal/urls.py | 10 +++++++ src/authentic2_journal/utils.py | 20 +++++++++++++ src/authentic2_journal/views.py | 21 ++++++++++++++ 15 files changed, 159 insertions(+) create mode 100644 src/authentic2_journal/__init__.py create mode 100644 src/authentic2_journal/admin.py create mode 100644 src/authentic2_journal/apps.py create mode 100644 src/authentic2_journal/event_logger.py create mode 100644 src/authentic2_journal/kinds.py create mode 100644 src/authentic2_journal/migrations/__init__.py create mode 100644 src/authentic2_journal/models.py create mode 100644 src/authentic2_journal/tables.py create mode 100644 src/authentic2_journal/templates/authentic2_journal/user_events.html create mode 100644 src/authentic2_journal/urls.py create mode 100644 src/authentic2_journal/utils.py create mode 100644 src/authentic2_journal/views.py diff --git a/MANIFEST.in b/MANIFEST.in index b0517243..79bcf8ed 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -22,6 +22,7 @@ recursive-include src/authentic2/manager/templates *.html recursive-include src/authentic2_auth_saml/templates/authentic2_auth_saml *.html recursive-include src/authentic2_auth_oidc/templates/authentic2_auth_oidc *.html recursive-include src/authentic2_idp_oidc/templates/authentic2_idp_oidc *.html +recursive-include src/authentic2_journal/templates/authentic2_journal *.html recursive-include src/authentic2/vendor/totp_js/js *.js recursive-include src/authentic2/saml/fixtures *.json @@ -41,6 +42,7 @@ recursive-include src/django_rbac/locale *.po *.mo recursive-include src/authentic2_auth_saml/locale *.po *.mo recursive-include src/authentic2_auth_oidc/locale *.po *.mo recursive-include src/authentic2_idp_oidc/locale *.po *.mo +recursive-include src/authentic2_journal/locale *.po *.mo recursive-include src/authentic2 README xrds.xml *.txt yadis.xrdf recursive-include src/authentic2_provisionning_ldap/tests *.ldif diff --git a/setup.py b/setup.py index 27bb3c64..a1027688 100755 --- a/setup.py +++ b/setup.py @@ -165,5 +165,6 @@ setup(name="authentic2", 'authentic2-idp-cas = authentic2_idp_cas:Plugin', 'authentic2-idp-oidc = authentic2_idp_oidc:Plugin', 'authentic2-provisionning-ldap = authentic2_provisionning_ldap:Plugin', + 'authentic2-journal = authentic2_journal:Plugin', ], }) diff --git a/src/authentic2/settings.py b/src/authentic2/settings.py index 8c9289a6..0ee122a2 100644 --- a/src/authentic2/settings.py +++ b/src/authentic2/settings.py @@ -126,6 +126,7 @@ INSTALLED_APPS = ( 'authentic2.disco_service', 'authentic2.manager', 'authentic2_provisionning_ldap', + 'authentic2_journal', 'authentic2', 'django_rbac', 'authentic2.a2_rbac', diff --git a/src/authentic2_journal/__init__.py b/src/authentic2_journal/__init__.py new file mode 100644 index 00000000..ceb3ba24 --- /dev/null +++ b/src/authentic2_journal/__init__.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +class Plugin(object): + def get_after_urls(self): + from django.conf.urls import include, url + + return [url(r'^manage/journal/', include(__name__ + '.urls'))] + + def get_apps(self): + return [__name__] diff --git a/src/authentic2_journal/admin.py b/src/authentic2_journal/admin.py new file mode 100644 index 00000000..e69de29b diff --git a/src/authentic2_journal/apps.py b/src/authentic2_journal/apps.py new file mode 100644 index 00000000..a38187f0 --- /dev/null +++ b/src/authentic2_journal/apps.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class Authentic2JournalConfig(AppConfig): + name = 'authentic2_journal' diff --git a/src/authentic2_journal/event_logger.py b/src/authentic2_journal/event_logger.py new file mode 100644 index 00000000..d6622f17 --- /dev/null +++ b/src/authentic2_journal/event_logger.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +from authentic2_journal.models import Line +from authentic2_journal import kinds +from authentic2_journal.utils import (new_line, new_action_reference, + new_modification_reference) + + +def register(user, ou, content=None): + line = new_line(user=user, obj=ou, kind=kinds.ActionRegister, content=content) + new_reference(line, user) + new_reference(line, ou) + + +def create(user, obj, content=None): + line = new_line(user, ou, kinds.ModificationCreate, content) + new_reference(line, user) + new_reference(line, obj) diff --git a/src/authentic2_journal/kinds.py b/src/authentic2_journal/kinds.py new file mode 100644 index 00000000..701ada99 --- /dev/null +++ b/src/authentic2_journal/kinds.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- + +class BaseEvent(object): + pass + + +class BaseAction(BaseEvent): + pass + + +class BaseModification(BaseEvent): + pass + + +class ActionRegister(BaseAction): + pass + + +class ModificationCreate(BaseModification): + pass diff --git a/src/authentic2_journal/migrations/__init__.py b/src/authentic2_journal/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/authentic2_journal/models.py b/src/authentic2_journal/models.py new file mode 100644 index 00000000..56314906 --- /dev/null +++ b/src/authentic2_journal/models.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models +try: + from django.contrib.contenttypes.fields import GenericForeignKey +except ImportError: + from django.contrib.contenttypes.generic import GenericForeignKey +from django.contrib.contenttypes.models import ContentType +from django.utils.translation import ugettext_lazy as _ +from jsonfield import JSONField + +from authentic2_journal import kinds + + +class Line(models.Model): + timestamp = models.DateTimeField(auto_now=True, verbose_name=_('timestamp')) + kind = models.ForeignKey(kinds.BaseEvent) + content = JSONField(blank=True,null=True, verbose_name=_('content')) + + +class Reference(models.Model): + timestamp = models.DateTimeField(auto_now=True, verbose_name=_('timestamp')) + line = models.ForeignKey(Line) + representation = models.TextField(max_length=64) + target_ct = models.ForeignKey(ContentType) + target_id = models.IntegerField(default=0) + target = GenericForeignKey('target_ct', 'target_id') diff --git a/src/authentic2_journal/tables.py b/src/authentic2_journal/tables.py new file mode 100644 index 00000000..bb241037 --- /dev/null +++ b/src/authentic2_journal/tables.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +import django_tables2 as tables + +from .models import Reference + + +class UserEventsTable(tables.Table): + class Meta: + attrs = {'class': 'main'} + model = Reference + exclude = ['line', 'target_id', 'target_ct'] + empty_text = _('None') diff --git a/src/authentic2_journal/templates/authentic2_journal/user_events.html b/src/authentic2_journal/templates/authentic2_journal/user_events.html new file mode 100644 index 00000000..4af22975 --- /dev/null +++ b/src/authentic2_journal/templates/authentic2_journal/user_events.html @@ -0,0 +1,10 @@ +{% extends "authentic2/manager/base.html" %} +{% load i18n staticfiles django_tables2 %} + +{% block page_title %} +{% trans "User events journal" %} +{% endblock %} + +{% block content %} + {% render_table table "authentic2/manager/table.html" %} +{% endblock %} diff --git a/src/authentic2_journal/urls.py b/src/authentic2_journal/urls.py new file mode 100644 index 00000000..1ca5c1c1 --- /dev/null +++ b/src/authentic2_journal/urls.py @@ -0,0 +1,10 @@ +from django.conf.urls import url + +from . import views + + +urlpatterns = [ + url('^users/(?P\d+)/$', + views.user_journal, + name='a2-journal-user'), +] diff --git a/src/authentic2_journal/utils.py b/src/authentic2_journal/utils.py new file mode 100644 index 00000000..e9ba5c24 --- /dev/null +++ b/src/authentic2_journal/utils.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- + +from . import kinds +from .models import Line, Reference +from django.contrib.contenttypes.models import ContentType + + +def new_line(user, obj, kind=kinds.BaseEvent, content={}): + line = Line.objects.create( + kind=kind, + content=content) + return line + + +def new_reference(line, obj): + reference = Reference.objects.create( + line=line, + target_ct=ContentType.objects.get_for_model(obj.__class), + target_id=obj.pk) + return reference diff --git a/src/authentic2_journal/views.py b/src/authentic2_journal/views.py new file mode 100644 index 00000000..0916a467 --- /dev/null +++ b/src/authentic2_journal/views.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from django.contrib.auth import get_user_model + +from authentic2.views import SimpleSubTableView +from .tables import UserEventsTable +from .models import Reference +from .utils import get_actions_kinds, get_modification_kinds + + +class UserJournal(SimpleSubTableView): + model = get_user_model() + table_class = UserEventsTable + template_name = 'authentic2/manager/user_events.html' + permissions = ['custom_user.view_user'] + filter_table_by_perm = False + + def get_table_queryset(self): + return Reference.objects.filter(target=self.object) + + +user_journal = UserJournal.as_view() -- 2.19.1