From 18c4d6704b67ee91f35a7206783ec77135876bd7 Mon Sep 17 00:00:00 2001 From: Echo G Date: Wed, 25 Mar 2020 17:32:06 -0400 Subject: [PATCH 1/5] Adds way to redirect user for connect flow. Redirects users back to Calypso if they aren't signed in to WordPress. --- class.jetpack.php | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/class.jetpack.php b/class.jetpack.php index 3179f800a7874..8e4d1926c85a9 100644 --- a/class.jetpack.php +++ b/class.jetpack.php @@ -641,6 +641,9 @@ private function __construct() { add_action( 'jetpack_event_log', array( 'Jetpack', 'log' ), 10, 2 ); + add_filter( 'login_url', array( $this, 'login_url' ), 10, 2 ); + add_action( 'login_init', array( $this, 'login_init' ) ); + add_filter( 'determine_current_user', array( $this, 'wp_rest_authenticate' ) ); add_filter( 'rest_authentication_errors', array( $this, 'wp_rest_authentication_errors' ) ); @@ -4019,6 +4022,45 @@ function plugin_action_links( $actions ) { return array_merge( $jetpack_home, $actions ); } + /** + * Filters the login URL to include the registration flow in case the user isn't logged in. + * + * @param string $login_url The wp-login URL. + * @param string $redirect URL to redirect users after logging in. + * @since Jetpack 8.4 + * @return string + */ + public function login_url( $login_url, $redirect ) { + parse_str( wp_parse_url( $redirect, PHP_URL_QUERY ), $redirect_parts ); + if ( ! empty( $redirect_parts['connect_login_redirect'] ) ) { + $login_url = add_query_arg( 'connect_login_redirect', 'true', $login_url ); + } + return $login_url; + } + + /** + * Redirects non-authenticated users to authenticate with Calypso if redirect flag is set. + * + * @since Jetpack 8.4 + */ + public function login_init() { + // phpcs:ignore WordPress.Security.NonceVerification + if ( ! empty( $_GET['connect_login_redirect'] ) ) { + add_filter( 'allowed_redirect_hosts', array( &$this, 'allow_wpcom_environments' ) ); + wp_safe_redirect( + add_query_arg( + array( + 'forceInstall' => 1, + 'url' => rawurlencode( get_site_url() ), + ), + // @todo provide way to go to specific calypso env. + 'https://wordpress.com/jetpack/connect' + ) + ); + exit; + } + } + /* * Registration flow: * 1 - ::admin_page_load() action=register From 90c8b1ca91b94fb5e22872b0bbc8ae2df260a72e Mon Sep 17 00:00:00 2001 From: Echo G Date: Thu, 26 Mar 2020 11:53:06 -0400 Subject: [PATCH 2/5] Adds utility to get to appropriate Calypso host. --- class.jetpack.php | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/class.jetpack.php b/class.jetpack.php index 8e4d1926c85a9..36a2c716e9c20 100644 --- a/class.jetpack.php +++ b/class.jetpack.php @@ -4054,7 +4054,7 @@ public function login_init() { 'url' => rawurlencode( get_site_url() ), ), // @todo provide way to go to specific calypso env. - 'https://wordpress.com/jetpack/connect' + self::get_calypso_host() . 'jetpack/connect' ) ); exit; @@ -7162,6 +7162,28 @@ public static function get_calypso_env() { return ''; } + /** + * Returns the hostname with protocol for Calypso. + * Used for developing Jetpack with Calypso. + * + * @since 8.4.0 + * + * @return string Calypso host. + */ + public static function get_calypso_host() { + $calypso_env = self::get_calypso_env(); + switch ( $calypso_env ) { + case 'development': + return 'http://calypso.localhost:3000/'; + case 'wpcalypso': + return 'https://wpcalypso.wordpress.com/'; + case 'horizon': + return 'https://horizon.wordpress.com/'; + default: + return 'https://wordpress.com/'; + } + } + /** * Checks whether or not TOS has been agreed upon. * Will return true if a user has clicked to register, or is already connected. From 37c6a53196597e9353fe86861f5b9324a32595ff Mon Sep 17 00:00:00 2001 From: Echo G Date: Thu, 26 Mar 2020 12:05:08 -0400 Subject: [PATCH 3/5] Makes redirect query param a constant. --- class.jetpack.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/class.jetpack.php b/class.jetpack.php index 36a2c716e9c20..1e70022147908 100644 --- a/class.jetpack.php +++ b/class.jetpack.php @@ -378,6 +378,14 @@ class Jetpack { */ public static $plugin_upgrade_lock_key = 'jetpack_upgrade_lock'; + /** + * Constant for login redirect key. + * + * @var string + * @since 8.4.0 + */ + protected static $jetpack_redirect_login = 'jetpack_connect_login_redirect'; + /** * Holds the singleton instance of this class * @@ -4032,8 +4040,8 @@ function plugin_action_links( $actions ) { */ public function login_url( $login_url, $redirect ) { parse_str( wp_parse_url( $redirect, PHP_URL_QUERY ), $redirect_parts ); - if ( ! empty( $redirect_parts['connect_login_redirect'] ) ) { - $login_url = add_query_arg( 'connect_login_redirect', 'true', $login_url ); + if ( ! empty( $redirect_parts[ self::$jetpack_redirect_login ] ) ) { + $login_url = add_query_arg( self::$jetpack_redirect_login, 'true', $login_url ); } return $login_url; } @@ -4045,7 +4053,7 @@ public function login_url( $login_url, $redirect ) { */ public function login_init() { // phpcs:ignore WordPress.Security.NonceVerification - if ( ! empty( $_GET['connect_login_redirect'] ) ) { + if ( ! empty( $_GET[ self::$jetpack_redirect_login ] ) ) { add_filter( 'allowed_redirect_hosts', array( &$this, 'allow_wpcom_environments' ) ); wp_safe_redirect( add_query_arg( From fa8dded7795f62e381c999114ee09e69ac3882b5 Mon Sep 17 00:00:00 2001 From: Echo G Date: Thu, 26 Mar 2020 17:00:06 -0400 Subject: [PATCH 4/5] Adds unit tests for added methods. --- class.jetpack.php | 2 +- tests/php/general/test_class.jetpack.php | 74 ++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/class.jetpack.php b/class.jetpack.php index 1e70022147908..e277654c00710 100644 --- a/class.jetpack.php +++ b/class.jetpack.php @@ -384,7 +384,7 @@ class Jetpack { * @var string * @since 8.4.0 */ - protected static $jetpack_redirect_login = 'jetpack_connect_login_redirect'; + public static $jetpack_redirect_login = 'jetpack_connect_login_redirect'; /** * Holds the singleton instance of this class diff --git a/tests/php/general/test_class.jetpack.php b/tests/php/general/test_class.jetpack.php index c646a5570b6a8..7dffaedfb1cae 100644 --- a/tests/php/general/test_class.jetpack.php +++ b/tests/php/general/test_class.jetpack.php @@ -1208,4 +1208,78 @@ public function partner_code_provider() { ); } + /** + * Tests login URL only adds redirect param when redirect param is in original request. + * + * @since 8.4.0 + * @return void + */ + public function test_login_url_add_redirect() { + $login_url = wp_login_url( '/wp-admin' ); + $this->assertStringNotContainsString( $login_url, Jetpack::$jetpack_redirect_login ); + + $login_url = wp_login_url( '/wp-admin?' . Jetpack::$jetpack_redirect_login . '=true' ); + parse_str( wp_parse_url( $login_url, PHP_URL_QUERY ), $login_parts ); + $this->assertArraySubset( array( Jetpack::$jetpack_redirect_login => 'true' ), $login_parts, true ); + } + + /** + * Tests login redirect sending users to Calypso when redirect param is set. + * + * @since 8.4.0 + * @return void + */ + public function test_login_init_redirect() { + tests_add_filter( + 'wp_redirect', + function( $location ) { + $expected_location = add_query_arg( + array( + 'forceInstall' => 1, + 'url' => rawurlencode( get_site_url() ), + ), + 'https://wordpress.com/jetpack/connect' + ); + $this->assertEquals( $location, $expected_location ); + throw new Exception(); // Cause an exception, as we don't want to run exit. + } + ); + + // Remove core filters that add headers. + remove_filter( 'login_init', 'wp_admin_headers' ); + remove_filter( 'login_init', 'send_frame_options_header' ); + + // Run it once and no exception is thrown. + do_action( 'login_init' ); + + $this->expectException( Exception::class ); + $_GET[ Jetpack::$jetpack_redirect_login ] = 'true'; + do_action( 'login_init' ); // Now expect an exception. + } + + /** + * Tests getting the correct Calypso host. + * + * @since 8.4.0 + * @return void + */ + public function test_get_calypso_host() { + // No env. + $this->assertEquals( 'https://wordpress.com/', Jetpack::get_calypso_host() ); + + $_GET['calypso_env'] = 'development'; + $this->assertEquals( 'http://calypso.localhost:3000/', Jetpack::get_calypso_host() ); + + $_GET['calypso_env'] = 'wpcalypso'; + $this->assertEquals( 'https://wpcalypso.wordpress.com/', Jetpack::get_calypso_host() ); + + $_GET['calypso_env'] = 'horizon'; + $this->assertEquals( 'https://horizon.wordpress.com/', Jetpack::get_calypso_host() ); + + $_GET['calypso_env'] = 'stage'; + $this->assertEquals( 'https://wordpress.com/', Jetpack::get_calypso_host() ); + + $_GET['calypso_env'] = 'production'; + $this->assertEquals( 'https://wordpress.com/', Jetpack::get_calypso_host() ); + } } // end class From 0d46a7b620f17624eb3414079c909ef495950fc0 Mon Sep 17 00:00:00 2001 From: Echo G Date: Fri, 27 Mar 2020 12:06:46 -0400 Subject: [PATCH 5/5] Fixes unit test to work in older version of PHPUnit. --- tests/php/general/test_class.jetpack.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/php/general/test_class.jetpack.php b/tests/php/general/test_class.jetpack.php index 7dffaedfb1cae..4c3a34da7bd0d 100644 --- a/tests/php/general/test_class.jetpack.php +++ b/tests/php/general/test_class.jetpack.php @@ -1216,7 +1216,7 @@ public function partner_code_provider() { */ public function test_login_url_add_redirect() { $login_url = wp_login_url( '/wp-admin' ); - $this->assertStringNotContainsString( $login_url, Jetpack::$jetpack_redirect_login ); + $this->assertFalse( strpos( $login_url, Jetpack::$jetpack_redirect_login ) ); $login_url = wp_login_url( '/wp-admin?' . Jetpack::$jetpack_redirect_login . '=true' ); parse_str( wp_parse_url( $login_url, PHP_URL_QUERY ), $login_parts );