Files
main-site/apps/core/middleware.py
Claude 9d7821b94d
Some checks failed
CI / nightly-e2e (pull_request) Has been skipped
CI / deploy (pull_request) Has been skipped
CI / pr-e2e (pull_request) Successful in 1m26s
CI / ci (pull_request) Failing after 1m50s
Fix mypy typing for admin message guard
2026-03-15 17:39:53 +00:00

68 lines
2.3 KiB
Python

from __future__ import annotations
import secrets
from typing import Any, cast
from django.contrib.messages import get_messages
from .consent import ConsentService
class ConsentMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request.consent = ConsentService.get_consent(request)
return self.get_response(request)
class SecurityHeadersMiddleware:
def __init__(self, get_response):
self.get_response = get_response
ADMIN_PREFIXES = ("/cms/", "/django-admin/")
def __call__(self, request):
nonce = secrets.token_urlsafe(16)
request.csp_nonce = nonce
response = self.get_response(request)
if request.path.startswith(self.ADMIN_PREFIXES):
return response
response["Content-Security-Policy"] = (
f"default-src 'self'; "
f"script-src 'self' 'nonce-{nonce}' https://challenges.cloudflare.com; "
"style-src 'self' https://fonts.googleapis.com; "
"img-src 'self' data: blob:; "
"font-src 'self' https://fonts.gstatic.com; "
"connect-src 'self' https://challenges.cloudflare.com; "
"frame-src https://challenges.cloudflare.com; "
"object-src 'none'; "
"base-uri 'self'; "
"frame-ancestors 'self'"
)
response["Permissions-Policy"] = "camera=(), microphone=(), geolocation=()"
return response
class AdminMessageGuardMiddleware:
ADMIN_PREFIXES = ("/cms/", "/django-admin/")
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# The public site has no legitimate use of Django's shared flash queue.
# Drain any stale admin messages before frontend rendering can see them.
if not request.path.startswith(self.ADMIN_PREFIXES):
storage = cast(Any, get_messages(request))
list(storage)
storage._queued_messages = []
storage._loaded_data = []
for sub_storage in getattr(storage, "storages", []):
sub_storage._queued_messages = []
sub_storage._loaded_data = []
sub_storage.used = True
storage.used = True
return self.get_response(request)