111 lines
4.7 KiB
PHP
111 lines
4.7 KiB
PHP
<?php
|
|
/**
|
|
* File: ResendVerificationService.php
|
|
* Version: 1.4
|
|
* Path: /app/Services/ResendVerificationService.php
|
|
* Purpose: Encapsulates logic for validating, logging, and processing verification email resends.
|
|
* Project: Wizdom Networks Website
|
|
*/
|
|
|
|
namespace WizdomNetworks\WizeWeb\Services;
|
|
|
|
use WizdomNetworks\WizeWeb\Utilities\Database;
|
|
use WizdomNetworks\WizeWeb\Utilities\Logger;
|
|
use WizdomNetworks\WizeWeb\Services\EmailService;
|
|
use WizdomNetworks\WizeWeb\Services\VerificationService;
|
|
|
|
class ResendVerificationService
|
|
{
|
|
/**
|
|
* @var EmailService Handles email composition and delivery.
|
|
*/
|
|
private EmailService $emailService;
|
|
|
|
/**
|
|
* @var VerificationService Handles generation and storage of verification codes.
|
|
*/
|
|
private VerificationService $verificationService;
|
|
|
|
/**
|
|
* Constructor initializes email and verification services.
|
|
*/
|
|
public function __construct()
|
|
{
|
|
$this->emailService = new EmailService();
|
|
$this->verificationService = new VerificationService();
|
|
}
|
|
|
|
/**
|
|
* Attempts to resend a verification email for a given type and address.
|
|
* Performs rate limiting checks and logs the attempt if permitted.
|
|
* Generates and assigns a new verification code and triggers an email send.
|
|
*
|
|
* @param string $type Either 'contact' or 'newsletter'
|
|
* @param string $email Email address to resend to
|
|
* @return array ['success' => bool, 'message' => string] Outcome and message for user feedback
|
|
*/
|
|
public function attemptResend(string $type, string $email): array
|
|
{
|
|
try {
|
|
$db = Database::getConnection();
|
|
|
|
// Rate limit: no more than 3 per day
|
|
$stmt = $db->prepare("SELECT COUNT(*) FROM verification_attempts WHERE email = ? AND type = ? AND attempted_at >= NOW() - INTERVAL 1 DAY");
|
|
$stmt->execute([$email, $type]);
|
|
if ((int)$stmt->fetchColumn() >= 3) {
|
|
return ['success' => false, 'message' => 'You have reached the daily resend limit. Please try again tomorrow.'];
|
|
}
|
|
|
|
// Rate limit: no more than 1 every 5 minutes
|
|
$stmt = $db->prepare("SELECT COUNT(*) FROM verification_attempts WHERE email = ? AND type = ? AND attempted_at >= NOW() - INTERVAL 5 MINUTE");
|
|
$stmt->execute([$email, $type]);
|
|
if ((int)$stmt->fetchColumn() > 0) {
|
|
return ['success' => false, 'message' => 'You must wait a few minutes before requesting another verification email.'];
|
|
}
|
|
|
|
// Log attempt
|
|
$stmt = $db->prepare("INSERT INTO verification_attempts (email, type, attempted_at, ip_address, user_agent) VALUES (?, ?, NOW(), ?, ?)");
|
|
$stmt->execute([
|
|
$email,
|
|
$type,
|
|
$_SERVER['REMOTE_ADDR'] ?? 'unknown',
|
|
$_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
|
|
]);
|
|
|
|
$code = $this->verificationService->generateCode();
|
|
$expiry = $this->verificationService->getExpirationTime();
|
|
|
|
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) {
|
|
return ['success' => false, 'message' => 'Email is already verified or not found.'];
|
|
}
|
|
|
|
$this->verificationService->assignCodeToRecord('subscribers', $row['id'], $code, $expiry);
|
|
$this->emailService->sendVerificationEmail($email, $code, 'verify_newsletter');
|
|
} elseif ($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) {
|
|
return ['success' => false, 'message' => 'Email is already verified or not found.'];
|
|
}
|
|
|
|
$this->verificationService->assignCodeToRecord('contact_messages', $row['id'], $code, $expiry);
|
|
$this->emailService->sendVerificationEmail($email, $code, 'verify_contact');
|
|
} else {
|
|
return ['success' => false, 'message' => 'Invalid verification type specified.'];
|
|
}
|
|
|
|
return ['success' => true, 'message' => 'We just sent you a new verification link.'];
|
|
} catch (\Throwable $e) {
|
|
Logger::error("ResendVerificationService::attemptResend exception: " . $e->getMessage());
|
|
return ['success' => false, 'message' => 'An unexpected error occurred.'];
|
|
}
|
|
}
|
|
}
|