prepare($sql); if ($stmt === false) { return null; } $stmt->bind_param('s', $username); $stmt->execute(); $result = $stmt->get_result(); $member = $result !== false ? $result->fetch_assoc() : null; $stmt->close(); return $member ?: null; } function auth_verify_password(array $member, string $password): bool { if (!empty($member['password_hash'])) { return password_verify($password, $member['password_hash']); } return hash_equals((string) $member['password'], $password); } function auth_upgrade_legacy_password(string $username, string $password): void { global $conn; $hash = password_hash($password, PASSWORD_DEFAULT); $sql = 'UPDATE members SET password_hash = ?, password_last_changed = NOW() WHERE username = ? LIMIT 1'; $stmt = $conn->prepare($sql); if ($stmt === false) { return; } $stmt->bind_param('ss', $hash, $username); $stmt->execute(); $stmt->close(); } function auth_record_login(string $username): void { global $conn; $sql = 'UPDATE members SET last_login_at = NOW() WHERE username = ? LIMIT 1'; $stmt = $conn->prepare($sql); if ($stmt === false) { return; } $stmt->bind_param('s', $username); $stmt->execute(); $stmt->close(); } function auth_attempt_login(string $username, string $password): ?array { $member = auth_find_member($username); if ($member === null) { return null; } if (!auth_verify_password($member, $password)) { return null; } if (empty($member['password_hash'])) { auth_upgrade_legacy_password($username, $password); $member = auth_find_member($username) ?: $member; } auth_record_login($username); return $member; } function auth_update_profile(string $username, ?string $email, ?string $growerName, ?string $phone): bool { global $conn; $sql = "UPDATE members SET email = NULLIF(?, ''), growername = NULLIF(?, ''), phone = NULLIF(?, ''), profile_updated_at = NOW() WHERE username = ? LIMIT 1"; $stmt = $conn->prepare($sql); if ($stmt === false) { return false; } $stmt->bind_param('ssss', $email, $growerName, $phone, $username); $success = $stmt->execute(); $stmt->close(); return (bool) $success; } function auth_set_password(string $username, string $password): bool { global $conn; $hash = password_hash($password, PASSWORD_DEFAULT); $sql = 'UPDATE members SET password_hash = ?, password = "", password_last_changed = NOW() WHERE username = ? LIMIT 1'; $stmt = $conn->prepare($sql); if ($stmt === false) { return false; } $stmt->bind_param('ss', $hash, $username); $success = $stmt->execute(); $stmt->close(); return (bool) $success; } function auth_change_password(string $username, string $currentPassword, string $newPassword, string $confirmPassword): array { if ($newPassword === '' || $confirmPassword === '') { return [false, 'Please enter and confirm the new password.']; } if ($newPassword !== $confirmPassword) { return [false, 'New password and confirmation do not match.']; } if (strlen($newPassword) < 8) { return [false, 'New password must be at least 8 characters long.']; } $member = auth_find_member($username); if ($member === null || !auth_verify_password($member, $currentPassword)) { return [false, 'Current password is incorrect.']; } if (!auth_set_password($username, $newPassword)) { return [false, 'Unable to update the password. Please try again.']; } return [true, 'Password updated successfully.']; } ?>