'error', 'message' => 'Something went wrong'); if (isset($_POST['email'])) { // Check rate limit first (3 attempts per 30 minutes to prevent abuse) if (RateLimitMiddleware::isLimited('password_reset', 3, 1800)) { $remaining = RateLimitMiddleware::getTimeRemaining('password_reset', 1800); $response['status'] = 'error'; $response['message'] = "Too many password reset requests. Please try again in {$remaining} seconds."; $response['retry_after'] = $remaining; echo json_encode($response); exit(); } $email = $_POST['email']; // Check if the email exists $sql = "SELECT user_id FROM users WHERE email = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param("s", $email); $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows > 0) { $user = $result->fetch_assoc(); $user_id = $user['user_id']; // Generate a unique token $token = bin2hex(random_bytes(50)); // Store the token and expiration time in the database $expiry = date("Y-m-d H:i:s", strtotime('+3 hour')); // Token expires in 3 hour $sql = "INSERT INTO password_resets (user_id, token, expires_at) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE token = VALUES(token), expires_at = VALUES(expires_at)"; $stmt = $conn->prepare($sql); $stmt->bind_param("iss", $user_id, $token, $expiry); $stmt->execute(); // Send the reset link to the user $reset_link = "https://www.4wdcsa.co.za/reset_password.php?token=$token"; $subject = "Password Reset Request"; $message = "Click the following link to reset your password: $reset_link"; sendEmail($email, $subject, $message); // Reset rate limit on successful request RateLimitMiddleware::reset('password_reset'); $response['status'] = 'success'; $response['message'] = 'Password reset link has been sent to your email.'; } else { // Increment rate limit even for non-existent emails (prevent email enumeration) RateLimitMiddleware::incrementAttempt('password_reset', 1800); $response['message'] = 'Email not found.'; } } echo json_encode($response); ?>