From 4b2568cf339a2d9e0d996f3a1278e01b00d2409e Mon Sep 17 00:00:00 2001
From: Paul Marillonnet <pmarillonnet@entrouvert.com>
Date: Wed, 19 Dec 2018 12:11:01 +0100
Subject: [PATCH 2/5] add user profile journal (#20695)

---
 src/authentic2/forms/__init__.py              |  6 +++
 src/authentic2/profile_urls.py                |  4 +-
 .../authentic2/user_profile_journal.html      | 22 ++++++++++
 src/authentic2/views.py                       | 42 ++++++++++++++++++-
 4 files changed, 72 insertions(+), 2 deletions(-)
 create mode 100644 src/authentic2/templates/authentic2/user_profile_journal.html

diff --git a/src/authentic2/forms/__init__.py b/src/authentic2/forms/__init__.py
index ee887e14..9d8a4434 100644
--- a/src/authentic2/forms/__init__.py
+++ b/src/authentic2/forms/__init__.py
@@ -8,6 +8,7 @@ from django.utils import html
 
 from authentic2.compat import get_user_model
 from authentic2.forms.fields import PasswordField
+from authentic2.forms.widgets import DateTimeWidget
 
 from .. import app_settings
 from ..exponential_retry_timeout import ExponentialRetryTimeout
@@ -220,3 +221,8 @@ class AuthenticationForm(auth_forms.AuthenticationForm):
 
 class SiteImportForm(forms.Form):
     site_json = forms.FileField(label=_('Site Export File'))
+
+
+class EventTimewindowForm(forms.Form):
+    after = forms.DateTimeField(label=_('After'), widget=DateTimeWidget)
+    before = forms.DateTimeField(label=_('Before'), widget=DateTimeWidget)
diff --git a/src/authentic2/profile_urls.py b/src/authentic2/profile_urls.py
index 10538fed..85b8dd3e 100644
--- a/src/authentic2/profile_urls.py
+++ b/src/authentic2/profile_urls.py
@@ -9,7 +9,8 @@ from django.views.decorators.debug import sensitive_post_parameters
 
 from authentic2.utils import import_module_or_class, redirect
 from . import app_settings, decorators, profile_views, hooks
-from .views import (logged_in, edit_profile, email_change, email_change_verify, profile)
+from .views import (logged_in, edit_profile, email_change, email_change_verify, profile,
+        user_profile_journal)
 
 SET_PASSWORD_FORM_CLASS = import_module_or_class(
         app_settings.A2_REGISTRATION_SET_PASSWORD_FORM_CLASS)
@@ -94,4 +95,5 @@ urlpatterns = [
         auth_views.password_reset_done,
         name='auth_password_reset_done'),
     url(r'^switch-back/$', profile_views.switch_back, name='a2-switch-back'),
+    url('^journal/$', user_profile_journal, name='user-profile-journal'),
 ]
diff --git a/src/authentic2/templates/authentic2/user_profile_journal.html b/src/authentic2/templates/authentic2/user_profile_journal.html
new file mode 100644
index 00000000..ee61a187
--- /dev/null
+++ b/src/authentic2/templates/authentic2/user_profile_journal.html
@@ -0,0 +1,22 @@
+{% extends "authentic2/base-page.html" %}
+{% load i18n %}
+{% load authentic2_journal %}
+
+{% block content %}
+  <h1>{% trans "User journal" %}</h1>
+  <ul>
+  {% for line in object_list %}
+      <li>{{ line.timestamp }} - {{ line|to_representation }}</li>
+  {% empty %}
+      <li>{% trans "No journal entry yet." %}</li>
+  {% endfor %}
+  </ul>
+  {% block pagination %}
+    {% include "gadjo/pagination.html" %}
+  {% endblock %}
+  <form action="{% url 'user-profile-journal' %}" method="get">
+    {% csrf_token %}
+    {{ form }}
+    <input type="submit" value="Submit">
+  </form>
+{% endblock %}
diff --git a/src/authentic2/views.py b/src/authentic2/views.py
index 478bdb02..763ec44e 100644
--- a/src/authentic2/views.py
+++ b/src/authentic2/views.py
@@ -7,12 +7,14 @@ import re
 import collections
 
 
+from datetime import datetime
 from django.conf import settings
 from django.shortcuts import render_to_response, render
 from django.template.loader import render_to_string, select_template
 from django.views.generic.edit import UpdateView, FormView
 from django.views.generic import RedirectView, TemplateView
 from django.views.generic.base import View
+from django.views.generic.list import ListView
 from django.contrib.auth import SESSION_KEY
 from django import http, shortcuts
 from django.core import mail, signing
@@ -21,7 +23,8 @@ from django.core.exceptions import ValidationError
 from django.contrib import messages
 from django.utils.translation import ugettext as _
 from django.contrib.auth import logout as auth_logout
-from django.contrib.auth import REDIRECT_FIELD_NAME
+from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model
+from django.contrib.contenttypes.models import ContentType
 from django.http import (HttpResponseRedirect, HttpResponseForbidden,
     HttpResponse)
 from django.core.exceptions import PermissionDenied
@@ -37,6 +40,7 @@ from django.db.models.query import Q
 
 
 from . import (utils, app_settings, forms, compat, decorators, constants, models, cbv, hooks)
+from authentic2_journal.models import Reference, Line
 
 
 logger = logging.getLogger(__name__)
@@ -613,6 +617,42 @@ class LoggedInView(View):
 
 logged_in = never_cache(LoggedInView.as_view())
 
+
+class UserProfileJournal(ListView, FormView):
+    model = Line
+    form_class = forms.EventTimewindowForm
+    paginate_by = 10
+
+    def get_queryset(self):
+        timewindow = {}
+        for qs_param, qs_suffix in {'after': 'gte', 'before': 'lte'}.items():
+            delimiter = self.request.GET.get(qs_param)
+            if delimiter:
+                try:
+                    dt = datetime.strptime(delimiter, '%d/%m/%Y %H:%M:%S')
+                except:
+                    logger.info('UserProfileJournal wrong %s timestamp query '
+                            'string parameter: %s' % (qs_param, delimiter))
+                else:
+                    timewindow.update({'timestamp__%s' % qs_suffix: dt})
+        """
+        Timestamp consistency allows for time window filtering on Reference
+        objects directly
+        """
+        return [ref.line for ref in Reference.objects.filter(
+            target_id=self.request.user.pk,
+            target_ct=ContentType.objects.get_for_model(get_user_model()),
+            **timewindow)]
+
+    def get_template_names(self):
+        return [
+            'profiles/user_profile_journal.html',
+            'authentic2/user_profile_journal.html',
+        ]
+
+user_profile_journal = login_required(UserProfileJournal.as_view())
+
+
 def csrf_failure_view(request, reason=""):
     messages.warning(request, _('The page is out of date, it was reloaded for you'))
     return HttpResponseRedirect(request.get_full_path())
-- 
2.20.1

