diff --git a/content/underskriftskampanje/medisinsk-cannabis-pa-resept/90-form.php b/content/underskriftskampanje/medisinsk-cannabis-pa-resept/90-form.php index f5de520..0e7bd25 100644 --- a/content/underskriftskampanje/medisinsk-cannabis-pa-resept/90-form.php +++ b/content/underskriftskampanje/medisinsk-cannabis-pa-resept/90-form.php @@ -1,4 +1,7 @@
Har du allerede signert, men ikke mottatt bekreftelsesmail? Send bekreftelse på nytt
+ = $petition_signatures ?? '' ?> diff --git a/content/underskriftskampanje/medisinsk-cannabis-pa-resept/send-bekreftelse-pa-nytt/01-content.php b/content/underskriftskampanje/medisinsk-cannabis-pa-resept/send-bekreftelse-pa-nytt/01-content.php new file mode 100644 index 0000000..c27f249 --- /dev/null +++ b/content/underskriftskampanje/medisinsk-cannabis-pa-resept/send-bekreftelse-pa-nytt/01-content.php @@ -0,0 +1,21 @@ +Skriv inn e-postadressen du brukte da du signerte, så sender vi en ny bekreftelseslenke.
+ + + + + + + +Tilbake til underskriftskampanjen
diff --git a/content/underskriftskampanje/medisinsk-cannabis-pa-resept/send-bekreftelse-pa-nytt/metadata.ini b/content/underskriftskampanje/medisinsk-cannabis-pa-resept/send-bekreftelse-pa-nytt/metadata.ini new file mode 100644 index 0000000..b76829d --- /dev/null +++ b/content/underskriftskampanje/medisinsk-cannabis-pa-resept/send-bekreftelse-pa-nytt/metadata.ini @@ -0,0 +1,8 @@ +title = "Send bekreftelse på nytt" +plugins = "petition-form" +petition_id = "medisinsk-cannabis-pa-resept" +petition_title = "Underskriftskampanje: Ja til medisinsk cannabis på resept!" + +[en] +title = "Resend confirmation" +petition_title = "Petition: Yes to medical cannabis on prescription!" diff --git a/content/underskriftskampanje/medisinsk-cannabis-pa-resept/send-bekreftelse-pa-nytt/styles.css b/content/underskriftskampanje/medisinsk-cannabis-pa-resept/send-bekreftelse-pa-nytt/styles.css new file mode 100644 index 0000000..9d0d6fc --- /dev/null +++ b/content/underskriftskampanje/medisinsk-cannabis-pa-resept/send-bekreftelse-pa-nytt/styles.css @@ -0,0 +1 @@ +@import url("../styles.css"); diff --git a/content/underskriftskampanje/medisinsk-cannabis-pa-resept/takk/01-content.php b/content/underskriftskampanje/medisinsk-cannabis-pa-resept/takk/01-content.php index e7384f2..228644e 100644 --- a/content/underskriftskampanje/medisinsk-cannabis-pa-resept/takk/01-content.php +++ b/content/underskriftskampanje/medisinsk-cannabis-pa-resept/takk/01-content.php @@ -8,4 +8,6 @@ +Fikk du ikke e-posten? Send bekreftelse på nytt
+ diff --git a/custom/languages/no.ini b/custom/languages/no.ini index 3d6bb08..5684a99 100644 --- a/custom/languages/no.ini +++ b/custom/languages/no.ini @@ -79,6 +79,14 @@ gdpr_consent_text = "Jeg har lest per gdpr_consent_required = "Du må samtykke til personvernerklæringen for å signere." newsletter_subscribe = "Jeg ønsker å motta nyhetsbrev fra Stopp Lidelsen (omtrent 12 i året). Du kan melde deg av når som helst." email_rights_info = "Du har rett til innsyn, retting og sletting av dine opplysninger. Kontakt oss på kontakt@stopplidelsen.no eller klag til Datatilsynet (datatilsynet.no)." +resend_title = "Fikk du ikke e-posten?" +resend_description = "Skriv inn e-postadressen du brukte da du signerte, så sender vi en ny bekreftelseslenke." +resend_email_placeholder = "din@epost.no" +resend_submit = "Send på nytt" +resend_success = "Hvis e-postadressen finnes i vårt system, har vi sendt en ny bekreftelseslenke." +resend_not_found = "Vi fant ingen ubekreftet signatur med denne e-postadressen. Kanskje du skrev feil da du signerte? Du kan gjerne prøve å signere på nytt." +resend_already_confirmed = "Denne signaturen er allerede bekreftet." +resend_rate_limit = "Vennligst vent litt før du ber om en ny e-post." [regions] agder = "Agder" diff --git a/custom/plugins/page/petition-form.php b/custom/plugins/page/petition-form.php index f650744..1fca8d5 100644 --- a/custom/plugins/page/petition-form.php +++ b/custom/plugins/page/petition-form.php @@ -799,6 +799,105 @@ function petitionGetSignatureByToken(string $csvPath, string $token): ?array { return $signature; } +/** + * Get pending signature data by email address + * Returns signature data if found and pending, null otherwise + */ +function petitionGetPendingSignatureByEmail(string $csvPath, string $email): ?array { + if (!file_exists($csvPath)) { + return null; + } + + $fp = fopen($csvPath, 'r'); + if (!$fp) { + return null; + } + + $signature = null; + $email = strtolower(trim($email)); + + if (flock($fp, LOCK_SH)) { + fgetcsv($fp, null, ',', '"', ''); // Skip header + + // CSV format: timestamp, email, firstname, surname, region, display, status, token, token_created, ip_hash + while (($row = fgetcsv($fp, null, ',', '"', '')) !== false) { + if (isset($row[1]) && strtolower($row[1]) === $email) { + $signature = [ + 'email' => $row[1], + 'firstname' => $row[2], + 'surname' => $row[3], + 'region' => $row[4], + 'display' => $row[5], + 'status' => $row[6], + 'token' => $row[7], + 'token_created' => $row[8] ?? 0 + ]; + break; + } + } + + flock($fp, LOCK_UN); + } + + fclose($fp); + return $signature; +} + +/** + * Update token for an existing signature (for resend functionality) + */ +function petitionUpdateSignatureToken(string $csvPath, string $email, string $newToken): bool { + if (!file_exists($csvPath)) { + return false; + } + + $fp = fopen($csvPath, 'r+'); + if (!$fp) { + return false; + } + + if (!flock($fp, LOCK_EX)) { + fclose($fp); + return false; + } + + $rows = []; + $header = fgetcsv($fp, null, ',', '"', ''); + $rows[] = $header; + + $found = false; + $email = strtolower(trim($email)); + $currentTime = time(); + + while (($row = fgetcsv($fp, null, ',', '"', '')) !== false) { + if (isset($row[1]) && strtolower($row[1]) === $email && $row[6] === 'pending') { + $row[7] = $newToken; // Update token + $row[8] = $currentTime; // Update token_created + $found = true; + } + $rows[] = $row; + } + + if (!$found) { + flock($fp, LOCK_UN); + fclose($fp); + return false; + } + + // Rewrite file + rewind($fp); + ftruncate($fp, 0); + + foreach ($rows as $row) { + fputcsv($fp, $row, ',', '"', ''); + } + + flock($fp, LOCK_UN); + fclose($fp); + + return true; +} + /** * Send thank you email with delete link (with retry wrapper) */ @@ -1136,7 +1235,8 @@ function petitionGetPageData(?Context $ctx): ?array { $csvPath = petitionGetCsvPath($petitionId); // loadMetadata() already merges language-specific metadata via Hook::PROCESS_CONTENT - $petitionTitle = $metadata['title'] ?? $petitionId; + // Use petition_title if set (for subpages), otherwise fall back to page title + $petitionTitle = $metadata['petition_title'] ?? $metadata['title'] ?? $petitionId; $thankYouPage = $metadata['thank_you_page'] ?? 'takk'; $formErrors = []; @@ -1195,6 +1295,64 @@ function petitionGetPageData(?Context $ctx): ?array { } } + // Handle resend confirmation request (POST from thank-you page) + if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['petition_resend'])) { + $resendEmail = strtolower(trim($_POST['resend_email'] ?? '')); + + // Rate limit check (reuse existing IP rate limiting) + if (!petitionCheckIPRateLimit($petitionId . '-resend', 3, 300)) { + $confirmMessage = ['type' => 'error', 'text' => petitionT($ctx, 'petition', 'resend_rate_limit')]; + } elseif (empty($resendEmail) || !filter_var($resendEmail, FILTER_VALIDATE_EMAIL)) { + $confirmMessage = ['type' => 'error', 'text' => petitionT($ctx, 'petition', 'email_required')]; + } else { + // Look up signature by email + $signature = petitionGetPendingSignatureByEmail($csvPath, $resendEmail); + + if ($signature === null) { + // Email not found at all + $confirmMessage = ['type' => 'error', 'text' => petitionT($ctx, 'petition', 'resend_not_found')]; + } elseif ($signature['status'] === 'confirmed') { + // Already confirmed + $confirmMessage = ['type' => 'info', 'text' => petitionT($ctx, 'petition', 'resend_already_confirmed')]; + } else { + // Generate new token and update signature + $newToken = bin2hex(random_bytes(32)); + if (petitionUpdateSignatureToken($csvPath, $resendEmail, $newToken)) { + // Build confirmation URL + $langPrefix = $ctx->get('langPrefix', ''); + $currentPath = trim($ctx->requestPath, '/'); + // Remove subpage suffixes to get petition base path + $currentPath = preg_replace('#/(takk|send-bekreftelse-pa-nytt)$#', '', $currentPath); + $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; + $host = $_SERVER['HTTP_HOST']; + $confirmUrl = "{$protocol}://{$host}{$langPrefix}/{$currentPath}/?confirm={$newToken}#sign-now"; + + // Send confirmation email + $signatureData = [ + 'email' => $signature['email'], + 'firstname' => $signature['firstname'], + 'surname' => $signature['surname'] + ]; + + if (petitionSendConfirmationEmail($signatureData, $confirmUrl, $petitionTitle, $petitionId, $ctx)) { + $confirmMessage = ['type' => 'success', 'text' => petitionT($ctx, 'petition', 'resend_success')]; + } else { + $confirmMessage = ['type' => 'error', 'text' => petitionT($ctx, 'petition', 'error_email_send')]; + } + } else { + $confirmMessage = ['type' => 'error', 'text' => petitionT($ctx, 'petition', 'resend_not_found')]; + } + } + } + + // Store message in session and redirect back (PRG pattern) + $_SESSION['petition_resend_message'] = $confirmMessage; + $langPrefix = $ctx->get('langPrefix', ''); + $currentPath = trim($ctx->requestPath, '/'); + header("Location: {$langPrefix}/{$currentPath}/"); + exit; + } + // Handle form submission if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['petition_submit'])) { @@ -1401,5 +1559,11 @@ Hooks::add(Hook::TEMPLATE_VARS, function(array $vars, Context $ctx) { unset($_SESSION['petition_subscribed_newsletter']); } + // Check for resend confirmation message (for thank you page) + if (isset($_SESSION['petition_resend_message'])) { + $vars['petition_resend_message'] = $_SESSION['petition_resend_message']; + unset($_SESSION['petition_resend_message']); + } + return $vars; });