mirror of
https://github.com/django/django.git
synced 2025-06-16 08:59:17 +00:00
[5.1.x] Added helpers in csrf_tests and logging_tests to assert logs from log_response()
.
Backport of ad6f99889838ccc2c30b3c02ed3868c9b565e81b from main.
This commit is contained in:
parent
bb92acacac
commit
32a9cb2179
@ -1,3 +1,4 @@
|
|||||||
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -55,6 +56,21 @@ class CsrfFunctionTestMixin:
|
|||||||
actual = _unmask_cipher_token(masked_secret)
|
actual = _unmask_cipher_token(masked_secret)
|
||||||
self.assertEqual(actual, secret)
|
self.assertEqual(actual, secret)
|
||||||
|
|
||||||
|
def assertForbiddenReason(
|
||||||
|
self, response, logger_cm, reason, levelno=logging.WARNING
|
||||||
|
):
|
||||||
|
self.assertEqual(
|
||||||
|
records_len := len(logger_cm.records),
|
||||||
|
1,
|
||||||
|
f"Unexpected number of records for {logger_cm=} in {levelno=} (expected 1, "
|
||||||
|
f"got {records_len}).",
|
||||||
|
)
|
||||||
|
record = logger_cm.records[0]
|
||||||
|
self.assertEqual(record.getMessage(), "Forbidden (%s): " % reason)
|
||||||
|
self.assertEqual(record.levelno, levelno)
|
||||||
|
self.assertEqual(record.status_code, 403)
|
||||||
|
self.assertEqual(response.status_code, 403)
|
||||||
|
|
||||||
|
|
||||||
class CsrfFunctionTests(CsrfFunctionTestMixin, SimpleTestCase):
|
class CsrfFunctionTests(CsrfFunctionTestMixin, SimpleTestCase):
|
||||||
def test_unmask_cipher_token(self):
|
def test_unmask_cipher_token(self):
|
||||||
@ -345,8 +361,7 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
|
|||||||
mw.process_request(req)
|
mw.process_request(req)
|
||||||
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
||||||
resp = mw.process_view(req, post_form_view, (), {})
|
resp = mw.process_view(req, post_form_view, (), {})
|
||||||
self.assertEqual(403, resp.status_code)
|
self.assertForbiddenReason(resp, cm, expected)
|
||||||
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % expected)
|
|
||||||
|
|
||||||
def test_no_csrf_cookie(self):
|
def test_no_csrf_cookie(self):
|
||||||
"""
|
"""
|
||||||
@ -371,9 +386,8 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
|
|||||||
mw.process_request(req)
|
mw.process_request(req)
|
||||||
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
||||||
resp = mw.process_view(req, post_form_view, (), {})
|
resp = mw.process_view(req, post_form_view, (), {})
|
||||||
self.assertEqual(403, resp.status_code)
|
|
||||||
self.assertEqual(resp["Content-Type"], "text/html; charset=utf-8")
|
self.assertEqual(resp["Content-Type"], "text/html; charset=utf-8")
|
||||||
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % expected)
|
self.assertForbiddenReason(resp, cm, expected)
|
||||||
|
|
||||||
def test_csrf_cookie_bad_or_missing_token(self):
|
def test_csrf_cookie_bad_or_missing_token(self):
|
||||||
"""
|
"""
|
||||||
@ -478,18 +492,12 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
|
|||||||
mw = CsrfViewMiddleware(post_form_view)
|
mw = CsrfViewMiddleware(post_form_view)
|
||||||
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
||||||
resp = mw.process_view(req, post_form_view, (), {})
|
resp = mw.process_view(req, post_form_view, (), {})
|
||||||
self.assertEqual(403, resp.status_code)
|
self.assertForbiddenReason(resp, cm, REASON_NO_CSRF_COOKIE)
|
||||||
self.assertEqual(
|
|
||||||
cm.records[0].getMessage(), "Forbidden (%s): " % REASON_NO_CSRF_COOKIE
|
|
||||||
)
|
|
||||||
|
|
||||||
req = self._get_request(method="DELETE")
|
req = self._get_request(method="DELETE")
|
||||||
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
||||||
resp = mw.process_view(req, post_form_view, (), {})
|
resp = mw.process_view(req, post_form_view, (), {})
|
||||||
self.assertEqual(403, resp.status_code)
|
self.assertForbiddenReason(resp, cm, REASON_NO_CSRF_COOKIE)
|
||||||
self.assertEqual(
|
|
||||||
cm.records[0].getMessage(), "Forbidden (%s): " % REASON_NO_CSRF_COOKIE
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_put_and_delete_allowed(self):
|
def test_put_and_delete_allowed(self):
|
||||||
"""
|
"""
|
||||||
@ -877,11 +885,7 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
|
|||||||
mw.process_request(req)
|
mw.process_request(req)
|
||||||
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
||||||
resp = mw.process_view(req, post_form_view, (), {})
|
resp = mw.process_view(req, post_form_view, (), {})
|
||||||
self.assertEqual(resp.status_code, 403)
|
self.assertForbiddenReason(resp, cm, REASON_CSRF_TOKEN_MISSING)
|
||||||
self.assertEqual(
|
|
||||||
cm.records[0].getMessage(),
|
|
||||||
"Forbidden (%s): " % REASON_CSRF_TOKEN_MISSING,
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_reading_post_data_raises_os_error(self):
|
def test_reading_post_data_raises_os_error(self):
|
||||||
"""
|
"""
|
||||||
@ -906,9 +910,8 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
|
|||||||
self.assertIs(mw._origin_verified(req), False)
|
self.assertIs(mw._origin_verified(req), False)
|
||||||
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
||||||
response = mw.process_view(req, post_form_view, (), {})
|
response = mw.process_view(req, post_form_view, (), {})
|
||||||
self.assertEqual(response.status_code, 403)
|
|
||||||
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
|
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
|
||||||
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % msg)
|
self.assertForbiddenReason(response, cm, msg)
|
||||||
|
|
||||||
@override_settings(ALLOWED_HOSTS=["www.example.com"])
|
@override_settings(ALLOWED_HOSTS=["www.example.com"])
|
||||||
def test_bad_origin_null_origin(self):
|
def test_bad_origin_null_origin(self):
|
||||||
@ -921,9 +924,8 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
|
|||||||
self.assertIs(mw._origin_verified(req), False)
|
self.assertIs(mw._origin_verified(req), False)
|
||||||
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
||||||
response = mw.process_view(req, post_form_view, (), {})
|
response = mw.process_view(req, post_form_view, (), {})
|
||||||
self.assertEqual(response.status_code, 403)
|
|
||||||
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
|
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
|
||||||
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % msg)
|
self.assertForbiddenReason(response, cm, msg)
|
||||||
|
|
||||||
@override_settings(ALLOWED_HOSTS=["www.example.com"])
|
@override_settings(ALLOWED_HOSTS=["www.example.com"])
|
||||||
def test_bad_origin_bad_protocol(self):
|
def test_bad_origin_bad_protocol(self):
|
||||||
@ -937,9 +939,8 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
|
|||||||
self.assertIs(mw._origin_verified(req), False)
|
self.assertIs(mw._origin_verified(req), False)
|
||||||
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
||||||
response = mw.process_view(req, post_form_view, (), {})
|
response = mw.process_view(req, post_form_view, (), {})
|
||||||
self.assertEqual(response.status_code, 403)
|
|
||||||
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
|
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
|
||||||
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % msg)
|
self.assertForbiddenReason(response, cm, msg)
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
ALLOWED_HOSTS=["www.example.com"],
|
ALLOWED_HOSTS=["www.example.com"],
|
||||||
@ -964,9 +965,8 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
|
|||||||
self.assertIs(mw._origin_verified(req), False)
|
self.assertIs(mw._origin_verified(req), False)
|
||||||
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
||||||
response = mw.process_view(req, post_form_view, (), {})
|
response = mw.process_view(req, post_form_view, (), {})
|
||||||
self.assertEqual(response.status_code, 403)
|
|
||||||
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
|
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
|
||||||
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % msg)
|
self.assertForbiddenReason(response, cm, msg)
|
||||||
self.assertEqual(mw.allowed_origins_exact, {"http://no-match.com"})
|
self.assertEqual(mw.allowed_origins_exact, {"http://no-match.com"})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
mw.allowed_origin_subdomains,
|
mw.allowed_origin_subdomains,
|
||||||
@ -990,9 +990,8 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
|
|||||||
self.assertIs(mw._origin_verified(req), False)
|
self.assertIs(mw._origin_verified(req), False)
|
||||||
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
with self.assertLogs("django.security.csrf", "WARNING") as cm:
|
||||||
response = mw.process_view(req, post_form_view, (), {})
|
response = mw.process_view(req, post_form_view, (), {})
|
||||||
self.assertEqual(response.status_code, 403)
|
|
||||||
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
|
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
|
||||||
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % msg)
|
self.assertForbiddenReason(response, cm, msg)
|
||||||
|
|
||||||
@override_settings(ALLOWED_HOSTS=["www.example.com"])
|
@override_settings(ALLOWED_HOSTS=["www.example.com"])
|
||||||
def test_good_origin_insecure(self):
|
def test_good_origin_insecure(self):
|
||||||
|
@ -94,6 +94,28 @@ class DefaultLoggingTests(
|
|||||||
|
|
||||||
|
|
||||||
class LoggingAssertionMixin:
|
class LoggingAssertionMixin:
|
||||||
|
|
||||||
|
def assertLogRecord(
|
||||||
|
self,
|
||||||
|
logger_cm,
|
||||||
|
level,
|
||||||
|
msg,
|
||||||
|
status_code,
|
||||||
|
exc_class=None,
|
||||||
|
):
|
||||||
|
self.assertEqual(
|
||||||
|
records_len := len(logger_cm.records),
|
||||||
|
1,
|
||||||
|
f"Wrong number of calls for {logger_cm=} in {level=} (expected 1, got "
|
||||||
|
f"{records_len}).",
|
||||||
|
)
|
||||||
|
record = logger_cm.records[0]
|
||||||
|
self.assertEqual(record.getMessage(), msg)
|
||||||
|
self.assertEqual(record.status_code, status_code)
|
||||||
|
if exc_class:
|
||||||
|
self.assertIsNotNone(record.exc_info)
|
||||||
|
self.assertEqual(record.exc_info[0], exc_class)
|
||||||
|
|
||||||
def assertLogsRequest(
|
def assertLogsRequest(
|
||||||
self, url, level, msg, status_code, logger="django.request", exc_class=None
|
self, url, level, msg, status_code, logger="django.request", exc_class=None
|
||||||
):
|
):
|
||||||
@ -102,17 +124,7 @@ class LoggingAssertionMixin:
|
|||||||
self.client.get(url)
|
self.client.get(url)
|
||||||
except views.UncaughtException:
|
except views.UncaughtException:
|
||||||
pass
|
pass
|
||||||
self.assertEqual(
|
self.assertLogRecord(cm, level, msg, status_code, exc_class)
|
||||||
len(cm.records),
|
|
||||||
1,
|
|
||||||
"Wrong number of calls for logger %r in %r level." % (logger, level),
|
|
||||||
)
|
|
||||||
record = cm.records[0]
|
|
||||||
self.assertEqual(record.getMessage(), msg)
|
|
||||||
self.assertEqual(record.status_code, status_code)
|
|
||||||
if exc_class:
|
|
||||||
self.assertIsNotNone(record.exc_info)
|
|
||||||
self.assertEqual(record.exc_info[0], exc_class)
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(DEBUG=True, ROOT_URLCONF="logging_tests.urls")
|
@override_settings(DEBUG=True, ROOT_URLCONF="logging_tests.urls")
|
||||||
@ -135,6 +147,14 @@ class HandlerLoggingTests(
|
|||||||
msg="Not Found: /does_not_exist/",
|
msg="Not Found: /does_not_exist/",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def test_async_page_not_found_warning(self):
|
||||||
|
logger = "django.request"
|
||||||
|
level = "WARNING"
|
||||||
|
with self.assertLogs(logger, level) as cm:
|
||||||
|
await self.async_client.get("/does_not_exist/")
|
||||||
|
|
||||||
|
self.assertLogRecord(cm, level, "Not Found: /does_not_exist/", 404)
|
||||||
|
|
||||||
def test_page_not_found_raised(self):
|
def test_page_not_found_raised(self):
|
||||||
self.assertLogsRequest(
|
self.assertLogsRequest(
|
||||||
url="/does_not_exist_raised/",
|
url="/does_not_exist_raised/",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user