Resolve PR review gaps across comments, security, feeds, and UX
All checks were successful
CI / nightly-e2e (pull_request) Has been skipped
CI / ci (pull_request) Successful in 48s

This commit is contained in:
Codex_B
2026-02-28 13:47:21 +00:00
parent 932b05cc02
commit 36ac487cbd
15 changed files with 325 additions and 7 deletions

View File

@@ -37,6 +37,7 @@ def article_og_image_url(context, article) -> str:
@register.simple_tag(takes_context=True)
def article_json_ld(context, article):
request = context["request"]
nonce = getattr(request, "csp_nonce", "")
data = {
"@context": "https://schema.org",
"@type": "Article",
@@ -49,5 +50,9 @@ def article_json_ld(context, article):
"image": _article_image_url(request, article),
}
return mark_safe(
'<script type="application/ld+json">' + json.dumps(data, ensure_ascii=True) + "</script>"
'<script type="application/ld+json" nonce="'
+ nonce
+ '">'
+ json.dumps(data, ensure_ascii=True)
+ "</script>"
)

View File

@@ -64,3 +64,38 @@ def test_article_comment_form_contains_csrf_token(client, home_page):
html = resp.content.decode()
assert resp.status_code == 200
assert "csrfmiddlewaretoken" in html
@pytest.mark.django_db
def test_consent_rejects_open_redirect(client, home_page):
resp = client.post(
"/consent/",
{"reject_all": "1"},
HTTP_REFERER="https://evil.example.com/phish",
)
assert resp.status_code == 302
assert resp["Location"] == "/"
@pytest.mark.django_db
def test_article_json_ld_script_has_csp_nonce(client, home_page):
index = ArticleIndexPage(title="Articles", slug="articles")
home_page.add_child(instance=index)
author = AuthorFactory()
article = ArticlePage(
title="Nonce Article",
slug="nonce-article",
author=author,
summary="summary",
body=[("rich_text", "<p>Body</p>")],
)
index.add_child(instance=article)
article.save_revision().publish()
resp = client.get("/articles/nonce-article/")
csp = resp["Content-Security-Policy"]
match = re.search(r"nonce-([^' ;]+)", csp)
assert match
nonce = match.group(1)
html = resp.content.decode()
assert f'type="application/ld+json" nonce="{nonce}"' in html

View File

@@ -2,6 +2,7 @@ from __future__ import annotations
from django.http import HttpRequest, HttpResponse, HttpResponseNotAllowed
from django.shortcuts import redirect, render
from django.utils.http import url_has_allowed_host_and_scheme
from apps.core.consent import ConsentService
@@ -24,6 +25,12 @@ def consent_view(request: HttpRequest) -> HttpResponse:
advertising = request.POST.get("advertising") in {"true", "1", "on"}
target = request.META.get("HTTP_REFERER", "/")
if not url_has_allowed_host_and_scheme(
url=target,
allowed_hosts={request.get_host()},
require_https=request.is_secure(),
):
target = "/"
response = redirect(target)
ConsentService.set_consent(response, analytics=analytics, advertising=advertising)
return response