From b2849880ec70d717b0d4143152fb860feeee0a38 Mon Sep 17 00:00:00 2001
From: Javier Casares
' . esc_html__( 'Account-level API key from the ROBOTSTXT store (create your free account there to get one). Optional — the free catalog works without it — but required to link your subscriptions, install premium plugins, and receive their updates. Encrypted before storage.', 'robotstxt-manager' ) . '
'; + printf( + '%s
', + wp_kses_post( + sprintf( + /* translators: %s: Registration URL. */ + __( 'Account-level API key from the ROBOTSTXT store (create your free account there to get one). Optional — the free catalog works without it — but required to link your subscriptions, install premium plugins, and receive their updates. Encrypted before storage.', 'robotstxt-manager' ), + esc_url( 'https://www.robotstxt.software/wp-login.php?action=register' ) + ) + ) + ); } // Action buttons. @@ -333,6 +342,14 @@ class Robotstxt_Manager_Settings { return is_string( $raw ) ? $raw : ''; } + // If the input is already encrypted (v2: prefix), it means the browser + // auto-filled the password field with the stored encrypted value. + // Return it as-is (already encrypted) rather than re-encrypting or + // trying to read the option (which may not be saved yet in the WP flow). + if ( str_starts_with( $plain, 'v2:' ) ) { + return $plain; + } + // Account keys are UUIDs issued by the store; reject anything that // cannot be one rather than storing a mangled key that only fails // later at connection time. @@ -379,7 +396,25 @@ class Robotstxt_Manager_Settings { wp_send_json_error( array( 'message' => __( 'Insufficient permissions.', 'robotstxt-manager' ) ) ); } - $client = Robotstxt_Manager_Core_Client::from_options(); + // Allow testing a key from the form field (not yet saved) by passing it in the request. + $input_key = ''; + if ( isset( $_POST['robotstxt_manager_api_key'] ) ) { + $unslashed = wp_unslash( $_POST['robotstxt_manager_api_key'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- sanitized below. + if ( is_string( $unslashed ) ) { + $input_key = sanitize_text_field( $unslashed ); + } + } + + $store_url = get_option( 'robotstxt_manager_store_url', 'https://www.robotstxt.software' ); + $store_url = is_string( $store_url ) ? $store_url : 'https://www.robotstxt.software'; + + // Use input key if provided, otherwise fall back to saved (decrypted) key. + if ( '' !== $input_key ) { + $client = new Robotstxt_Manager_Core_Client( $store_url, $input_key ); + } else { + $client = Robotstxt_Manager_Core_Client::from_options(); + } + $result = $client->test_connection(); if ( $result['ok'] ) { diff --git a/admin/js/robotstxt-manager-settings.js b/admin/js/robotstxt-manager-settings.js index c0f465a..f11d499 100644 --- a/admin/js/robotstxt-manager-settings.js +++ b/admin/js/robotstxt-manager-settings.js @@ -20,11 +20,14 @@ $btn.prop( 'disabled', true ).text( RobotstxtManagerSettings.i18n.testing ); $result.text( '' ).css( 'color', '' ); + var apiKey = $( '#robotstxt_manager_api_key' ).val(); + $.post( RobotstxtManagerSettings.ajaxUrl, { action: 'robotstxt_manager_test_connection', nonce: RobotstxtManagerSettings.nonce, + robotstxt_manager_api_key: apiKey, }, function ( response ) { if ( response.success ) { diff --git a/admin/views/page-settings.php b/admin/views/page-settings.php index 89b5d4a..83cd17d 100644 --- a/admin/views/page-settings.php +++ b/admin/views/page-settings.php @@ -11,6 +11,7 @@ if ( ! defined( 'ABSPATH' ) ) { ?>