Fixed #4376 -- login_required now works with bound methods. Thanks, Steven Bethard.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@6658 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
8216abe748
commit
8eeb9feab0
|
@ -8,19 +8,9 @@ def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIE
|
||||||
redirecting to the log-in page if necessary. The test should be a callable
|
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.
|
that takes the user object and returns True if the user passes.
|
||||||
"""
|
"""
|
||||||
if not login_url:
|
def decorate(view_func):
|
||||||
from django.conf import settings
|
return _CheckLogin(view_func, test_func, login_url, redirect_field_name)
|
||||||
login_url = settings.LOGIN_URL
|
return decorate
|
||||||
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__
|
|
||||||
|
|
||||||
return _checklogin
|
|
||||||
return _dec
|
|
||||||
|
|
||||||
def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME):
|
def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME):
|
||||||
"""
|
"""
|
||||||
|
@ -42,3 +32,33 @@ def permission_required(perm, login_url=None):
|
||||||
"""
|
"""
|
||||||
return user_passes_test(lambda u: u.has_perm(perm), login_url=login_url)
|
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)
|
||||||
|
|
|
@ -250,6 +250,22 @@ class ClientTest(TestCase):
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(response.context['user'].username, 'testclient')
|
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):
|
def test_view_with_login_and_custom_redirect(self):
|
||||||
"Request a page that is protected with @login_required(redirect_field_name='redirect_to')"
|
"Request a page that is protected with @login_required(redirect_field_name='redirect_to')"
|
||||||
|
|
||||||
|
@ -295,6 +311,40 @@ class ClientTest(TestCase):
|
||||||
response = self.client.get('/test_client/login_protected_view/')
|
response = self.client.get('/test_client/login_protected_view/')
|
||||||
self.assertRedirects(response, 'http://testserver/accounts/login/?next=/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):
|
def test_session_modifying_view(self):
|
||||||
"Request a page that modifies the session"
|
"Request a page that modifies the session"
|
||||||
# Session value isn't set initially
|
# Session value isn't set initially
|
||||||
|
|
|
@ -13,7 +13,10 @@ urlpatterns = patterns('',
|
||||||
(r'^form_view/$', views.form_view),
|
(r'^form_view/$', views.form_view),
|
||||||
(r'^form_view_with_template/$', views.form_view_with_template),
|
(r'^form_view_with_template/$', views.form_view_with_template),
|
||||||
(r'^login_protected_view/$', views.login_protected_view),
|
(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'^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'^session_view/$', views.session_view),
|
||||||
(r'^broken_view/$', views.broken_view),
|
(r'^broken_view/$', views.broken_view),
|
||||||
(r'^mail_sending_view/$', views.mail_sending_view),
|
(r'^mail_sending_view/$', views.mail_sending_view),
|
||||||
|
|
|
@ -3,7 +3,7 @@ from xml.dom.minidom import parseString
|
||||||
from django.core.mail import EmailMessage, SMTPConnection
|
from django.core.mail import EmailMessage, SMTPConnection
|
||||||
from django.template import Context, Template
|
from django.template import Context, Template
|
||||||
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseNotFound
|
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.forms import Form
|
||||||
from django.newforms import fields
|
from django.newforms import fields
|
||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
|
@ -130,6 +130,38 @@ def login_protected_view_changed_redirect(request):
|
||||||
return HttpResponse(t.render(c))
|
return HttpResponse(t.render(c))
|
||||||
login_protected_view_changed_redirect = login_required(redirect_field_name="redirect_to")(login_protected_view_changed_redirect)
|
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):
|
def session_view(request):
|
||||||
"A view that modifies the session"
|
"A view that modifies the session"
|
||||||
request.session['tobacconist'] = 'hovercraft'
|
request.session['tobacconist'] = 'hovercraft'
|
||||||
|
|
Loading…
Reference in New Issue