mirror of
https://github.com/django/django.git
synced 2025-05-05 14:37:31 +00:00
Refs #31949 -- Made @sensitive_variables/sensitive_post_parameters decorators to work with async functions.
Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
parent
f8092ee9ad
commit
38e391e95f
@ -1,4 +1,5 @@
|
|||||||
import functools
|
import functools
|
||||||
|
import inspect
|
||||||
import itertools
|
import itertools
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
@ -17,6 +18,7 @@ from django.utils.encoding import force_str
|
|||||||
from django.utils.module_loading import import_string
|
from django.utils.module_loading import import_string
|
||||||
from django.utils.regex_helper import _lazy_re_compile
|
from django.utils.regex_helper import _lazy_re_compile
|
||||||
from django.utils.version import PY311, get_docs_version
|
from django.utils.version import PY311, get_docs_version
|
||||||
|
from django.views.decorators.debug import coroutine_functions_to_sensitive_variables
|
||||||
|
|
||||||
# Minimal Django templates engine to render the error templates
|
# Minimal Django templates engine to render the error templates
|
||||||
# regardless of the project's TEMPLATES setting. Templates are
|
# regardless of the project's TEMPLATES setting. Templates are
|
||||||
@ -239,21 +241,37 @@ class SafeExceptionReporterFilter:
|
|||||||
Replace the values of variables marked as sensitive with
|
Replace the values of variables marked as sensitive with
|
||||||
stars (*********).
|
stars (*********).
|
||||||
"""
|
"""
|
||||||
# Loop through the frame's callers to see if the sensitive_variables
|
|
||||||
# decorator was used.
|
|
||||||
current_frame = tb_frame.f_back
|
|
||||||
sensitive_variables = None
|
sensitive_variables = None
|
||||||
while current_frame is not None:
|
|
||||||
if (
|
# Coroutines don't have a proper `f_back` so they need to be inspected
|
||||||
current_frame.f_code.co_name == "sensitive_variables_wrapper"
|
# separately. Handle this by stashing the registered sensitive
|
||||||
and "sensitive_variables_wrapper" in current_frame.f_locals
|
# variables in a global dict indexed by `hash(file_path:line_number)`.
|
||||||
):
|
if (
|
||||||
# The sensitive_variables decorator was used, so we take note
|
tb_frame.f_code.co_flags & inspect.CO_COROUTINE != 0
|
||||||
# of the sensitive variables' names.
|
and tb_frame.f_code.co_name != "sensitive_variables_wrapper"
|
||||||
wrapper = current_frame.f_locals["sensitive_variables_wrapper"]
|
):
|
||||||
sensitive_variables = getattr(wrapper, "sensitive_variables", None)
|
key = hash(
|
||||||
break
|
f"{tb_frame.f_code.co_filename}:{tb_frame.f_code.co_firstlineno}"
|
||||||
current_frame = current_frame.f_back
|
)
|
||||||
|
sensitive_variables = coroutine_functions_to_sensitive_variables.get(
|
||||||
|
key, None
|
||||||
|
)
|
||||||
|
|
||||||
|
if sensitive_variables is None:
|
||||||
|
# Loop through the frame's callers to see if the
|
||||||
|
# sensitive_variables decorator was used.
|
||||||
|
current_frame = tb_frame
|
||||||
|
while current_frame is not None:
|
||||||
|
if (
|
||||||
|
current_frame.f_code.co_name == "sensitive_variables_wrapper"
|
||||||
|
and "sensitive_variables_wrapper" in current_frame.f_locals
|
||||||
|
):
|
||||||
|
# The sensitive_variables decorator was used, so take note
|
||||||
|
# of the sensitive variables' names.
|
||||||
|
wrapper = current_frame.f_locals["sensitive_variables_wrapper"]
|
||||||
|
sensitive_variables = getattr(wrapper, "sensitive_variables", None)
|
||||||
|
break
|
||||||
|
current_frame = current_frame.f_back
|
||||||
|
|
||||||
cleansed = {}
|
cleansed = {}
|
||||||
if self.is_active(request) and sensitive_variables:
|
if self.is_active(request) and sensitive_variables:
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
|
import inspect
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
from asgiref.sync import iscoroutinefunction
|
||||||
|
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
|
|
||||||
|
coroutine_functions_to_sensitive_variables = {}
|
||||||
|
|
||||||
|
|
||||||
def sensitive_variables(*variables):
|
def sensitive_variables(*variables):
|
||||||
"""
|
"""
|
||||||
@ -33,13 +38,42 @@ def sensitive_variables(*variables):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
@wraps(func)
|
if iscoroutinefunction(func):
|
||||||
def sensitive_variables_wrapper(*func_args, **func_kwargs):
|
|
||||||
if variables:
|
@wraps(func)
|
||||||
sensitive_variables_wrapper.sensitive_variables = variables
|
async def sensitive_variables_wrapper(*func_args, **func_kwargs):
|
||||||
|
return await func(*func_args, **func_kwargs)
|
||||||
|
|
||||||
|
wrapped_func = func
|
||||||
|
while getattr(wrapped_func, "__wrapped__", None) is not None:
|
||||||
|
wrapped_func = wrapped_func.__wrapped__
|
||||||
|
|
||||||
|
try:
|
||||||
|
file_path = inspect.getfile(wrapped_func)
|
||||||
|
_, first_file_line = inspect.getsourcelines(wrapped_func)
|
||||||
|
except TypeError: # Raises for builtins or native functions.
|
||||||
|
raise ValueError(
|
||||||
|
f"{func.__name__} cannot safely be wrapped by "
|
||||||
|
"@sensitive_variables, make it either non-async or defined in a "
|
||||||
|
"Python file (not a builtin or from a native extension)."
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
sensitive_variables_wrapper.sensitive_variables = "__ALL__"
|
key = hash(f"{file_path}:{first_file_line}")
|
||||||
return func(*func_args, **func_kwargs)
|
|
||||||
|
if variables:
|
||||||
|
coroutine_functions_to_sensitive_variables[key] = variables
|
||||||
|
else:
|
||||||
|
coroutine_functions_to_sensitive_variables[key] = "__ALL__"
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
|
def sensitive_variables_wrapper(*func_args, **func_kwargs):
|
||||||
|
if variables:
|
||||||
|
sensitive_variables_wrapper.sensitive_variables = variables
|
||||||
|
else:
|
||||||
|
sensitive_variables_wrapper.sensitive_variables = "__ALL__"
|
||||||
|
return func(*func_args, **func_kwargs)
|
||||||
|
|
||||||
return sensitive_variables_wrapper
|
return sensitive_variables_wrapper
|
||||||
|
|
||||||
@ -77,19 +111,37 @@ def sensitive_post_parameters(*parameters):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def decorator(view):
|
def decorator(view):
|
||||||
@wraps(view)
|
if iscoroutinefunction(view):
|
||||||
def sensitive_post_parameters_wrapper(request, *args, **kwargs):
|
|
||||||
if not isinstance(request, HttpRequest):
|
@wraps(view)
|
||||||
raise TypeError(
|
async def sensitive_post_parameters_wrapper(request, *args, **kwargs):
|
||||||
"sensitive_post_parameters didn't receive an HttpRequest "
|
if not isinstance(request, HttpRequest):
|
||||||
"object. If you are decorating a classmethod, make sure "
|
raise TypeError(
|
||||||
"to use @method_decorator."
|
"sensitive_post_parameters didn't receive an HttpRequest "
|
||||||
)
|
"object. If you are decorating a classmethod, make sure to use "
|
||||||
if parameters:
|
"@method_decorator."
|
||||||
request.sensitive_post_parameters = parameters
|
)
|
||||||
else:
|
if parameters:
|
||||||
request.sensitive_post_parameters = "__ALL__"
|
request.sensitive_post_parameters = parameters
|
||||||
return view(request, *args, **kwargs)
|
else:
|
||||||
|
request.sensitive_post_parameters = "__ALL__"
|
||||||
|
return await view(request, *args, **kwargs)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
@wraps(view)
|
||||||
|
def sensitive_post_parameters_wrapper(request, *args, **kwargs):
|
||||||
|
if not isinstance(request, HttpRequest):
|
||||||
|
raise TypeError(
|
||||||
|
"sensitive_post_parameters didn't receive an HttpRequest "
|
||||||
|
"object. If you are decorating a classmethod, make sure to use "
|
||||||
|
"@method_decorator."
|
||||||
|
)
|
||||||
|
if parameters:
|
||||||
|
request.sensitive_post_parameters = parameters
|
||||||
|
else:
|
||||||
|
request.sensitive_post_parameters = "__ALL__"
|
||||||
|
return view(request, *args, **kwargs)
|
||||||
|
|
||||||
return sensitive_post_parameters_wrapper
|
return sensitive_post_parameters_wrapper
|
||||||
|
|
||||||
|
@ -205,6 +205,10 @@ filtered out of error reports in a production environment (that is, where
|
|||||||
exception reporting, and consider implementing a :ref:`custom filter
|
exception reporting, and consider implementing a :ref:`custom filter
|
||||||
<custom-error-reports>` if necessary.
|
<custom-error-reports>` if necessary.
|
||||||
|
|
||||||
|
.. versionchanged:: 5.0
|
||||||
|
|
||||||
|
Support for wrapping ``async`` functions was added.
|
||||||
|
|
||||||
.. function:: sensitive_post_parameters(*parameters)
|
.. function:: sensitive_post_parameters(*parameters)
|
||||||
|
|
||||||
If one of your views receives an :class:`~django.http.HttpRequest` object
|
If one of your views receives an :class:`~django.http.HttpRequest` object
|
||||||
@ -245,6 +249,10 @@ filtered out of error reports in a production environment (that is, where
|
|||||||
``user_change_password`` in the ``auth`` admin) to prevent the leaking of
|
``user_change_password`` in the ``auth`` admin) to prevent the leaking of
|
||||||
sensitive information such as user passwords.
|
sensitive information such as user passwords.
|
||||||
|
|
||||||
|
.. versionchanged:: 5.0
|
||||||
|
|
||||||
|
Support for wrapping ``async`` functions was added.
|
||||||
|
|
||||||
.. _custom-error-reports:
|
.. _custom-error-reports:
|
||||||
|
|
||||||
Custom error reports
|
Custom error reports
|
||||||
|
@ -241,6 +241,8 @@ Decorators
|
|||||||
* :func:`~django.views.decorators.cache.cache_control`
|
* :func:`~django.views.decorators.cache.cache_control`
|
||||||
* :func:`~django.views.decorators.cache.never_cache`
|
* :func:`~django.views.decorators.cache.never_cache`
|
||||||
* :func:`~django.views.decorators.common.no_append_slash`
|
* :func:`~django.views.decorators.common.no_append_slash`
|
||||||
|
* :func:`~django.views.decorators.debug.sensitive_variables`
|
||||||
|
* :func:`~django.views.decorators.debug.sensitive_post_parameters`
|
||||||
* ``xframe_options_deny()``
|
* ``xframe_options_deny()``
|
||||||
* ``xframe_options_sameorigin()``
|
* ``xframe_options_sameorigin()``
|
||||||
* ``xframe_options_exempt()``
|
* ``xframe_options_exempt()``
|
||||||
@ -253,7 +255,9 @@ Email
|
|||||||
Error Reporting
|
Error Reporting
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
* ...
|
* :func:`~django.views.decorators.debug.sensitive_variables` and
|
||||||
|
:func:`~django.views.decorators.debug.sensitive_post_parameters` can now be
|
||||||
|
used with asynchronous functions.
|
||||||
|
|
||||||
File Storage
|
File Storage
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
@ -9,6 +9,8 @@ from io import StringIO
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest import mock, skipIf, skipUnless
|
from unittest import mock, skipIf, skipUnless
|
||||||
|
|
||||||
|
from asgiref.sync import async_to_sync, iscoroutinefunction
|
||||||
|
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
from django.db import DatabaseError, connection
|
from django.db import DatabaseError, connection
|
||||||
@ -39,6 +41,10 @@ from django.views.debug import (
|
|||||||
from django.views.decorators.debug import sensitive_post_parameters, sensitive_variables
|
from django.views.decorators.debug import sensitive_post_parameters, sensitive_variables
|
||||||
|
|
||||||
from ..views import (
|
from ..views import (
|
||||||
|
async_sensitive_method_view,
|
||||||
|
async_sensitive_method_view_nested,
|
||||||
|
async_sensitive_view,
|
||||||
|
async_sensitive_view_nested,
|
||||||
custom_exception_reporter_filter_view,
|
custom_exception_reporter_filter_view,
|
||||||
index_page,
|
index_page,
|
||||||
multivalue_dict_key_error,
|
multivalue_dict_key_error,
|
||||||
@ -1351,7 +1357,10 @@ class ExceptionReportTestMixin:
|
|||||||
Asserts that potentially sensitive info are displayed in the response.
|
Asserts that potentially sensitive info are displayed in the response.
|
||||||
"""
|
"""
|
||||||
request = self.rf.post("/some_url/", self.breakfast_data)
|
request = self.rf.post("/some_url/", self.breakfast_data)
|
||||||
response = view(request)
|
if iscoroutinefunction(view):
|
||||||
|
response = async_to_sync(view)(request)
|
||||||
|
else:
|
||||||
|
response = view(request)
|
||||||
if check_for_vars:
|
if check_for_vars:
|
||||||
# All variables are shown.
|
# All variables are shown.
|
||||||
self.assertContains(response, "cooked_eggs", status_code=500)
|
self.assertContains(response, "cooked_eggs", status_code=500)
|
||||||
@ -1371,7 +1380,10 @@ class ExceptionReportTestMixin:
|
|||||||
Asserts that certain sensitive info are not displayed in the response.
|
Asserts that certain sensitive info are not displayed in the response.
|
||||||
"""
|
"""
|
||||||
request = self.rf.post("/some_url/", self.breakfast_data)
|
request = self.rf.post("/some_url/", self.breakfast_data)
|
||||||
response = view(request)
|
if iscoroutinefunction(view):
|
||||||
|
response = async_to_sync(view)(request)
|
||||||
|
else:
|
||||||
|
response = view(request)
|
||||||
if check_for_vars:
|
if check_for_vars:
|
||||||
# Non-sensitive variable's name and value are shown.
|
# Non-sensitive variable's name and value are shown.
|
||||||
self.assertContains(response, "cooked_eggs", status_code=500)
|
self.assertContains(response, "cooked_eggs", status_code=500)
|
||||||
@ -1418,7 +1430,10 @@ class ExceptionReportTestMixin:
|
|||||||
with self.settings(ADMINS=[("Admin", "admin@fattie-breakie.com")]):
|
with self.settings(ADMINS=[("Admin", "admin@fattie-breakie.com")]):
|
||||||
mail.outbox = [] # Empty outbox
|
mail.outbox = [] # Empty outbox
|
||||||
request = self.rf.post("/some_url/", self.breakfast_data)
|
request = self.rf.post("/some_url/", self.breakfast_data)
|
||||||
view(request)
|
if iscoroutinefunction(view):
|
||||||
|
async_to_sync(view)(request)
|
||||||
|
else:
|
||||||
|
view(request)
|
||||||
self.assertEqual(len(mail.outbox), 1)
|
self.assertEqual(len(mail.outbox), 1)
|
||||||
email = mail.outbox[0]
|
email = mail.outbox[0]
|
||||||
|
|
||||||
@ -1451,7 +1466,10 @@ class ExceptionReportTestMixin:
|
|||||||
with self.settings(ADMINS=[("Admin", "admin@fattie-breakie.com")]):
|
with self.settings(ADMINS=[("Admin", "admin@fattie-breakie.com")]):
|
||||||
mail.outbox = [] # Empty outbox
|
mail.outbox = [] # Empty outbox
|
||||||
request = self.rf.post("/some_url/", self.breakfast_data)
|
request = self.rf.post("/some_url/", self.breakfast_data)
|
||||||
view(request)
|
if iscoroutinefunction(view):
|
||||||
|
async_to_sync(view)(request)
|
||||||
|
else:
|
||||||
|
view(request)
|
||||||
self.assertEqual(len(mail.outbox), 1)
|
self.assertEqual(len(mail.outbox), 1)
|
||||||
email = mail.outbox[0]
|
email = mail.outbox[0]
|
||||||
|
|
||||||
@ -1543,6 +1561,24 @@ class ExceptionReporterFilterTests(
|
|||||||
self.verify_safe_response(sensitive_view)
|
self.verify_safe_response(sensitive_view)
|
||||||
self.verify_safe_email(sensitive_view)
|
self.verify_safe_email(sensitive_view)
|
||||||
|
|
||||||
|
def test_async_sensitive_request(self):
|
||||||
|
with self.settings(DEBUG=True):
|
||||||
|
self.verify_unsafe_response(async_sensitive_view)
|
||||||
|
self.verify_unsafe_email(async_sensitive_view)
|
||||||
|
|
||||||
|
with self.settings(DEBUG=False):
|
||||||
|
self.verify_safe_response(async_sensitive_view)
|
||||||
|
self.verify_safe_email(async_sensitive_view)
|
||||||
|
|
||||||
|
def test_async_sensitive_nested_request(self):
|
||||||
|
with self.settings(DEBUG=True):
|
||||||
|
self.verify_unsafe_response(async_sensitive_view_nested)
|
||||||
|
self.verify_unsafe_email(async_sensitive_view_nested)
|
||||||
|
|
||||||
|
with self.settings(DEBUG=False):
|
||||||
|
self.verify_safe_response(async_sensitive_view_nested)
|
||||||
|
self.verify_safe_email(async_sensitive_view_nested)
|
||||||
|
|
||||||
def test_paranoid_request(self):
|
def test_paranoid_request(self):
|
||||||
"""
|
"""
|
||||||
No POST parameters and frame variables can be seen in the
|
No POST parameters and frame variables can be seen in the
|
||||||
@ -1598,6 +1634,46 @@ class ExceptionReporterFilterTests(
|
|||||||
)
|
)
|
||||||
self.verify_safe_email(sensitive_method_view, check_for_POST_params=False)
|
self.verify_safe_email(sensitive_method_view, check_for_POST_params=False)
|
||||||
|
|
||||||
|
def test_async_sensitive_method(self):
|
||||||
|
"""
|
||||||
|
The sensitive_variables decorator works with async object methods.
|
||||||
|
"""
|
||||||
|
with self.settings(DEBUG=True):
|
||||||
|
self.verify_unsafe_response(
|
||||||
|
async_sensitive_method_view, check_for_POST_params=False
|
||||||
|
)
|
||||||
|
self.verify_unsafe_email(
|
||||||
|
async_sensitive_method_view, check_for_POST_params=False
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.settings(DEBUG=False):
|
||||||
|
self.verify_safe_response(
|
||||||
|
async_sensitive_method_view, check_for_POST_params=False
|
||||||
|
)
|
||||||
|
self.verify_safe_email(
|
||||||
|
async_sensitive_method_view, check_for_POST_params=False
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_async_sensitive_method_nested(self):
|
||||||
|
"""
|
||||||
|
The sensitive_variables decorator works with async object methods.
|
||||||
|
"""
|
||||||
|
with self.settings(DEBUG=True):
|
||||||
|
self.verify_unsafe_response(
|
||||||
|
async_sensitive_method_view_nested, check_for_POST_params=False
|
||||||
|
)
|
||||||
|
self.verify_unsafe_email(
|
||||||
|
async_sensitive_method_view_nested, check_for_POST_params=False
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.settings(DEBUG=False):
|
||||||
|
self.verify_safe_response(
|
||||||
|
async_sensitive_method_view_nested, check_for_POST_params=False
|
||||||
|
)
|
||||||
|
self.verify_safe_email(
|
||||||
|
async_sensitive_method_view_nested, check_for_POST_params=False
|
||||||
|
)
|
||||||
|
|
||||||
def test_sensitive_function_arguments(self):
|
def test_sensitive_function_arguments(self):
|
||||||
"""
|
"""
|
||||||
Sensitive variables don't leak in the sensitive_variables decorator's
|
Sensitive variables don't leak in the sensitive_variables decorator's
|
||||||
@ -1890,6 +1966,30 @@ class NonHTMLResponseExceptionReporterFilter(
|
|||||||
with self.settings(DEBUG=False):
|
with self.settings(DEBUG=False):
|
||||||
self.verify_safe_response(sensitive_view, check_for_vars=False)
|
self.verify_safe_response(sensitive_view, check_for_vars=False)
|
||||||
|
|
||||||
|
def test_async_sensitive_request(self):
|
||||||
|
"""
|
||||||
|
Sensitive POST parameters cannot be seen in the default
|
||||||
|
error reports for sensitive requests.
|
||||||
|
"""
|
||||||
|
with self.settings(DEBUG=True):
|
||||||
|
self.verify_unsafe_response(async_sensitive_view, check_for_vars=False)
|
||||||
|
|
||||||
|
with self.settings(DEBUG=False):
|
||||||
|
self.verify_safe_response(async_sensitive_view, check_for_vars=False)
|
||||||
|
|
||||||
|
def test_async_sensitive_request_nested(self):
|
||||||
|
"""
|
||||||
|
Sensitive POST parameters cannot be seen in the default
|
||||||
|
error reports for sensitive requests.
|
||||||
|
"""
|
||||||
|
with self.settings(DEBUG=True):
|
||||||
|
self.verify_unsafe_response(
|
||||||
|
async_sensitive_view_nested, check_for_vars=False
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.settings(DEBUG=False):
|
||||||
|
self.verify_safe_response(async_sensitive_view_nested, check_for_vars=False)
|
||||||
|
|
||||||
def test_paranoid_request(self):
|
def test_paranoid_request(self):
|
||||||
"""
|
"""
|
||||||
No POST parameters can be seen in the default error reports
|
No POST parameters can be seen in the default error reports
|
||||||
|
@ -178,6 +178,46 @@ def sensitive_view(request):
|
|||||||
return technical_500_response(request, *exc_info)
|
return technical_500_response(request, *exc_info)
|
||||||
|
|
||||||
|
|
||||||
|
@sensitive_variables("sauce")
|
||||||
|
@sensitive_post_parameters("bacon-key", "sausage-key")
|
||||||
|
async def async_sensitive_view(request):
|
||||||
|
# Do not just use plain strings for the variables' values in the code so
|
||||||
|
# that the tests don't return false positives when the function's source is
|
||||||
|
# displayed in the exception report.
|
||||||
|
cooked_eggs = "".join(["s", "c", "r", "a", "m", "b", "l", "e", "d"]) # NOQA
|
||||||
|
sauce = "".join( # NOQA
|
||||||
|
["w", "o", "r", "c", "e", "s", "t", "e", "r", "s", "h", "i", "r", "e"]
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
raise Exception
|
||||||
|
except Exception:
|
||||||
|
exc_info = sys.exc_info()
|
||||||
|
send_log(request, exc_info)
|
||||||
|
return technical_500_response(request, *exc_info)
|
||||||
|
|
||||||
|
|
||||||
|
@sensitive_variables("sauce")
|
||||||
|
@sensitive_post_parameters("bacon-key", "sausage-key")
|
||||||
|
async def async_sensitive_function(request):
|
||||||
|
# Do not just use plain strings for the variables' values in the code so
|
||||||
|
# that the tests don't return false positives when the function's source is
|
||||||
|
# displayed in the exception report.
|
||||||
|
cooked_eggs = "".join(["s", "c", "r", "a", "m", "b", "l", "e", "d"]) # NOQA
|
||||||
|
sauce = "".join( # NOQA
|
||||||
|
["w", "o", "r", "c", "e", "s", "t", "e", "r", "s", "h", "i", "r", "e"]
|
||||||
|
)
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
|
||||||
|
async def async_sensitive_view_nested(request):
|
||||||
|
try:
|
||||||
|
await async_sensitive_function(request)
|
||||||
|
except Exception:
|
||||||
|
exc_info = sys.exc_info()
|
||||||
|
send_log(request, exc_info)
|
||||||
|
return technical_500_response(request, *exc_info)
|
||||||
|
|
||||||
|
|
||||||
@sensitive_variables()
|
@sensitive_variables()
|
||||||
@sensitive_post_parameters()
|
@sensitive_post_parameters()
|
||||||
def paranoid_view(request):
|
def paranoid_view(request):
|
||||||
@ -309,11 +349,54 @@ class Klass:
|
|||||||
send_log(request, exc_info)
|
send_log(request, exc_info)
|
||||||
return technical_500_response(request, *exc_info)
|
return technical_500_response(request, *exc_info)
|
||||||
|
|
||||||
|
@sensitive_variables("sauce")
|
||||||
|
async def async_method(self, request):
|
||||||
|
# Do not just use plain strings for the variables' values in the code
|
||||||
|
# so that the tests don't return false positives when the function's
|
||||||
|
# source is displayed in the exception report.
|
||||||
|
cooked_eggs = "".join(["s", "c", "r", "a", "m", "b", "l", "e", "d"]) # NOQA
|
||||||
|
sauce = "".join( # NOQA
|
||||||
|
["w", "o", "r", "c", "e", "s", "t", "e", "r", "s", "h", "i", "r", "e"]
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
raise Exception
|
||||||
|
except Exception:
|
||||||
|
exc_info = sys.exc_info()
|
||||||
|
send_log(request, exc_info)
|
||||||
|
return technical_500_response(request, *exc_info)
|
||||||
|
|
||||||
|
@sensitive_variables("sauce")
|
||||||
|
async def _async_method_inner(self, request):
|
||||||
|
# Do not just use plain strings for the variables' values in the code
|
||||||
|
# so that the tests don't return false positives when the function's
|
||||||
|
# source is displayed in the exception report.
|
||||||
|
cooked_eggs = "".join(["s", "c", "r", "a", "m", "b", "l", "e", "d"]) # NOQA
|
||||||
|
sauce = "".join( # NOQA
|
||||||
|
["w", "o", "r", "c", "e", "s", "t", "e", "r", "s", "h", "i", "r", "e"]
|
||||||
|
)
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
async def async_method_nested(self, request):
|
||||||
|
try:
|
||||||
|
await self._async_method_inner(request)
|
||||||
|
except Exception:
|
||||||
|
exc_info = sys.exc_info()
|
||||||
|
send_log(request, exc_info)
|
||||||
|
return technical_500_response(request, *exc_info)
|
||||||
|
|
||||||
|
|
||||||
def sensitive_method_view(request):
|
def sensitive_method_view(request):
|
||||||
return Klass().method(request)
|
return Klass().method(request)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_sensitive_method_view(request):
|
||||||
|
return await Klass().async_method(request)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_sensitive_method_view_nested(request):
|
||||||
|
return await Klass().async_method_nested(request)
|
||||||
|
|
||||||
|
|
||||||
@sensitive_variables("sauce")
|
@sensitive_variables("sauce")
|
||||||
@sensitive_post_parameters("bacon-key", "sausage-key")
|
@sensitive_post_parameters("bacon-key", "sausage-key")
|
||||||
def multivalue_dict_key_error(request):
|
def multivalue_dict_key_error(request):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user