Bugfixes aus dem Code-Review: - XSS: unescaptes $_SERVER['PHP_SELF'] in csvupload.php und letzteneintraege.php durch feste Seitennamen ersetzt. - Stripe-Webhook: Event-Deduplizierung (neue Tabelle stripe_webhook_events) gegen doppelte Verarbeitung/Dolibarr-Rechnungen bei Retry-Zustellung. - Stripe-Webhook: Tarifwechsel aus dem Kundenportal wird lokal nachgezogen (plan_code aus dem Preis-lookup_key bei subscription.updated). - Post-Redirect-Get fuer jahresauswertung, mailversenden und die Selbst-Stricheintragung - verhindert Doppelbuchung/Doppelversand per Browser-Refresh. - Jahresbonus: Mails erst nach erfolgreichem Commit; Restcent-Ausgleich beim letzten Empfaenger, damit die Summe exakt stimmt. - Verschachtelte HTML-Dokumente in csvupload/einzahlung/stricheintragen entfernt (Layout kommt aus header.php). - Rate-Limit fuer den Versand von E-Mail-Verifizierungslinks. Neue Funktionen: - Mitglieder koennen ihren zuletzt selbst eingetragenen Strich wieder stornieren (nur eigene Web-Eintraege, Kassenwart-Eintraege bleiben). - Monatsuebersicht des eigenen Verbrauchs im Mitglieder-Dashboard. - Automatische Zahlungserinnerung: opt-in pro Mandant ab der Warnschwelle, mit Intervall; Cron-Skript scripts/send-payment-reminders.php. - CSV-Import fuer Mitgliederlisten inkl. herunterladbarer Vorlage (mitglieder-vorlage.php), Semikolon-/Komma- und BOM-Erkennung. - Logo als PDF-Wasserzeichen pro Mandant (Upload in den Mandant- Einstellungen, geschuetzt unter var/tenant_logos/, ersetzt den Text-Wasserzeichen im Ausdruck). Robusterer Teilnehmer-Lookup im Dashboard ueber user_id (Fallback E-Mail).
83 lines
2.9 KiB
PHP
83 lines
2.9 KiB
PHP
<?php
|
|
|
|
require_once __DIR__ . '/functions.php';
|
|
require_once __DIR__ . '/app/saas-mail.php';
|
|
require_once __DIR__ . '/app/rate-limit.php';
|
|
|
|
$pdo = app_db_pdo();
|
|
$user = saas_require_login();
|
|
$errors = [];
|
|
$message = '';
|
|
$verificationLink = null;
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
app_require_csrf();
|
|
|
|
// Begrenzt den Versand von Verifizierungsmails pro Konto und IP, damit ein
|
|
// eingeloggter Nutzer den Mailversand nicht durch wiederholtes Absenden
|
|
// missbrauchen kann.
|
|
$userBucketOk = app_rate_limit_check($pdo, 'emailverify_user:' . (int)$user['user_id'], 5, 3600);
|
|
$ipBucketOk = app_rate_limit_check($pdo, 'emailverify_ip:' . app_client_ip(), 10, 3600);
|
|
|
|
if (!$userBucketOk || !$ipBucketOk) {
|
|
$errors[] = 'Es wurden bereits mehrere Verifizierungslinks angefordert. Bitte prüfe dein Postfach und versuche es später erneut.';
|
|
} else {
|
|
$result = saas_request_email_verification($pdo, (int)$user['user_id'], (int)$user['tenant_id']);
|
|
|
|
if ($result['ok']) {
|
|
if (!empty($result['already_verified'])) {
|
|
$message = 'Die E-Mail-Adresse ist bereits bestätigt.';
|
|
} else {
|
|
$message = 'Der Verifizierungslink wurde vorbereitet.';
|
|
if (saas_should_show_auth_links() && !empty($result['token'])) {
|
|
$verificationLink = 'email-verifizieren.php?token=' . urlencode((string)$result['token']);
|
|
}
|
|
if (!empty($result['token'])) {
|
|
saas_send_email_verification_mail((string)$user['email'], (string)$result['token']);
|
|
}
|
|
}
|
|
} else {
|
|
$errors = $result['errors'];
|
|
}
|
|
}
|
|
}
|
|
|
|
include 'header.php';
|
|
include 'headerline.php';
|
|
include 'nav.php';
|
|
?>
|
|
|
|
<section id="banner">
|
|
<div class="content">
|
|
<h2>E-Mail verifizieren</h2>
|
|
|
|
<?php if ($message !== ''): ?>
|
|
<div class="hint-box success">
|
|
<p><?php echo saas_html($message); ?></p>
|
|
<?php if ($verificationLink !== null): ?>
|
|
<p><a href="<?php echo saas_html($verificationLink); ?>">Dev-Link zur Verifizierung</a></p>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($errors !== []): ?>
|
|
<div class="hint-box error">
|
|
<?php foreach ($errors as $error): ?>
|
|
<p><?php echo saas_html($error); ?></p>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<form method="post" action="email-verifikation-senden.php">
|
|
<?php echo app_csrf_field(); ?>
|
|
<p><?php echo saas_html($user['email']); ?></p>
|
|
<ul class="actions">
|
|
<li><button type="submit">Verifizierungslink vorbereiten</button></li>
|
|
<li><a href="konto.php" class="button alt">Zurück</a></li>
|
|
</ul>
|
|
</form>
|
|
</div>
|
|
</section>
|
|
|
|
<?php include 'footer.php'; ?>
|