From cfdabfbb406e12ddb6a57d62ac63bb608bd59079 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Tue, 17 Feb 2015 20:07:44 +0100 Subject: [PATCH] Added utils.views.CSRFMixin to append the csrf token to a view Fixes: #1476 --- openslides/core/views.py | 11 +---------- openslides/utils/views.py | 29 +++++++++++++++++++++-------- tests/unit/utils/test_views.py | 13 +++++++++++++ 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/openslides/core/views.py b/openslides/core/views.py index 1a7b0c4ec..6ccac1472 100644 --- a/openslides/core/views.py +++ b/openslides/core/views.py @@ -10,7 +10,6 @@ from django.utils.importlib import import_module from django.utils.translation import ugettext as _ from haystack.views import SearchView as _SearchView from django.http import HttpResponse -from django.views.decorators.csrf import ensure_csrf_cookie from openslides import get_version as get_openslides_version from openslides import get_git_commit_id, RELEASE @@ -27,7 +26,7 @@ from .exceptions import TagException from .serializers import CustomSlideSerializer, TagSerializer -class IndexView(utils_views.View): +class IndexView(utils_views.CSRFMixin, utils_views.View): """ The primary view for OpenSlides using AngularJS. @@ -36,14 +35,6 @@ class IndexView(utils_views.View): to the custom staticfiles directory. See STATICFILES_DIRS in settings.py. """ - @classmethod - def as_view(cls, *args, **kwargs): - """ - Makes sure that the csrf cookie is send. - """ - view = super().as_view(*args, **kwargs) - return ensure_csrf_cookie(view) - def get(self, *args, **kwargs): with open(finders.find('templates/index.html')) as f: content = f.read() diff --git a/openslides/utils/views.py b/openslides/utils/views.py index 35e78601e..6b0d2cb61 100644 --- a/openslides/utils/views.py +++ b/openslides/utils/views.py @@ -7,14 +7,16 @@ from django.contrib.auth.decorators import login_required from django.core.context_processors import csrf from django.core.exceptions import ImproperlyConfigured, PermissionDenied from django.core.urlresolvers import reverse -from django.http import (HttpResponse, HttpResponseRedirect) +from django.http import HttpResponse, HttpResponseRedirect from django.utils.decorators import method_decorator -from django.utils.translation import ugettext as _, ugettext_lazy +from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy from django.views import generic as django_views +from django.views.decorators.csrf import ensure_csrf_cookie from reportlab.lib.units import cm from reportlab.platypus import SimpleDocTemplate, Spacer -from rest_framework.views import APIView as _APIView from rest_framework.response import Response +from rest_framework.views import APIView as _APIView from .exceptions import OpenSlidesError from .forms import CSVImportForm @@ -25,7 +27,7 @@ from .utils import html_strong View = django_views.View -class LoginMixin(object): +class LoginMixin: """ Mixin for Views, that only can be viseted from users how are logedin. """ @@ -38,7 +40,7 @@ class LoginMixin(object): return super().dispatch(request, *args, **kwargs) -class PermissionMixin(object): +class PermissionMixin: """ Mixin for views, that only can be visited from users with special permissions. @@ -73,7 +75,7 @@ class PermissionMixin(object): return super().dispatch(request, *args, **kwargs) -class AjaxMixin(object): +class AjaxMixin: """ Mixin to response to an ajax request with an json object. """ @@ -97,7 +99,7 @@ class AjaxMixin(object): return HttpResponse(json.dumps(self.get_ajax_context())) -class ExtraContextMixin(object): +class ExtraContextMixin: """ Mixin to send the signal 'template_manipulation' to add extra content to the context of the view. @@ -115,7 +117,7 @@ class ExtraContextMixin(object): return context -class UrlMixin(object): +class UrlMixin: url_name_args = None def get_url(self, url_name=None, url=None, args=None, use_absolute_url_link=None): @@ -280,6 +282,17 @@ class ModelFormMixin(FormMixin): form.save_m2m() +class CSRFMixin: + """ + Adds the csrf cookie to the response. + """ + + @classmethod + def as_view(cls, *args, **kwargs): + view = super().as_view(*args, **kwargs) + return ensure_csrf_cookie(view) + + class TemplateView(PermissionMixin, ExtraContextMixin, django_views.TemplateView): """ View to return with an template. diff --git a/tests/unit/utils/test_views.py b/tests/unit/utils/test_views.py index 4be914be4..180ed59f5 100644 --- a/tests/unit/utils/test_views.py +++ b/tests/unit/utils/test_views.py @@ -331,3 +331,16 @@ class TestAPIView(TestCase): self.assertFalse( hasattr(views.APIView, 'method_call'), "The APIView should not have the method 'method_call'") + + +class TestCSRFMixin(TestCase): + @patch('builtins.super') + def test_as_view(self, mock_super): + """ + Tests, that ensure_csrf_cookie is called. + """ + mock_super().as_view.return_value = 'super_view' + with patch('openslides.utils.views.ensure_csrf_cookie') as ensure_csrf_cookie: + views.CSRFMixin.as_view() + + ensure_csrf_cookie.assert_called_once_with('super_view')