parent
35cecb1ebd
commit
5848bea9dc
|
@ -226,6 +226,7 @@ class AdminSite(object):
|
|||
# Admin-site-wide views.
|
||||
urlpatterns = patterns('',
|
||||
url(r'^$', wrap(self.index), name='index'),
|
||||
url(r'^login/$', self.login, name='login'),
|
||||
url(r'^logout/$', wrap(self.logout), name='logout'),
|
||||
url(r'^password_change/$', wrap(self.password_change, cacheable=True), name='password_change'),
|
||||
url(r'^password_change/done/$', wrap(self.password_change_done, cacheable=True), name='password_change_done'),
|
||||
|
@ -337,7 +338,9 @@ class AdminSite(object):
|
|||
title=_('Log in'),
|
||||
app_path=request.get_full_path(),
|
||||
)
|
||||
context[REDIRECT_FIELD_NAME] = request.get_full_path()
|
||||
if (REDIRECT_FIELD_NAME not in request.GET and
|
||||
REDIRECT_FIELD_NAME not in request.POST):
|
||||
context[REDIRECT_FIELD_NAME] = request.get_full_path()
|
||||
context.update(extra_context or {})
|
||||
|
||||
defaults = {
|
||||
|
|
|
@ -1,30 +1,14 @@
|
|||
from functools import wraps
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.contrib.admin.forms import AdminAuthenticationForm
|
||||
from django.contrib.auth.views import login
|
||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||
from django.contrib.auth.decorators import user_passes_test
|
||||
|
||||
|
||||
def staff_member_required(view_func):
|
||||
def staff_member_required(view_func, redirect_field_name=REDIRECT_FIELD_NAME, login_url='admin:login'):
|
||||
"""
|
||||
Decorator for views that checks that the user is logged in and is a staff
|
||||
member, displaying the login page if necessary.
|
||||
"""
|
||||
@wraps(view_func)
|
||||
def _checklogin(request, *args, **kwargs):
|
||||
if request.user.is_active and request.user.is_staff:
|
||||
# The user is valid. Continue to the admin page.
|
||||
return view_func(request, *args, **kwargs)
|
||||
|
||||
assert hasattr(request, 'session'), "The Django admin requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
|
||||
defaults = {
|
||||
'template_name': 'admin/login.html',
|
||||
'authentication_form': AdminAuthenticationForm,
|
||||
'extra_context': {
|
||||
'title': _('Log in'),
|
||||
'app_path': request.get_full_path(),
|
||||
REDIRECT_FIELD_NAME: request.get_full_path(),
|
||||
},
|
||||
}
|
||||
return login(request, **defaults)
|
||||
return _checklogin
|
||||
return user_passes_test(
|
||||
lambda u: u.is_active and u.is_staff,
|
||||
login_url=login_url,
|
||||
redirect_field_name=redirect_field_name
|
||||
)(view_func)
|
||||
|
|
|
@ -38,7 +38,7 @@ class AdminDocViewTests(TestCase):
|
|||
|
||||
def test_index(self):
|
||||
self.client.logout()
|
||||
response = self.client.get(reverse('django-admindocs-docroot'))
|
||||
response = self.client.get(reverse('django-admindocs-docroot'), follow=True)
|
||||
# Should display the login screen
|
||||
self.assertContains(response,
|
||||
'<input type="hidden" name="next" value="/admindocs/" />', html=True)
|
||||
|
|
|
@ -1297,11 +1297,11 @@ class AdminViewPermissionsTest(TestCase):
|
|||
superuser.is_active = False
|
||||
superuser.save()
|
||||
|
||||
response = self.client.get('/test_admin/admin/')
|
||||
response = self.client.get('/test_admin/admin/', follow=True)
|
||||
self.assertContains(response, 'id="login-form"')
|
||||
self.assertNotContains(response, 'Log out')
|
||||
|
||||
response = self.client.get('/test_admin/admin/secure-view/')
|
||||
response = self.client.get('/test_admin/admin/secure-view/', follow=True)
|
||||
self.assertContains(response, 'id="login-form"')
|
||||
|
||||
def testDisabledStaffPermissionsWhenLoggedIn(self):
|
||||
|
@ -1310,11 +1310,11 @@ class AdminViewPermissionsTest(TestCase):
|
|||
superuser.is_staff = False
|
||||
superuser.save()
|
||||
|
||||
response = self.client.get('/test_admin/admin/')
|
||||
response = self.client.get('/test_admin/admin/', follow=True)
|
||||
self.assertContains(response, 'id="login-form"')
|
||||
self.assertNotContains(response, 'Log out')
|
||||
|
||||
response = self.client.get('/test_admin/admin/secure-view/')
|
||||
response = self.client.get('/test_admin/admin/secure-view/', follow=True)
|
||||
self.assertContains(response, 'id="login-form"')
|
||||
|
||||
def testAppIndexFailEarly(self):
|
||||
|
@ -1338,6 +1338,25 @@ class AdminViewPermissionsTest(TestCase):
|
|||
response = self.client.get('/test_admin/admin/admin_views/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_shortcut_view_only_available_to_staff(self):
|
||||
"""
|
||||
Only admin users should be able to use the admin shortcut view.
|
||||
"""
|
||||
model_ctype = ContentType.objects.get_for_model(ModelWithStringPrimaryKey)
|
||||
obj = ModelWithStringPrimaryKey.objects.create(string_pk='foo')
|
||||
shortcut_url = "/test_admin/admin/r/%s/%s/" % (model_ctype.pk, obj.pk)
|
||||
|
||||
# Not logged in: we should see the login page.
|
||||
response = self.client.get(shortcut_url, follow=False)
|
||||
self.assertTemplateUsed(response, 'admin/login.html')
|
||||
|
||||
# Logged in? Redirect.
|
||||
self.client.login(username='super', password='secret')
|
||||
response = self.client.get(shortcut_url, follow=False)
|
||||
# Can't use self.assertRedirects() because User.get_absolute_url() is silly.
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.url, 'http://example.com/dummy/foo/')
|
||||
|
||||
|
||||
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
|
||||
class AdminViewsNoUrlTest(TestCase):
|
||||
|
@ -1625,162 +1644,25 @@ class AdminViewStringPrimaryKeyTest(TestCase):
|
|||
|
||||
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
|
||||
class SecureViewTests(TestCase):
|
||||
"""
|
||||
Test behaviour of a view protected by the staff_member_required decorator.
|
||||
"""
|
||||
urls = "admin_views.urls"
|
||||
fixtures = ['admin-views-users.xml']
|
||||
|
||||
def setUp(self):
|
||||
# login POST dicts
|
||||
self.super_login = {
|
||||
LOGIN_FORM_KEY: 1,
|
||||
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||
'username': 'super',
|
||||
'password': 'secret',
|
||||
}
|
||||
self.super_email_login = {
|
||||
LOGIN_FORM_KEY: 1,
|
||||
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||
'username': 'super@example.com',
|
||||
'password': 'secret',
|
||||
}
|
||||
self.super_email_bad_login = {
|
||||
LOGIN_FORM_KEY: 1,
|
||||
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||
'username': 'super@example.com',
|
||||
'password': 'notsecret',
|
||||
}
|
||||
self.adduser_login = {
|
||||
LOGIN_FORM_KEY: 1,
|
||||
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||
'username': 'adduser',
|
||||
'password': 'secret',
|
||||
}
|
||||
self.changeuser_login = {
|
||||
LOGIN_FORM_KEY: 1,
|
||||
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||
'username': 'changeuser',
|
||||
'password': 'secret',
|
||||
}
|
||||
self.deleteuser_login = {
|
||||
LOGIN_FORM_KEY: 1,
|
||||
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||
'username': 'deleteuser',
|
||||
'password': 'secret',
|
||||
}
|
||||
self.joepublic_login = {
|
||||
LOGIN_FORM_KEY: 1,
|
||||
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||
'username': 'joepublic',
|
||||
'password': 'secret',
|
||||
}
|
||||
|
||||
def tearDown(self):
|
||||
self.client.logout()
|
||||
|
||||
def test_secure_view_shows_login_if_not_logged_in(self):
|
||||
"Ensure that we see the login form"
|
||||
response = self.client.get('/test_admin/admin/secure-view/')
|
||||
"""
|
||||
Ensure that we see the admin login form.
|
||||
"""
|
||||
secure_url = '/test_admin/admin/secure-view/'
|
||||
response = self.client.get(secure_url)
|
||||
self.assertRedirects(response, '%s?next=%s' % (reverse('admin:login'), secure_url))
|
||||
response = self.client.get(secure_url, follow=True)
|
||||
self.assertTemplateUsed(response, 'admin/login.html')
|
||||
|
||||
def test_secure_view_login_successfully_redirects_to_original_url(self):
|
||||
response = self.client.get('/test_admin/admin/secure-view/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
query_string = 'the-answer=42'
|
||||
redirect_url = '/test_admin/admin/secure-view/?%s' % query_string
|
||||
new_next = {REDIRECT_FIELD_NAME: redirect_url}
|
||||
login = self.client.post('/test_admin/admin/secure-view/', dict(self.super_login, **new_next), QUERY_STRING=query_string)
|
||||
self.assertRedirects(login, redirect_url)
|
||||
|
||||
def test_staff_member_required_decorator_works_as_per_admin_login(self):
|
||||
"""
|
||||
Make sure only staff members can log in.
|
||||
|
||||
Successful posts to the login page will redirect to the orignal url.
|
||||
Unsuccessfull attempts will continue to render the login page with
|
||||
a 200 status code.
|
||||
"""
|
||||
# Super User
|
||||
response = self.client.get('/test_admin/admin/secure-view/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
login = self.client.post('/test_admin/admin/secure-view/', self.super_login)
|
||||
self.assertRedirects(login, '/test_admin/admin/secure-view/')
|
||||
self.assertFalse(login.context)
|
||||
self.client.get('/test_admin/admin/logout/')
|
||||
# make sure the view removes test cookie
|
||||
self.assertEqual(self.client.session.test_cookie_worked(), False)
|
||||
|
||||
# Test if user enters email address
|
||||
response = self.client.get('/test_admin/admin/secure-view/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
login = self.client.post('/test_admin/admin/secure-view/', self.super_email_login)
|
||||
self.assertContains(login, ERROR_MESSAGE)
|
||||
# only correct passwords get a username hint
|
||||
login = self.client.post('/test_admin/admin/secure-view/', self.super_email_bad_login)
|
||||
self.assertContains(login, ERROR_MESSAGE)
|
||||
new_user = User(username='jondoe', password='secret', email='super@example.com')
|
||||
new_user.save()
|
||||
# check to ensure if there are multiple email addresses a user doesn't get a 500
|
||||
login = self.client.post('/test_admin/admin/secure-view/', self.super_email_login)
|
||||
self.assertContains(login, ERROR_MESSAGE)
|
||||
|
||||
# Add User
|
||||
response = self.client.get('/test_admin/admin/secure-view/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
login = self.client.post('/test_admin/admin/secure-view/', self.adduser_login)
|
||||
self.assertRedirects(login, '/test_admin/admin/secure-view/')
|
||||
self.assertFalse(login.context)
|
||||
self.client.get('/test_admin/admin/logout/')
|
||||
|
||||
# Change User
|
||||
response = self.client.get('/test_admin/admin/secure-view/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
login = self.client.post('/test_admin/admin/secure-view/', self.changeuser_login)
|
||||
self.assertRedirects(login, '/test_admin/admin/secure-view/')
|
||||
self.assertFalse(login.context)
|
||||
self.client.get('/test_admin/admin/logout/')
|
||||
|
||||
# Delete User
|
||||
response = self.client.get('/test_admin/admin/secure-view/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
login = self.client.post('/test_admin/admin/secure-view/', self.deleteuser_login)
|
||||
self.assertRedirects(login, '/test_admin/admin/secure-view/')
|
||||
self.assertFalse(login.context)
|
||||
self.client.get('/test_admin/admin/logout/')
|
||||
|
||||
# Regular User should not be able to login.
|
||||
response = self.client.get('/test_admin/admin/secure-view/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
login = self.client.post('/test_admin/admin/secure-view/', self.joepublic_login)
|
||||
self.assertEqual(login.status_code, 200)
|
||||
# Login.context is a list of context dicts we just need to check the first one.
|
||||
self.assertContains(login, ERROR_MESSAGE)
|
||||
|
||||
# 8509 - if a normal user is already logged in, it is possible
|
||||
# to change user into the superuser without error
|
||||
login = self.client.login(username='joepublic', password='secret')
|
||||
# Check and make sure that if user expires, data still persists
|
||||
self.client.get('/test_admin/admin/secure-view/')
|
||||
self.client.post('/test_admin/admin/secure-view/', self.super_login)
|
||||
# make sure the view removes test cookie
|
||||
self.assertEqual(self.client.session.test_cookie_worked(), False)
|
||||
|
||||
def test_shortcut_view_only_available_to_staff(self):
|
||||
"""
|
||||
Only admin users should be able to use the admin shortcut view.
|
||||
"""
|
||||
model_ctype = ContentType.objects.get_for_model(ModelWithStringPrimaryKey)
|
||||
obj = ModelWithStringPrimaryKey.objects.create(string_pk='foo')
|
||||
shortcut_url = "/test_admin/admin/r/%s/%s/" % (model_ctype.pk, obj.pk)
|
||||
|
||||
# Not logged in: we should see the login page.
|
||||
response = self.client.get(shortcut_url, follow=False)
|
||||
self.assertTemplateUsed(response, 'admin/login.html')
|
||||
|
||||
# Logged in? Redirect.
|
||||
self.client.login(username='super', password='secret')
|
||||
response = self.client.get(shortcut_url, follow=False)
|
||||
# Can't use self.assertRedirects() because User.get_absolute_url() is silly.
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.url, 'http://example.com/dummy/foo/')
|
||||
self.assertEqual(response.context[REDIRECT_FIELD_NAME], secure_url)
|
||||
|
||||
|
||||
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
|
||||
|
|
Loading…
Reference in New Issue