Fix frontend CSRF, clean reader URLs, and review findings
CSRF / actions: - List action forms now send both REQUEST_TOKEN (Contao gate) and _token (Symfony, validated via isCsrfTokenValid) — mirrors the editor; fixes the 400/500 "Ungültiger CSRF-Token" on publish/toggle/duplicate/delete Public reader / URLs: - Reader & results read auto_item via Input::get (marks the route param used) so clean path URLs /<page>/<alias> no longer 404 - List controller generates path URLs via ['parameters' => '/'.$alias] - Allow re-participation in the same session after a 60s cooldown Review fixes: - Results: merge answer snapshots by questionId+type (no more split cards on label edits); seed "Vielleicht" when allowMaybe so screen matches Excel - Reader: replace generic answer hint with per-option "weiter zu Frage X" only when a jump is configured; strip HTML tags from survey description - PDF: render free-text frequency summary; drop duplicate "Minimum" label - Drag-sort: bundle SortableJS locally, drop the duplicated inline sort CSS/JS from _survey_assets, throttle the backend MutationObserver - Backend: move hardcoded tl_survey operation labels to TL_LANG (de+en) - Remove dead code: SurveyEditorVoter, SurveyPermissionService, categoryFilter/categorySummary + helpers, orphaned publishSurvey lang key Reader layout: - max-width 1000px (other views keep 1400px); back/next buttons fill the width as equal, card-sized halves; sort handle icon offset tweak Docs: update AI_HANDOVER (dual-token CSRF, clean URLs) and README Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -68,9 +68,9 @@ final class MemberSurveyListController extends AbstractFrontendModuleController
|
||||
'questionCount' => (int) ($survey['questionCount'] ?? 0),
|
||||
'participationCount' => (int) ($survey['participationCount'] ?? 0),
|
||||
'editUrl' => $editPage instanceof PageModel ? $this->generateContentUrl($editPage, ['survey' => $surveyId]) : null,
|
||||
'publicUrl' => $readerPage instanceof PageModel ? $this->generateContentUrl($readerPage, ['auto_item' => $alias]) : null,
|
||||
'draftUrl' => $readerPage instanceof PageModel ? $this->generateContentUrl($readerPage, ['auto_item' => $alias, 'preview' => '1']) : null,
|
||||
'resultsUrl' => $resultsPage instanceof PageModel ? $this->generateContentUrl($resultsPage, ['auto_item' => $alias]) : null,
|
||||
'publicUrl' => $readerPage instanceof PageModel ? $this->generateContentUrl($readerPage, ['parameters' => '/'.$alias]) : null,
|
||||
'draftUrl' => $readerPage instanceof PageModel ? $this->generateContentUrl($readerPage, ['parameters' => '/'.$alias, 'preview' => '1']) : null,
|
||||
'resultsUrl' => $resultsPage instanceof PageModel ? $this->generateContentUrl($resultsPage, ['parameters' => '/'.$alias]) : null,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -90,8 +90,16 @@ final class MemberSurveyListController extends AbstractFrontendModuleController
|
||||
{
|
||||
$surveyId = (int) $request->request->get('item_id', 0);
|
||||
$action = (string) $request->request->get('_survey_action');
|
||||
$token = (string) $request->request->get('_token', '');
|
||||
|
||||
if ($surveyId <= 0 || '' === $action) {
|
||||
throw new \RuntimeException('Ungültige Umfrage-Aktion.');
|
||||
}
|
||||
|
||||
// Session-basierter Symfony-Token (wie im Editor): zuverlässig für
|
||||
// eingeloggte Mitglieder. Der Contao-REQUEST_TOKEN ist cookie-gebunden
|
||||
// und im Frontend-Fragment-Flow nicht stabil verfügbar.
|
||||
if (!$this->isCsrfTokenValid($action.'-'.$surveyId, $token)) {
|
||||
throw new \RuntimeException('Ungültiger CSRF-Token.');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user