[1.10.x] Fixed #27567 -- Fixed crash in the debug view when request.user errors.

Backport of 373140b07a from master
This commit is contained in:
Andreas Pelme 2016-12-03 19:51:32 +01:00 committed by Tim Graham
parent 6265ca25f3
commit f1f4a7f5a9
3 changed files with 45 additions and 5 deletions

View File

@ -11,7 +11,7 @@ from django.template.defaultfilters import force_escape, pprint
from django.urls import Resolver404, resolve
from django.utils import lru_cache, six, timezone
from django.utils.datastructures import MultiValueDict
from django.utils.encoding import force_bytes, smart_text
from django.utils.encoding import force_bytes, force_text, smart_text
from django.utils.module_loading import import_string
from django.utils.translation import ugettext as _
@ -285,12 +285,24 @@ class ExceptionReporter(object):
'ascii', errors='replace'
)
from django import get_version
if self.request is None:
user_str = None
else:
try:
user_str = force_text(self.request.user)
except Exception:
# request.user may raise OperationalError if the database is
# unavailable, for example.
user_str = '[unable to retrieve the current user]'
c = {
'is_email': self.is_email,
'unicode_hint': unicode_hint,
'frames': frames,
'request': self.request,
'filtered_POST': self.filter.get_post_parameters(self.request),
'user_str': user_str,
'settings': get_safe_settings(),
'sys_executable': sys.executable,
'sys_version_info': '%d.%d.%d' % sys.version_info[0:3],
@ -898,9 +910,9 @@ Exception Value: {{ exception_value|force_escape }}
<h2>Request information</h2>
{% if request %}
{% if request.user %}
{% if user_str %}
<h3 id="user-info">USER</h3>
<p>{{ request.user }}</p>
<p>{{ user_str }}</p>
{% endif %}
<h3 id="get-info">GET</h3>
@ -1099,7 +1111,7 @@ File "{{ frame.filename }}" in {{ frame.function }}
{% if exception_type %}Exception Type: {{ exception_type }}{% if request %} at {{ request.path_info }}{% endif %}
{% if exception_value %}Exception Value: {{ exception_value }}{% endif %}{% endif %}{% endif %}
{% if request %}Request information:
{% if request.user %}USER: {{ request.user }}{% endif %}
{% if user_str %}USER: {{ user_str }}{% endif %}
GET:{% for k, v in request.GET.items %}
{{ k }} = {{ v|stringformat:"r" }}{% empty %} No GET data{% endfor %}

View File

@ -9,4 +9,5 @@ Django 1.10.5 fixes several bugs in 1.10.4.
Bugfixes
========
* ...
* Fixed a crash in the debug view if ``request.user`` can't be retrieved, such
as if the database is unavailable (:ticket:`27567`).

View File

@ -464,6 +464,33 @@ class ExceptionReporterTests(SimpleTestCase):
html = reporter.get_traceback_html()
self.assertIn("http://evil.com/", html)
def test_exception_fetching_user(self):
"""
The error page can be rendered if the current user can't be retrieved
(such as when the database is unavailable).
"""
class ExceptionUser(object):
def __str__(self):
raise Exception()
request = self.rf.get('/test_view/')
request.user = ExceptionUser()
try:
raise ValueError('Oops')
except ValueError:
exc_type, exc_value, tb = sys.exc_info()
reporter = ExceptionReporter(request, exc_type, exc_value, tb)
html = reporter.get_traceback_html()
self.assertIn('<h1>ValueError at /test_view/</h1>', html)
self.assertIn('<pre class="exception_value">Oops</pre>', html)
self.assertIn('<h3 id="user-info">USER</h3>', html)
self.assertIn('<p>[unable to retrieve the current user]</p>', html)
text = reporter.get_traceback_text()
self.assertIn('USER: [unable to retrieve the current user]', text)
class PlainTextReportTests(SimpleTestCase):
rf = RequestFactory()