Fixed #20126 -- XViewMiddleware moved to django.contrib.admindocs.middleware

This commit is contained in:
Łukasz Langa 2013-05-18 17:43:21 +02:00
parent a7e2835276
commit 660762681c
12 changed files with 124 additions and 41 deletions

View File

@ -0,0 +1,23 @@
from django.conf import settings
from django import http
class XViewMiddleware(object):
"""
Adds an X-View header to internal HEAD requests -- used by the documentation system.
"""
def process_view(self, request, view_func, view_args, view_kwargs):
"""
If the request method is HEAD and either the IP is internal or the
user is a logged-in staff member, quickly return with an x-header
indicating the view function. This is used by the documentation module
to lookup the view function for an arbitrary page.
"""
assert hasattr(request, 'user'), (
"The XView middleware requires authentication middleware to be "
"installed. Edit your MIDDLEWARE_CLASSES setting to insert "
"'django.contrib.auth.middleware.AuthenticationMiddleware'.")
if request.method == 'HEAD' and (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or
(request.user.is_active and request.user.is_staff)):
response = http.HttpResponse()
response['X-View'] = "%s.%s" % (view_func.__module__, view_func.__name__)
return response

View File

@ -1,23 +1,6 @@
from django.conf import settings """XViewMiddleware has been moved to django.contrib.admindocs.middleware."""
from django import http
class XViewMiddleware(object): import warnings
""" warnings.warn(__doc__, PendingDeprecationWarning, stacklevel=2)
Adds an X-View header to internal HEAD requests -- used by the documentation system.
""" from django.contrib.admindocs.middleware import XViewMiddleware
def process_view(self, request, view_func, view_args, view_kwargs):
"""
If the request method is HEAD and either the IP is internal or the
user is a logged-in staff member, quickly return with an x-header
indicating the view function. This is used by the documentation module
to lookup the view function for an arbitrary page.
"""
assert hasattr(request, 'user'), (
"The XView middleware requires authentication middleware to be "
"installed. Edit your MIDDLEWARE_CLASSES setting to insert "
"'django.contrib.auth.middleware.AuthenticationMiddleware'.")
if request.method == 'HEAD' and (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or
(request.user.is_active and request.user.is_staff)):
response = http.HttpResponse()
response['X-View'] = "%s.%s" % (view_func.__module__, view_func.__name__)
return response

View File

@ -31,7 +31,7 @@ the following:
* **Optional:** Linking to templates requires the :setting:`ADMIN_FOR` * **Optional:** Linking to templates requires the :setting:`ADMIN_FOR`
setting to be configured. setting to be configured.
* **Optional:** Using the admindocs bookmarklets requires the * **Optional:** Using the admindocs bookmarklets requires the
:mod:`XViewMiddleware<django.middleware.doc>` to be installed. :mod:`XViewMiddleware<django.contrib.admindocs.middleware>` to be installed.
Once those steps are complete, you can start browsing the documentation by Once those steps are complete, you can start browsing the documentation by
going to your admin interface and clicking the "Documentation" link in the going to your admin interface and clicking the "Documentation" link in the
@ -156,7 +156,7 @@ Edit this object
Using these bookmarklets requires that you are either logged into the Using these bookmarklets requires that you are either logged into the
:mod:`Django admin <django.contrib.admin>` as a :mod:`Django admin <django.contrib.admin>` as a
:class:`~django.contrib.auth.models.User` with :class:`~django.contrib.auth.models.User` with
:attr:`~django.contrib.auth.models.User.is_staff` set to `True`, or :attr:`~django.contrib.auth.models.User.is_staff` set to `True`, or that the
that the :mod:`django.middleware.doc` middleware and :mod:`XViewMiddleware <django.contrib.admindocs.middleware>` is installed and
:mod:`XViewMiddleware <django.middleware.doc>` are installed and you you are accessing the site from an IP address listed in
are accessing the site from an IP address listed in :setting:`INTERNAL_IPS`. :setting:`INTERNAL_IPS`.

View File

@ -71,19 +71,6 @@ Adds a few conveniences for perfectionists:
* Sends broken link notification emails to :setting:`MANAGERS` (see * Sends broken link notification emails to :setting:`MANAGERS` (see
:doc:`/howto/error-reporting`). :doc:`/howto/error-reporting`).
View metadata middleware
------------------------
.. module:: django.middleware.doc
:synopsis: Middleware to help your app self-document.
.. class:: XViewMiddleware
Sends custom ``X-View`` HTTP headers to HEAD requests that come from IP
addresses defined in the :setting:`INTERNAL_IPS` setting. This is used by
Django's :doc:`automatic documentation system </ref/contrib/admin/admindocs>`.
Depends on :class:`~django.contrib.auth.middleware.AuthenticationMiddleware`.
GZip middleware GZip middleware
--------------- ---------------

View File

@ -1243,7 +1243,7 @@ Default: ``()`` (Empty tuple)
A tuple of IP addresses, as strings, that: A tuple of IP addresses, as strings, that:
* See debug comments, when :setting:`DEBUG` is ``True`` * See debug comments, when :setting:`DEBUG` is ``True``
* Receive X headers if the ``XViewMiddleware`` is installed (see * Receive X headers in admindocs if the ``XViewMiddleware`` is installed (see
:doc:`/topics/http/middleware`) :doc:`/topics/http/middleware`)
.. setting:: LANGUAGE_CODE .. setting:: LANGUAGE_CODE

View File

@ -502,6 +502,10 @@ Miscellaneous
ineffective so it has been removed, along with its generic implementation, ineffective so it has been removed, along with its generic implementation,
previously available in ``django.core.xheaders``. previously available in ``django.core.xheaders``.
* The ``XViewMiddleware`` has been moved from ``django.middleware.doc`` to
``django.contrib.admindocs.middleware`` because it is an implementation
detail of admindocs, proven not to be reusable in general.
Features deprecated in 1.6 Features deprecated in 1.6
========================== ==========================

View File

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<django-objects version="1.0">
<object pk="100" model="auth.user">
<field type="CharField" name="username">super</field>
<field type="CharField" name="first_name">Super</field>
<field type="CharField" name="last_name">User</field>
<field type="CharField" name="email">super@example.com</field>
<field type="CharField" name="password">sha1$995a3$6011485ea3834267d719b4c801409b8b1ddd0158</field>
<field type="BooleanField" name="is_staff">True</field>
<field type="BooleanField" name="is_active">True</field>
<field type="BooleanField" name="is_superuser">True</field>
<field type="DateTimeField" name="last_login">2007-05-30 13:20:10</field>
<field type="DateTimeField" name="date_joined">2007-05-30 13:20:10</field>
<field to="auth.group" name="groups" rel="ManyToManyRel"></field>
<field to="auth.permission" name="user_permissions" rel="ManyToManyRel"></field>
</object>
</django-objects>

View File

45
tests/admin_docs/tests.py Normal file
View File

@ -0,0 +1,45 @@
from django.contrib.auth.models import User
from django.test import TestCase
from django.test.utils import override_settings
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class XViewMiddlewareTest(TestCase):
fixtures = ['data.xml']
urls = 'admin_docs.urls'
def test_xview_func(self):
user = User.objects.get(username='super')
response = self.client.head('/xview/func/')
self.assertFalse('X-View' in response)
self.client.login(username='super', password='secret')
response = self.client.head('/xview/func/')
self.assertTrue('X-View' in response)
self.assertEqual(response['X-View'], 'admin_docs.views.xview')
user.is_staff = False
user.save()
response = self.client.head('/xview/func/')
self.assertFalse('X-View' in response)
user.is_staff = True
user.is_active = False
user.save()
response = self.client.head('/xview/func/')
self.assertFalse('X-View' in response)
def test_xview_class(self):
user = User.objects.get(username='super')
response = self.client.head('/xview/class/')
self.assertFalse('X-View' in response)
self.client.login(username='super', password='secret')
response = self.client.head('/xview/class/')
self.assertTrue('X-View' in response)
self.assertEqual(response['X-View'], 'admin_docs.views.XViewClass')
user.is_staff = False
user.save()
response = self.client.head('/xview/class/')
self.assertFalse('X-View' in response)
user.is_staff = True
user.is_active = False
user.save()
response = self.client.head('/xview/class/')
self.assertFalse('X-View' in response)

11
tests/admin_docs/urls.py Normal file
View File

@ -0,0 +1,11 @@
# coding: utf-8
from __future__ import absolute_import
from django.conf.urls import patterns
from . import views
urlpatterns = patterns('',
(r'^xview/func/$', views.xview_dec(views.xview)),
(r'^xview/class/$', views.xview_dec(views.XViewClass.as_view())),
)

13
tests/admin_docs/views.py Normal file
View File

@ -0,0 +1,13 @@
from django.http import HttpResponse
from django.utils.decorators import decorator_from_middleware
from django.views.generic import View
from django.contrib.admindocs.middleware import XViewMiddleware
xview_dec = decorator_from_middleware(XViewMiddleware)
def xview(request):
return HttpResponse()
class XViewClass(View):
def get(self, request):
return HttpResponse()