Added helpers in csrf_tests and logging_tests to assert logs from log_response().
Some checks failed
Linters / flake8 (push) Has been cancelled
Linters / isort (push) Has been cancelled
Linters / black (push) Has been cancelled
Tests / Windows, SQLite, Python 3.13 (push) Has been cancelled
Tests / JavaScript tests (push) Has been cancelled

This commit is contained in:
Natalia 2025-05-19 22:46:00 -03:00 committed by nessita
parent 8970468159
commit ad6f998898
2 changed files with 57 additions and 38 deletions

View file

@ -1,3 +1,4 @@
import logging
import re
from django.conf import settings
@ -55,6 +56,21 @@ class CsrfFunctionTestMixin:
actual = _unmask_cipher_token(masked_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):
def test_unmask_cipher_token(self):
@ -345,8 +361,7 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
mw.process_request(req)
with self.assertLogs("django.security.csrf", "WARNING") as cm:
resp = mw.process_view(req, post_form_view, (), {})
self.assertEqual(403, resp.status_code)
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % expected)
self.assertForbiddenReason(resp, cm, expected)
def test_no_csrf_cookie(self):
"""
@ -371,9 +386,8 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
mw.process_request(req)
with self.assertLogs("django.security.csrf", "WARNING") as cm:
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(cm.records[0].getMessage(), "Forbidden (%s): " % expected)
self.assertForbiddenReason(resp, cm, expected)
def test_csrf_cookie_bad_or_missing_token(self):
"""
@ -478,18 +492,12 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
mw = CsrfViewMiddleware(post_form_view)
with self.assertLogs("django.security.csrf", "WARNING") as cm:
resp = mw.process_view(req, post_form_view, (), {})
self.assertEqual(403, resp.status_code)
self.assertEqual(
cm.records[0].getMessage(), "Forbidden (%s): " % REASON_NO_CSRF_COOKIE
)
self.assertForbiddenReason(resp, cm, REASON_NO_CSRF_COOKIE)
req = self._get_request(method="DELETE")
with self.assertLogs("django.security.csrf", "WARNING") as cm:
resp = mw.process_view(req, post_form_view, (), {})
self.assertEqual(403, resp.status_code)
self.assertEqual(
cm.records[0].getMessage(), "Forbidden (%s): " % REASON_NO_CSRF_COOKIE
)
self.assertForbiddenReason(resp, cm, REASON_NO_CSRF_COOKIE)
def test_put_and_delete_allowed(self):
"""
@ -873,11 +881,7 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
mw.process_request(req)
with self.assertLogs("django.security.csrf", "WARNING") as cm:
resp = mw.process_view(req, post_form_view, (), {})
self.assertEqual(resp.status_code, 403)
self.assertEqual(
cm.records[0].getMessage(),
"Forbidden (%s): " % REASON_CSRF_TOKEN_MISSING,
)
self.assertForbiddenReason(resp, cm, REASON_CSRF_TOKEN_MISSING)
def test_reading_post_data_raises_os_error(self):
"""
@ -902,9 +906,8 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
self.assertIs(mw._origin_verified(req), False)
with self.assertLogs("django.security.csrf", "WARNING") as cm:
response = mw.process_view(req, post_form_view, (), {})
self.assertEqual(response.status_code, 403)
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"])
def test_bad_origin_null_origin(self):
@ -917,9 +920,8 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
self.assertIs(mw._origin_verified(req), False)
with self.assertLogs("django.security.csrf", "WARNING") as cm:
response = mw.process_view(req, post_form_view, (), {})
self.assertEqual(response.status_code, 403)
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"])
def test_bad_origin_bad_protocol(self):
@ -933,9 +935,8 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
self.assertIs(mw._origin_verified(req), False)
with self.assertLogs("django.security.csrf", "WARNING") as cm:
response = mw.process_view(req, post_form_view, (), {})
self.assertEqual(response.status_code, 403)
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"],
@ -960,9 +961,8 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
self.assertIs(mw._origin_verified(req), False)
with self.assertLogs("django.security.csrf", "WARNING") as cm:
response = mw.process_view(req, post_form_view, (), {})
self.assertEqual(response.status_code, 403)
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_origin_subdomains,
@ -986,9 +986,8 @@ class CsrfViewMiddlewareTestMixin(CsrfFunctionTestMixin):
self.assertIs(mw._origin_verified(req), False)
with self.assertLogs("django.security.csrf", "WARNING") as cm:
response = mw.process_view(req, post_form_view, (), {})
self.assertEqual(response.status_code, 403)
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"])
def test_good_origin_insecure(self):