Django

Code

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

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

updated version with tests

  • django/contrib/auth/decorators.py

    old new  
    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

    old new  
    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

    old new  
    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

    old new  
    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"