diff --git a/backend/celerybeat-schedule b/backend/celerybeat-schedule index f634f04d..9f71c945 100644 Binary files a/backend/celerybeat-schedule and b/backend/celerybeat-schedule differ diff --git a/igny8-wp-integration-plugin/admin/class-admin.php b/igny8-wp-integration-plugin/admin/class-admin.php index f6b41efd..ed1f4b00 100644 --- a/igny8-wp-integration-plugin/admin/class-admin.php +++ b/igny8-wp-integration-plugin/admin/class-admin.php @@ -161,31 +161,58 @@ class Igny8Admin { * Render settings page */ public function render_settings_page() { - // Handle form submission - if (isset($_POST['igny8_connect']) && check_admin_referer('igny8_settings_nonce')) { - $this->handle_connection(); + // Handle form submission (use wp_verify_nonce to avoid wp_die on failure) + if (isset($_POST['igny8_connect'])) { + if (empty($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'igny8_settings_nonce')) { + add_settings_error( + 'igny8_settings', + 'igny8_nonce', + __('Security check failed. Please refresh the page and try again.', 'igny8-bridge'), + 'error' + ); + } else { + $this->handle_connection(); + } } - - // Handle revoke API key - if (isset($_POST['igny8_revoke_api_key']) && check_admin_referer('igny8_revoke_api_key')) { - self::revoke_api_key(); - add_settings_error( - 'igny8_settings', - 'igny8_api_key_revoked', - __('API key revoked and removed from this site.', 'igny8-bridge'), - 'updated' - ); + + // Handle revoke API key (use wp_verify_nonce) + if (isset($_POST['igny8_revoke_api_key'])) { + if (empty($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'igny8_revoke_api_key')) { + add_settings_error( + 'igny8_settings', + 'igny8_nonce_revoke', + __('Security check failed. Could not revoke API key.', 'igny8-bridge'), + 'error' + ); + } else { + self::revoke_api_key(); + add_settings_error( + 'igny8_settings', + 'igny8_api_key_revoked', + __('API key revoked and removed from this site.', 'igny8-bridge'), + 'updated' + ); + } } - - // Handle webhook secret regeneration - if (isset($_POST['igny8_regenerate_secret']) && check_admin_referer('igny8_regenerate_secret')) { - $new_secret = igny8_regenerate_webhook_secret(); - add_settings_error( - 'igny8_settings', - 'igny8_secret_regenerated', - __('Webhook secret regenerated. Update it in your IGNY8 SaaS app settings.', 'igny8-bridge'), - 'updated' - ); + + // Handle webhook secret regeneration (use wp_verify_nonce) + if (isset($_POST['igny8_regenerate_secret'])) { + if (empty($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'igny8_regenerate_secret')) { + add_settings_error( + 'igny8_settings', + 'igny8_nonce_regen', + __('Security check failed. Could not regenerate secret.', 'igny8-bridge'), + 'error' + ); + } else { + $new_secret = igny8_regenerate_webhook_secret(); + add_settings_error( + 'igny8_settings', + 'igny8_secret_regenerated', + __('Webhook secret regenerated. Update it in your IGNY8 SaaS app settings.', 'igny8-bridge'), + 'updated' + ); + } } // Include settings template diff --git a/igny8-wp-integration-plugin/docs/WORDPRESS-PLUGIN-INTEGRATION.md b/igny8-wp-integration-plugin/docs/WORDPRESS-PLUGIN-INTEGRATION.md index cdaed2cf..e35f99eb 100644 --- a/igny8-wp-integration-plugin/docs/WORDPRESS-PLUGIN-INTEGRATION.md +++ b/igny8-wp-integration-plugin/docs/WORDPRESS-PLUGIN-INTEGRATION.md @@ -79,6 +79,8 @@ function igny8_get_headers() { } ``` +Note (required): The bridge now requires all three credentials to be provided in Settings → IGNY8 API: **Email**, **Password**, and **API Key**. These map to WordPress options `igny8_email`, `igny8_access_token`/`igny8_refresh_token`, and `igny8_api_key`. The API key will be stored with `igny8_store_secure_option()` when available; if any required credential is missing the plugin will not establish the connection. + --- ## API Client Class diff --git a/master-docs/WORDPRESS-PLUGIN-INTEGRATION.md b/master-docs/WORDPRESS-PLUGIN-INTEGRATION.md index dba2364b..40034b02 100644 --- a/master-docs/WORDPRESS-PLUGIN-INTEGRATION.md +++ b/master-docs/WORDPRESS-PLUGIN-INTEGRATION.md @@ -59,6 +59,8 @@ function igny8_get_headers() { } ``` +Note (required): To establish a bridge connection the plugin now requires three credentials to be provided and saved in the WordPress settings: **Email**, **Password**, and **API Key**. All three are stored as options (`igny8_email`, `igny8_access_token`/`igny8_refresh_token`, `igny8_api_key`) — the API key is stored using secure storage helpers when available. The bridge will refuse connection if any of these are missing. + --- ## API Client Class