From 49aee0b4466af4baeb16709b0c0112955d93fd86 Mon Sep 17 00:00:00 2001 From: peptiderepo Date: Sat, 18 Apr 2026 07:24:01 +0700 Subject: [PATCH] fix: add Cloudflare token to encrypted fields list (fixes 401 on image gen) prautoblogger_cloudflare_ai_token was missing from the $encrypted array in sanitize_field(), so the token was stored as plaintext. On read, decrypt() failed on the non-encrypted value and returned empty string, causing HTTP 401 on every Cloudflare Workers AI call. Fix: add the field to the encrypted list so future saves encrypt it. Also add legacy plaintext detection in get_api_token() and the validator so the existing DB value works immediately and gets auto-encrypted on first use. Co-Authored-By: Claude Opus 4.6 --- includes/admin/class-admin-page.php | 2 +- .../class-cloudflare-image-support.php | 19 ++++++++++++++++--- .../class-cloudflare-image-validator.php | 10 ++++++++-- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/includes/admin/class-admin-page.php b/includes/admin/class-admin-page.php index e5a1ebc..fa6381c 100755 --- a/includes/admin/class-admin-page.php +++ b/includes/admin/class-admin-page.php @@ -242,7 +242,7 @@ class PRAutoBlogger_Admin_Page { $option_name = substr( $filter, strlen( 'sanitize_option_' ) ); } - $encrypted = [ 'prautoblogger_openrouter_api_key', 'prautoblogger_ga4_credentials_json' ]; + $encrypted = [ 'prautoblogger_openrouter_api_key', 'prautoblogger_ga4_credentials_json', 'prautoblogger_cloudflare_ai_token' ]; if ( in_array( $option_name, $encrypted, true ) ) { // Empty value means password field wasn't touched — keep existing. if ( '' === $value ) { diff --git a/includes/providers/class-cloudflare-image-support.php b/includes/providers/class-cloudflare-image-support.php index e4a05a2..a0afdb6 100644 --- a/includes/providers/class-cloudflare-image-support.php +++ b/includes/providers/class-cloudflare-image-support.php @@ -23,11 +23,24 @@ class PRAutoBlogger_Cloudflare_Image_Support { * @return string Plaintext token, or empty string if not set / decrypt fails. */ public function get_api_token(): string { - $encrypted = (string) get_option( 'prautoblogger_cloudflare_ai_token', '' ); - if ( '' === $encrypted ) { + $stored = (string) get_option( 'prautoblogger_cloudflare_ai_token', '' ); + if ( '' === $stored ) { return ''; } - return (string) PRAutoBlogger_Encryption::decrypt( $encrypted ); + + // If the token is already encrypted (has "enc:" prefix), decrypt it. + if ( PRAutoBlogger_Encryption::is_encrypted( $stored ) ) { + return (string) PRAutoBlogger_Encryption::decrypt( $stored ); + } + + // Legacy: token was saved as plaintext before the field was added to + // the encrypted list in sanitize_field(). Encrypt it now so future + // reads go through the normal path, then return the plaintext value. + $cipher = PRAutoBlogger_Encryption::encrypt( $stored ); + if ( '' !== $cipher ) { + update_option( 'prautoblogger_cloudflare_ai_token', $cipher ); + } + return $stored; } /** diff --git a/includes/providers/class-cloudflare-image-validator.php b/includes/providers/class-cloudflare-image-validator.php index 764c3f0..1aa295d 100644 --- a/includes/providers/class-cloudflare-image-validator.php +++ b/includes/providers/class-cloudflare-image-validator.php @@ -40,8 +40,14 @@ class PRAutoBlogger_Cloudflare_Image_Validator { ); } - $encrypted = (string) get_option( 'prautoblogger_cloudflare_ai_token', '' ); - $api_token = '' === $encrypted ? '' : (string) PRAutoBlogger_Encryption::decrypt( $encrypted ); + $stored = (string) get_option( 'prautoblogger_cloudflare_ai_token', '' ); + $api_token = ''; + if ( '' !== $stored ) { + // Handle legacy plaintext tokens (saved before the field was in the encrypted list). + $api_token = PRAutoBlogger_Encryption::is_encrypted( $stored ) + ? (string) PRAutoBlogger_Encryption::decrypt( $stored ) + : $stored; + } if ( '' === $api_token ) { return $this->err( 'token_empty',