Skip to content

Commit 32fd8de

Browse files
committed
[4.2.x] Added helpers in csrf_tests and logging_tests to assert logs from log_response().
Backport of ad6f998 from main.
1 parent acbe655 commit 32fd8de

File tree

2 files changed

+57
-38
lines changed

2 files changed

+57
-38
lines changed

tests/csrf_tests/tests.py

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
import re
23

34
from django.conf import settings
@@ -57,6 +58,21 @@ def assertMaskedSecretCorrect(self, masked_secret, secret):
5758
actual = _unmask_cipher_token(masked_secret)
5859
self.assertEqual(actual, secret)
5960

61+
def assertForbiddenReason(
62+
self, response, logger_cm, reason, levelno=logging.WARNING
63+
):
64+
self.assertEqual(
65+
records_len := len(logger_cm.records),
66+
1,
67+
f"Unexpected number of records for {logger_cm=} in {levelno=} (expected 1, "
68+
f"got {records_len}).",
69+
)
70+
record = logger_cm.records[0]
71+
self.assertEqual(record.getMessage(), "Forbidden (%s): " % reason)
72+
self.assertEqual(record.levelno, levelno)
73+
self.assertEqual(record.status_code, 403)
74+
self.assertEqual(response.status_code, 403)
75+
6076

6177
class CsrfFunctionTests(CsrfFunctionTestMixin, SimpleTestCase):
6278
def test_unmask_cipher_token(self):
@@ -347,8 +363,7 @@ def _check_bad_or_missing_cookie(self, cookie, expected):
347363
mw.process_request(req)
348364
with self.assertLogs("django.security.csrf", "WARNING") as cm:
349365
resp = mw.process_view(req, post_form_view, (), {})
350-
self.assertEqual(403, resp.status_code)
351-
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % expected)
366+
self.assertForbiddenReason(resp, cm, expected)
352367

353368
def test_no_csrf_cookie(self):
354369
"""
@@ -373,9 +388,8 @@ def _check_bad_or_missing_token(
373388
mw.process_request(req)
374389
with self.assertLogs("django.security.csrf", "WARNING") as cm:
375390
resp = mw.process_view(req, post_form_view, (), {})
376-
self.assertEqual(403, resp.status_code)
377391
self.assertEqual(resp["Content-Type"], "text/html; charset=utf-8")
378-
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % expected)
392+
self.assertForbiddenReason(resp, cm, expected)
379393

380394
def test_csrf_cookie_bad_or_missing_token(self):
381395
"""
@@ -480,18 +494,12 @@ def test_put_and_delete_rejected(self):
480494
mw = CsrfViewMiddleware(post_form_view)
481495
with self.assertLogs("django.security.csrf", "WARNING") as cm:
482496
resp = mw.process_view(req, post_form_view, (), {})
483-
self.assertEqual(403, resp.status_code)
484-
self.assertEqual(
485-
cm.records[0].getMessage(), "Forbidden (%s): " % REASON_NO_CSRF_COOKIE
486-
)
497+
self.assertForbiddenReason(resp, cm, REASON_NO_CSRF_COOKIE)
487498

488499
req = self._get_request(method="DELETE")
489500
with self.assertLogs("django.security.csrf", "WARNING") as cm:
490501
resp = mw.process_view(req, post_form_view, (), {})
491-
self.assertEqual(403, resp.status_code)
492-
self.assertEqual(
493-
cm.records[0].getMessage(), "Forbidden (%s): " % REASON_NO_CSRF_COOKIE
494-
)
502+
self.assertForbiddenReason(resp, cm, REASON_NO_CSRF_COOKIE)
495503

496504
def test_put_and_delete_allowed(self):
497505
"""
@@ -879,11 +887,7 @@ def test_reading_post_data_raises_unreadable_post_error(self):
879887
mw.process_request(req)
880888
with self.assertLogs("django.security.csrf", "WARNING") as cm:
881889
resp = mw.process_view(req, post_form_view, (), {})
882-
self.assertEqual(resp.status_code, 403)
883-
self.assertEqual(
884-
cm.records[0].getMessage(),
885-
"Forbidden (%s): " % REASON_CSRF_TOKEN_MISSING,
886-
)
890+
self.assertForbiddenReason(resp, cm, REASON_CSRF_TOKEN_MISSING)
887891

888892
def test_reading_post_data_raises_os_error(self):
889893
"""
@@ -908,9 +912,8 @@ def test_bad_origin_bad_domain(self):
908912
self.assertIs(mw._origin_verified(req), False)
909913
with self.assertLogs("django.security.csrf", "WARNING") as cm:
910914
response = mw.process_view(req, post_form_view, (), {})
911-
self.assertEqual(response.status_code, 403)
912915
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
913-
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % msg)
916+
self.assertForbiddenReason(response, cm, msg)
914917

915918
@override_settings(ALLOWED_HOSTS=["www.example.com"])
916919
def test_bad_origin_null_origin(self):
@@ -923,9 +926,8 @@ def test_bad_origin_null_origin(self):
923926
self.assertIs(mw._origin_verified(req), False)
924927
with self.assertLogs("django.security.csrf", "WARNING") as cm:
925928
response = mw.process_view(req, post_form_view, (), {})
926-
self.assertEqual(response.status_code, 403)
927929
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
928-
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % msg)
930+
self.assertForbiddenReason(response, cm, msg)
929931

930932
@override_settings(ALLOWED_HOSTS=["www.example.com"])
931933
def test_bad_origin_bad_protocol(self):
@@ -939,9 +941,8 @@ def test_bad_origin_bad_protocol(self):
939941
self.assertIs(mw._origin_verified(req), False)
940942
with self.assertLogs("django.security.csrf", "WARNING") as cm:
941943
response = mw.process_view(req, post_form_view, (), {})
942-
self.assertEqual(response.status_code, 403)
943944
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
944-
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % msg)
945+
self.assertForbiddenReason(response, cm, msg)
945946

946947
@override_settings(
947948
ALLOWED_HOSTS=["www.example.com"],
@@ -966,9 +967,8 @@ def test_bad_origin_csrf_trusted_origin_bad_protocol(self):
966967
self.assertIs(mw._origin_verified(req), False)
967968
with self.assertLogs("django.security.csrf", "WARNING") as cm:
968969
response = mw.process_view(req, post_form_view, (), {})
969-
self.assertEqual(response.status_code, 403)
970970
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
971-
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % msg)
971+
self.assertForbiddenReason(response, cm, msg)
972972
self.assertEqual(mw.allowed_origins_exact, {"http://no-match.com"})
973973
self.assertEqual(
974974
mw.allowed_origin_subdomains,
@@ -992,9 +992,8 @@ def test_bad_origin_cannot_be_parsed(self):
992992
self.assertIs(mw._origin_verified(req), False)
993993
with self.assertLogs("django.security.csrf", "WARNING") as cm:
994994
response = mw.process_view(req, post_form_view, (), {})
995-
self.assertEqual(response.status_code, 403)
996995
msg = REASON_BAD_ORIGIN % req.META["HTTP_ORIGIN"]
997-
self.assertEqual(cm.records[0].getMessage(), "Forbidden (%s): " % msg)
996+
self.assertForbiddenReason(response, cm, msg)
998997

999998
@override_settings(ALLOWED_HOSTS=["www.example.com"])
1000999
def test_good_origin_insecure(self):

tests/logging_tests/tests.py

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,28 @@ def test_django_logger_debug(self):
9494

9595

9696
class LoggingAssertionMixin:
97+
98+
def assertLogRecord(
99+
self,
100+
logger_cm,
101+
level,
102+
msg,
103+
status_code,
104+
exc_class=None,
105+
):
106+
self.assertEqual(
107+
records_len := len(logger_cm.records),
108+
1,
109+
f"Wrong number of calls for {logger_cm=} in {level=} (expected 1, got "
110+
f"{records_len}).",
111+
)
112+
record = logger_cm.records[0]
113+
self.assertEqual(record.getMessage(), msg)
114+
self.assertEqual(record.status_code, status_code)
115+
if exc_class:
116+
self.assertIsNotNone(record.exc_info)
117+
self.assertEqual(record.exc_info[0], exc_class)
118+
97119
def assertLogsRequest(
98120
self, url, level, msg, status_code, logger="django.request", exc_class=None
99121
):
@@ -102,17 +124,7 @@ def assertLogsRequest(
102124
self.client.get(url)
103125
except views.UncaughtException:
104126
pass
105-
self.assertEqual(
106-
len(cm.records),
107-
1,
108-
"Wrong number of calls for logger %r in %r level." % (logger, level),
109-
)
110-
record = cm.records[0]
111-
self.assertEqual(record.getMessage(), msg)
112-
self.assertEqual(record.status_code, status_code)
113-
if exc_class:
114-
self.assertIsNotNone(record.exc_info)
115-
self.assertEqual(record.exc_info[0], exc_class)
127+
self.assertLogRecord(cm, level, msg, status_code, exc_class)
116128

117129

118130
@override_settings(DEBUG=True, ROOT_URLCONF="logging_tests.urls")
@@ -135,6 +147,14 @@ def test_page_not_found_warning(self):
135147
msg="Not Found: /does_not_exist/",
136148
)
137149

150+
async def test_async_page_not_found_warning(self):
151+
logger = "django.request"
152+
level = "WARNING"
153+
with self.assertLogs(logger, level) as cm:
154+
await self.async_client.get("/does_not_exist/")
155+
156+
self.assertLogRecord(cm, level, "Not Found: /does_not_exist/", 404)
157+
138158
def test_page_not_found_raised(self):
139159
self.assertLogsRequest(
140160
url="/does_not_exist_raised/",

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy