views.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. from __future__ import unicode_literals
  2. import datetime
  3. import decimal
  4. import os
  5. import sys
  6. from django.core.exceptions import PermissionDenied, SuspiciousOperation
  7. from django.core.urlresolvers import get_resolver
  8. from django.http import HttpResponse, HttpResponseRedirect, JsonResponse, Http404
  9. from django.shortcuts import render_to_response, render
  10. from django.template import Context, RequestContext, TemplateDoesNotExist
  11. from django.views.debug import technical_500_response, SafeExceptionReporterFilter
  12. from django.views.decorators.debug import (sensitive_post_parameters,
  13. sensitive_variables)
  14. from django.utils._os import upath
  15. from django.utils.log import getLogger
  16. from django.views.generic import View
  17. from . import BrokenException, except_args
  18. dirs = (os.path.join(os.path.dirname(upath(__file__)), 'other_templates'),)
  19. def index_page(request):
  20. """Dummy index page"""
  21. return HttpResponse('<html><body>Dummy page</body></html>')
  22. def raises(request):
  23. # Make sure that a callable that raises an exception in the stack frame's
  24. # local vars won't hijack the technical 500 response. See:
  25. # http://code.djangoproject.com/ticket/15025
  26. def callable():
  27. raise Exception
  28. try:
  29. raise Exception
  30. except Exception:
  31. return technical_500_response(request, *sys.exc_info())
  32. def raises500(request):
  33. # We need to inspect the HTML generated by the fancy 500 debug view but
  34. # the test client ignores it, so we send it explicitly.
  35. try:
  36. raise Exception
  37. except Exception:
  38. return technical_500_response(request, *sys.exc_info())
  39. def raises400(request):
  40. raise SuspiciousOperation
  41. def raises403(request):
  42. raise PermissionDenied
  43. def raises404(request):
  44. resolver = get_resolver(None)
  45. resolver.resolve('/not-in-urls')
  46. def technical404(request):
  47. raise Http404("Testing technical 404.")
  48. class Http404View(View):
  49. def get(self, request):
  50. raise Http404("Testing class-based technical 404.")
  51. def redirect(request):
  52. """
  53. Forces an HTTP redirect.
  54. """
  55. return HttpResponseRedirect("target/")
  56. def view_exception(request, n):
  57. raise BrokenException(except_args[int(n)])
  58. def template_exception(request, n):
  59. return render_to_response('debug/template_exception.html',
  60. {'arg': except_args[int(n)]})
  61. def jsi18n(request):
  62. return render_to_response('jsi18n.html')
  63. # Some views to exercise the shortcuts
  64. def render_to_response_view(request):
  65. return render_to_response('debug/render_test.html', {
  66. 'foo': 'FOO',
  67. 'bar': 'BAR',
  68. })
  69. def render_to_response_view_with_request_context(request):
  70. return render_to_response('debug/render_test.html', {
  71. 'foo': 'FOO',
  72. 'bar': 'BAR',
  73. }, context_instance=RequestContext(request))
  74. def render_to_response_view_with_content_type(request):
  75. return render_to_response('debug/render_test.html', {
  76. 'foo': 'FOO',
  77. 'bar': 'BAR',
  78. }, content_type='application/x-rendertest')
  79. def render_to_response_view_with_dirs(request):
  80. return render_to_response('render_dirs_test.html', dirs=dirs)
  81. def render_view(request):
  82. return render(request, 'debug/render_test.html', {
  83. 'foo': 'FOO',
  84. 'bar': 'BAR',
  85. })
  86. def render_view_with_base_context(request):
  87. return render(request, 'debug/render_test.html', {
  88. 'foo': 'FOO',
  89. 'bar': 'BAR',
  90. }, context_instance=Context())
  91. def render_view_with_content_type(request):
  92. return render(request, 'debug/render_test.html', {
  93. 'foo': 'FOO',
  94. 'bar': 'BAR',
  95. }, content_type='application/x-rendertest')
  96. def render_view_with_status(request):
  97. return render(request, 'debug/render_test.html', {
  98. 'foo': 'FOO',
  99. 'bar': 'BAR',
  100. }, status=403)
  101. def render_view_with_current_app(request):
  102. return render(request, 'debug/render_test.html', {
  103. 'foo': 'FOO',
  104. 'bar': 'BAR',
  105. }, current_app="foobar_app")
  106. def render_view_with_current_app_conflict(request):
  107. # This should fail because we don't passing both a current_app and
  108. # context_instance:
  109. return render(request, 'debug/render_test.html', {
  110. 'foo': 'FOO',
  111. 'bar': 'BAR',
  112. }, current_app="foobar_app", context_instance=RequestContext(request))
  113. def render_with_dirs(request):
  114. return render(request, 'render_dirs_test.html', dirs=dirs)
  115. def raises_template_does_not_exist(request, path='i_dont_exist.html'):
  116. # We need to inspect the HTML generated by the fancy 500 debug view but
  117. # the test client ignores it, so we send it explicitly.
  118. try:
  119. return render_to_response(path)
  120. except TemplateDoesNotExist:
  121. return technical_500_response(request, *sys.exc_info())
  122. def render_no_template(request):
  123. # If we do not specify a template, we need to make sure the debug
  124. # view doesn't blow up.
  125. return render(request, [], {})
  126. def send_log(request, exc_info):
  127. logger = getLogger('django.request')
  128. # The default logging config has a logging filter to ensure admin emails are
  129. # only sent with DEBUG=False, but since someone might choose to remove that
  130. # filter, we still want to be able to test the behavior of error emails
  131. # with DEBUG=True. So we need to remove the filter temporarily.
  132. admin_email_handler = [
  133. h for h in logger.handlers
  134. if h.__class__.__name__ == "AdminEmailHandler"
  135. ][0]
  136. orig_filters = admin_email_handler.filters
  137. admin_email_handler.filters = []
  138. admin_email_handler.include_html = True
  139. logger.error('Internal Server Error: %s', request.path,
  140. exc_info=exc_info,
  141. extra={
  142. 'status_code': 500,
  143. 'request': request
  144. }
  145. )
  146. admin_email_handler.filters = orig_filters
  147. def non_sensitive_view(request):
  148. # Do not just use plain strings for the variables' values in the code
  149. # so that the tests don't return false positives when the function's source
  150. # is displayed in the exception report.
  151. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  152. sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']) # NOQA
  153. try:
  154. raise Exception
  155. except Exception:
  156. exc_info = sys.exc_info()
  157. send_log(request, exc_info)
  158. return technical_500_response(request, *exc_info)
  159. @sensitive_variables('sauce')
  160. @sensitive_post_parameters('bacon-key', 'sausage-key')
  161. def sensitive_view(request):
  162. # Do not just use plain strings for the variables' values in the code
  163. # so that the tests don't return false positives when the function's source
  164. # is displayed in the exception report.
  165. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  166. sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']) # NOQA
  167. try:
  168. raise Exception
  169. except Exception:
  170. exc_info = sys.exc_info()
  171. send_log(request, exc_info)
  172. return technical_500_response(request, *exc_info)
  173. @sensitive_variables()
  174. @sensitive_post_parameters()
  175. def paranoid_view(request):
  176. # Do not just use plain strings for the variables' values in the code
  177. # so that the tests don't return false positives when the function's source
  178. # is displayed in the exception report.
  179. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  180. sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']) # NOQA
  181. try:
  182. raise Exception
  183. except Exception:
  184. exc_info = sys.exc_info()
  185. send_log(request, exc_info)
  186. return technical_500_response(request, *exc_info)
  187. def sensitive_args_function_caller(request):
  188. try:
  189. sensitive_args_function(''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']))
  190. except Exception:
  191. exc_info = sys.exc_info()
  192. send_log(request, exc_info)
  193. return technical_500_response(request, *exc_info)
  194. @sensitive_variables('sauce')
  195. def sensitive_args_function(sauce):
  196. # Do not just use plain strings for the variables' values in the code
  197. # so that the tests don't return false positives when the function's source
  198. # is displayed in the exception report.
  199. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  200. raise Exception
  201. def sensitive_kwargs_function_caller(request):
  202. try:
  203. sensitive_kwargs_function(''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']))
  204. except Exception:
  205. exc_info = sys.exc_info()
  206. send_log(request, exc_info)
  207. return technical_500_response(request, *exc_info)
  208. @sensitive_variables('sauce')
  209. def sensitive_kwargs_function(sauce=None):
  210. # Do not just use plain strings for the variables' values in the code
  211. # so that the tests don't return false positives when the function's source
  212. # is displayed in the exception report.
  213. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  214. raise Exception
  215. class UnsafeExceptionReporterFilter(SafeExceptionReporterFilter):
  216. """
  217. Ignores all the filtering done by its parent class.
  218. """
  219. def get_post_parameters(self, request):
  220. return request.POST
  221. def get_traceback_frame_variables(self, request, tb_frame):
  222. return tb_frame.f_locals.items()
  223. @sensitive_variables()
  224. @sensitive_post_parameters()
  225. def custom_exception_reporter_filter_view(request):
  226. # Do not just use plain strings for the variables' values in the code
  227. # so that the tests don't return false positives when the function's source
  228. # is displayed in the exception report.
  229. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  230. sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']) # NOQA
  231. request.exception_reporter_filter = UnsafeExceptionReporterFilter()
  232. try:
  233. raise Exception
  234. except Exception:
  235. exc_info = sys.exc_info()
  236. send_log(request, exc_info)
  237. return technical_500_response(request, *exc_info)
  238. class Klass(object):
  239. @sensitive_variables('sauce')
  240. def method(self, request):
  241. # Do not just use plain strings for the variables' values in the code
  242. # so that the tests don't return false positives when the function's
  243. # source is displayed in the exception report.
  244. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  245. sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']) # NOQA
  246. try:
  247. raise Exception
  248. except Exception:
  249. exc_info = sys.exc_info()
  250. send_log(request, exc_info)
  251. return technical_500_response(request, *exc_info)
  252. def sensitive_method_view(request):
  253. return Klass().method(request)
  254. @sensitive_variables('sauce')
  255. @sensitive_post_parameters('bacon-key', 'sausage-key')
  256. def multivalue_dict_key_error(request):
  257. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  258. sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']) # NOQA
  259. try:
  260. request.POST['bar']
  261. except Exception:
  262. exc_info = sys.exc_info()
  263. send_log(request, exc_info)
  264. return technical_500_response(request, *exc_info)
  265. def json_response_view(request):
  266. return JsonResponse({
  267. 'a': [1, 2, 3],
  268. 'foo': {'bar': 'baz'},
  269. # Make sure datetime and Decimal objects would be serialized properly
  270. 'timestamp': datetime.datetime(2013, 5, 19, 20),
  271. 'value': decimal.Decimal('3.14'),
  272. })