WizdomWeb/app/Controllers/ResendVerficationController...

104 lines
4.4 KiB
PHP

<?php
/**
* File: ResendVerificationController.php
* Version: 1.2
* Path: /app/Controllers/ResendVerificationController.php
* Purpose: Handles logic for resending verification emails for both newsletter and contact types with rate-limiting and expiration.
* Project: Wizdom Networks Website
*/
namespace WizdomNetworks\WizeWeb\Controllers;
use WizdomNetworks\WizeWeb\Core\View;
use WizdomNetworks\WizeWeb\Utils\Database;
use WizdomNetworks\WizeWeb\Utils\Logger;
use WizdomNetworks\WizeWeb\Services\NewsletterService;
use WizdomNetworks\WizeWeb\Services\ContactService;
class ResendVerificationController
{
public function handle(): void
{
$email = trim($_POST['email'] ?? '');
$type = trim($_POST['type'] ?? '');
if (!$email || !$type || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
View::render('pages/verify_failed', ['reason' => 'Invalid email or type.']);
return;
}
try {
$db = Database::getConnection();
// Rate limit: no more than 3 per day
$dailyCheck = $db->prepare("SELECT COUNT(*) FROM verification_attempts WHERE email = ? AND type = ? AND attempted_at >= NOW() - INTERVAL 1 DAY");
$dailyCheck->execute([$email, $type]);
$dailyCount = $dailyCheck->fetchColumn();
if ($dailyCount >= 3) {
View::render('pages/verify_failed', ['reason' => 'You have reached the daily resend limit. Please try again tomorrow.']);
return;
}
// Rate limit: no more than 1 every 5 minutes
$recentCheck = $db->prepare("SELECT COUNT(*) FROM verification_attempts WHERE email = ? AND type = ? AND attempted_at >= NOW() - INTERVAL 5 MINUTE");
$recentCheck->execute([$email, $type]);
$recentCount = $recentCheck->fetchColumn();
if ($recentCount > 0) {
View::render('pages/verify_failed', ['reason' => 'You must wait a few minutes before requesting another verification email.']);
return;
}
// Log attempt
$log = $db->prepare("INSERT INTO verification_attempts (email, type, attempted_at, ip_address, user_agent) VALUES (?, ?, NOW(), ?, ?)");
$log->execute([
$email,
$type,
$_SERVER['REMOTE_ADDR'] ?? 'unknown',
$_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
]);
$code = bin2hex(random_bytes(16));
$expiry = (new \DateTime())->modify('+72 hours')->format('Y-m-d H:i:s');
if ($type === 'newsletter') {
$stmt = $db->prepare("SELECT id, is_verified FROM subscribers WHERE email = ?");
$stmt->execute([$email]);
$row = $stmt->fetch();
if (!$row || (int)$row['is_verified'] === 1) {
View::render('pages/verify_failed', ['reason' => 'Email is already verified or not found.']);
return;
}
$update = $db->prepare("UPDATE subscribers SET verification_code = ?, is_verified = 0, verification_expires_at = ? WHERE id = ?");
$update->execute([$code, $expiry, $row['id']]);
NewsletterService::sendVerificationEmail($email, $code);
}
if ($type === 'contact') {
$stmt = $db->prepare("SELECT id, is_verified FROM contact_messages WHERE email = ? ORDER BY created_at DESC LIMIT 1");
$stmt->execute([$email]);
$row = $stmt->fetch();
if (!$row || (int)$row['is_verified'] === 1) {
View::render('pages/verify_failed', ['reason' => 'Email is already verified or not found.']);
return;
}
$update = $db->prepare("UPDATE contact_messages SET verification_code = ?, is_verified = 0, verification_expires_at = ? WHERE id = ?");
$update->execute([$code, $expiry, $row['id']]);
ContactService::sendVerificationEmail($email, $code);
}
View::render('pages/verify_success', [
'type' => $type,
'message' => 'We just sent you a new verification link.'
]);
} catch (\Throwable $e) {
Logger::error("Resend verification failed: " . $e->getMessage());
View::render('pages/verify_failed', ['reason' => 'Unexpected error occurred.']);
}
}
}