From 5977d88ed6f86e5b2c165161d95c09f91312394d Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 21 Feb 2020 15:24:29 +0100 Subject: [PATCH 01/11] Test turbolinks --- note_kfet/settings/base.py | 3 +++ requirements.txt | 2 ++ templates/base.html | 3 +++ 3 files changed, 8 insertions(+) diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 410f496f..66acb044 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -55,6 +55,8 @@ INSTALLED_APPS = [ # Autocomplete 'dal', 'dal_select2', + # turbolinks + 'turbolinks', # Note apps 'activity', @@ -75,6 +77,7 @@ MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.contrib.sites.middleware.CurrentSiteMiddleware', + 'turbolinks.middleware.TurbolinksMiddleware', ] ROOT_URLCONF = 'note_kfet.urls' diff --git a/requirements.txt b/requirements.txt index 2899ef61..2d377b43 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,9 @@ djangorestframework==3.9.0 django-rest-polymorphic==0.1.8 django-reversion==3.0.3 django-tables2==2.1.0 +django-turbolinks==0.5.1 docutils==0.14 +psycopg2==2.8.4 idna==2.8 oauthlib==3.1.0 Pillow==6.1.0 diff --git a/templates/base.html b/templates/base.html index ba7b4c9e..f881f00e 100644 --- a/templates/base.html +++ b/templates/base.html @@ -149,6 +149,9 @@ SPDX-License-Identifier: GPL-3.0-or-later + {% block extrajavascript %} {% endblock extrajavascript %} From d5bb1ee3100666022ae792dea250f6e143bf1b9a Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 21 Feb 2020 15:43:01 +0100 Subject: [PATCH 02/11] Don't use local static JS file --- templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/base.html b/templates/base.html index f881f00e..80140a8f 100644 --- a/templates/base.html +++ b/templates/base.html @@ -150,7 +150,7 @@ SPDX-License-Identifier: GPL-3.0-or-later integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"> {% block extrajavascript %} {% endblock extrajavascript %} From 52663d75fa095872a346711d07783273eedb0881 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 21 Feb 2020 17:07:28 +0100 Subject: [PATCH 03/11] Move scripts location --- templates/base.html | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/templates/base.html b/templates/base.html index 80140a8f..5e6f8cec 100644 --- a/templates/base.html +++ b/templates/base.html @@ -36,6 +36,33 @@ SPDX-License-Identifier: GPL-3.0-or-later {{ form.media }} {% endif %} + {# Select2 JavaScript #} + + + + + + + + + + + {# Bootstrap JavaScript #} + + + + + {# Turbolinks JavaScript #} + + {% block extracss %}{% endblock %} @@ -139,19 +166,6 @@ SPDX-License-Identifier: GPL-3.0-or-later -{# Bootstrap JavaScript #} - - - - {% block extrajavascript %} {% endblock extrajavascript %} From 0728ba4a5c931c04d3f61fe20565347e7fd120bf Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 21 Feb 2020 17:20:42 +0100 Subject: [PATCH 04/11] Reduce autoloaded libraries --- templates/base.html | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/templates/base.html b/templates/base.html index 5e6f8cec..448172ac 100644 --- a/templates/base.html +++ b/templates/base.html @@ -40,12 +40,8 @@ SPDX-License-Identifier: GPL-3.0-or-later - - - - - - + + {# Bootstrap JavaScript #} - - - - - {# Bootstrap JavaScript #} + {# Si un formulaire requiert des données supplémentaires (notamment JS), les données sont chargées #} + {% if form.media %} + {{ form.media }} + {% endif %} + {% block extracss %}{% endblock %} From c64347def77308cdbc00ec5b806b79f62c572d50 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 21 Feb 2020 17:59:20 +0100 Subject: [PATCH 06/11] Don't use slim version of jQuery (select2 requires AjaX) --- templates/base.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/base.html b/templates/base.html index 22c7232d..751ea96a 100644 --- a/templates/base.html +++ b/templates/base.html @@ -32,9 +32,9 @@ SPDX-License-Identifier: GPL-3.0-or-later href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"> {# Bootstrap JavaScript #} - + From 3fd99ebac7041fc536e40f0c4e099aca947dcbc2 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 21 Feb 2020 18:28:21 +0100 Subject: [PATCH 07/11] Ability to disable cache storage --- apps/member/views.py | 3 +++ apps/note/views.py | 5 +++++ templates/base.html | 3 +++ 3 files changed, 11 insertions(+) diff --git a/apps/member/views.py b/apps/member/views.py index 3570f7b2..6f982c64 100644 --- a/apps/member/views.py +++ b/apps/member/views.py @@ -249,6 +249,9 @@ class ClubAddMemberView(LoginRequiredMixin, CreateView): context = super().get_context_data(**kwargs) context['formset'] = MemberFormSet() context['helper'] = FormSetHelper() + + context['no_cache'] = True + return context def post(self, request, *args, **kwargs): diff --git a/apps/note/views.py b/apps/note/views.py index b012ad8b..c7e98ddc 100644 --- a/apps/note/views.py +++ b/apps/note/views.py @@ -28,6 +28,9 @@ class TransactionCreate(LoginRequiredMixin, CreateView): context = super().get_context_data(**kwargs) context['title'] = _('Transfer money from your account ' 'to one or others') + + context['no_cache'] = True + return context def get_form(self, form_class=None): @@ -146,6 +149,8 @@ class ConsoView(LoginRequiredMixin, CreateView): template_type=template_type) context['title'] = template_type + context['no_cache'] = True + return context def get_success_url(self): diff --git a/templates/base.html b/templates/base.html index 751ea96a..15ebef01 100644 --- a/templates/base.html +++ b/templates/base.html @@ -22,6 +22,9 @@ SPDX-License-Identifier: GPL-3.0-or-later + {% if no_cache %} + + {% endif %} {# Bootstrap CSS #} Date: Fri, 21 Feb 2020 18:45:18 +0100 Subject: [PATCH 08/11] Remove django-turbolinks dependency --- note_kfet/middlewares.py | 52 ++++++++++++++++++++++++++++++++++++++ note_kfet/settings/base.py | 4 +-- requirements.txt | 1 - 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 note_kfet/middlewares.py diff --git a/note_kfet/middlewares.py b/note_kfet/middlewares.py new file mode 100644 index 00000000..360132bf --- /dev/null +++ b/note_kfet/middlewares.py @@ -0,0 +1,52 @@ +# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +from urllib3.packages.rfc3986 import urlparse + +try: + from django.utils.deprecation import MiddlewareMixin +except ImportError: + MiddlewareMixin = object +from django.http import HttpResponseForbidden + + +def same_origin(current_uri, redirect_uri): + a = urlparse(current_uri) + if not a.scheme: + return True + b = urlparse(redirect_uri) + return (a.scheme, a.hostname, a.port) == (b.scheme, b.hostname, b.port) + + +class TurbolinksMiddleware(MiddlewareMixin): + + def process_request(self, request): + referrer = request.META.get('HTTP_X_XHR_REFERER') + if referrer: + # overwrite referrer + request.META['HTTP_REFERER'] = referrer + return + + def process_response(self, request, response): + referrer = request.META.get('HTTP_X_XHR_REFERER') + if not referrer: + # turbolinks not enabled + return response + + method = request.COOKIES.get('request_method') + if not method or method != request.method: + response.set_cookie('request_method', request.method) + + if response.has_header('Location'): + # this is a redirect response + loc = response['Location'] + request.session['_turbolinks_redirect_to'] = loc + + # cross domain blocker + if referrer and not same_origin(loc, referrer): + return HttpResponseForbidden() + else: + if request.session.get('_turbolinks_redirect_to'): + loc = request.session.pop('_turbolinks_redirect_to') + response['X-XHR-Redirected-To'] = loc + return response diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 66acb044..9019b4e0 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -55,8 +55,6 @@ INSTALLED_APPS = [ # Autocomplete 'dal', 'dal_select2', - # turbolinks - 'turbolinks', # Note apps 'activity', @@ -77,7 +75,7 @@ MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.contrib.sites.middleware.CurrentSiteMiddleware', - 'turbolinks.middleware.TurbolinksMiddleware', + 'note_kfet.middlewares.TurbolinksMiddleware', ] ROOT_URLCONF = 'note_kfet.urls' diff --git a/requirements.txt b/requirements.txt index 872a451c..21c24808 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,6 @@ djangorestframework==3.9.0 django-rest-polymorphic==0.1.8 django-reversion==3.0.3 django-tables2==2.1.0 -django-turbolinks==0.5.1 docutils==0.14 psycopg2==2.8.4 idna==2.8 From d8b510a0beadb365d1bba5dff993e3daddf67159 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 21 Feb 2020 18:54:05 +0100 Subject: [PATCH 09/11] Use django-material's middleware --- note_kfet/middlewares.py | 92 +++++++++++++++++++++----------------- note_kfet/settings/base.py | 1 + 2 files changed, 53 insertions(+), 40 deletions(-) diff --git a/note_kfet/middlewares.py b/note_kfet/middlewares.py index 360132bf..e2b8d7c6 100644 --- a/note_kfet/middlewares.py +++ b/note_kfet/middlewares.py @@ -1,52 +1,64 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later -from urllib3.packages.rfc3986 import urlparse +from django.http import HttpResponseRedirect -try: - from django.utils.deprecation import MiddlewareMixin -except ImportError: - MiddlewareMixin = object -from django.http import HttpResponseForbidden +from urllib.parse import urlencode, parse_qs, urlsplit, urlunsplit -def same_origin(current_uri, redirect_uri): - a = urlparse(current_uri) - if not a.scheme: - return True - b = urlparse(redirect_uri) - return (a.scheme, a.hostname, a.port) == (b.scheme, b.hostname, b.port) +class SmoothNavigationMiddleware(object): + """Keep `?back=` queryset parameter on POST requests.""" + def __init__(self, get_response): + self.get_response = get_response + def __call__(self, request): # noqa D102 + response = self.get_response(request) -class TurbolinksMiddleware(MiddlewareMixin): + if isinstance(response, HttpResponseRedirect): + back = request.GET.get('back') + if back: + _, _, back_path, _, _ = urlsplit(back) + scheme, netloc, path, query_string, fragment = urlsplit(response['location']) + query_params = parse_qs(query_string) - def process_request(self, request): - referrer = request.META.get('HTTP_X_XHR_REFERER') - if referrer: - # overwrite referrer - request.META['HTTP_REFERER'] = referrer - return + if path == back_path: + query_params.pop('back', None) + elif 'back' not in query_params: + query_params['back'] = [back] - def process_response(self, request, response): - referrer = request.META.get('HTTP_X_XHR_REFERER') - if not referrer: - # turbolinks not enabled - return response + new_query_string = urlencode(query_params, doseq=True) + response['location'] = urlunsplit((scheme, netloc, path, new_query_string, fragment)) - method = request.COOKIES.get('request_method') - if not method or method != request.method: - response.set_cookie('request_method', request.method) - - if response.has_header('Location'): - # this is a redirect response - loc = response['Location'] - request.session['_turbolinks_redirect_to'] = loc - - # cross domain blocker - if referrer and not same_origin(loc, referrer): - return HttpResponseForbidden() - else: - if request.session.get('_turbolinks_redirect_to'): - loc = request.session.pop('_turbolinks_redirect_to') - response['X-XHR-Redirected-To'] = loc return response + + +class TurbolinksMiddleware(object): + """ + Send the `Turbolinks-Location` header in response to a visit that was redirected, + and Turbolinks will replace the browser's topmost history entry. + """ + + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + response = self.get_response(request) + + is_turbolinks = request.META.get('HTTP_TURBOLINKS_REFERRER') + is_response_redirect = response.has_header('Location') + + if is_turbolinks: + if is_response_redirect: + location = response['Location'] + prev_location = request.session.pop('_turbolinks_redirect_to', None) + if prev_location is not None: + # relative subsequent redirect + if location.startswith('.'): + location = prev_location.split('?')[0] + location + request.session['_turbolinks_redirect_to'] = location + else: + if request.session.get('_turbolinks_redirect_to'): + location = request.session.pop('_turbolinks_redirect_to') + response['Turbolinks-Location'] = location + return response + diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index 9019b4e0..b45dc55c 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -75,6 +75,7 @@ MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.contrib.sites.middleware.CurrentSiteMiddleware', + 'note_kfet.middlewares.SmoothNavigationMiddleware', 'note_kfet.middlewares.TurbolinksMiddleware', ] From 9a0d74c18bfc57eb7a546c4eed2ea6e653f97899 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Fri, 21 Feb 2020 19:46:56 +0100 Subject: [PATCH 10/11] Fix no cache in ConsoView --- apps/note/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/note/views.py b/apps/note/views.py index c7e98ddc..9a23a231 100644 --- a/apps/note/views.py +++ b/apps/note/views.py @@ -140,6 +140,8 @@ class ConsoView(LoginRequiredMixin, CreateView): context = super().get_context_data(**kwargs) context['template_types'] = TransactionCategory.objects.all() + context['no_cache'] = True + if 'template_type' not in self.kwargs.keys(): return context @@ -149,8 +151,6 @@ class ConsoView(LoginRequiredMixin, CreateView): template_type=template_type) context['title'] = template_type - context['no_cache'] = True - return context def get_success_url(self): From 82355135b060fb01a45be1e94212fbbc6d2f0f06 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Fri, 21 Feb 2020 21:15:49 +0100 Subject: [PATCH 11/11] Remove SmoothNavigation Middleware --- note_kfet/middlewares.py | 26 -------------------------- note_kfet/settings/base.py | 1 - templates/base.html | 9 +++------ 3 files changed, 3 insertions(+), 33 deletions(-) diff --git a/note_kfet/middlewares.py b/note_kfet/middlewares.py index e2b8d7c6..73b87e36 100644 --- a/note_kfet/middlewares.py +++ b/note_kfet/middlewares.py @@ -6,32 +6,6 @@ from django.http import HttpResponseRedirect from urllib.parse import urlencode, parse_qs, urlsplit, urlunsplit -class SmoothNavigationMiddleware(object): - """Keep `?back=` queryset parameter on POST requests.""" - def __init__(self, get_response): - self.get_response = get_response - - def __call__(self, request): # noqa D102 - response = self.get_response(request) - - if isinstance(response, HttpResponseRedirect): - back = request.GET.get('back') - if back: - _, _, back_path, _, _ = urlsplit(back) - scheme, netloc, path, query_string, fragment = urlsplit(response['location']) - query_params = parse_qs(query_string) - - if path == back_path: - query_params.pop('back', None) - elif 'back' not in query_params: - query_params['back'] = [back] - - new_query_string = urlencode(query_params, doseq=True) - response['location'] = urlunsplit((scheme, netloc, path, new_query_string, fragment)) - - return response - - class TurbolinksMiddleware(object): """ Send the `Turbolinks-Location` header in response to a visit that was redirected, diff --git a/note_kfet/settings/base.py b/note_kfet/settings/base.py index b45dc55c..9019b4e0 100644 --- a/note_kfet/settings/base.py +++ b/note_kfet/settings/base.py @@ -75,7 +75,6 @@ MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.contrib.sites.middleware.CurrentSiteMiddleware', - 'note_kfet.middlewares.SmoothNavigationMiddleware', 'note_kfet.middlewares.TurbolinksMiddleware', ] diff --git a/templates/base.html b/templates/base.html index 15ebef01..4b5f9872 100644 --- a/templates/base.html +++ b/templates/base.html @@ -34,7 +34,7 @@ SPDX-License-Identifier: GPL-3.0-or-later - {# Bootstrap JavaScript #} + {# JQuery, Bootstrap and Turbolinks JavaScript #} @@ -44,11 +44,8 @@ SPDX-License-Identifier: GPL-3.0-or-later - - {# Turbolinks JavaScript #} - + {# Si un formulaire requiert des données supplémentaires (notamment JS), les données sont chargées #} {% if form.media %}