'', 'token' => '', 'client' => 0]; /** A row in the log for a password link - $user_id 0 when the address has no account. */ $reset_log = function ($action, $description, $user_id, $client_id) use ($mysqli, $ip, $user_agent) { mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Client Login', log_action = '" . escapeSql($action) . "', log_description = '" . escapeSql($description) . "', log_ip = '$ip', log_user_agent = '$user_agent', log_client_id = " . intval($client_id) . ", log_user_id = " . intval($user_id)); logForwardQueue('audit', mysqli_insert_id($mysqli)); }; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['password_reset_email_request']) && $can_email) { $email = trim((string) ($_POST['email'] ?? '')); // From one address, ten asks in ten minutes is plenty - after that, nothing is sent $asked = intval(mysqli_fetch_row(mysqli_query($mysqli, "SELECT COUNT(*) FROM logs WHERE log_type = 'Client Login' AND log_action = 'Reset Requested' AND log_ip = '$ip' AND log_created_at > NOW() - INTERVAL 10 MINUTE"))[0]); $row = null; if ($asked < 10 && filter_var($email, FILTER_VALIDATE_EMAIL)) { $email_sql = escapeSql($email); $row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT user_id, user_email, contact_name, contact_client_id FROM users JOIN contacts ON contact_user_id = user_id JOIN clients ON client_id = contact_client_id WHERE user_email = '$email_sql' AND user_type = 2 AND user_auth_method = 'local' AND user_status = 1 AND user_archived_at IS NULL AND contact_archived_at IS NULL AND client_archived_at IS NULL LIMIT 1")); } $reset_log('Reset Requested', 'Asked for a portal password link for ' . mb_substr($email, 0, 200), intval($row['user_id'] ?? 0), intval($row['contact_client_id'] ?? 0)); if ($row) { $user_id = intval($row['user_id']); $recent = intval(mysqli_fetch_row(mysqli_query($mysqli, "SELECT COUNT(*) FROM logs WHERE log_type = 'Client Login' AND log_action = 'Reset Sent' AND log_user_id = $user_id AND log_created_at > NOW() - INTERVAL " . PORTAL_RESET_REQUEST_GAP_MINUTES . " MINUTE"))[0]); if (!$recent) { portalMailPasswordReset($user_id); $reset_log('Reset Sent', 'Emailed a portal password link to ' . $row['user_email'], $user_id, intval($row['contact_client_id'])); } } $message = "If there is a client portal account for that address, a link to reset its password is on its way. It works for " . PORTAL_RESET_LINK_MINUTES . " minutes."; $message_type = 'success'; } elseif ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['password_reset_set_password'])) { $link = ['email' => (string) ($_POST['email'] ?? ''), 'token' => (string) ($_POST['token'] ?? ''), 'client' => intval($_POST['client'] ?? 0)]; $link_user = portalPasswordLinkUser($link['email'], $link['token'], $link['client']); $password = (string) ($_POST['new_password'] ?? ''); if (!$link_user) { $message = 'That link has run out or has been used already. Ask for a new one below.'; } elseif (($problem = userPasswordProblem($password)) !== '') { $message = $problem; } elseif ($password !== (string) ($_POST['confirm_password'] ?? '')) { $message = 'The two passwords are not the same - type it again in both.'; } else { $user_id = intval($link_user['user_id']); $hash = escapeSql(password_hash($password, PASSWORD_DEFAULT)); mysqli_query($mysqli, "UPDATE users SET user_password = '$hash' WHERE user_id = $user_id AND user_type = 2"); portalPasswordLinkClear($user_id); $reset_log('Password Reset', 'Set a new portal password from an emailed link', $user_id, $link['client']); portalMailAccountChange($link_user['user_email'], $link_user['contact_name'], 'password_link'); $_SESSION['login_message'] = 'Your password is set - sign in with it below.'; $_SESSION['login_message_type'] = 'success'; header("Location: /login.php"); exit(); } } elseif (isset($_GET['token'])) { $link = ['email' => (string) ($_GET['email'] ?? ''), 'token' => (string) $_GET['token'], 'client' => intval($_GET['client'] ?? 0)]; $link_user = portalPasswordLinkUser($link['email'], $link['token'], $link['client']); if (!$link_user) { $message = 'That link has run out or has been used already.' . ($can_email ? ' Ask for a new one below.' : ' Ask us for a new one.'); } } ?> <?= escapeHtml($company_name) ?> | <?= $link_user ? 'Set your password' : 'Reset your password' ?>