views.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. from __future__ import unicode_literals
  2. import datetime
  3. import decimal
  4. import sys
  5. from django.core.exceptions import PermissionDenied, SuspiciousOperation
  6. from django.core.urlresolvers import get_resolver
  7. from django.http import Http404, HttpResponse, JsonResponse
  8. from django.shortcuts import render, render_to_response
  9. from django.template import TemplateDoesNotExist
  10. from django.utils.log import getLogger
  11. from django.views.debug import (
  12. SafeExceptionReporterFilter, technical_500_response,
  13. )
  14. from django.views.decorators.debug import (
  15. sensitive_post_parameters, sensitive_variables,
  16. )
  17. from django.views.generic import View
  18. from . import BrokenException, except_args
  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 view_exception(request, n):
  52. raise BrokenException(except_args[int(n)])
  53. def template_exception(request, n):
  54. return render_to_response('debug/template_exception.html',
  55. {'arg': except_args[int(n)]})
  56. def jsi18n(request):
  57. return render_to_response('jsi18n.html')
  58. def raises_template_does_not_exist(request, path='i_dont_exist.html'):
  59. # We need to inspect the HTML generated by the fancy 500 debug view but
  60. # the test client ignores it, so we send it explicitly.
  61. try:
  62. return render_to_response(path)
  63. except TemplateDoesNotExist:
  64. return technical_500_response(request, *sys.exc_info())
  65. def render_no_template(request):
  66. # If we do not specify a template, we need to make sure the debug
  67. # view doesn't blow up.
  68. return render(request, [], {})
  69. def send_log(request, exc_info):
  70. logger = getLogger('django.request')
  71. # The default logging config has a logging filter to ensure admin emails are
  72. # only sent with DEBUG=False, but since someone might choose to remove that
  73. # filter, we still want to be able to test the behavior of error emails
  74. # with DEBUG=True. So we need to remove the filter temporarily.
  75. admin_email_handler = [
  76. h for h in logger.handlers
  77. if h.__class__.__name__ == "AdminEmailHandler"
  78. ][0]
  79. orig_filters = admin_email_handler.filters
  80. admin_email_handler.filters = []
  81. admin_email_handler.include_html = True
  82. logger.error('Internal Server Error: %s', request.path,
  83. exc_info=exc_info,
  84. extra={
  85. 'status_code': 500,
  86. 'request': request
  87. }
  88. )
  89. admin_email_handler.filters = orig_filters
  90. def non_sensitive_view(request):
  91. # Do not just use plain strings for the variables' values in the code
  92. # so that the tests don't return false positives when the function's source
  93. # is displayed in the exception report.
  94. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  95. sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']) # NOQA
  96. try:
  97. raise Exception
  98. except Exception:
  99. exc_info = sys.exc_info()
  100. send_log(request, exc_info)
  101. return technical_500_response(request, *exc_info)
  102. @sensitive_variables('sauce')
  103. @sensitive_post_parameters('bacon-key', 'sausage-key')
  104. def sensitive_view(request):
  105. # Do not just use plain strings for the variables' values in the code
  106. # so that the tests don't return false positives when the function's source
  107. # is displayed in the exception report.
  108. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  109. sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']) # NOQA
  110. try:
  111. raise Exception
  112. except Exception:
  113. exc_info = sys.exc_info()
  114. send_log(request, exc_info)
  115. return technical_500_response(request, *exc_info)
  116. @sensitive_variables()
  117. @sensitive_post_parameters()
  118. def paranoid_view(request):
  119. # Do not just use plain strings for the variables' values in the code
  120. # so that the tests don't return false positives when the function's source
  121. # is displayed in the exception report.
  122. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  123. sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']) # NOQA
  124. try:
  125. raise Exception
  126. except Exception:
  127. exc_info = sys.exc_info()
  128. send_log(request, exc_info)
  129. return technical_500_response(request, *exc_info)
  130. def sensitive_args_function_caller(request):
  131. try:
  132. sensitive_args_function(''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']))
  133. except Exception:
  134. exc_info = sys.exc_info()
  135. send_log(request, exc_info)
  136. return technical_500_response(request, *exc_info)
  137. @sensitive_variables('sauce')
  138. def sensitive_args_function(sauce):
  139. # Do not just use plain strings for the variables' values in the code
  140. # so that the tests don't return false positives when the function's source
  141. # is displayed in the exception report.
  142. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  143. raise Exception
  144. def sensitive_kwargs_function_caller(request):
  145. try:
  146. sensitive_kwargs_function(''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']))
  147. except Exception:
  148. exc_info = sys.exc_info()
  149. send_log(request, exc_info)
  150. return technical_500_response(request, *exc_info)
  151. @sensitive_variables('sauce')
  152. def sensitive_kwargs_function(sauce=None):
  153. # Do not just use plain strings for the variables' values in the code
  154. # so that the tests don't return false positives when the function's source
  155. # is displayed in the exception report.
  156. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  157. raise Exception
  158. class UnsafeExceptionReporterFilter(SafeExceptionReporterFilter):
  159. """
  160. Ignores all the filtering done by its parent class.
  161. """
  162. def get_post_parameters(self, request):
  163. return request.POST
  164. def get_traceback_frame_variables(self, request, tb_frame):
  165. return tb_frame.f_locals.items()
  166. @sensitive_variables()
  167. @sensitive_post_parameters()
  168. def custom_exception_reporter_filter_view(request):
  169. # Do not just use plain strings for the variables' values in the code
  170. # so that the tests don't return false positives when the function's source
  171. # is displayed in the exception report.
  172. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  173. sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']) # NOQA
  174. request.exception_reporter_filter = UnsafeExceptionReporterFilter()
  175. try:
  176. raise Exception
  177. except Exception:
  178. exc_info = sys.exc_info()
  179. send_log(request, exc_info)
  180. return technical_500_response(request, *exc_info)
  181. class Klass(object):
  182. @sensitive_variables('sauce')
  183. def method(self, request):
  184. # Do not just use plain strings for the variables' values in the code
  185. # so that the tests don't return false positives when the function's
  186. # source is displayed in the exception report.
  187. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  188. sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']) # NOQA
  189. try:
  190. raise Exception
  191. except Exception:
  192. exc_info = sys.exc_info()
  193. send_log(request, exc_info)
  194. return technical_500_response(request, *exc_info)
  195. def sensitive_method_view(request):
  196. return Klass().method(request)
  197. @sensitive_variables('sauce')
  198. @sensitive_post_parameters('bacon-key', 'sausage-key')
  199. def multivalue_dict_key_error(request):
  200. cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd']) # NOQA
  201. sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e']) # NOQA
  202. try:
  203. request.POST['bar']
  204. except Exception:
  205. exc_info = sys.exc_info()
  206. send_log(request, exc_info)
  207. return technical_500_response(request, *exc_info)
  208. def json_response_view(request):
  209. return JsonResponse({
  210. 'a': [1, 2, 3],
  211. 'foo': {'bar': 'baz'},
  212. # Make sure datetime and Decimal objects would be serialized properly
  213. 'timestamp': datetime.datetime(2013, 5, 19, 20),
  214. 'value': decimal.Decimal('3.14'),
  215. })