Merged in feature/MAW-855-import-code-into-aws (pull request #2)

code import from pantheon

* code import from pantheon
This commit is contained in:
Tony Volpe
2023-12-04 23:08:14 +00:00
parent 8c9b1312bc
commit 8f4b5efda6
4766 changed files with 185592 additions and 239967 deletions

View File

@@ -154,7 +154,7 @@ class Client {
if ( is_array( $body ) ) {
// We cast this to a new variable, because the array form of $body needs to be
// maintained so it can be passed into the request later on in the code.
if ( count( $body ) > 0 ) {
if ( array() !== $body ) {
$body_to_hash = wp_json_encode( self::_stringify_data( $body ) );
} else {
$body_to_hash = '';
@@ -206,7 +206,7 @@ class Client {
$request['headers'] = array_merge(
$args['headers'],
array(
'Authorization' => 'X_JETPACK ' . join( ' ', $header_pieces ),
'Authorization' => 'X_JETPACK ' . implode( ' ', $header_pieces ),
)
);

View File

@@ -114,6 +114,7 @@ class Error_Handler {
'invalid_body_hash',
'invalid_nonce',
'signature_mismatch',
'invalid_connection_owner',
);
/**
@@ -139,7 +140,7 @@ class Error_Handler {
// If the site gets reconnected, clear errors.
add_action( 'jetpack_site_registered', array( $this, 'delete_all_errors' ) );
add_action( 'jetpack_get_site_data_success', array( $this, 'delete_all_errors' ) );
add_action( 'jetpack_get_site_data_success', array( $this, 'delete_all_api_errors' ) );
add_filter( 'jetpack_connection_disconnect_site_wpcom', array( $this, 'delete_all_errors_and_return_unfiltered_value' ) );
add_filter( 'jetpack_connection_delete_all_tokens', array( $this, 'delete_all_errors_and_return_unfiltered_value' ) );
add_action( 'jetpack_unlinked_user', array( $this, 'delete_all_errors' ) );
@@ -170,6 +171,7 @@ class Error_Handler {
case 'signature_mismatch':
case 'no_user_tokens':
case 'no_token_for_user':
case 'invalid_connection_owner':
add_action( 'admin_notices', array( $this, 'generic_admin_notice_error' ) );
add_action( 'react_connection_errors_initial_state', array( $this, 'jetpack_react_dashboard_error' ) );
$this->error_code = $error_code;
@@ -277,7 +279,8 @@ class Error_Handler {
$stored_errors[ $error_code ][ $user_id ] = $error_array;
// Let's store a maximum of 5 different user ids for each error code.
if ( count( $stored_errors[ $error_code ] ) > 5 ) {
$error_code_count = is_countable( $stored_errors[ $error_code ] ) ? count( $stored_errors[ $error_code ] ) : 0;
if ( $error_code_count > 5 ) {
// array_shift will destroy keys here because they are numeric, so manually remove first item.
$keys = array_keys( $stored_errors[ $error_code ] );
unset( $stored_errors[ $error_code ][ $keys[0] ] );
@@ -308,7 +311,7 @@ class Error_Handler {
$signature_details = $data['signature_details'];
if ( ! isset( $signature_details['token'] ) || empty( $signature_details['token'] ) ) {
if ( ! isset( $signature_details['token'] ) ) {
return false;
}
@@ -389,12 +392,14 @@ class Error_Handler {
* @return string $the user id or `invalid` if user id not present.
*/
public function get_user_id_from_token( $token ) {
$parsed_token = explode( ':', wp_unslash( $token ) );
$user_id = 'invalid';
if ( isset( $parsed_token[2] ) && ctype_digit( $parsed_token[2] ) ) {
$user_id = $parsed_token[2];
} else {
$user_id = 'invalid';
if ( $token ) {
$parsed_token = explode( ':', wp_unslash( $token ) );
if ( isset( $parsed_token[2] ) && ctype_digit( $parsed_token[2] ) ) {
$user_id = $parsed_token[2];
}
}
return $user_id;
@@ -482,6 +487,47 @@ class Error_Handler {
$this->delete_verified_errors();
}
/**
* Delete all stored and verified API errors from the database, leave the non-API errors intact.
*
* @since 1.54.0
*
* @return void
*/
public function delete_all_api_errors() {
$type_filter = function ( $errors ) {
if ( is_array( $errors ) ) {
foreach ( $errors as $key => $error ) {
if ( ! empty( $error['error_type'] ) && in_array( $error['error_type'], array( 'xmlrpc', 'rest' ), true ) ) {
unset( $errors[ $key ] );
}
}
}
return count( $errors ) ? $errors : null;
};
$stored_errors = $this->get_stored_errors();
if ( is_array( $stored_errors ) && count( $stored_errors ) ) {
$stored_errors = array_filter( array_map( $type_filter, $stored_errors ) );
if ( count( $stored_errors ) ) {
update_option( static::STORED_ERRORS_OPTION, $stored_errors );
} else {
delete_option( static::STORED_ERRORS_OPTION );
}
}
$verified_errors = $this->get_verified_errors();
if ( is_array( $verified_errors ) && count( $verified_errors ) ) {
$verified_errors = array_filter( array_map( $type_filter, $verified_errors ) );
if ( count( $verified_errors ) ) {
update_option( static::STORED_VERIFIED_ERRORS_OPTION, $verified_errors );
} else {
delete_option( static::STORED_VERIFIED_ERRORS_OPTION );
}
}
}
/**
* Delete all stored and verified errors from the database and returns unfiltered value
*

View File

@@ -29,6 +29,8 @@ class Initial_State {
private static function get_data() {
global $wp_version;
$status = new Status();
return array(
'apiRoot' => esc_url_raw( rest_url() ),
'apiNonce' => wp_create_nonce( 'wp_rest' ),
@@ -37,8 +39,10 @@ class Initial_State {
'userConnectionData' => REST_Connector::get_user_connection_data( false ),
'connectedPlugins' => REST_Connector::get_connection_plugins( false ),
'wpVersion' => $wp_version,
'siteSuffix' => ( new Status() )->get_site_suffix(),
'siteSuffix' => $status->get_site_suffix(),
'connectionErrors' => Error_Handler::get_instance()->get_verified_errors(),
'isOfflineMode' => $status->is_offline_mode(),
'calypsoEnv' => ( new Status\Host() )->get_calypso_env(),
);
}
@@ -55,4 +59,17 @@ class Initial_State {
return 'var JP_CONNECTION_INITIAL_STATE=JSON.parse(decodeURIComponent("' . rawurlencode( wp_json_encode( self::get_data() ) ) . '"));';
}
/**
* Render the initial state using an inline script.
*
* @param string $handle The JS script handle.
*
* @return void
*/
public static function render_script( $handle ) {
if ( ! static::$rendered ) {
wp_add_inline_script( $handle, static::render(), 'before' );
}
}
}

View File

@@ -12,6 +12,7 @@ use Automattic\Jetpack\Constants;
use Automattic\Jetpack\Heartbeat;
use Automattic\Jetpack\Roles;
use Automattic\Jetpack\Status;
use Automattic\Jetpack\Status\Host;
use Automattic\Jetpack\Terms_Of_Service;
use Automattic\Jetpack\Tracking;
use Jetpack_IXR_Client;
@@ -134,6 +135,9 @@ class Manager {
// Initialize connection notices.
new Connection_Notice();
// Initialize token locks.
new Tokens_Locks();
}
/**
@@ -203,7 +207,6 @@ class Manager {
// The jetpack.authorize method should be available for unauthenticated users on a site with an
// active Jetpack connection, so that additional users can link their account.
$callback = array( $this->xmlrpc_server, 'authorize_xmlrpc_methods' );
} else {
// Any other unsigned request should expose the bootstrap methods.
$callback = array( $this->xmlrpc_server, 'bootstrap_xmlrpc_methods' );
@@ -785,6 +788,25 @@ class Manager {
$connection_owner = get_userdata( $user_token->external_user_id );
}
if ( $connection_owner === false ) {
Error_Handler::get_instance()->report_error(
new WP_Error(
'invalid_connection_owner',
'Invalid connection owner',
array(
'user_id' => $user_id,
'has_user_token' => (bool) $user_token,
'error_type' => 'connection',
'signature_details' => array(
'token' => '',
),
)
),
false,
true
);
}
return $connection_owner;
}
@@ -1046,6 +1068,11 @@ class Manager {
* @return true|WP_Error The error object.
*/
public function register( $api_endpoint = 'register' ) {
// Clean-up leftover tokens just in-case.
// This fixes an edge case that was preventing users to register when the blog token was missing but
// there were still leftover user tokens present.
$this->delete_all_connection_tokens( true );
add_action( 'pre_update_jetpack_option_register', array( '\\Jetpack_Options', 'delete_option' ) );
$secrets = ( new Secrets() )->generate( 'register', get_current_user_id(), 600 );
@@ -1125,7 +1152,7 @@ class Manager {
'timeout' => $timeout,
);
$args['body'] = $this->apply_activation_source_to_args( $args['body'] );
$args['body'] = static::apply_activation_source_to_args( $args['body'] );
// TODO: fix URLs for bad hosts.
$response = Client::_wp_remote_request(
@@ -1643,6 +1670,11 @@ class Manager {
return false;
}
if ( ( new Status() )->is_offline_mode() && ! apply_filters( 'jetpack_connection_disconnect_site_wpcom_offline_mode', false ) ) {
// Prevent potential disconnect of the live site by removing WPCOM tokens.
return false;
}
/**
* Fires upon the disconnect attempt.
* Return `false` to prevent the disconnect.
@@ -1686,7 +1718,6 @@ class Manager {
( new Tracking() )->record_user_event( 'restore_connection_reconnect' );
$this->disconnect_site_wpcom( true );
$this->delete_all_connection_tokens( true );
return $this->register();
}
@@ -1884,10 +1915,11 @@ class Manager {
'site_lang' => get_locale(),
'site_created' => $this->get_assumed_site_creation_date(),
'allow_site_connection' => ! $this->has_connected_owner(),
'calypso_env' => ( new Host() )->get_calypso_env(),
)
);
$body = $this->apply_activation_source_to_args( urlencode_deep( $body ) );
$body = static::apply_activation_source_to_args( urlencode_deep( $body ) );
$api_url = $this->api_url( 'authorize' );

View File

@@ -184,7 +184,7 @@ class Nonce_Handler {
// Removing zeroes in case AUTO_INCREMENT of the options table is broken, and all ID's are zeroes.
$ids = array_filter( $ids );
if ( ! count( $ids ) ) {
if ( array() === $ids ) {
// There's nothing to remove.
return false;
}

View File

@@ -12,7 +12,7 @@ namespace Automattic\Jetpack\Connection;
*/
class Package_Version {
const PACKAGE_VERSION = '1.51.7';
const PACKAGE_VERSION = '1.57.0';
const PACKAGE_SLUG = 'connection';

View File

@@ -521,7 +521,7 @@ class REST_Connector {
*/
public static function is_request_signed_by_jetpack_debugger( $pub_key = null ) {
// phpcs:disable WordPress.Security.NonceVerification.Recommended
if ( ! isset( $_GET['signature'], $_GET['timestamp'], $_GET['url'], $_GET['rest_route'] ) ) {
if ( ! isset( $_GET['signature'] ) || ! isset( $_GET['timestamp'] ) || ! isset( $_GET['url'] ) || ! isset( $_GET['rest_route'] ) ) {
return false;
}

View File

@@ -59,7 +59,7 @@ class Secrets {
$user_id = get_current_user_id();
}
$callable = apply_filters( 'jetpack_connection_secret_generator', array( get_called_class(), 'secret_callable_method' ) );
$callable = apply_filters( 'jetpack_connection_secret_generator', array( static::class, 'secret_callable_method' ) );
$secrets = Jetpack_Options::get_raw_option(
self::LEGACY_SECRETS_OPTION_NAME,

View File

@@ -0,0 +1,77 @@
<?php
/**
* The Jetpack Connection Tokens Locks class file.
*
* @package automattic/jetpack-connection
*/
namespace Automattic\Jetpack\Connection;
/**
*
* Jetpack Connection tokens cleanup during migration.
* This class encapsulates plugin or tool specific code that activates token lock upon migration.
*
* The connection tokens are locked to the current domain.
* If the database is imported on another site (domain name doesn't match), the tokens get removed.
*
* @see https://github.com/Automattic/jetpack/pull/23597
* @see \Automattic\Jetpack\Connection\Tokens::is_locked()
*/
class Tokens_Locks {
/**
* Whether the class has been initialized.
*
* @var bool
*/
private static $is_initialized = false;
/**
* Run the initializers if they haven't been run already.
*/
public function __construct() {
if ( static::$is_initialized ) {
return;
}
$this->init_aiowpm();
static::$is_initialized = true;
}
/**
* Set the token lock for AIOWPM plugin export.
*
* @param array $params The filter parameters.
*
* @return array
*/
public function aiowpm_set_lock( $params ) {
( new Tokens() )->set_lock();
return $params;
}
/**
* Remove the token lock for AIOWPM plugin export.
*
* @param array $params The filter parameters.
*
* @return array
*/
public function aiowpm_remove_lock( $params ) {
( new Tokens() )->remove_lock();
return $params;
}
/**
* Initialize the All-in-One-WP-Migration plugin hooks.
*
* @return void
*/
private function init_aiowpm() {
add_filter( 'ai1wm_export', array( $this, 'aiowpm_set_lock' ), 180 );
add_filter( 'ai1wm_export', array( $this, 'aiowpm_remove_lock' ), 250 );
}
}

View File

@@ -552,7 +552,7 @@ class Tokens {
$nonce = substr( sha1( wp_rand( 0, 1000000 ) ), 0, 10 );
}
$normalized_request_string = join(
$normalized_request_string = implode(
"\n",
array(
$token_key,
@@ -576,7 +576,7 @@ class Tokens {
$header_pieces[] = sprintf( '%s="%s"', $key, $value );
}
return join( ' ', $header_pieces );
return implode( ' ', $header_pieces );
}
/**