Author: lukeplant
Date: 2007-11-07 16:45:07 -0600 (Wed, 07 Nov 2007)
New Revision: 6658
Modified:
django/trunk/django/contrib/auth/decorators.py
django/trunk/tests/modeltests/test_client/models.py
django/trunk/tests/modeltests/test_client/urls.py
django/trunk/tests/modeltests/test_client/views.py
Log:
Fixed #4376 -- login_required now works with bound methods. Thanks, Steven
Bethard.
Modified: django/trunk/django/contrib/auth/decorators.py
===================================================================
--- django/trunk/django/contrib/auth/decorators.py 2007-11-07 06:36:24 UTC
(rev 6657)
+++ django/trunk/django/contrib/auth/decorators.py 2007-11-07 22:45:07 UTC
(rev 6658)
@@ -8,20 +8,10 @@
redirecting to the log-in page if necessary. The test should be a callable
that takes the user object and returns True if the user passes.
"""
- if not login_url:
- from django.conf import settings
- login_url = settings.LOGIN_URL
- def _dec(view_func):
- def _checklogin(request, *args, **kwargs):
- if test_func(request.user):
- return view_func(request, *args, **kwargs)
- return HttpResponseRedirect('%s?%s=%s' % (login_url,
redirect_field_name, urlquote(request.get_full_path())))
- _checklogin.__doc__ = view_func.__doc__
- _checklogin.__dict__ = view_func.__dict__
+ def decorate(view_func):
+ return _CheckLogin(view_func, test_func, login_url,
redirect_field_name)
+ return decorate
- return _checklogin
- return _dec
-
def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME):
"""
Decorator for views that checks that the user is logged in, redirecting
@@ -42,3 +32,33 @@
"""
return user_passes_test(lambda u: u.has_perm(perm), login_url=login_url)
+class _CheckLogin(object):
+ """
+ Class that checks that the user passes the given test, redirecting to
+ the log-in page if necessary. If the test is passed, the view function
+ is invoked. The test should be a callable that takes the user object
+ and returns True if the user passes.
+
+ We use a class here so that we can define __get__. This way, when a
+ _CheckLogin object is used as a method decorator, the view function
+ is properly bound to its instance.
+ """
+ def __init__(self, view_func, test_func, login_url=None,
redirect_field_name=REDIRECT_FIELD_NAME):
+ if not login_url:
+ from django.conf import settings
+ login_url = settings.LOGIN_URL
+ self.view_func = view_func
+ self.test_func = test_func
+ self.login_url = login_url
+ self.redirect_field_name = redirect_field_name
+
+ def __get__(self, obj, cls=None):
+ view_func = self.view_func.__get__(obj, cls)
+ return _CheckLogin(view_func, self.test_func, self.login_url,
self.redirect_field_name)
+
+ def __call__(self, request, *args, **kwargs):
+ if self.test_func(request.user):
+ return self.view_func(request, *args, **kwargs)
+ path = urlquote(request.get_full_path())
+ tup = self.login_url, self.redirect_field_name, path
+ return HttpResponseRedirect('%s?%s=%s' % tup)
Modified: django/trunk/tests/modeltests/test_client/models.py
===================================================================
--- django/trunk/tests/modeltests/test_client/models.py 2007-11-07 06:36:24 UTC
(rev 6657)
+++ django/trunk/tests/modeltests/test_client/models.py 2007-11-07 22:45:07 UTC
(rev 6658)
@@ -250,6 +250,22 @@
self.assertEqual(response.status_code, 200)
self.assertEqual(response.context['user'].username, 'testclient')
+ def test_view_with_method_login(self):
+ "Request a page that is protected with a @login_required method"
+
+ # Get the page without logging in. Should result in 302.
+ response = self.client.get('/test_client/login_protected_method_view/')
+ self.assertRedirects(response,
'http://testserver/accounts/login/?next=/test_client/login_protected_method_view/')
+
+ # Log in
+ login = self.client.login(username='testclient', password='password')
+ self.failUnless(login, 'Could not log in')
+
+ # Request a page that requires a login
+ response = self.client.get('/test_client/login_protected_method_view/')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['user'].username, 'testclient')
+
def test_view_with_login_and_custom_redirect(self):
"Request a page that is protected with
@login_required(redirect_field_name='redirect_to')"
@@ -295,6 +311,40 @@
response = self.client.get('/test_client/login_protected_view/')
self.assertRedirects(response,
'http://testserver/accounts/login/?next=/test_client/login_protected_view/')
+ def test_view_with_permissions(self):
+ "Request a page that is protected with @permission_required"
+
+ # Get the page without logging in. Should result in 302.
+ response = self.client.get('/test_client/permission_protected_view/')
+ self.assertRedirects(response,
'http://testserver/accounts/login/?next=/test_client/permission_protected_view/')
+
+ # Log in
+ login = self.client.login(username='testclient', password='password')
+ self.failUnless(login, 'Could not log in')
+
+ # Log in with wrong permissions. Should result in 302.
+ response = self.client.get('/test_client/permission_protected_view/')
+ self.assertRedirects(response,
'http://testserver/accounts/login/?next=/test_client/permission_protected_view/')
+
+ # TODO: Log in with right permissions and request the page again
+
+ def test_view_with_method_permissions(self):
+ "Request a page that is protected with a @permission_required method"
+
+ # Get the page without logging in. Should result in 302.
+ response =
self.client.get('/test_client/permission_protected_method_view/')
+ self.assertRedirects(response,
'http://testserver/accounts/login/?next=/test_client/permission_protected_method_view/')
+
+ # Log in
+ login = self.client.login(username='testclient', password='password')
+ self.failUnless(login, 'Could not log in')
+
+ # Log in with wrong permissions. Should result in 302.
+ response =
self.client.get('/test_client/permission_protected_method_view/')
+ self.assertRedirects(response,
'http://testserver/accounts/login/?next=/test_client/permission_protected_method_view/')
+
+ # TODO: Log in with right permissions and request the page again
+
def test_session_modifying_view(self):
"Request a page that modifies the session"
# Session value isn't set initially
Modified: django/trunk/tests/modeltests/test_client/urls.py
===================================================================
--- django/trunk/tests/modeltests/test_client/urls.py 2007-11-07 06:36:24 UTC
(rev 6657)
+++ django/trunk/tests/modeltests/test_client/urls.py 2007-11-07 22:45:07 UTC
(rev 6658)
@@ -13,7 +13,10 @@
(r'^form_view/$', views.form_view),
(r'^form_view_with_template/$', views.form_view_with_template),
(r'^login_protected_view/$', views.login_protected_view),
+ (r'^login_protected_method_view/$', views.login_protected_method_view),
(r'^login_protected_view_custom_redirect/$',
views.login_protected_view_changed_redirect),
+ (r'^permission_protected_view/$', views.permission_protected_view),
+ (r'^permission_protected_method_view/$',
views.permission_protected_method_view),
(r'^session_view/$', views.session_view),
(r'^broken_view/$', views.broken_view),
(r'^mail_sending_view/$', views.mail_sending_view),
Modified: django/trunk/tests/modeltests/test_client/views.py
===================================================================
--- django/trunk/tests/modeltests/test_client/views.py 2007-11-07 06:36:24 UTC
(rev 6657)
+++ django/trunk/tests/modeltests/test_client/views.py 2007-11-07 22:45:07 UTC
(rev 6658)
@@ -3,7 +3,7 @@
from django.core.mail import EmailMessage, SMTPConnection
from django.template import Context, Template
from django.http import HttpResponse, HttpResponseRedirect,
HttpResponseNotFound
-from django.contrib.auth.decorators import login_required
+from django.contrib.auth.decorators import login_required, permission_required
from django.newforms.forms import Form
from django.newforms import fields
from django.shortcuts import render_to_response
@@ -130,6 +130,38 @@
return HttpResponse(t.render(c))
login_protected_view_changed_redirect =
login_required(redirect_field_name="redirect_to")(login_protected_view_changed_redirect)
+def permission_protected_view(request):
+ "A simple view that is permission protected."
+ t = Template('This is a permission protected test. '
+ 'Username is {{ user.username }}. '
+ 'Permissions are {{ user.get_all_permissions }}.' ,
+ name='Permissions Template')
+ c = Context({'user': request.user})
+ return HttpResponse(t.render(c))
+permission_protected_view =
permission_required('modeltests.test_perm')(permission_protected_view)
+
+class _ViewManager(object):
+ def login_protected_view(self, request):
+ t = Template('This is a login protected test using a method. '
+ 'Username is {{ user.username }}.',
+ name='Login Method Template')
+ c = Context({'user': request.user})
+ return HttpResponse(t.render(c))
+ login_protected_view = login_required(login_protected_view)
+
+ def permission_protected_view(self, request):
+ t = Template('This is a permission protected test using a method. '
+ 'Username is {{ user.username }}. '
+ 'Permissions are {{ user.get_all_permissions }}.' ,
+ name='Permissions Template')
+ c = Context({'user': request.user})
+ return HttpResponse(t.render(c))
+ permission_protected_view =
permission_required('modeltests.test_perm')(permission_protected_view)
+
+_view_manager = _ViewManager()
+login_protected_method_view = _view_manager.login_protected_view
+permission_protected_method_view = _view_manager.permission_protected_view
+
def session_view(request):
"A view that modifies the session"
request.session['tobacconist'] = 'hovercraft'
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---