Ticket #4376: django.contrib.auth.decorators.3.diff

File django.contrib.auth.decorators.3.diff, 8.9 KB (added by anonymous, 8 years ago)

updated version with tests

  • django/contrib/auth/decorators.py

     
    88    redirecting to the log-in page if necessary. The test should be a callable
    99    that takes the user object and returns True if the user passes.
    1010    """
    11     if not login_url:
    12         from django.conf import settings
    13         login_url = settings.LOGIN_URL
    14     def _dec(view_func):
    15         def _checklogin(request, *args, **kwargs):
    16             if test_func(request.user):
    17                 return view_func(request, *args, **kwargs)
    18             return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path())))
    19         _checklogin.__doc__ = view_func.__doc__
    20         _checklogin.__dict__ = view_func.__dict__
     11    def decorate(view_func):
     12        return _CheckLogin(view_func, test_func, login_url)
     13    return decorate
    2114
    22         return _checklogin
    23     return _dec
    24 
    25 login_required = user_passes_test(lambda u: u.is_authenticated())
    26 login_required.__doc__ = (
     15def login_required(view_func):
    2716    """
    2817    Decorator for views that checks that the user is logged in, redirecting
    2918    to the log-in page if necessary.
    3019    """
    31     )
     20    return _CheckLogin(view_func, lambda u: u.is_authenticated())
    3221
    3322def permission_required(perm, login_url=None):
    3423    """
     
    3726    """
    3827    return user_passes_test(lambda u: u.has_perm(perm), login_url=login_url)
    3928
     29
     30class _CheckLogin(object):
     31    """
     32    Class that checks that the user passes the given test, redirecting to
     33    the log-in page if necessary. If the test is passed, the view function
     34    is invoked. The test should be a callable that takes the user object
     35    and returns True if the user passes.
     36
     37    We use a class here so that we can define __get__. This way, when a
     38    _CheckLogin object is used as a method decorator, the view function
     39    is properly bound to its instance.
     40    """
     41    def __init__(self, view_func, test_func, login_url=None):
     42        if not login_url:
     43            from django.conf import settings
     44            login_url = settings.LOGIN_URL
     45        self.view_func = view_func
     46        self.test_func = test_func
     47        self.login_url = login_url
     48       
     49    def __get__(self, obj, cls=None):
     50        view_func = self.view_func.__get__(obj, cls)
     51        return _CheckLogin(view_func, self.test_func, self.login_url)
     52   
     53    def __call__(self, request, *args, **kwargs):
     54        if self.test_func(request.user):
     55            return self.view_func(request, *args, **kwargs)
     56        path = quote(request.get_full_path())
     57        tup = self.login_url, REDIRECT_FIELD_NAME, path
     58        return HttpResponseRedirect('%s?%s=%s' % tup)
     59
  • tests/modeltests/test_client/models.py

     
    218218        self.assertEqual(response.status_code, 200)
    219219        self.assertEqual(response.context['user'].username, 'testclient')
    220220
     221    def test_view_with_method_login(self):
     222        "Request a page that is protected with a @login_required method"
     223       
     224        # Get the page without logging in. Should result in 302.
     225        response = self.client.get('/test_client/login_protected_method_view/')
     226        self.assertRedirects(response, '/accounts/login/')
     227       
     228        # Log in
     229        self.client.login(username='testclient', password='password')
     230
     231        # Request a page that requires a login
     232        response = self.client.get('/test_client/login_protected_method_view/')
     233        self.assertEqual(response.status_code, 200)
     234        self.assertEqual(response.context['user'].username, 'testclient')
     235
     236    def test_view_with_permissions(self):
     237        "Request a page that is protected with @permission_required"
     238       
     239        # Get the page without logging in. Should result in 302.
     240        response = self.client.get('/test_client/permission_protected_view/')
     241        self.assertRedirects(response, '/accounts/login/')
     242       
     243        # Log in with wrong permissions. Should result in 302.
     244        self.client.login(username='testclient', password='password')
     245        response = self.client.get('/test_client/permission_protected_view/')
     246        self.assertRedirects(response, '/accounts/login/')
     247
     248        # TODO: Log in with right permissions and request the page again
     249
     250    def test_view_with_method_permissions(self):
     251        "Request a page that is protected with a @permission_required method"
     252       
     253        # Get the page without logging in. Should result in 302.
     254        response = self.client.get('/test_client/permission_protected_method_view/')
     255        self.assertRedirects(response, '/accounts/login/')
     256       
     257        # Log in with wrong permissions. Should result in 302.
     258        self.client.login(username='testclient', password='password')
     259        response = self.client.get('/test_client/permission_protected_method_view/')
     260        self.assertRedirects(response, '/accounts/login/')
     261
     262        # TODO: Log in with right permissions and request the page again
     263
    221264    def test_view_with_bad_login(self):
    222265        "Request a page that is protected with @login, but use bad credentials"
    223266
  • tests/modeltests/test_client/urls.py

     
    1313    (r'^form_view/$', views.form_view),
    1414    (r'^form_view_with_template/$', views.form_view_with_template),
    1515    (r'^login_protected_view/$', views.login_protected_view),
     16    (r'^permission_protected_view/$', views.permission_protected_view),
     17    (r'^login_protected_method_view/$', views.login_protected_method_view),
     18    (r'^permission_protected_method_view/$', views.permission_protected_method_view),
    1619    (r'^session_view/$', views.session_view),
    1720    (r'^broken_view/$', views.broken_view),
    1821    (r'^mail_sending_view/$', views.mail_sending_view),
  • tests/modeltests/test_client/views.py

     
    22from django.core.mail import EmailMessage, SMTPConnection
    33from django.template import Context, Template
    44from django.http import HttpResponse, HttpResponseRedirect, HttpResponseNotFound
    5 from django.contrib.auth.decorators import login_required
     5from django.contrib.auth.decorators import login_required, permission_required
    66from django.newforms.forms import Form
    77from django.newforms import fields
    88from django.shortcuts import render_to_response
     
    112112def login_protected_view(request):
    113113    "A simple view that is login protected."
    114114    t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template')
    115     c = Context({'user': request.user})
     115    c = Context({'user': request.user})
    116116   
    117117    return HttpResponse(t.render(c))
    118 login_protected_view = login_required(login_protected_view)
     118login_protected_view = login_required(login_protected_view)
     119
     120def permission_protected_view(request):
     121    "A simple view that is permission protected."
     122    t = Template('This is a permission protected test. '
     123                 'Username is {{ user.username }}. '
     124                 'Permissions are {{ user.get_all_permissions }}.' ,
     125                 name='Permissions Template')
     126    c = Context({'user': request.user})
     127    return HttpResponse(t.render(c))
     128permission_protected_view = permission_required('modeltests.test_perm')(permission_protected_view)
     129
     130class _ViewManager(object):
     131    def login_protected_view(self, request):
     132        t = Template('This is a login protected test using a method. '
     133                     'Username is {{ user.username }}.',
     134                     name='Login Method Template')
     135        c = Context({'user': request.user})
     136        return HttpResponse(t.render(c))
     137    login_protected_view = login_required(login_protected_view)
     138
     139    def permission_protected_view(self, request):
     140        t = Template('This is a permission protected test using a method. '
     141                     'Username is {{ user.username }}. '
     142                     'Permissions are {{ user.get_all_permissions }}.' ,
     143                     name='Permissions Template')
     144        c = Context({'user': request.user})
     145        return HttpResponse(t.render(c))
     146    permission_protected_view = permission_required('modeltests.test_perm')(permission_protected_view)
     147
     148_view_manager = _ViewManager()
     149login_protected_method_view = _view_manager.login_protected_view
     150permission_protected_method_view = _view_manager.permission_protected_view
     151
    119152
    120153def session_view(request):
    121154    "A view that modifies the session"
Back to Top