| | |
| | | <?php |
| | | namespace JVBase\integrations; |
| | | |
| | | use JVBase\meta\MetaManager; |
| | | use WP_Error; |
| | | if (!defined('ABSPATH')) { |
| | | exit; |
| | |
| | | { |
| | | private string $site_key; |
| | | private string $secret_key; |
| | | private bool $auto_protect_forms = true; |
| | | private string $theme = 'light'; |
| | | private string $size = 'normal'; |
| | | |
| | |
| | | { |
| | | $this->site_key = $this->credentials['site_key'] ?? ''; |
| | | $this->secret_key = $this->credentials['secret_key'] ?? ''; |
| | | $this->auto_protect_forms = $this->credentials['auto_protect_forms'] ?? true; |
| | | $this->theme = $this->credentials['theme'] ?? 'light'; |
| | | $this->size = $this->credentials['size'] ?? 'normal'; |
| | | |
| | | if ($this->isSetUp()) { |
| | | $this->initializeTurnstileProtection(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | return array_key_exists('success', $result); |
| | | } |
| | | |
| | | /** |
| | | * Initialize Turnstile protection on various forms |
| | | */ |
| | | private function initializeTurnstileProtection(): void |
| | | { |
| | | // Skip on local development if configured |
| | | if (defined('JVB_LOCAL') && strpos(get_home_url(), JVB_LOCAL) !== false) { |
| | | return; |
| | | } |
| | | |
| | | if (!$this->auto_protect_forms) { |
| | | return; |
| | | } |
| | | |
| | | // WordPress login/registration forms |
| | | add_action('login_enqueue_scripts', [$this, 'enqueueTurnstileScripts']); |
| | | add_action('login_form', [$this, 'renderTurnstile']); |
| | | add_action('register_form', [$this, 'renderTurnstile']); |
| | | add_action('lostpassword_form', [$this, 'renderTurnstile']); |
| | | |
| | | // Verification hooks |
| | | add_filter('authenticate', [$this, 'verifyLoginTurnstile'], 99, 3); |
| | | add_filter('registration_errors', [$this, 'verifyRegisterTurnstile'], 10, 3); |
| | | add_action('lostpassword_post', [$this, 'verifyLostpasswordTurnstile']); |
| | | |
| | | // Custom form support |
| | | add_action('jvb_form_before_submit', [$this, 'renderTurnstile']); |
| | | add_filter('jvb_form_validate', [$this, 'validateFormTurnstile'], 10, 2); |
| | | } |
| | | |
| | | protected function validateCredentials(array $credentials): bool |
| | | { |
| | | if (empty($credentials['site_key'])) { |
| | |
| | | */ |
| | | public function verifyTurnstile(?string $token = null, string $remote_ip = ''): bool |
| | | { |
| | | $this->ensureInitialized(); |
| | | if (!$this->isSetUp()) { |
| | | return false; |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * Verify login form Turnstile |
| | | */ |
| | | public function verifyLoginTurnstile($user, string $username, string $password) |
| | | { |
| | | // Skip verification if already logged in or no credentials |
| | | if (is_user_logged_in() || empty($username) || empty($password)) { |
| | | return $user; |
| | | } |
| | | |
| | | // Skip on AJAX requests for compatibility |
| | | if (wp_doing_ajax()) { |
| | | return $user; |
| | | } |
| | | |
| | | // If already have an error, return it |
| | | if (is_wp_error($user)) { |
| | | return $user; |
| | | } |
| | | |
| | | // Verify Turnstile |
| | | if (!$this->verifyTurnstile()) { |
| | | return new \WP_Error( |
| | | 'turnstile_verification_failed', |
| | | '<strong>ERROR</strong>: Please complete the security check.' |
| | | ); |
| | | } |
| | | |
| | | return $user; |
| | | } |
| | | |
| | | /** |
| | | * Verify registration form Turnstile |
| | | */ |
| | | public function verifyRegisterTurnstile($errors, string $sanitized_user_login, string $user_email) |
| | | { |
| | | if (!$this->verifyTurnstile()) { |
| | | $errors->add( |
| | | 'turnstile_verification_failed', |
| | | '<strong>ERROR</strong>: Please complete the security check.' |
| | | ); |
| | | } |
| | | return $errors; |
| | | } |
| | | |
| | | /** |
| | | * Verify lost password form Turnstile |
| | | */ |
| | | public function verifyLostpasswordTurnstile($errors): void |
| | | { |
| | | if (!$this->verifyTurnstile()) { |
| | | if (!is_wp_error($errors)) { |
| | | $errors = new \WP_Error(); |
| | | } |
| | | $errors->add( |
| | | 'turnstile_verification_failed', |
| | | '<strong>ERROR</strong>: Please complete the security check.' |
| | | ); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Validate Turnstile for custom JVB forms |
| | | */ |
| | | public function validateFormTurnstile(array $errors, array $form_data): array |
| | | { |
| | | if (!$this->verifyTurnstile()) { |
| | | $errors[] = 'Please complete the security verification.'; |
| | | } |
| | | return $errors; |
| | | } |
| | | |
| | | /** |
| | | * Get site key for frontend use |
| | | */ |
| | | public function getSiteKey(): string |
| | |
| | | // Cloudflare Turnstile uses POST parameters, not headers |
| | | return []; |
| | | } |
| | | |
| | | protected function getApiUrl(string $endpoint, ?string $baseKey = null): string |
| | | { |
| | | // Only used for direct API calls, not through base class methods |
| | | return 'https://challenges.cloudflare.com/turnstile/v0/siteverify'; |
| | | } |
| | | } |