Rechtstexte ohne Zugangscode erreichbar (Voraussetzung fuer PayPal-/Google-Freischaltung)

Impressum, Datenschutz, AGB, Widerruf und Muster-Widerrufsformular liegen jetzt vor der
Zugangsschranke. Grund: PayPal prueft vor der Freischaltung von "Log in with PayPal" die
angegebene Datenschutz- und AGB-Adresse tatsaechlich nach — hinter der Schranke haette deren
Pruefteam nur die Code-Eingabe gesehen und die Freischaltung waere gescheitert. Google verlangt
beim Veroeffentlichen ebenfalls eine erreichbare Datenschutzerklaerung. Rechtlich ist das
ohnehin die saubere Seite; diese Seiten enthalten keine Shop- oder Kundendaten.

Bewusst eng gefasst: feste Liste der fuenf Seiten (kein Praefix-Match), dazu nur Stylesheets
und Logo/Favicons, damit die Seiten beim Pruefteam gestaltet ankommen. Die JS-Buendel aus
/_astro/ bleiben gesperrt — darin stecken u.a. die Produktdaten.

Lokal geprueft: die fuenf Rechtstexte + CSS + Logo liefern 200, waehrend Startseite, Shop,
Warenkorb, Checkout, Konto, Verwaltung, Produktseiten und alle JS-Buendel weiterhin auf die
Zugangscode-Seite umleiten und /api/verwaltung/ weiterhin 401 liefert.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
qcigano
2026-08-04 10:17:54 +02:00
co-authored by Claude Opus 5
parent be56c78c4f
commit 578da49fd1
+34
View File
@@ -42,6 +42,29 @@
import { COOKIE_NAME, ROLE_COOKIE_NAME, SESSION_TAGE, signSession, verifySession, getCookie } from "./_shared/auth.js"; import { COOKIE_NAME, ROLE_COOKIE_NAME, SESSION_TAGE, signSession, verifySession, getCookie } from "./_shared/auth.js";
/* Seiten, die auch ohne Zugangscode ausgeliefert werden (siehe Begründung unten in onRequest).
Bewusst als feste, vollständige Liste statt "alles was mit X anfängt" — so kann hier nicht
versehentlich mehr freigegeben werden als gewollt. */
const OEFFENTLICHE_SEITEN = new Set([
"/impressum",
"/datenschutz",
"/agb",
"/widerruf",
"/muster-widerrufsformular",
]);
/* Damit diese Seiten nicht nackt/ohne Gestaltung beim Prüfteam ankommen, sind zusätzlich die
rein gestalterischen Dateien freigegeben: Stylesheets sowie Logo/Favicons. Bewusst NUR
.css aus /_astro/ — die JavaScript-Bündel dort enthalten u.a. Produktdaten und bleiben
deshalb weiterhin hinter der Schranke. */
function istOeffentlichErreichbar(pfad) {
const ohneSlash = pfad.endsWith("/") && pfad.length > 1 ? pfad.slice(0, -1) : pfad;
if (OEFFENTLICHE_SEITEN.has(ohneSlash)) return true;
if (pfad.startsWith("/_astro/") && pfad.endsWith(".css")) return true;
if (/^\/(logo\.png|favicon\.ico|favicon-\d+x\d+\.png|apple-touch-icon\.png|icon-\d+(-maskable)?\.png)$/.test(pfad)) return true;
return false;
}
async function handleAuth(request, env) { async function handleAuth(request, env) {
let body; let body;
try { try {
@@ -89,6 +112,17 @@ export async function onRequest(context) {
return next(); return next();
} }
// Rechtstexte (Impressum, Datenschutz, AGB, Widerruf) bleiben IMMER ohne Zugangscode
// erreichbar. Grund: PayPal prüft vor der Freischaltung von "Log in with PayPal" die
// angegebene Datenschutz- und AGB-Adresse tatsächlich nach — hinter der Zugangsschranke
// sähe deren Prüfteam nur die Code-Eingabe, und die Freischaltung würde scheitern. Gleiches
// gilt für Google (verlangt beim Veröffentlichen eine erreichbare Datenschutzerklärung).
// Rechtlich ist das ohnehin die saubere Seite: Impressum und Datenschutzerklärung sollen
// "ständig verfügbar" sein. Diese Seiten enthalten keine Shop-/Kundendaten.
if (istOeffentlichErreichbar(url.pathname)) {
return next();
}
// Fail-open-Absicherung: fehlen die Zugangs-Secrets komplett (z.B. noch nicht gesetzt), lieber // Fail-open-Absicherung: fehlen die Zugangs-Secrets komplett (z.B. noch nicht gesetzt), lieber
// GAR KEINE Schranke scharf schalten, als sich selbst aus der eigenen Seite auszusperren. // GAR KEINE Schranke scharf schalten, als sich selbst aus der eigenen Seite auszusperren.
const codesKonfiguriert = !!(env.SITE_ACCESS_SECRET && (env.SITE_ACCESS_CODE_QCIGA || env.SITE_ACCESS_CODE_VANVAN)); const codesKonfiguriert = !!(env.SITE_ACCESS_SECRET && (env.SITE_ACCESS_CODE_QCIGA || env.SITE_ACCESS_CODE_VANVAN));