From 6518dbcad51637807c647f928c551645970fee55 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Wed, 10 Jan 2018 11:57:14 +0100
Subject: [PATCH] django stronghold middleware introduced for global required
 login feature

---
 requirements.txt                        | 1 +
 smash/smash/settings.py                 | 6 +++++-
 smash/web/api_views/appointment.py      | 3 ---
 smash/web/api_views/appointment_type.py | 2 --
 smash/web/api_views/configuration.py    | 3 ---
 smash/web/api_views/daily_planning.py   | 3 ---
 smash/web/api_views/location.py         | 2 --
 smash/web/api_views/redcap.py           | 3 ---
 smash/web/api_views/subject.py          | 6 ------
 smash/web/api_views/worker.py           | 5 -----
 smash/web/urls.py                       | 3 +--
 smash/web/views/__init__.py             | 2 --
 smash/web/views/export.py               | 3 ---
 smash/web/views/mails.py                | 2 --
 14 files changed, 7 insertions(+), 37 deletions(-)

diff --git a/requirements.txt b/requirements.txt
index 50cf9ab3..d974c761 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -13,4 +13,5 @@ django-excel==0.0.9
 pyexcel-xls==0.5.0
 pyexcel==0.5.3
 pycurl==7.43.0
+django-stronghold==0.2.9
 
diff --git a/smash/smash/settings.py b/smash/smash/settings.py
index 86456861..26ff7d06 100644
--- a/smash/smash/settings.py
+++ b/smash/smash/settings.py
@@ -36,6 +36,7 @@ INSTALLED_APPS = [
     'django_otp.plugins.otp_totp',
     'two_factor',
     'web',
+    'stronghold',
 
     'debug_toolbar'
 ]
@@ -50,6 +51,7 @@ MIDDLEWARE = [
     'django_otp.middleware.OTPMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
+    'stronghold.middleware.LoginRequiredMiddleware',
 ]
 
 ROOT_URLCONF = 'smash.urls'
@@ -119,9 +121,11 @@ STATIC_URL = '/static/'
 MEDIA_URL = '/media/'
 
 # Used for @login_required ecosystem
-# LOGIN_URL = '/login'
 LOGIN_URL = 'two_factor:login'
 LOGIN_REDIRECT_URL = 'web.views.appointments'
 LOGOUT_REDIRECT_URL = 'web.views.appointments'
 
+# Used for LoginRequiredMiddleware
+STRONGHOLD_PUBLIC_NAMED_URLS = (LOGIN_URL,)
+
 from local_settings import *
diff --git a/smash/web/api_views/appointment.py b/smash/web/api_views/appointment.py
index a51ddfc0..5f44aadf 100644
--- a/smash/web/api_views/appointment.py
+++ b/smash/web/api_views/appointment.py
@@ -1,7 +1,6 @@
 import logging
 from datetime import datetime
 
-from django.contrib.auth.decorators import login_required
 from django.http import JsonResponse
 from django.urls import reverse
 from django.utils import timezone
@@ -16,7 +15,6 @@ from web.views.notifications import get_filter_locations, \
 logger = logging.getLogger(__name__)
 
 
-@login_required
 def get_appointments(request, type, min_date, max_date):
     if type == APPOINTMENT_LIST_GENERIC:
         result = Appointment.objects.filter(location__in=get_filter_locations(request.user),
@@ -42,7 +40,6 @@ def get_appointments(request, type, min_date, max_date):
     return result.order_by("datetime_when")
 
 
-@login_required
 def appointments(request, type):
     try:
         # id of the query from dataTable: https://datatables.net/manual/server-side
diff --git a/smash/web/api_views/appointment_type.py b/smash/web/api_views/appointment_type.py
index 66f9af83..5fd8e80e 100644
--- a/smash/web/api_views/appointment_type.py
+++ b/smash/web/api_views/appointment_type.py
@@ -1,10 +1,8 @@
-from django.contrib.auth.decorators import login_required
 from django.http import JsonResponse
 
 from web.models import AppointmentType
 
 
-@login_required
 def appointment_types(request):
     appointments = AppointmentType.objects.filter().all()
     result = []
diff --git a/smash/web/api_views/configuration.py b/smash/web/api_views/configuration.py
index c332d385..12c420dc 100644
--- a/smash/web/api_views/configuration.py
+++ b/smash/web/api_views/configuration.py
@@ -1,10 +1,8 @@
-from django.contrib.auth.decorators import login_required
 from django.http import JsonResponse
 
 from web.models import ConfigurationItem
 
 
-@login_required
 def configuration_items(request):
     # id of the query from dataTable: https://datatables.net/manual/server-side
     draw = int(request.GET.get("draw", "-1"))
@@ -33,7 +31,6 @@ def configuration_items(request):
     })
 
 
-@login_required
 def update_configuration_item(request):
     id = int(request.GET.get("id", "-1"))
     value = request.GET.get("value", None)
diff --git a/smash/web/api_views/daily_planning.py b/smash/web/api_views/daily_planning.py
index bd739c5c..2502a76d 100644
--- a/smash/web/api_views/daily_planning.py
+++ b/smash/web/api_views/daily_planning.py
@@ -3,7 +3,6 @@ import json
 import logging
 from operator import itemgetter
 
-from django.contrib.auth.decorators import login_required
 from django.http import JsonResponse
 from django.shortcuts import get_object_or_404
 
@@ -234,7 +233,6 @@ def get_generic_appointment_events(request, date):
     return result.values()
 
 
-@login_required
 def events(request, date):
     appointments = Appointment.objects.filter(
         datetime_when__date=date,
@@ -326,7 +324,6 @@ def availabilities(request, date):
     })
 
 
-@login_required
 def events_persist(request):
     try:
         event_links = json.loads(request.POST.get('events_to_persist'))
diff --git a/smash/web/api_views/location.py b/smash/web/api_views/location.py
index d5da64ab..f6e09ced 100644
--- a/smash/web/api_views/location.py
+++ b/smash/web/api_views/location.py
@@ -1,10 +1,8 @@
-from django.contrib.auth.decorators import login_required
 from django.http import JsonResponse
 
 from web.models import Location
 
 
-@login_required
 def locations(request):
     locations = Location.objects.all()
     data = []
diff --git a/smash/web/api_views/redcap.py b/smash/web/api_views/redcap.py
index 677e4334..31124060 100644
--- a/smash/web/api_views/redcap.py
+++ b/smash/web/api_views/redcap.py
@@ -1,10 +1,8 @@
-from django.contrib.auth.decorators import login_required
 from django.http import JsonResponse
 
 from web.models import MissingSubject
 
 
-@login_required
 def ignore_missing_subject(request, missing_subject_id):
     missing_subjects = MissingSubject.objects.filter(id=missing_subject_id)
     for missing_subject in missing_subjects:
@@ -15,7 +13,6 @@ def ignore_missing_subject(request, missing_subject_id):
     })
 
 
-@login_required
 def unignore_missing_subject(request, missing_subject_id):
     missing_subjects = MissingSubject.objects.filter(id=missing_subject_id)
     for missing_subject in missing_subjects:
diff --git a/smash/web/api_views/subject.py b/smash/web/api_views/subject.py
index b84e207c..a7fd4daf 100644
--- a/smash/web/api_views/subject.py
+++ b/smash/web/api_views/subject.py
@@ -1,6 +1,5 @@
 import logging
 
-from django.contrib.auth.decorators import login_required
 from django.db.models import Count, Case, When, Min
 from django.db.models import Q
 from django.http import JsonResponse
@@ -14,7 +13,6 @@ from web.views.subject import SUBJECT_LIST_GENERIC, SUBJECT_LIST_NO_VISIT, SUBJE
 logger = logging.getLogger(__name__)
 
 
-@login_required
 def cities(request):
     result_subjects = Subject.objects.filter(city__isnull=False).values_list('city').distinct()
     return JsonResponse({
@@ -22,7 +20,6 @@ def cities(request):
     })
 
 
-@login_required
 def referrals(request):
     result_subjects = Subject.objects.filter(referral__isnull=False).values_list('referral').distinct()
     return JsonResponse({
@@ -30,7 +27,6 @@ def referrals(request):
     })
 
 
-@login_required
 def get_subjects(request, type):
     if type == SUBJECT_LIST_GENERIC:
         return Subject.objects.all()
@@ -214,7 +210,6 @@ def get_subjects_filtered(subjects_to_be_filtered, filters):
     return result
 
 
-@login_required
 def subjects(request, type):
     try:
         # id of the query from dataTable: https://datatables.net/manual/server-side
@@ -260,7 +255,6 @@ def subjects(request, type):
         return e500_error(request)
 
 
-@login_required
 def types(request):
     data = [{"id": subject_type_id, "name": subject_type_name} for subject_type_id, subject_type_name in
             SUBJECT_TYPE_CHOICES.items()]
diff --git a/smash/web/api_views/worker.py b/smash/web/api_views/worker.py
index d9edbcc1..4b15ec74 100644
--- a/smash/web/api_views/worker.py
+++ b/smash/web/api_views/worker.py
@@ -1,6 +1,5 @@
 import datetime
 
-from django.contrib.auth.decorators import login_required
 from django.http import JsonResponse
 from django.utils import timezone
 
@@ -8,7 +7,6 @@ from web.api_views.daily_planning import get_workers_for_daily_planning, get_ava
 from ..models import Worker
 
 
-@login_required
 def specializations(request):
     workers = Worker.objects.filter(specialization__isnull=False).values_list('specialization').distinct()
     return JsonResponse({
@@ -16,7 +14,6 @@ def specializations(request):
     })
 
 
-@login_required
 def units(request):
     workers = Worker.objects.filter(unit__isnull=False).values_list('unit').distinct()
     return JsonResponse({
@@ -24,7 +21,6 @@ def units(request):
     })
 
 
-@login_required
 def workers_for_daily_planning(request):
     workers = get_workers_for_daily_planning(request)
     workers_list_for_json = []
@@ -38,7 +34,6 @@ def workers_for_daily_planning(request):
     return JsonResponse(workers_list_for_json, safe=False)
 
 
-@login_required
 def availabilities(request):
     result = []
     min_date = request.GET.get("start_date")
diff --git a/smash/web/urls.py b/smash/web/urls.py
index 6376c8d2..a98a3d95 100644
--- a/smash/web/urls.py
+++ b/smash/web/urls.py
@@ -16,7 +16,6 @@ Including another URLconf
 from django.conf import settings
 from django.conf.urls import include
 from django.conf.urls import url
-from django.contrib.auth.decorators import login_required
 from django.contrib.auth.views import logout
 from django.views.defaults import page_not_found
 from django.views.generic import TemplateView
@@ -148,7 +147,7 @@ urlpatterns = [
     ####################
 
 
-    url(r'^daily_planning$', login_required(TemplateView.as_view(template_name='daily_planning.html')),
+    url(r'^daily_planning$', TemplateView.as_view(template_name='daily_planning.html'),
         name='web.views.daily_planning'),
 
     ####################
diff --git a/smash/web/views/__init__.py b/smash/web/views/__init__.py
index 0afadd68..0b41fe04 100644
--- a/smash/web/views/__init__.py
+++ b/smash/web/views/__init__.py
@@ -1,6 +1,5 @@
 # coding=utf-8
 from django.conf import settings
-from django.contrib.auth.decorators import login_required
 from django.shortcuts import redirect, render
 from django.views.generic.base import ContextMixin
 
@@ -35,7 +34,6 @@ def e400_bad_request(request, context=None):
     return render(request, "errors/400.html", context, status=400)
 
 
-@login_required
 def wrap_response(request, template, params):
     final_params = extend_context(params, request)
     return render(request, template, final_params)
diff --git a/smash/web/views/export.py b/smash/web/views/export.py
index 5279b6b8..874a103d 100644
--- a/smash/web/views/export.py
+++ b/smash/web/views/export.py
@@ -2,7 +2,6 @@
 import csv
 
 import django_excel as excel
-from django.contrib.auth.decorators import login_required
 from django.http import HttpResponse
 
 from notifications import get_today_midnight_date
@@ -10,7 +9,6 @@ from . import e500_error, wrap_response
 from ..models import Subject, Appointment
 
 
-@login_required
 def export_to_csv(request, data_type="subjects"):
     # Create the HttpResponse object with the appropriate CSV header.
     response = HttpResponse(content_type='text/csv')
@@ -30,7 +28,6 @@ def export_to_csv(request, data_type="subjects"):
     return response
 
 
-@login_required
 def export_to_excel(request, data_type="subjects"):
     filename = data_type + '-' + get_today_midnight_date().strftime("%Y-%m-%d") + ".xls"
     if data_type == "subjects":
diff --git a/smash/web/views/mails.py b/smash/web/views/mails.py
index abe5d7f7..260b8dae 100644
--- a/smash/web/views/mails.py
+++ b/smash/web/views/mails.py
@@ -3,7 +3,6 @@ import StringIO
 from wsgiref.util import FileWrapper
 
 from django.contrib import messages
-from django.contrib.auth.decorators import login_required
 from django.http import HttpResponse
 from django.shortcuts import get_object_or_404
 from django.urls import reverse_lazy
@@ -72,7 +71,6 @@ class MailTemplatesEditView(UpdateView, WrappedView):
     context_object_name = "mail_template"
 
 
-@login_required
 def generate(request, mail_template_id, instance_id):
     mail_template = get_object_or_404(MailTemplate, id=mail_template_id)
     instance = get_object_or_404(CONTEXT_TYPES_MAPPING[mail_template.context], id=instance_id)
-- 
GitLab