From cfe7ff2af4eb3e4ed85ed5f1538bb68b1c5d4f22 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 2 Oct 2019 01:15:09 +0200 Subject: [PATCH 001/102] Introduce Google_Proxy_Client and use it for authentication via the proxy. --- .../Clients/Google_Proxy_Client.php | 111 ++++++++++++++++++ .../Authentication/Clients/OAuth_Client.php | 111 ++++++++++++++++-- 2 files changed, 210 insertions(+), 12 deletions(-) create mode 100644 includes/Core/Authentication/Clients/Google_Proxy_Client.php diff --git a/includes/Core/Authentication/Clients/Google_Proxy_Client.php b/includes/Core/Authentication/Clients/Google_Proxy_Client.php new file mode 100644 index 00000000000..b441bbf7b77 --- /dev/null +++ b/includes/Core/Authentication/Clients/Google_Proxy_Client.php @@ -0,0 +1,111 @@ +getAccessToken(); + if ( empty( $old_access_token['access_token'] ) ) { + $url = add_query_arg( 'access_token', $old_access_token['access_token'], $url ); + } + + $this->getLogger()->info( 'OAuth2 access token refresh' ); + $auth = $this->getOAuth2Service(); + $auth->setRefreshToken( $refresh_token ); + + // Set our own parameters. + $auth->setGrantType( 'refresh_token_proxy' ); + $auth->setExtensionParams( + array( + 'grant_type' => 'refresh_token', + 'access_token' => $old_access_token['access_token'], + ) + ); + + $http_handler = HttpHandlerFactory::build( $this->getHttpClient() ); + + $creds = $auth->fetchAuthToken( $http_handler ); + if ( $creds && isset( $creds['access_token'] ) ) { + $creds['created'] = time(); + $this->setAccessToken( $creds ); + } + + return $creds; + } + + /** + * Creates an auth URL for the authentication proxy. + * + * @since 1.0.0 + * + * @param string|array $scope Optional. One or more scopes. Default is the originally passed scopes. + * @return string Auth URL to redirect the user to. + */ + public function createAuthUrl( $scope = null ) { + $url = parent::createAuthUrl( $scope ); + + $old_access_token = $this->getAccessToken(); + if ( ! empty( $old_access_token['access_token'] ) ) { + $url = add_query_arg( 'access_token', $old_access_token['access_token'], $url ); + } + + return $url; + } + + /** + * Creates a Google auth object for the authentication proxy. + * + * @since 1.0.0 + */ + protected function createOAuth2Service() { + $auth = new OAuth2( + array( + 'clientId' => $this->getClientId(), + 'clientSecret' => $this->getClientSecret(), + 'authorizationUri' => self::OAUTH2_AUTH_URL, + 'tokenCredentialUri' => self::OAUTH2_TOKEN_URI, + 'redirectUri' => $this->getRedirectUri(), + 'issuer' => $this->config['client_id'], + 'signingKey' => $this->config['signing_key'], + 'signingAlgorithm' => $this->config['signing_algorithm'], + ) + ); + + return $auth; + } +} diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index 6c4809d67f9..1185dbdd7a0 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -35,6 +35,8 @@ final class OAuth_Client { const OPTION_REDIRECT_URL = 'googlesitekit_redirect_url'; const OPTION_AUTH_SCOPES = 'googlesitekit_auth_scopes'; const OPTION_ERROR_CODE = 'googlesitekit_error_code'; + const OPTION_PROXY_NONCE = 'googlesitekit_proxy_nonce'; + const PROXY_URL = 'https://sitekit.withgoogle.com'; /** * Plugin context. @@ -165,7 +167,11 @@ public function get_client() { return $this->google_client; } - $this->google_client = new Google_Client(); + if ( $this->using_proxy() ) { + $this->google_client = new Google_Proxy_Client(); + } else { + $this->google_client = new Google_Client(); + } // Return unconfigured client if credentials not yet set. $client_credentials = $this->get_client_credentials(); @@ -181,8 +187,6 @@ public function get_client() { // Offline access so we can access the refresh token even when the user is logged out. $this->google_client->setAccessType( 'offline' ); - $this->google_client->setApprovalPrompt( 'force' ); - $this->google_client->setPrompt( 'consent' ); $this->google_client->setRedirectUri( $this->get_redirect_uri() ); @@ -197,11 +201,13 @@ public function get_client() { } $token = array( - 'access_token' => $access_token, - 'refresh_token' => $this->get_refresh_token(), - 'expires_in' => $this->user_options->get( self::OPTION_ACCESS_TOKEN_EXPIRES_IN ), - 'created' => $this->user_options->get( self::OPTION_ACCESS_TOKEN_CREATED ), + 'access_token' => $access_token, + 'expires_in' => $this->user_options->get( self::OPTION_ACCESS_TOKEN_EXPIRES_IN ), + 'created' => $this->user_options->get( self::OPTION_ACCESS_TOKEN_CREATED ), ); + if ( ! $this->using_proxy() ) { + $token['refresh_token'] = $this->get_refresh_token(); + } $this->google_client->setAccessToken( $token ); @@ -219,11 +225,12 @@ public function get_client() { * @since 1.0.0 */ public function refresh_token() { - // Check for a valid stored refresh token. If it's been set, grab the authentication token. - $refresh_token = $this->get_refresh_token(); - - if ( empty( $refresh_token ) ) { - $this->user_options->set( self::OPTION_ERROR_CODE, 'refresh_token_not_exist' ); + $refresh_token = ''; + if ( ! $this->using_proxy() ) { + $refresh_token = $this->get_refresh_token(); + if ( empty( $refresh_token ) ) { + $this->user_options->set( self::OPTION_ERROR_CODE, 'refresh_token_not_exist' ); + } } // Stop if google_client not initialized yet. @@ -474,6 +481,11 @@ public function authorize_user() { } if ( ! empty( $authentication_token['error'] ) ) { + if ( $this->using_proxy() && ! empty( $authentication_token['code'] ) ) { + wp_safe_redirect( $this->get_proxy_setup_url( $authentication_token['code'] ) ); + exit(); + } + $this->user_options->set( self::OPTION_ERROR_CODE, $authentication_token['error'] ); wp_safe_redirect( admin_url() ); exit(); @@ -532,6 +544,81 @@ function( $scope ) { exit(); } + /** + * Determines whether the authentication proxy is used. + * + * In order to streamline the setup and authentication flow, the plugin uses a proxy mechanism based on an external + * service. This can be overridden by providing actual GCP credentials with the {@see 'googlesitekit_oauth_secret'} + * filter. + * + * @since 1.0.0 + * + * @return bool True if proxy authentication is used, false otherwise. + */ + public function using_proxy() { + $credentials = $this->get_client_credentials(); + + // If no credentials yet, assume true. + if ( ! is_object( $credentials ) || empty( $credentials->web->client_id ) ) { + return true; + } + + // If proxy credentials, return true. + if ( false !== strpos( $credentials->web->client_id, '.apps.sitekit.withgoogle.com' ) ) { + return true; + } + + return false; + } + + /** + * Returns the setup URL to the authentication proxy. + * + * @param string $code Optional. Temporary access code for an undelegated access token. Default empty string. + * @return string URL to the setup page on the authentication proxy. + */ + public function get_proxy_setup_url( $code = '' ) { + $url = self::PROXY_URL . '/site-management/setup/'; + + $credentials = $this->get_client_credentials(); + + if ( ! is_object( $credentials ) || empty( $credentials->web->client_id ) ) { + $home_url = home_url(); + $home_url_no_scheme = str_replace( array( 'http://', 'https://' ), '', $home_url ); + + $rest_root = str_replace( array( 'http://', 'https://' ), '', rest_url() ); + $rest_root = str_replace( $home_url_no_scheme, '', $rest_root ); + + $admin_root = str_replace( array( 'http://', 'https://' ), '', admin_url() ); + $admin_root = str_replace( $home_url_no_scheme, '', $admin_root ); + + $nonce = get_option( self::OPTION_PROXY_NONCE, '' ); + if ( empty( $nonce ) ) { + $nonce = wp_create_nonce( 'googlesitekit_proxy' ); + update_option( self::OPTION_PROXY_NONCE, $nonce ); + } + + return add_query_arg( + array( + 'nonce' => $nonce, + 'name' => get_bloginfo( 'name' ), + 'url' => $home_url, + 'rest_root' => $rest_root, + 'admin_root' => $admin_root, + ), + $url + ); + } + + return add_query_arg( + array( + 'site_id' => $credentials->web->client_id, + 'code' => $code, + ), + $url + ); + } + /** * Converts the given error code to a user-facing message. * From 16ce8109638c935d78ce2e9f01c0203ea664ebba Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 2 Oct 2019 01:15:40 +0200 Subject: [PATCH 002/102] Introduce REST route for receiving proxy site ID and secret. --- includes/Core/REST_API/REST_Routes.php | 46 ++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/includes/Core/REST_API/REST_Routes.php b/includes/Core/REST_API/REST_Routes.php index 4393c11b278..76cd9e50f26 100644 --- a/includes/Core/REST_API/REST_Routes.php +++ b/includes/Core/REST_API/REST_Routes.php @@ -16,6 +16,7 @@ use Google\Site_Kit\Core\Permissions\Permissions; use Google\Site_Kit\Core\Storage\User_Options; use Google\Site_Kit\Core\Authentication\Authentication; +use Google\Site_Kit\Core\Authentication\Clients\OAuth_Client; use Google\Site_Kit\Core\Util\Reset; use WP_Post; use WP_REST_Server; @@ -578,6 +579,51 @@ function( $dataset ) use ( $module ) { ), ) ), + new REST_Route( + 'oauth/site', + array( + array( + 'methods' => WP_REST_Server::CREATABLE, + 'callback' => function( WP_REST_Request $request ) { + $auth_client = $this->authentication->get_auth_client(); + if ( ! $auth_client->using_proxy() ) { + return new WP_Error( 'invalid_authentication_mode', __( 'Invalid authentication mode.', 'google-site-kit' ), array( 'status' => 500 ) ); + } + $nonce = get_option( OAuth_Client::OPTION_PROXY_NONCE, '' ); + delete_option( OAuth_Client::OPTION_PROXY_NONCE ); + if ( $nonce !== $request['nonce'] ) { + return new WP_Error( 'invalid_nonce', __( 'Invalid nonce.', 'google-site-kit' ), array( 'status' => 400 ) ); + } + $data = array( + 'oauth2_client_id' => sanitize_text_field( $request['site_id'] ), + 'oauth2_client_secret' => sanitize_text_field( $request['site_secret'] ), + ); + $credentials = $this->authentication->credentials(); + if ( ! $credentials->set( $data ) ) { + return new WP_Error( 'set_credentials_failed', __( 'Failed to set credentials.', 'google-site-kit' ), array( 'status' => 500 ) ); + } + return new WP_REST_Response( array( 'status' => true ), 200 ); + }, + 'args' => array( + 'nonce' => array( + 'type' => 'string', + 'description' => __( 'WordPress nonce for the authentication proxy setup.', 'google-site-kit' ), + 'required' => true, + ), + 'site_id' => array( + 'type' => 'string', + 'description' => __( 'Site ID for the authentication proxy.', 'google-site-kit' ), + 'required' => true, + ), + 'site_secret' => array( + 'type' => 'string', + 'description' => __( 'Site secret for the authentication proxy.', 'google-site-kit' ), + 'required' => true, + ), + ), + ), + ) + ), // TODO: Remove this and replace usage with calls to wp/v1/posts. new REST_Route( 'core/search/data/post-search', From 8a385e50a75e081a760f6d698c94e90431d11689 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 2 Oct 2019 01:27:09 +0200 Subject: [PATCH 003/102] Support revoking tokens via proxy. --- .../Clients/Google_Proxy_Client.php | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/includes/Core/Authentication/Clients/Google_Proxy_Client.php b/includes/Core/Authentication/Clients/Google_Proxy_Client.php index b441bbf7b77..6e124083284 100644 --- a/includes/Core/Authentication/Clients/Google_Proxy_Client.php +++ b/includes/Core/Authentication/Clients/Google_Proxy_Client.php @@ -68,6 +68,38 @@ public function fetchAccessTokenWithRefreshToken( $refresh_token = null ) { return $creds; } + /** + * Revokes an OAuth2 access token using the authentication proxy. + * + * @since 1.0.0 + * + * @param string|array|null $token Optional. Access token. Default is the current one. + * @return bool True on success, false on failure. + */ + public function revokeToken( $token = null ) { + if ( ! $token ) { + $token = $this->getAccessToken(); + } + if ( is_array( $token ) ) { + $token = $token['access_token']; + } + + $response = wp_remote_get( + add_query_arg( + array( + 'client_id' => $this->getClientId(), + 'token' => $token, + ), + self::OAUTH2_REVOKE_URI + ) + ); + if ( is_wp_error( $response ) ) { + return false; + } + + return 200 === (int) wp_remote_retrieve_response_code( $response ); + } + /** * Creates an auth URL for the authentication proxy. * From cc8a4feae8f6630996ce60d567d1a53ee1f7acaf Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 2 Oct 2019 01:40:13 +0200 Subject: [PATCH 004/102] Support receiving a verification token via the proxy. --- .../Core/Authentication/Authentication.php | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index af7cc0a1d8c..06f9a172382 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -187,8 +187,14 @@ public function register() { 'init', function() { $this->handle_oauth(); - }, - 10 + } + ); + + add_action( + 'admin_init', + function() { + $this->handle_verification_token(); + } ); add_action( @@ -425,11 +431,9 @@ public function is_authenticated() { } /** - * Handle OAuth process. + * Handles receiving a temporary OAuth code. * * @since 1.0.0 - * - * @return void */ private function handle_oauth() { if ( defined( 'WP_CLI' ) && WP_CLI ) { @@ -504,6 +508,30 @@ private function handle_oauth() { } } + /** + * Handles receiving a verification token for a user by the authentication proxy. + * + * @since 1.0.0 + */ + private function handle_verification_token() { + if ( ! $this->using_proxy() ) { + return; + } + + $verification_token = filter_input( INPUT_GET, 'googlesitekit_verification_token' ); + if ( empty( $verification_token ) ) { + return; + } + + $this->verification_tag->set( $verification_token ); + + $code = (string) filter_input( INPUT_GET, 'googlesitekit_code' ); + + $auth_client = $this->get_auth_client(); + wp_safe_redirect( add_query_arg( 'verify', 'true', $auth_client->get_proxy_setup_url( $code ) ) ); + exit; + } + /** * Refresh authentication token when user login. * From 0bdaf75a91965c00a5e46788b73e679d3226f0e2 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 2 Oct 2019 02:19:09 +0200 Subject: [PATCH 005/102] Expose the URL for proxy setup temporarily. --- includes/Core/Authentication/Authentication.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index 06f9a172382..85b18281d8d 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -197,6 +197,19 @@ function() { } ); + // TODO: Remove this after testing. + add_action( + 'admin_notices', + function() { + $url = $this->get_auth_client()->get_proxy_setup_url(); + ?> +
+

TEMPORARY:

+
+ Date: Wed, 2 Oct 2019 02:38:43 +0200 Subject: [PATCH 006/102] When using proxy, set Search Console property asap. --- includes/Modules/Search_Console.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/includes/Modules/Search_Console.php b/includes/Modules/Search_Console.php index 78fc89bb9f1..57da5361689 100644 --- a/includes/Modules/Search_Console.php +++ b/includes/Modules/Search_Console.php @@ -43,6 +43,25 @@ public function register() { $this->register_screen_hook(); + // When using the proxy, simply set the Search Console property after receiving an access token, since it is + // already taken care of on the proxy side. + add_action( + 'admin_init', + function() { + $auth_client = $this->authentication->get_auth_client(); + if ( ! $auth_client->using_proxy() ) { + return; + } + + $access_token = $this->get_access_token(); + if ( empty( $access_token ) ) { + return; + } + + $this->options->set( self::PROPERTY_OPTION, trailingslashit( $this->context->get_reference_site_url() ) ); + } + ); + // Ensure that a Search Console property must be set at all times. add_filter( 'googlesitekit_setup_complete', From 5721b7dd4993ce40fd6535bca3b166715b8f4f2a Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 2 Oct 2019 02:59:11 +0200 Subject: [PATCH 007/102] Fix incorrect method name. --- includes/Core/Authentication/Authentication.php | 6 +++--- includes/Core/REST_API/REST_Routes.php | 2 +- includes/Modules/Search_Console.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index 85b18281d8d..5420bfc618b 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -201,7 +201,7 @@ function() { add_action( 'admin_notices', function() { - $url = $this->get_auth_client()->get_proxy_setup_url(); + $url = $this->get_oauth_client()->get_proxy_setup_url(); ?>

TEMPORARY:

@@ -527,7 +527,8 @@ private function handle_oauth() { * @since 1.0.0 */ private function handle_verification_token() { - if ( ! $this->using_proxy() ) { + $auth_client = $this->get_oauth_client(); + if ( ! $auth_client->using_proxy() ) { return; } @@ -540,7 +541,6 @@ private function handle_verification_token() { $code = (string) filter_input( INPUT_GET, 'googlesitekit_code' ); - $auth_client = $this->get_auth_client(); wp_safe_redirect( add_query_arg( 'verify', 'true', $auth_client->get_proxy_setup_url( $code ) ) ); exit; } diff --git a/includes/Core/REST_API/REST_Routes.php b/includes/Core/REST_API/REST_Routes.php index 76cd9e50f26..e8bfd98a3d3 100644 --- a/includes/Core/REST_API/REST_Routes.php +++ b/includes/Core/REST_API/REST_Routes.php @@ -585,7 +585,7 @@ function( $dataset ) use ( $module ) { array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => function( WP_REST_Request $request ) { - $auth_client = $this->authentication->get_auth_client(); + $auth_client = $this->authentication->get_oauth_client(); if ( ! $auth_client->using_proxy() ) { return new WP_Error( 'invalid_authentication_mode', __( 'Invalid authentication mode.', 'google-site-kit' ), array( 'status' => 500 ) ); } diff --git a/includes/Modules/Search_Console.php b/includes/Modules/Search_Console.php index 57da5361689..47d0e1f58a7 100644 --- a/includes/Modules/Search_Console.php +++ b/includes/Modules/Search_Console.php @@ -48,7 +48,7 @@ public function register() { add_action( 'admin_init', function() { - $auth_client = $this->authentication->get_auth_client(); + $auth_client = $this->authentication->get_oauth_client(); if ( ! $auth_client->using_proxy() ) { return; } From eee0739b2068a35042397f8e508136e53d21c971 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 2 Oct 2019 03:01:24 +0200 Subject: [PATCH 008/102] Fix undefined method call. --- includes/Modules/Search_Console.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Modules/Search_Console.php b/includes/Modules/Search_Console.php index 47d0e1f58a7..f4bbdee23cc 100644 --- a/includes/Modules/Search_Console.php +++ b/includes/Modules/Search_Console.php @@ -53,7 +53,7 @@ function() { return; } - $access_token = $this->get_access_token(); + $access_token = $auth_client->get_access_token(); if ( empty( $access_token ) ) { return; } From 4c7841c56a36ad92a45e86cdb5fd1bb3ee8e0adb Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Fri, 4 Oct 2019 12:45:30 +0200 Subject: [PATCH 009/102] Only delete current nonce if valid. --- includes/Core/REST_API/REST_Routes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Core/REST_API/REST_Routes.php b/includes/Core/REST_API/REST_Routes.php index e8bfd98a3d3..b7f46189257 100644 --- a/includes/Core/REST_API/REST_Routes.php +++ b/includes/Core/REST_API/REST_Routes.php @@ -590,10 +590,10 @@ function( $dataset ) use ( $module ) { return new WP_Error( 'invalid_authentication_mode', __( 'Invalid authentication mode.', 'google-site-kit' ), array( 'status' => 500 ) ); } $nonce = get_option( OAuth_Client::OPTION_PROXY_NONCE, '' ); - delete_option( OAuth_Client::OPTION_PROXY_NONCE ); if ( $nonce !== $request['nonce'] ) { return new WP_Error( 'invalid_nonce', __( 'Invalid nonce.', 'google-site-kit' ), array( 'status' => 400 ) ); } + delete_option( OAuth_Client::OPTION_PROXY_NONCE ); $data = array( 'oauth2_client_id' => sanitize_text_field( $request['site_id'] ), 'oauth2_client_secret' => sanitize_text_field( $request['site_secret'] ), From d4ee118379184180d5a23ced9799f23b11646f7d Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Fri, 4 Oct 2019 14:43:46 +0200 Subject: [PATCH 010/102] Properly catch proxy errors that include a temporary access code. --- .../Clients/Google_Proxy_Client.php | 68 ++++++++++++++++++- .../Clients/Google_Proxy_Exception.php | 49 +++++++++++++ .../Authentication/Clients/OAuth_Client.php | 8 +-- 3 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 includes/Core/Authentication/Clients/Google_Proxy_Exception.php diff --git a/includes/Core/Authentication/Clients/Google_Proxy_Client.php b/includes/Core/Authentication/Clients/Google_Proxy_Client.php index 6e124083284..fa5ebaadd1a 100644 --- a/includes/Core/Authentication/Clients/Google_Proxy_Client.php +++ b/includes/Core/Authentication/Clients/Google_Proxy_Client.php @@ -13,7 +13,9 @@ use Google_Client; use Google\Auth\OAuth2; use Google\Auth\HttpHandler\HttpHandlerFactory; +use Google\Auth\HttpHandler\HttpClientCache; use Exception; +use InvalidArgumentException; /** * Modified Google API client relying on the authentication proxy. @@ -28,6 +30,36 @@ final class Google_Proxy_Client extends Google_Client { const OAUTH2_TOKEN_URI = 'https://sitekit.withgoogle.com/o/oauth2/token'; const OAUTH2_AUTH_URL = 'https://sitekit.withgoogle.com/o/oauth2/auth'; + /** + * Fetches an OAuth 2.0 access token by using a temporary code. + * + * @since 1.0.0 + * + * @param string $code Temporary authorization code, or undelegated token code. + * @return array Access token. + * + * @throws InvalidArgumentException Thrown when the passed code is empty. + */ + public function fetchAccessTokenWithAuthCode( $code ) { + if ( strlen( $code ) === 0 ) { + throw new InvalidArgumentException( 'Invalid code' ); + } + + $auth = $this->getOAuth2Service(); + $auth->setCode( $code ); + $auth->setRedirectUri( $this->getRedirectUri() ); + + $http_handler = HttpHandlerFactory::build( $this->getHttpClient() ); + + $creds = $this->fetchAuthToken( $auth, $http_handler ); + if ( $creds && isset( $creds['access_token'] ) ) { + $creds['created'] = time(); + $this->setAccessToken( $creds ); + } + + return $creds; + } + /** * Fetches a fresh OAuth 2.0 access token by using a refresh token. * @@ -59,7 +91,7 @@ public function fetchAccessTokenWithRefreshToken( $refresh_token = null ) { $http_handler = HttpHandlerFactory::build( $this->getHttpClient() ); - $creds = $auth->fetchAuthToken( $http_handler ); + $creds = $this->fetchAuthToken( $auth, $http_handler ); if ( $creds && isset( $creds['access_token'] ) ) { $creds['created'] = time(); $this->setAccessToken( $creds ); @@ -140,4 +172,38 @@ protected function createOAuth2Service() { return $auth; } + + /** + * Fetches an OAuth 2.0 access token using a given auth object and HTTP handler. + * + * This method is used in place of {@see OAuth2::fetchAuthToken()}. + * + * @since 1.0.0 + * + * @param OAuth2 $auth OAuth2 instance. + * @param callable|null $http_handler Optional. HTTP handler callback. Default null. + * @return array Access token. + * + * @throws Google_Proxy_Exception Thrown when proxy returns an error accompanied by a temporary access code. + * @throws Exception Thrown when any other type of error occurs. + */ + private function fetchAuthToken( OAuth2 $auth, callable $http_handler = null ) { + if ( is_null( $http_handler ) ) { + $http_handler = HttpHandlerFactory::build( HttpClientCache::getHttpClient() ); + } + + $request = $auth->generateCredentialsRequest(); + $response = $http_handler( $request ); + $credentials = $auth->parseTokenResponse( $response ); + if ( ! empty( $credentials['error'] ) ) { + if ( ! empty( $credentials['code'] ) ) { + throw new Google_Proxy_Exception( $credentials['error'], 0, $credentials['code'] ); + } + throw new Exception( $credentials['error'] ); + } + + $auth->updateToken( $credentials ); + + return $credentials; + } } diff --git a/includes/Core/Authentication/Clients/Google_Proxy_Exception.php b/includes/Core/Authentication/Clients/Google_Proxy_Exception.php new file mode 100644 index 00000000000..2b7d7bdd64d --- /dev/null +++ b/includes/Core/Authentication/Clients/Google_Proxy_Exception.php @@ -0,0 +1,49 @@ +access_code = $access_code; + } + + /** + * Gets the temporary access code for an undelegated proxy token. + * + * @since 1.0.0 + * + * @return string Temporary code. + */ + public function getAccessCode() { + return $this->access_code; + } +} diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index 1185dbdd7a0..0d50c2d7fac 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -474,6 +474,9 @@ public function authorize_user() { try { $authentication_token = $this->get_client()->fetchAccessTokenWithAuthCode( $_GET['code'] ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification + } catch ( Google_Proxy_Exception $e ) { + wp_safe_redirect( $this->get_proxy_setup_url( $e->getAccessCode() ) ); + exit(); } catch ( Exception $e ) { $this->user_options->set( self::OPTION_ERROR_CODE, 'invalid_code' ); wp_safe_redirect( admin_url() ); @@ -481,11 +484,6 @@ public function authorize_user() { } if ( ! empty( $authentication_token['error'] ) ) { - if ( $this->using_proxy() && ! empty( $authentication_token['code'] ) ) { - wp_safe_redirect( $this->get_proxy_setup_url( $authentication_token['code'] ) ); - exit(); - } - $this->user_options->set( self::OPTION_ERROR_CODE, $authentication_token['error'] ); wp_safe_redirect( admin_url() ); exit(); From 8adec2eaff1b768b01c425304d58dab3c8db6a6a Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Fri, 4 Oct 2019 14:44:22 +0200 Subject: [PATCH 011/102] Add required slashes to proxy URLs. --- .../Core/Authentication/Clients/Google_Proxy_Client.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/Core/Authentication/Clients/Google_Proxy_Client.php b/includes/Core/Authentication/Clients/Google_Proxy_Client.php index fa5ebaadd1a..f52f84b1553 100644 --- a/includes/Core/Authentication/Clients/Google_Proxy_Client.php +++ b/includes/Core/Authentication/Clients/Google_Proxy_Client.php @@ -26,9 +26,9 @@ */ final class Google_Proxy_Client extends Google_Client { - const OAUTH2_REVOKE_URI = 'https://sitekit.withgoogle.com/o/oauth2/revoke'; - const OAUTH2_TOKEN_URI = 'https://sitekit.withgoogle.com/o/oauth2/token'; - const OAUTH2_AUTH_URL = 'https://sitekit.withgoogle.com/o/oauth2/auth'; + const OAUTH2_REVOKE_URI = 'https://sitekit.withgoogle.com/o/oauth2/revoke/'; + const OAUTH2_TOKEN_URI = 'https://sitekit.withgoogle.com/o/oauth2/token/'; + const OAUTH2_AUTH_URL = 'https://sitekit.withgoogle.com/o/oauth2/auth/'; /** * Fetches an OAuth 2.0 access token by using a temporary code. From 87a57bbb40e4c61480e1b21e2b17a8517e3f1c96 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Mon, 7 Oct 2019 20:39:27 +0200 Subject: [PATCH 012/102] Bring back usage of refresh token. --- .../Clients/Google_Proxy_Client.php | 46 +++++-------------- .../Authentication/Clients/OAuth_Client.php | 9 ++-- 2 files changed, 15 insertions(+), 40 deletions(-) diff --git a/includes/Core/Authentication/Clients/Google_Proxy_Client.php b/includes/Core/Authentication/Clients/Google_Proxy_Client.php index f52f84b1553..9429d0e2bd8 100644 --- a/includes/Core/Authentication/Clients/Google_Proxy_Client.php +++ b/includes/Core/Authentication/Clients/Google_Proxy_Client.php @@ -16,6 +16,7 @@ use Google\Auth\HttpHandler\HttpClientCache; use Exception; use InvalidArgumentException; +use LogicException; /** * Modified Google API client relying on the authentication proxy. @@ -63,37 +64,33 @@ public function fetchAccessTokenWithAuthCode( $code ) { /** * Fetches a fresh OAuth 2.0 access token by using a refresh token. * + * @since 1.0.0 + * * @param string $refresh_token Optional. Refresh token. Unused here. * @return array Access token. + * + * @throws LogicException Thrown when no refresh token is available. */ public function fetchAccessTokenWithRefreshToken( $refresh_token = null ) { if ( null === $refresh_token ) { - $refresh_token = ''; - } - - $old_access_token = $this->getAccessToken(); - if ( empty( $old_access_token['access_token'] ) ) { - $url = add_query_arg( 'access_token', $old_access_token['access_token'], $url ); + if ( ! isset( $this->token['refresh_token'] ) ) { + throw new LogicException( 'refresh token must be passed in or set as part of setAccessToken' ); + } + $refresh_token = $this->token['refresh_token']; } $this->getLogger()->info( 'OAuth2 access token refresh' ); $auth = $this->getOAuth2Service(); $auth->setRefreshToken( $refresh_token ); - // Set our own parameters. - $auth->setGrantType( 'refresh_token_proxy' ); - $auth->setExtensionParams( - array( - 'grant_type' => 'refresh_token', - 'access_token' => $old_access_token['access_token'], - ) - ); - $http_handler = HttpHandlerFactory::build( $this->getHttpClient() ); $creds = $this->fetchAuthToken( $auth, $http_handler ); if ( $creds && isset( $creds['access_token'] ) ) { $creds['created'] = time(); + if ( ! isset( $creds['refresh_token'] ) ) { + $creds['refresh_token'] = $refresh_token; + } $this->setAccessToken( $creds ); } @@ -132,25 +129,6 @@ public function revokeToken( $token = null ) { return 200 === (int) wp_remote_retrieve_response_code( $response ); } - /** - * Creates an auth URL for the authentication proxy. - * - * @since 1.0.0 - * - * @param string|array $scope Optional. One or more scopes. Default is the originally passed scopes. - * @return string Auth URL to redirect the user to. - */ - public function createAuthUrl( $scope = null ) { - $url = parent::createAuthUrl( $scope ); - - $old_access_token = $this->getAccessToken(); - if ( ! empty( $old_access_token['access_token'] ) ) { - $url = add_query_arg( 'access_token', $old_access_token['access_token'], $url ); - } - - return $url; - } - /** * Creates a Google auth object for the authentication proxy. * diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index 0d50c2d7fac..bd679b2fe4d 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -225,12 +225,9 @@ public function get_client() { * @since 1.0.0 */ public function refresh_token() { - $refresh_token = ''; - if ( ! $this->using_proxy() ) { - $refresh_token = $this->get_refresh_token(); - if ( empty( $refresh_token ) ) { - $this->user_options->set( self::OPTION_ERROR_CODE, 'refresh_token_not_exist' ); - } + $refresh_token = $this->get_refresh_token(); + if ( empty( $refresh_token ) ) { + $this->user_options->set( self::OPTION_ERROR_CODE, 'refresh_token_not_exist' ); } // Stop if google_client not initialized yet. From f491d251c2cf38a4756a7944001949abd3a053b1 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Mon, 7 Oct 2019 20:52:36 +0200 Subject: [PATCH 013/102] Handle refreshing token via proxy gracefully and include link to continue in error message. --- .../Core/Authentication/Authentication.php | 13 ++++- .../Authentication/Clients/OAuth_Client.php | 53 +++++++++++++------ 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index 5420bfc618b..07abd6bde65 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -863,7 +863,18 @@ private function get_authentication_oauth_error_notice() { return ''; } - return '

' . esc_html( $message ) . '

'; + $message = wp_kses( + $message, + array( + 'a' => array( + 'href' => array(), + ), + 'strong' => array(), + 'em' => array(), + ) + ); + + return '

' . $message . '

'; }, 'type' => Notice::TYPE_ERROR, 'active_callback' => function() { diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index bd679b2fe4d..50ae6acf4b1 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -36,6 +36,7 @@ final class OAuth_Client { const OPTION_AUTH_SCOPES = 'googlesitekit_auth_scopes'; const OPTION_ERROR_CODE = 'googlesitekit_error_code'; const OPTION_PROXY_NONCE = 'googlesitekit_proxy_nonce'; + const OPTION_PROXY_ACCESS_CODE = 'googlesitekit_proxy_access_code'; const PROXY_URL = 'https://sitekit.withgoogle.com'; /** @@ -237,26 +238,31 @@ public function refresh_token() { try { $authentication_token = $this->google_client->fetchAccessTokenWithRefreshToken( $refresh_token ); + } catch ( Google_Proxy_Exception $e ) { + $this->user_options->set( self::OPTION_ERROR_CODE, $e->getMessage() ); + $this->user_options->set( self::OPTION_PROXY_ACCESS_CODE, $e->getAccessCode() ); + return; + } catch ( \Exception $e ) { + $this->user_options->set( self::OPTION_ERROR_CODE, 'invalid_grant' ); + return; + } - // Refresh token is expired or revoked. - if ( ! empty( $authentication_token['error'] ) ) { - $this->user_options->set( self::OPTION_ERROR_CODE, $authentication_token['error'] ); - return; - } - - if ( ! isset( $authentication_token['access_token'] ) ) { - $this->user_options->set( self::OPTION_ERROR_CODE, 'access_token_not_received' ); - return; - } + // Refresh token is expired or revoked. + if ( ! empty( $authentication_token['error'] ) ) { + $this->user_options->set( self::OPTION_ERROR_CODE, $authentication_token['error'] ); + return; + } - $this->set_access_token( - $authentication_token['access_token'], - isset( $authentication_token['expires_in'] ) ? $authentication_token['expires_in'] : '', - isset( $authentication_token['created'] ) ? $authentication_token['created'] : 0 - ); - } catch ( \Exception $e ) { - $this->user_options->set( self::OPTION_ERROR_CODE, $e->getCode() ); + if ( ! isset( $authentication_token['access_token'] ) ) { + $this->user_options->set( self::OPTION_ERROR_CODE, 'access_token_not_received' ); + return; } + + $this->set_access_token( + $authentication_token['access_token'], + isset( $authentication_token['expires_in'] ) ? $authentication_token['expires_in'] : '', + isset( $authentication_token['created'] ) ? $authentication_token['created'] : 0 + ); } /** @@ -656,6 +662,19 @@ public function get_error_message( $error_code ) { $message = __( 'Unable to receive access token because of an unsupported grant type.', 'google-site-kit' ); break; default: + if ( $this->using_proxy() ) { + $access_code = $this->user_options->get( self::OPTION_PROXY_ACCESS_CODE ); + if ( ! empty( $access_code ) ) { + $message = sprintf( + /* translators: 1: error code from API, 2: URL to re-authenticate */ + __( 'Setup Error (code: %1$s). Re-authenticate with Google', 'google-site-kit' ), + $error_code, + $this->get_proxy_setup_url( $access_code ) + ); + $this->user_options->delete( self::OPTION_PROXY_ACCESS_CODE ); + return $message; + } + } /* translators: %s: error code from API */ $message = sprintf( __( 'Unknown Error (code: %s).', 'google-site-kit' ), $error_code ); break; From 73c60d9d229833f0652b51c1de0654423dc57a46 Mon Sep 17 00:00:00 2001 From: "Matthew Riley MacPherson (tofumatt)" Date: Mon, 7 Oct 2019 20:37:13 +0100 Subject: [PATCH 014/102] chore: Add Optimize activation test --- .../specs/modules/optimize/activation.test.js | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/e2e/specs/modules/optimize/activation.test.js diff --git a/tests/e2e/specs/modules/optimize/activation.test.js b/tests/e2e/specs/modules/optimize/activation.test.js new file mode 100644 index 00000000000..e46bf443dc5 --- /dev/null +++ b/tests/e2e/specs/modules/optimize/activation.test.js @@ -0,0 +1,43 @@ +/** + * WordPress dependencies + */ +import { visitAdminPage, activatePlugin } from '@wordpress/e2e-test-utils'; + +/** + * Internal dependencies + */ +import { + deactivateUtilityPlugins, + resetSiteKit, + setSearchConsoleProperty, + setSiteVerification, + setupAnalytics, +} from '../../../utils'; + +describe( 'Optimize Activation', () => { + beforeEach( async () => { + await activatePlugin( 'e2e-tests-auth-plugin' ); + await setSiteVerification(); + await setSearchConsoleProperty(); + await setupAnalytics(); + } ); + + afterEach( async () => { + await deactivateUtilityPlugins(); + await resetSiteKit(); + } ); + + it( 'should lead you to the activation page', async () => { + await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' ); + + // Activate the "Connect more services" tab. + await page.waitForSelector( '.mdc-tab:nth-of-type(2)', { text: 'Connect More Services' } ); + await page.click( '.mdc-tab:nth-of-type(2)', { text: 'Connect More Services' } ); + + await page.waitForSelector( '.googlesitekit-settings-connect-module--optimize .googlesitekit-cta-link', { text: 'Set up Optimize' } ); + await page.click( '.googlesitekit-settings-connect-module--optimize .googlesitekit-cta-link', { text: 'Set up Optimize' } ); + + await page.waitForSelector( 'h2.googlesitekit-setup-module__title' ); + await expect( page ).toMatchElement( 'h2.googlesitekit-setup-module__title', { text: 'Optimize' } ); + } ); +} ); From 31c2eeca9c707987b903d5101cf2f2cfcc197d9f Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Fri, 11 Oct 2019 15:42:14 +0200 Subject: [PATCH 015/102] Delete new proxy options on reset. --- includes/Core/Util/Reset.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/includes/Core/Util/Reset.php b/includes/Core/Util/Reset.php index 25b3ea385dd..b8f8a42273d 100644 --- a/includes/Core/Util/Reset.php +++ b/includes/Core/Util/Reset.php @@ -121,6 +121,7 @@ private function delete_all_plugin_options() { $this->options->delete( Optimize::OPTION ); $this->options->delete( TagManager::OPTION ); $this->options->delete( First_Admin::OPTION ); + $this->options->delete( OAuth_Client::OPTION_PROXY_NONCE ); // Clean up old site verification data, moved to user options. // Also clean up other old unused options. @@ -162,6 +163,7 @@ private function delete_all_user_metas() { $user_options->delete( OAuth_Client::OPTION_REDIRECT_URL ); $user_options->delete( OAuth_Client::OPTION_AUTH_SCOPES ); $user_options->delete( OAuth_Client::OPTION_ERROR_CODE ); + $user_options->delete( OAuth_Client::OPTION_PROXY_ACCESS_CODE ); $user_options->delete( Verification::OPTION ); $user_options->delete( Verification_Tag::OPTION ); $user_options->delete( Profile::OPTION ); From 0afb4397a5fc6697834d0c9c199602964796358a Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Fri, 11 Oct 2019 15:43:08 +0200 Subject: [PATCH 016/102] Delete proxy access code on disconnect. --- includes/Core/Authentication/Authentication.php | 1 + 1 file changed, 1 insertion(+) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index 07abd6bde65..a9eb885e66c 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -389,6 +389,7 @@ public function disconnect() { $this->user_options->delete( Clients\OAuth_Client::OPTION_REDIRECT_URL ); $this->user_options->delete( Clients\OAuth_Client::OPTION_AUTH_SCOPES ); $this->user_options->delete( Clients\OAuth_Client::OPTION_ERROR_CODE ); + $this->user_options->delete( Clients\OAuth_Client::OPTION_PROXY_ACCESS_CODE ); $this->user_options->delete( Verification::OPTION ); $this->user_options->delete( Verification_Tag::OPTION ); $this->user_options->delete( Profile::OPTION ); From 6f7c5556f0e0c18c723108c2fcf8da2a53b4a5c6 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Fri, 11 Oct 2019 15:48:39 +0200 Subject: [PATCH 017/102] Correctly use Options class for storing valid proxy nonce. --- .../Authentication/Clients/OAuth_Client.php | 22 +++++++++++++++++-- includes/Core/REST_API/REST_Routes.php | 4 +--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index 50ae6acf4b1..1ef31e5e49b 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -593,10 +593,10 @@ public function get_proxy_setup_url( $code = '' ) { $admin_root = str_replace( array( 'http://', 'https://' ), '', admin_url() ); $admin_root = str_replace( $home_url_no_scheme, '', $admin_root ); - $nonce = get_option( self::OPTION_PROXY_NONCE, '' ); + $nonce = $this->options->get( self::OPTION_PROXY_NONCE ); if ( empty( $nonce ) ) { $nonce = wp_create_nonce( 'googlesitekit_proxy' ); - update_option( self::OPTION_PROXY_NONCE, $nonce ); + $this->options->set( self::OPTION_PROXY_NONCE, $nonce ); } return add_query_arg( @@ -620,6 +620,24 @@ public function get_proxy_setup_url( $code = '' ) { ); } + /** + * Checks whether the given proxy nonce is valid. + * + * @since 1.0.0 + * + * @param string $nonce Nonce to validate. + * @return bool True if nonce is valid, false otherwise. + */ + public function validate_proxy_nonce( $nonce ) { + $valid_nonce = $this->options->get( self::OPTION_PROXY_NONCE ); + if ( $nonce !== $valid_nonce ) { + return false; + } + + $this->options->delete( self::OPTION_PROXY_NONCE ); + return true; + } + /** * Converts the given error code to a user-facing message. * diff --git a/includes/Core/REST_API/REST_Routes.php b/includes/Core/REST_API/REST_Routes.php index b7f46189257..41a9e646dfa 100644 --- a/includes/Core/REST_API/REST_Routes.php +++ b/includes/Core/REST_API/REST_Routes.php @@ -589,11 +589,9 @@ function( $dataset ) use ( $module ) { if ( ! $auth_client->using_proxy() ) { return new WP_Error( 'invalid_authentication_mode', __( 'Invalid authentication mode.', 'google-site-kit' ), array( 'status' => 500 ) ); } - $nonce = get_option( OAuth_Client::OPTION_PROXY_NONCE, '' ); - if ( $nonce !== $request['nonce'] ) { + if ( ! $auth_client->validate_proxy_nonce( $request['nonce'] ) ) { return new WP_Error( 'invalid_nonce', __( 'Invalid nonce.', 'google-site-kit' ), array( 'status' => 400 ) ); } - delete_option( OAuth_Client::OPTION_PROXY_NONCE ); $data = array( 'oauth2_client_id' => sanitize_text_field( $request['site_id'] ), 'oauth2_client_secret' => sanitize_text_field( $request['site_secret'] ), From 644b5d6dca76a09c766844adc5c456413f32f4b9 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Fri, 11 Oct 2019 15:53:11 +0200 Subject: [PATCH 018/102] Introduce method that returns permissions proxy URL. --- .../Authentication/Clients/OAuth_Client.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index 1ef31e5e49b..ea8199d93a1 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -620,6 +620,25 @@ public function get_proxy_setup_url( $code = '' ) { ); } + /** + * Returns the permissions URL to the authentication proxy. + * + * This only returns a URL if the user already has an access token set. + * + * @since 1.0.0 + * + * @return string URL to the permissions page on the authentication proxy on success, + * or empty string on failure. + */ + public function get_proxy_permissions_url() { + $access_token = $this->get_access_token(); + if ( empty( $access_token ) ) { + return ''; + } + + return add_query_arg( 'token', $access_token, self::PROXY_URL . '/site-management/permissions/' ); + } + /** * Checks whether the given proxy nonce is valid. * From 95e56569ff2f36f6b1a500f7a6b2b49691bb85a8 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Fri, 11 Oct 2019 16:03:07 +0200 Subject: [PATCH 019/102] Expose proxy setup and permissions URLs to JS. --- .../Core/Authentication/Authentication.php | 91 +++++++++++-------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index a9eb885e66c..f34a737ea81 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -589,52 +589,67 @@ private function inline_js_admin_data( $data ) { $data['userData']['picture'] = $profile_data['photo']; } - $client_data = $this->credentials->get(); - $apikey = $this->get_api_key_client()->get_api_key(); - $gcp_project = $this->gcp_project->get(); + $auth_client = $this->get_oauth_client(); + if ( $auth_client->using_proxy() ) { + $access_code = (string) $this->user_options->get( Clients\OAuth_Client::OPTION_PROXY_ACCESS_CODE ); + $data['proxySetupURL'] = $auth_client->get_proxy_setup_url( $access_code ); + $data['proxyPermissionsURL'] = $auth_client->get_proxy_permissions_url(); - if ( current_user_can( Permissions::MANAGE_OPTIONS ) && isset( $client_data['oauth2_client_id'] ) ) { - $data['clientID'] = $client_data['oauth2_client_id']; - } else { - $data['clientID'] = ''; - } - if ( current_user_can( Permissions::MANAGE_OPTIONS ) && isset( $client_data['oauth2_client_secret'] ) ) { - $data['clientSecret'] = str_repeat( '•', strlen( $client_data['oauth2_client_secret'] ) ); - } else { + // TODO: Remove once related JS functionality is removed. For now, still set these as false-y. + $data['clientID'] = ''; $data['clientSecret'] = ''; - } - - if ( current_user_can( Permissions::MANAGE_OPTIONS ) && $apikey ) { - $data['apikey'] = $apikey; + $data['apikey'] = false; + $data['projectId'] = false; + $data['projectUrl'] = false; } else { - $data['apikey'] = false; - } + // TODO: Remove once related JS functionality is removed. + $client_data = $this->credentials->get(); + $apikey = $this->get_api_key_client()->get_api_key(); + $gcp_project = $this->gcp_project->get(); + + if ( current_user_can( Permissions::MANAGE_OPTIONS ) && isset( $client_data['oauth2_client_id'] ) ) { + $data['clientID'] = $client_data['oauth2_client_id']; + } else { + $data['clientID'] = ''; + } + if ( current_user_can( Permissions::MANAGE_OPTIONS ) && isset( $client_data['oauth2_client_secret'] ) ) { + $data['clientSecret'] = str_repeat( '•', strlen( $client_data['oauth2_client_secret'] ) ); + } else { + $data['clientSecret'] = ''; + } - // Make GCP project information available only to the creator. - if ( ! empty( $gcp_project['id'] ) && (int) get_current_user_id() === $gcp_project['wp_owner_id'] ) { - $data['projectId'] = $gcp_project['id']; - $data['projectUrl'] = add_query_arg( 'project', $gcp_project['id'], 'https://console.cloud.google.com/apis/credentials' ); - } else { - $data['projectId'] = false; - $data['projectUrl'] = false; - } + if ( current_user_can( Permissions::MANAGE_OPTIONS ) && $apikey ) { + $data['apikey'] = $apikey; + } else { + $data['apikey'] = false; + } - $data['connectUrl'] = esc_url_raw( $this->get_connect_url() ); - $data['disconnectUrl'] = esc_url_raw( $this->get_disconnect_url() ); + // Make GCP project information available only to the creator. + if ( ! empty( $gcp_project['id'] ) && (int) get_current_user_id() === $gcp_project['wp_owner_id'] ) { + $data['projectId'] = $gcp_project['id']; + $data['projectUrl'] = add_query_arg( 'project', $gcp_project['id'], 'https://console.cloud.google.com/apis/credentials' ); + } else { + $data['projectId'] = false; + $data['projectUrl'] = false; + } + + $external_sitename = html_entity_decode( get_bloginfo( 'name' ), ENT_QUOTES ); + $external_sitename = str_replace( '&', 'and', $external_sitename ); + $external_sitename = trim( preg_replace( '/([^A-Za-z0-9 ]+|google)/i', '', $external_sitename ) ); + if ( strlen( $external_sitename ) < 4 ) { + $external_sitename .= ' Site Kit'; + } + $external_page_params = array( + 'sitename' => substr( $external_sitename, 0, 30 ), // limit to 30 chars. + 'siteurl' => untrailingslashit( home_url() ), + ); - $external_sitename = html_entity_decode( get_bloginfo( 'name' ), ENT_QUOTES ); - $external_sitename = str_replace( '&', 'and', $external_sitename ); - $external_sitename = trim( preg_replace( '/([^A-Za-z0-9 ]+|google)/i', '', $external_sitename ) ); - if ( strlen( $external_sitename ) < 4 ) { - $external_sitename .= ' Site Kit'; + $data['externalCredentialsURL'] = esc_url_raw( add_query_arg( $external_page_params, 'https://developers.google.com/web/site-kit' ) ); + $data['externalAPIKeyURL'] = esc_url_raw( add_query_arg( $external_page_params, 'https://developers.google.com/web/site-kit/apikey' ) ); } - $external_page_params = array( - 'sitename' => substr( $external_sitename, 0, 30 ), // limit to 30 chars. - 'siteurl' => untrailingslashit( home_url() ), - ); - $data['externalCredentialsURL'] = esc_url_raw( add_query_arg( $external_page_params, 'https://developers.google.com/web/site-kit' ) ); - $data['externalAPIKeyURL'] = esc_url_raw( add_query_arg( $external_page_params, 'https://developers.google.com/web/site-kit/apikey' ) ); + $data['connectUrl'] = esc_url_raw( $this->get_connect_url() ); + $data['disconnectUrl'] = esc_url_raw( $this->get_disconnect_url() ); return $data; } From 1ef4b7a46bb01f194bd88871bf9f9f716320a4d6 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Fri, 11 Oct 2019 16:05:52 +0200 Subject: [PATCH 020/102] Only allow administrators to authenticate, due to verification requirements. --- includes/Core/Permissions/Permissions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/Core/Permissions/Permissions.php b/includes/Core/Permissions/Permissions.php index d00e82f8807..be33956c7a8 100644 --- a/includes/Core/Permissions/Permissions.php +++ b/includes/Core/Permissions/Permissions.php @@ -104,8 +104,8 @@ public function __construct( Context $context, Authentication $authentication = $this->authentication = $authentication; $this->primitive_to_core = array( - // Allow contributors and up to authenticate. - self::AUTHENTICATE => 'edit_posts', + // By default, only allow administrators and up to authenticate. + self::AUTHENTICATE => 'manage_options', // Allow contributors and up to view their own post's insights. self::VIEW_POSTS_INSIGHTS => 'edit_posts', From ec399261313b75975c6a290a56b587c1fdee3956 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Fri, 11 Oct 2019 17:53:59 +0200 Subject: [PATCH 021/102] If using proxy, automatically set verified flag and Search Console property since the proxy handles it. --- .../Authentication/Clients/OAuth_Client.php | 13 +++++++++++++ includes/Modules/Search_Console.php | 19 ------------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index ea8199d93a1..2875fed94e2 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -527,6 +527,19 @@ function( $scope ) { ); $this->set_granted_scopes( $scopes ); + // If using the proxy, these values can reliably be set at this point because the proxy already took care of + // them. + // TODO: In the future, once the old authentication mechanism no longer exists, this should be resolved in + // another way. + if ( $this->using_proxy() ) { + if ( ! $this->user_options->get( 'googlesitekit_site_verified_meta' ) ) { + $this->user_options->set( 'googlesitekit_site_verified_meta', 'verified' ); + } + if ( ! $this->options->get( 'googlesitekit_search_console_property' ) ) { + $this->options->set( 'googlesitekit_search_console_property', trailingslashit( $this->context->get_reference_site_url() ) ); + } + } + $redirect_url = $this->user_options->get( self::OPTION_REDIRECT_URL ); if ( $redirect_url ) { diff --git a/includes/Modules/Search_Console.php b/includes/Modules/Search_Console.php index f4bbdee23cc..78fc89bb9f1 100644 --- a/includes/Modules/Search_Console.php +++ b/includes/Modules/Search_Console.php @@ -43,25 +43,6 @@ public function register() { $this->register_screen_hook(); - // When using the proxy, simply set the Search Console property after receiving an access token, since it is - // already taken care of on the proxy side. - add_action( - 'admin_init', - function() { - $auth_client = $this->authentication->get_oauth_client(); - if ( ! $auth_client->using_proxy() ) { - return; - } - - $access_token = $auth_client->get_access_token(); - if ( empty( $access_token ) ) { - return; - } - - $this->options->set( self::PROPERTY_OPTION, trailingslashit( $this->context->get_reference_site_url() ) ); - } - ); - // Ensure that a Search Console property must be set at all times. add_filter( 'googlesitekit_setup_complete', From f8cf0a7c08061fce25e8fb5daae9e5c60d45f7b3 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Sun, 13 Oct 2019 22:17:09 +0300 Subject: [PATCH 022/102] remove clientCredentials step and component --- .../wizard-step-client-credentials.js | 259 ------------------ .../components/setup-wizard/wizard-steps.js | 8 - 2 files changed, 267 deletions(-) delete mode 100644 assets/js/components/setup-wizard/wizard-step-client-credentials.js diff --git a/assets/js/components/setup-wizard/wizard-step-client-credentials.js b/assets/js/components/setup-wizard/wizard-step-client-credentials.js deleted file mode 100644 index e2e3a88dfbc..00000000000 --- a/assets/js/components/setup-wizard/wizard-step-client-credentials.js +++ /dev/null @@ -1,259 +0,0 @@ -/** - * WizardStepClientCredentials component. - * - * Site Kit by Google, Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * External dependencies - */ -import PropTypes from 'prop-types'; -import data, { TYPE_CORE } from 'GoogleComponents/data'; -import Link from 'GoogleComponents/link'; -import { TextField, Input } from 'SiteKitCore/material-components'; -import Button from 'GoogleComponents/button'; -/** - * Internal dependencies - */ -import { sendAnalyticsTrackingEvent } from 'GoogleUtil'; -import HelpLink from 'GoogleComponents/help-link'; - -/** - * WordPress dependencies. - */ -const { __ } = wp.i18n; -const { Component } = wp.element; -const { addQueryArgs } = wp.url; - -class WizardStepClientCredentials extends Component { - constructor( props ) { - super( props ); - - this.state = { - clientConfiguration: '', - clientID: '', - clientSecret: '', - projectID: '', - isSaving: false, - errorMsg: '', - }; - - this.handleClientConfigurationEntry = this.handleClientConfigurationEntry.bind( this ); - this.onProceed = this.onProceed.bind( this ); - } - - async componentDidMount() { - const { - isSiteKitConnected, - siteConnectedSetup, - } = this.props; - - this._isMounted = true; - - // Double check isSiteKitConnected. - if ( ! isSiteKitConnected ) { - const response = await data.get( TYPE_CORE, 'site', 'credentials' ); - - if ( response && response.oauth2_client_id && response.oauth2_client_secret ) { - googlesitekit.setup.isSiteKitConnected = true; - siteConnectedSetup( true ); - } - } - } - - componentWillUnmount() { - this._isMounted = false; - } - - async onProceed() { - const { - clientID, - clientSecret, - projectID, - } = this.state; - - if ( 0 === clientID.length || 0 === clientSecret.length ) { - return; - } - - const credentials = { - clientID, - clientSecret, - }; - - sendAnalyticsTrackingEvent( 'plugin_setup', 'client_id_secret_entered' ); - - try { - this.setState( { isSaving: true } ); - - await data.set( TYPE_CORE, 'site', 'credentials', credentials ); - - if ( projectID && projectID.length ) { - await data.set( TYPE_CORE, 'site', 'gcpproject', { projectID } ); - } - - if ( this._isMounted ) { - this.setState( { - isSaving: false, - } ); - } - - // Go to next step. - this.props.siteConnectedSetup( true ); - } catch ( err ) { - if ( this._isMounted ) { - this.setState( { - errorMsg: err.message, - } ); - } - - this.props.setErrorMessage( err.message ); - } - } - - handleClientConfigurationEntry( e ) { - const value = e.target.value.trim(); - this.setState( { - clientConfiguration: value, - } ); - - if ( '' === value ) { - this.setState( { - errorMsg: '', - clientID: '', - clientSecret: '', - projectID: '', - } ); - return; - } - - let clientData = false; - try { - clientData = JSON.parse( value ); - } catch ( error ) { - this.setState( { - errorMsg: __( 'Unable to parse client configuration values.', 'google-site-kit' ), - clientID: '', - clientSecret: '', - projectID: '', - } ); - } - - if ( clientData && clientData.web ) { - const { - web: { - client_id: clientID, - client_secret: clientSecret, - project_id: projectID, - }, - } = clientData; - - this.setState( { - errorMsg: '', - clientID, - clientSecret, - projectID, - } ); - } - } - - render() { - let { externalCredentialsURL } = googlesitekit.admin; - - // If an Ad blocker is enabled, pass a quuery var in the external credentials URL. - const { canAdsRun } = googlesitekit; - if ( ! canAdsRun ) { - externalCredentialsURL = addQueryArgs( externalCredentialsURL, - { - warn_adblocker: 'true', /*eslint camelcase: 0*/ - } ); - } - const { - clientConfiguration, - clientID, - clientSecret, - errorMsg, - } = this.state; - - const externalCredentialsURLLabel = 'developers.google.com/web/sitekit'; - - return ( -
-
-
-
-

- { __( 'Welcome to Site Kit beta for developers.', 'google-site-kit' ) } -

-

- { __( 'To complete the setup, it will help if you\'re familiar with Google Cloud Platform and OAuth.', 'google-site-kit' ) } -

-

- { __( 'If that sounds like you, get started by creating a client configuration on ', 'google-site-kit' ) } - - { externalCredentialsURLLabel } - -

-

- { __( 'Once you paste it below, it will be valid for all other plugin users.', 'google-site-kit' ) } -

- { - errorMsg && errorMsg.length && -

- { errorMsg } -

- } - -
- - - -
-
- - -
-
-
-
-
- ); - } -} - -WizardStepClientCredentials.propTypes = { - siteConnectedSetup: PropTypes.func.isRequired, -}; - -export default WizardStepClientCredentials; diff --git a/assets/js/components/setup-wizard/wizard-steps.js b/assets/js/components/setup-wizard/wizard-steps.js index b06a336f062..fb0af32ca42 100644 --- a/assets/js/components/setup-wizard/wizard-steps.js +++ b/assets/js/components/setup-wizard/wizard-steps.js @@ -19,7 +19,6 @@ /** * External dependencies */ -import WizardStepClientCredentials from 'GoogleComponents/setup-wizard/wizard-step-client-credentials'; import WizardStepAuthentication from 'GoogleComponents/setup-wizard/wizard-step-authentication'; import WizardStepVerification from 'GoogleComponents/setup-wizard/wizard-step-verification'; import WizardStepSearchConsoleProperty from 'GoogleComponents/setup-wizard/wizard-step-search-console-property'; @@ -28,13 +27,6 @@ import WizardStepCompleteSetup from 'GoogleComponents/setup-wizard/wizard-step-c const { __ } = wp.i18n; const STEPS = { - clientCredentials: { - title: __( 'Create Client ID', 'google-site-kit' ), - required: true, - isApplicable: ( props ) => props.canSetup && ( ! props.isSiteKitConnected || ! props.hasSearchConsolePropertyFromTheStart ), - isCompleted: ( props ) => props.isSiteKitConnected, - Component: WizardStepClientCredentials, - }, authentication: { title: __( 'Authenticate', 'google-site-kit' ), required: true, From ac959c8a900246a2c67f03d3193a3bad43b4d4cb Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Sun, 13 Oct 2019 22:17:24 +0300 Subject: [PATCH 023/102] remove client configuration e2e test --- .../specs/auth-client-configuration.test.js | 46 ------------------- 1 file changed, 46 deletions(-) delete mode 100644 tests/e2e/specs/auth-client-configuration.test.js diff --git a/tests/e2e/specs/auth-client-configuration.test.js b/tests/e2e/specs/auth-client-configuration.test.js deleted file mode 100644 index ecbe18fa2ba..00000000000 --- a/tests/e2e/specs/auth-client-configuration.test.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * WordPress dependencies - */ -import { visitAdminPage } from '@wordpress/e2e-test-utils'; - -/** - * Internal dependencies - */ -import { pasteText, testClientConfig } from '../utils'; - -describe( 'Providing client configuration', () => { - beforeEach( async () => { - await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); - } ); - - it( 'Should have disabled button on load', async () => { - await page.waitForSelector( '#wizard-step-one-proceed' ); - - expect( await page.$eval( '#wizard-step-one-proceed', ( el ) => el.matches( '[disabled]' ) ) ).toBe( true ); - } ); - - it( 'Should have disabled button and display error when input is invalid', async () => { - await page.waitForSelector( '#client-configuration' ); - await pasteText( '#client-configuration', '{ invalid json }' ); - - await page.waitForSelector( '.googlesitekit-error-text' ); - await expect( page ).toMatchElement( '.googlesitekit-error-text', { text: 'Unable to parse client configuration values' } ); - - expect( await page.$eval( '#wizard-step-one-proceed', ( el ) => el.matches( '[disabled]' ) ) ).toBe( true ); - } ); - - it( 'Should have enabled button with valid value', async () => { - await page.waitForSelector( '#client-configuration' ); - await pasteText( '#client-configuration', JSON.stringify( testClientConfig ) ); - - await expect( page ).not.toMatchElement( '.googlesitekit-error-text', { text: 'Unable to parse client configuration values' } ); - - expect( await page.$eval( '#wizard-step-one-proceed', ( el ) => el.matches( '[disabled]' ) ) ).toBe( false ); - - await page.click( '#wizard-step-one-proceed' ); - - await page.waitForSelector( '.googlesitekit-wizard-step--two' ); - - await expect( page ).toMatchElement( '.googlesitekit-wizard-step__title', { text: 'Authenticate with Google' } ); - } ); -} ); From 3fd6a6049ac15fb0946e682940fbe187cee8364f Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Sun, 13 Oct 2019 22:17:51 +0300 Subject: [PATCH 024/102] remove client config input from auth-flow test --- tests/e2e/specs/auth-flow.test.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/e2e/specs/auth-flow.test.js b/tests/e2e/specs/auth-flow.test.js index e6fc3f08ff1..888374a63ba 100644 --- a/tests/e2e/specs/auth-flow.test.js +++ b/tests/e2e/specs/auth-flow.test.js @@ -9,9 +9,7 @@ import { activatePlugin, createURL, visitAdminPage } from '@wordpress/e2e-test-u import { deactivateUtilityPlugins, resetSiteKit, - pasteText, setSearchConsoleProperty, - testClientConfig, useRequestInterception, setClientConfig, setAuthToken, @@ -65,12 +63,8 @@ describe( 'Site Kit set up flow for the first time', () => { } ); it( 'authenticates from splash page', async () => { + await setClientConfig(); await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); - await page.waitForSelector( '#client-configuration' ); - - await pasteText( '#client-configuration', JSON.stringify( testClientConfig ) ); - await page.click( '#wizard-step-one-proceed' ); - await page.waitForSelector( '.googlesitekit-wizard-step--two .mdc-button' ); // Sign in with Google await page.setRequestInterception( true ); From ec91d1e218d100a0a94b1e638887acf07878f7b1 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Sun, 13 Oct 2019 22:39:49 +0300 Subject: [PATCH 025/102] remove client configuration from e2e tests --- tests/e2e/specs/auth-setup-search-console.test.js | 15 +++------------ tests/e2e/specs/auth-setup-verification.test.js | 15 +++------------ 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/tests/e2e/specs/auth-setup-search-console.test.js b/tests/e2e/specs/auth-setup-search-console.test.js index f2acc40afca..aee91ff8f8c 100644 --- a/tests/e2e/specs/auth-setup-search-console.test.js +++ b/tests/e2e/specs/auth-setup-search-console.test.js @@ -8,9 +8,8 @@ import { activatePlugin, createURL, visitAdminPage } from '@wordpress/e2e-test-u */ import { deactivateUtilityPlugins, - pasteText, resetSiteKit, - testClientConfig, + setClientConfig, useRequestInterception, wpApiFetch, } from '../utils'; @@ -53,12 +52,8 @@ describe( 'Site Kit set up flow for the first time with search console setup', ( } ); it( 'inserts property to search console when site does not exist', async () => { + await setClientConfig(); await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); - await page.waitForSelector( '#client-configuration' ); - - await pasteText( '#client-configuration', JSON.stringify( testClientConfig ) ); - await expect( page ).toClick( '#wizard-step-one-proceed' ); - await page.waitForSelector( '.googlesitekit-wizard-step--two button' ); await expect( page ).toClick( '.googlesitekit-wizard-step--two button', { text: /sign in with Google/i } ); await page.waitForNavigation(); @@ -76,12 +71,8 @@ describe( 'Site Kit set up flow for the first time with search console setup', ( } ); it( 'saves search console property when site exists', async () => { + await setClientConfig(); await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); - await page.waitForSelector( '#client-configuration' ); - - await pasteText( '#client-configuration', JSON.stringify( testClientConfig ) ); - await expect( page ).toClick( '#wizard-step-one-proceed' ); - await page.waitForSelector( '.googlesitekit-wizard-step--two button' ); await expect( page ).toClick( '.googlesitekit-wizard-step--two button', { text: /sign in with Google/i } ); await page.waitForNavigation(); diff --git a/tests/e2e/specs/auth-setup-verification.test.js b/tests/e2e/specs/auth-setup-verification.test.js index 81a369cd7fd..505cab8a758 100644 --- a/tests/e2e/specs/auth-setup-verification.test.js +++ b/tests/e2e/specs/auth-setup-verification.test.js @@ -8,9 +8,8 @@ import { activatePlugin, createURL, visitAdminPage } from '@wordpress/e2e-test-u */ import { deactivateUtilityPlugins, - pasteText, resetSiteKit, - testClientConfig, + setClientConfig, useRequestInterception, wpApiFetch, } from '../utils'; @@ -51,12 +50,8 @@ describe( 'Site Kit set up flow for the first time with site verification', () = } ); it( 'prompts for confirmation if user is not verified for the site', async () => { + await setClientConfig(); await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); - await page.waitForSelector( '#client-configuration' ); - - await pasteText( '#client-configuration', JSON.stringify( testClientConfig ) ); - await expect( page ).toClick( '#wizard-step-one-proceed' ); - await page.waitForSelector( '.googlesitekit-wizard-step--two button' ); await expect( page ).toClick( '.googlesitekit-wizard-step--two button', { text: /sign in with Google/i } ); await page.waitForNavigation(); @@ -78,6 +73,7 @@ describe( 'Site Kit set up flow for the first time with site verification', () = } ); it( 'does not prompt for verification if the user is already verified for the site', async () => { + await setClientConfig(); // Simulate that the user is already verified. await wpApiFetch( { path: 'google-site-kit/v1/e2e/verify-site', @@ -85,11 +81,6 @@ describe( 'Site Kit set up flow for the first time with site verification', () = } ); await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); - await page.waitForSelector( '#client-configuration' ); - - await pasteText( '#client-configuration', JSON.stringify( testClientConfig ) ); - await expect( page ).toClick( '#wizard-step-one-proceed' ); - await page.waitForSelector( '.googlesitekit-wizard-step--two button' ); await expect( page ).toClick( '.googlesitekit-wizard-step--two button', { text: /sign in with Google/i } ); await page.waitForNavigation(); From 419e8ca5389577468a2828e31a8b758057bee7f5 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Sun, 13 Oct 2019 22:40:18 +0300 Subject: [PATCH 026/102] remove step number from sign-in with google selector --- tests/e2e/specs/auth-flow.test.js | 2 +- tests/e2e/specs/auth-setup-search-console.test.js | 4 ++-- tests/e2e/specs/auth-setup-verification.test.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/e2e/specs/auth-flow.test.js b/tests/e2e/specs/auth-flow.test.js index 888374a63ba..69e29d47065 100644 --- a/tests/e2e/specs/auth-flow.test.js +++ b/tests/e2e/specs/auth-flow.test.js @@ -69,7 +69,7 @@ describe( 'Site Kit set up flow for the first time', () => { // Sign in with Google await page.setRequestInterception( true ); useRequestInterception( stubGoogleSignIn ); - await page.click( '.googlesitekit-wizard-step--two .mdc-button' ); + await expect( page ).toClick( '.googlesitekit-wizard-step button', { text: /sign in with Google/i } ); await page.waitForNavigation(); await expect( page ).toMatchElement( '#js-googlesitekit-dashboard' ); diff --git a/tests/e2e/specs/auth-setup-search-console.test.js b/tests/e2e/specs/auth-setup-search-console.test.js index aee91ff8f8c..1f9f04c1244 100644 --- a/tests/e2e/specs/auth-setup-search-console.test.js +++ b/tests/e2e/specs/auth-setup-search-console.test.js @@ -55,7 +55,7 @@ describe( 'Site Kit set up flow for the first time with search console setup', ( await setClientConfig(); await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); - await expect( page ).toClick( '.googlesitekit-wizard-step--two button', { text: /sign in with Google/i } ); + await expect( page ).toClick( '.googlesitekit-wizard-step button', { text: /sign in with Google/i } ); await page.waitForNavigation(); await page.waitForSelector( '.googlesitekit-setup-module__title' ); @@ -74,7 +74,7 @@ describe( 'Site Kit set up flow for the first time with search console setup', ( await setClientConfig(); await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); - await expect( page ).toClick( '.googlesitekit-wizard-step--two button', { text: /sign in with Google/i } ); + await expect( page ).toClick( '.googlesitekit-wizard-step button', { text: /sign in with Google/i } ); await page.waitForNavigation(); await page.waitForSelector( '.googlesitekit-setup-module__title' ); diff --git a/tests/e2e/specs/auth-setup-verification.test.js b/tests/e2e/specs/auth-setup-verification.test.js index 505cab8a758..e5247e0c9b7 100644 --- a/tests/e2e/specs/auth-setup-verification.test.js +++ b/tests/e2e/specs/auth-setup-verification.test.js @@ -53,7 +53,7 @@ describe( 'Site Kit set up flow for the first time with site verification', () = await setClientConfig(); await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); - await expect( page ).toClick( '.googlesitekit-wizard-step--two button', { text: /sign in with Google/i } ); + await expect( page ).toClick( '.googlesitekit-wizard-step button', { text: /sign in with Google/i } ); await page.waitForNavigation(); await expect( page ).toMatchElement( '.googlesitekit-wizard-step__title', { text: /Verify URL/i } ); @@ -82,7 +82,7 @@ describe( 'Site Kit set up flow for the first time with site verification', () = await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); - await expect( page ).toClick( '.googlesitekit-wizard-step--two button', { text: /sign in with Google/i } ); + await expect( page ).toClick( '.googlesitekit-wizard-step button', { text: /sign in with Google/i } ); await page.waitForNavigation(); await page.waitForSelector( '.googlesitekit-wizard-step__action button' ); From b13596c347eb441b5fd20f1cc175cc5d39a8c664 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Sun, 13 Oct 2019 23:04:39 +0300 Subject: [PATCH 027/102] update checks for step one of setup --- tests/e2e/specs/plugin-activation.test.js | 3 ++- tests/e2e/specs/plugin-reset.test.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/e2e/specs/plugin-activation.test.js b/tests/e2e/specs/plugin-activation.test.js index 85ed0cf6de6..70bc552c18a 100644 --- a/tests/e2e/specs/plugin-activation.test.js +++ b/tests/e2e/specs/plugin-activation.test.js @@ -32,7 +32,8 @@ describe( 'Plugin Activation Notice', () => { await page.click( '.googlesitekit-activation__button' ); await page.waitForSelector( '.googlesitekit-wizard-step__title' ); - await expect( page ).toMatchElement( 'h2.googlesitekit-wizard-step__title', { text: 'Welcome to Site Kit beta for developers.' } ); + // Ensure we're on the first step. + await expect( page ).toMatchElement( '.googlesitekit-wizard-progress-step__number--inprogress', { text: '1' } ); await deactivatePlugin( 'google-site-kit' ); } ); diff --git a/tests/e2e/specs/plugin-reset.test.js b/tests/e2e/specs/plugin-reset.test.js index 22b5655a847..81bf4627210 100644 --- a/tests/e2e/specs/plugin-reset.test.js +++ b/tests/e2e/specs/plugin-reset.test.js @@ -55,7 +55,7 @@ describe( 'Plugin Reset', () => { expect( page ).toClick( '.mdc-dialog--open .mdc-button', { text: 'Reset' } ), ] ); - await page.waitForSelector( '.googlesitekit-wizard-step--one' ); - await expect( page ).toMatchElement( '.googlesitekit-wizard-step__title', { text: /Welcome to Site Kit beta for developers/i } ); + // Ensure we're on the first step. + await expect( page ).toMatchElement( '.googlesitekit-wizard-progress-step__number--inprogress', { text: '1' } ); } ); } ); From 1ad64d7c2605164b4c4765ce641f78d830679883 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Sun, 13 Oct 2019 23:59:46 +0300 Subject: [PATCH 028/102] replace Client ID stories/tests with new Step One --- .storybook/storybook-data.js | 6 +++--- stories/setup.stories.js | 2 +- ...e-kit_Setup_Client_ID_0_document_0_small.png | Bin 43849 -> 0 bytes ...-kit_Setup_Client_ID_0_document_1_medium.png | Bin 51373 -> 0 bytes ...e-kit_Setup_Client_ID_0_document_2_large.png | Bin 52414 -> 0 bytes ...te-kit_Setup_Step_One_0_document_0_small.png | Bin 0 -> 29192 bytes ...e-kit_Setup_Step_One_0_document_1_medium.png | Bin 0 -> 41200 bytes ...te-kit_Setup_Step_One_0_document_2_large.png | Bin 0 -> 40711 bytes 8 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 tests/backstop/reference/google-site-kit_Setup_Client_ID_0_document_0_small.png delete mode 100644 tests/backstop/reference/google-site-kit_Setup_Client_ID_0_document_1_medium.png delete mode 100644 tests/backstop/reference/google-site-kit_Setup_Client_ID_0_document_2_large.png create mode 100644 tests/backstop/reference/google-site-kit_Setup_Step_One_0_document_0_small.png create mode 100644 tests/backstop/reference/google-site-kit_Setup_Step_One_0_document_1_medium.png create mode 100644 tests/backstop/reference/google-site-kit_Setup_Step_One_0_document_2_large.png diff --git a/.storybook/storybook-data.js b/.storybook/storybook-data.js index 5f03240d825..50ddf923d13 100644 --- a/.storybook/storybook-data.js +++ b/.storybook/storybook-data.js @@ -529,10 +529,10 @@ module.exports = [ }, }, { - id: 'setup--client-id', + id: 'setup--step-one', kind: 'Setup', - name: 'Client ID', - story: 'Client ID', + name: 'Step One', + story: 'Step One', parameters: { fileName: './stories/setup.stories.js', options: { diff --git a/stories/setup.stories.js b/stories/setup.stories.js index 0ab4aca5335..300d496409f 100644 --- a/stories/setup.stories.js +++ b/stories/setup.stories.js @@ -5,7 +5,7 @@ import { storiesOf } from '@storybook/react'; import Setup from 'GoogleComponents/setup'; storiesOf( 'Setup', module ) - .add( 'Client ID', () => { + .add( 'Step one', () => { googlesitekit.setup.isSiteKitConnected = false; googlesitekit.setup.isAuthenticated = false; googlesitekit.setup.isVerified = false; diff --git a/tests/backstop/reference/google-site-kit_Setup_Client_ID_0_document_0_small.png b/tests/backstop/reference/google-site-kit_Setup_Client_ID_0_document_0_small.png deleted file mode 100644 index 5be55c5097f3bb21f965e061f6f3634951b75123..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43849 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 Hr-UW|=R2VX diff --git a/tests/backstop/reference/google-site-kit_Setup_Client_ID_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_Setup_Client_ID_0_document_1_medium.png deleted file mode 100644 index 13cbad7861f7c6bf72bcf022d58072ccb8426dc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51373 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
WGJRsV2vPE~KOc@9CcaRK?W6Y$KZ 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 diff --git a/tests/backstop/reference/google-site-kit_Setup_Step_One_0_document_0_small.png b/tests/backstop/reference/google-site-kit_Setup_Step_One_0_document_0_small.png new file mode 100644 index 0000000000000000000000000000000000000000..49bfcff5a3578b613d6343b8182776bc428c75a4 GIT binary patch literal 29192 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 HV;b}y*YkWi literal 0 HcmV?d00001 diff --git a/tests/backstop/reference/google-site-kit_Setup_Step_One_0_document_1_medium.png b/tests/backstop/reference/google-site-kit_Setup_Step_One_0_document_1_medium.png new file mode 100644 index 0000000000000000000000000000000000000000..e9dd7d9c8d9a438962fd653a7f31d4b5648143b0 GIT binary patch literal 41200 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

4NJ<9hhfvQJs>g_$+S-QZ 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 z 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 CpyB}l literal 0 HcmV?d00001 diff --git a/tests/backstop/reference/google-site-kit_Setup_Step_One_0_document_2_large.png b/tests/backstop/reference/google-site-kit_Setup_Step_One_0_document_2_large.png new file mode 100644 index 0000000000000000000000000000000000000000..c66ea1f3ba22671ff6878252ed745293e20fa933 GIT binary patch literal 40711 zcmeFZXHZk^*Dj7-QRJ~8O0@t=R}_%0ASF_zg^qOTQbP-f4e7o2UIIZ%XrZWx^co-n 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 literal 0 HcmV?d00001 From b1d512ab7ba8e9f42f624ae73bf5c532e3993375 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Mon, 14 Oct 2019 15:23:42 +0200 Subject: [PATCH 029/102] Include site ID in query arguments to permissions URL (optionally). --- .../Core/Authentication/Clients/OAuth_Client.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index 2875fed94e2..b55f9fb8670 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -649,7 +649,17 @@ public function get_proxy_permissions_url() { return ''; } - return add_query_arg( 'token', $access_token, self::PROXY_URL . '/site-management/permissions/' ); + $query_args = array( 'token' => $access_token ); + + $credentials = $this->get_client_credentials(); + if ( is_object( $credentials ) && ! empty( $credentials->web->client_id ) ) { + $query_args['site_id'] = $credentials->web->client_id; + } + + return add_query_arg( + $query_args, + self::PROXY_URL . '/site-management/permissions/' + ); } /** From 002f47cfc131da0499cd2ec444534dd876aa3b23 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Mon, 14 Oct 2019 15:25:31 +0200 Subject: [PATCH 030/102] Include temporary permissions link for testing. --- includes/Core/Authentication/Authentication.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index f34a737ea81..f6276a4885d 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -201,10 +201,16 @@ function() { add_action( 'admin_notices', function() { - $url = $this->get_oauth_client()->get_proxy_setup_url(); + $setup_url = $this->get_oauth_client()->get_proxy_setup_url(); + $permissions_url = $this->get_oauth_client()->get_proxy_permissions_url(); ?>
-

TEMPORARY:

+

+ TEMPORARY: + + or + +

Date: Mon, 14 Oct 2019 15:26:14 +0200 Subject: [PATCH 031/102] Only show temporary proxy links for testing if proxy is in use. --- includes/Core/Authentication/Authentication.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index f6276a4885d..031df36af5f 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -201,6 +201,9 @@ function() { add_action( 'admin_notices', function() { + if ( ! $this->get_oauth_client()->using_proxy() ) { + return; + } $setup_url = $this->get_oauth_client()->get_proxy_setup_url(); $permissions_url = $this->get_oauth_client()->get_proxy_permissions_url(); ?> From e057c108ac886f64a1122ee7dae6ee291650d51c Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Mon, 14 Oct 2019 21:09:44 +0300 Subject: [PATCH 032/102] update setup-analytics to accept useSnippet also, simplify utility signature --- tests/e2e/utils/setup-analytics.js | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/tests/e2e/utils/setup-analytics.js b/tests/e2e/utils/setup-analytics.js index 369813bc8c3..840b40d0d4e 100644 --- a/tests/e2e/utils/setup-analytics.js +++ b/tests/e2e/utils/setup-analytics.js @@ -8,13 +8,19 @@ const defaultConnection = { propertyId: 200, profileId: 300, internalWebPropertyId: 400, + useSnippet: true, + // ampClientIdOptIn: (bool) }; /** * Activate and set up the Analytics module. - * @param {Object} config Optional configuration to use for module set up. + * @param {Object} connectionOverrides Optional connection overrides to use for module set up. */ -export async function setupAnalytics( config = { connection: defaultConnection } ) { +export async function setupAnalytics( connectionOverrides = {} ) { + const connection = { + ...defaultConnection, + ...connectionOverrides, + }; // Activate the module. await wpApiFetch( { method: 'post', @@ -26,8 +32,19 @@ export async function setupAnalytics( config = { connection: defaultConnection } method: 'post', path: 'google-site-kit/v1/modules/analytics/data/connection', data: { - data: config.connection, + data: connection, }, parse: false, } ); + + if ( connection.useSnippet ) { + await wpApiFetch( { + method: 'post', + path: 'google-site-kit/v1/modules/analytics/data/use-snippet', + data: { + data: { useSnippet: true }, + }, + parse: false, + } ); + } } From e25867b3cc26093b9a9cb6507b199950298acba6 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Mon, 14 Oct 2019 22:45:41 +0300 Subject: [PATCH 033/102] update optimize test --- .../specs/modules/optimize/activation.test.js | 67 ++++++++++++++++--- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/tests/e2e/specs/modules/optimize/activation.test.js b/tests/e2e/specs/modules/optimize/activation.test.js index e46bf443dc5..37dbcbf3e02 100644 --- a/tests/e2e/specs/modules/optimize/activation.test.js +++ b/tests/e2e/specs/modules/optimize/activation.test.js @@ -14,12 +14,34 @@ import { setupAnalytics, } from '../../../utils'; +async function proceedToOptimizeSetup() { + await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' ); + + await page.waitForSelector( '.mdc-tab-bar' ); + await expect( page ).toClick( '.mdc-tab', { text: /connect more services/i } ); + + await page.waitForSelector( '.googlesitekit-settings-connect-module--optimize' ); + + await Promise.all( [ + page.waitForNavigation(), + page.waitForSelector( '.googlesitekit-setup-module--optimize .googlesitekit-setup-module__title' ), + expect( page ).toClick( '.googlesitekit-cta-link', { text: /set up optimize/i } ), + ] ); +} + +async function finishOptimizeSetup() { + await Promise.all( [ + page.waitForNavigation(), + expect( page ).toClick( '.googlesitekit-setup-module--optimize button', { text: /Configure Optimize/i } ), + ] ); + await expect( page ).toMatchElement( '.googlesitekit-publisher-win__title', { text: /Congrats on completing the setup for Optimize!/i } ); +} + describe( 'Optimize Activation', () => { beforeEach( async () => { await activatePlugin( 'e2e-tests-auth-plugin' ); await setSiteVerification(); await setSearchConsoleProperty(); - await setupAnalytics(); } ); afterEach( async () => { @@ -27,17 +49,42 @@ describe( 'Optimize Activation', () => { await resetSiteKit(); } ); - it( 'should lead you to the activation page', async () => { - await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' ); + it( 'prompts to insert your Optimize ID when Analytics snippet is enabled', async () => { + await setupAnalytics( { useSnippet: true } ); + await proceedToOptimizeSetup(); + + const setupHandle = await page.$( '.googlesitekit-setup-module--optimize' ); + await expect( setupHandle ).toMatchElement( '.googlesitekit-setup-module__title', { text: /Optimize/i } ); + await expect( setupHandle ).toMatchElement( 'p', { text: /Please copy and paste your Optimize ID to complete your setup/i } ); + // Not able to use negation here for some reason. + // await expect( setupHandle ).not.toMatchElement( 'p', { text: /You disabled analytics auto insert snippet. If You are using Google Analytics code snippet, add the code below/i, visible: true } ); + // await expect( setupHandle ).not.toMatchElement( 'p', { text: /Click here for how to implement Optimize tag in Google Analytics Code Snippet/i } ); + + await expect( setupHandle ).toFill( 'input', 'gtm' ); + await expect( setupHandle ).toMatchElement( '.googlesitekit-error-text', { text: /Error: Not a valid Optimize ID./i } ); + await expect( setupHandle ).toFill( 'input', 'GTM-1234567' ); + await expect( setupHandle ).not.toMatchElement( '.googlesitekit-error-text', { text: /Error: Not a valid Optimize ID./i } ); + await setupHandle.dispose(); + + await finishOptimizeSetup(); + } ); + + it( 'prompts to insert your Optimize ID when Analytics snippet is disabled, with extra instructions', async () => { + await setupAnalytics( { useSnippet: false } ); + await proceedToOptimizeSetup(); - // Activate the "Connect more services" tab. - await page.waitForSelector( '.mdc-tab:nth-of-type(2)', { text: 'Connect More Services' } ); - await page.click( '.mdc-tab:nth-of-type(2)', { text: 'Connect More Services' } ); + const setupHandle = await page.$( '.googlesitekit-setup-module--optimize' ); + await expect( setupHandle ).toMatchElement( '.googlesitekit-setup-module__title', { text: /Optimize/i } ); + await expect( setupHandle ).toMatchElement( 'p', { text: /Please copy and paste your Optimize ID to complete your setup/i } ); + await expect( setupHandle ).toMatchElement( 'p', { text: /You disabled analytics auto insert snippet. If You are using Google Analytics code snippet, add the code below/i } ); + await expect( setupHandle ).toMatchElement( 'p', { text: /Click here for how to implement Optimize tag in Google Analytics Code Snippet/i } ); - await page.waitForSelector( '.googlesitekit-settings-connect-module--optimize .googlesitekit-cta-link', { text: 'Set up Optimize' } ); - await page.click( '.googlesitekit-settings-connect-module--optimize .googlesitekit-cta-link', { text: 'Set up Optimize' } ); + await expect( setupHandle ).toFill( 'input', 'gtm' ); + await expect( setupHandle ).toMatchElement( '.googlesitekit-error-text', { text: /Error: Not a valid Optimize ID./i } ); + await expect( setupHandle ).toFill( 'input', 'GTM-1234567' ); + await expect( setupHandle ).not.toMatchElement( '.googlesitekit-error-text', { text: /Error: Not a valid Optimize ID./i } ); + await setupHandle.dispose(); - await page.waitForSelector( 'h2.googlesitekit-setup-module__title' ); - await expect( page ).toMatchElement( 'h2.googlesitekit-setup-module__title', { text: 'Optimize' } ); + await finishOptimizeSetup(); } ); } ); From 49bdbed14b97faf6d4b860a8b97535fcaef60c1e Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Tue, 15 Oct 2019 09:54:05 +0300 Subject: [PATCH 034/102] simplify analytics setup with settings --- tests/e2e/utils/setup-analytics.js | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/tests/e2e/utils/setup-analytics.js b/tests/e2e/utils/setup-analytics.js index 840b40d0d4e..5cf4a27f080 100644 --- a/tests/e2e/utils/setup-analytics.js +++ b/tests/e2e/utils/setup-analytics.js @@ -3,7 +3,7 @@ */ import { wpApiFetch } from './wp-api-fetch'; -const defaultConnection = { +const defaultSettings = { accountId: 100, propertyId: 200, profileId: 300, @@ -14,12 +14,12 @@ const defaultConnection = { /** * Activate and set up the Analytics module. - * @param {Object} connectionOverrides Optional connection overrides to use for module set up. + * @param {Object} settingsOverrides Optional settings to override the defaults. */ -export async function setupAnalytics( connectionOverrides = {} ) { - const connection = { - ...defaultConnection, - ...connectionOverrides, +export async function setupAnalytics( settingsOverrides = {} ) { + const settings = { + ...defaultSettings, + ...settingsOverrides, }; // Activate the module. await wpApiFetch( { @@ -30,21 +30,10 @@ export async function setupAnalytics( connectionOverrides = {} ) { // Set dummy connection data. await wpApiFetch( { method: 'post', - path: 'google-site-kit/v1/modules/analytics/data/connection', + path: 'google-site-kit/v1/modules/analytics/data/settings', data: { - data: connection, + data: settings, }, parse: false, } ); - - if ( connection.useSnippet ) { - await wpApiFetch( { - method: 'post', - path: 'google-site-kit/v1/modules/analytics/data/use-snippet', - data: { - data: { useSnippet: true }, - }, - parse: false, - } ); - } } From eeab5c93fe668c6f1bffeebeebaedcba6698b74f Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Tue, 15 Oct 2019 11:30:56 +0200 Subject: [PATCH 035/102] Urlencode values that may contain special characters for query vars. --- includes/Core/Authentication/Clients/OAuth_Client.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index b55f9fb8670..d7f5a951d1c 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -615,10 +615,10 @@ public function get_proxy_setup_url( $code = '' ) { return add_query_arg( array( 'nonce' => $nonce, - 'name' => get_bloginfo( 'name' ), - 'url' => $home_url, - 'rest_root' => $rest_root, - 'admin_root' => $admin_root, + 'name' => rawurlencode( get_bloginfo( 'name' ) ), + 'url' => rawurlencode( $home_url ), + 'rest_root' => rawurlencode( $rest_root ), + 'admin_root' => rawurlencode( $admin_root ), ), $url ); From 1bc05f37a864bfdd84ee0b0507e29e88ee61a778 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Tue, 15 Oct 2019 11:40:18 +0200 Subject: [PATCH 036/102] Fix PHPUnit tests. --- .../Core/Authentication/AuthenticationTest.php | 4 ++-- .../Authentication/Clients/OAuth_ClientTest.php | 15 ++------------- .../integration/Core/REST_API/REST_RoutesTest.php | 1 + 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/tests/phpunit/integration/Core/Authentication/AuthenticationTest.php b/tests/phpunit/integration/Core/Authentication/AuthenticationTest.php index 408ff6d17a1..606528163c1 100644 --- a/tests/phpunit/integration/Core/Authentication/AuthenticationTest.php +++ b/tests/phpunit/integration/Core/Authentication/AuthenticationTest.php @@ -73,8 +73,8 @@ protected function assertAdminDataExtended() { 'clientSecret', 'connectUrl', 'disconnectUrl', - 'externalAPIKeyURL', - 'externalCredentialsURL', + 'proxySetupURL', + 'proxyPermissionsURL', 'projectId', 'projectUrl', 'userData', diff --git a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php index b09eaac324f..cc1f73a6358 100644 --- a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php +++ b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php @@ -50,19 +50,8 @@ public function test_refresh_token() { $client->refresh_token(); // At this point an error is triggered internally due to undefined indexes on $authentication_token - // and the saved error code is an integer from a PHPUnit exception. - // Let's just make sure the error code is not one related to client error handling. - $this->assertNotContains( - get_user_option( OAuth_Client::OPTION_ERROR_CODE, $user_id ), - array( - 'oauth_credentials_not_exist', - 'refresh_token_not_exist', - 'cannot_log_in', - 'invalid_grant', - 'invalid_code', - 'access_token_not_received', - ) - ); + // and the saved error code is 'invalid_grant' by default. + $this->assertEquals( 'invalid_grant', get_user_option( OAuth_Client::OPTION_ERROR_CODE, $user_id ) ); } public function test_revoke_token() { diff --git a/tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php b/tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php index 536fcc1704a..0075d3607bf 100644 --- a/tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php +++ b/tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php @@ -51,6 +51,7 @@ public function test_register() { '/' . REST_Routes::REST_ROOT . '/modules/(?P[a-z\\-]+)/data/(?P[a-z\\-]+)', '/' . REST_Routes::REST_ROOT . '/data', '/' . REST_Routes::REST_ROOT . '/modules/(?P[a-z\\-]+)/notifications', + '/' . REST_Routes::REST_ROOT . '/oauth/site', '/' . REST_Routes::REST_ROOT . '/core/search/data/post-search', ); From 78dc877ee9985529d429818a520f2a0adbde18d0 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Tue, 15 Oct 2019 12:24:10 +0200 Subject: [PATCH 037/102] Remove auth flow e2e test for editor since they can no longer use the plugin. --- tests/e2e/specs/auth-flow-editor.test.js | 72 ------------------------ 1 file changed, 72 deletions(-) delete mode 100644 tests/e2e/specs/auth-flow-editor.test.js diff --git a/tests/e2e/specs/auth-flow-editor.test.js b/tests/e2e/specs/auth-flow-editor.test.js deleted file mode 100644 index 743c74dd98d..00000000000 --- a/tests/e2e/specs/auth-flow-editor.test.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * WordPress dependencies - */ -import { - activatePlugin, - loginUser, - createURL, - visitAdminPage, -} from '@wordpress/e2e-test-utils'; - -/** - * Internal dependencies - */ -import { - logoutUser, - setAuthToken, - setClientConfig, - setSearchConsoleProperty, - setSiteVerification, - useRequestInterception, -} from '../utils'; - -describe( 'the set up flow for an editor', () => { - beforeAll( async () => { - await page.setRequestInterception( true ); - useRequestInterception( ( request ) => { - if ( request.url().startsWith( 'https://accounts.google.com/o/oauth2/auth' ) ) { - request.respond( { - status: 302, - headers: { - location: createURL( '/', 'oauth2callback=1&code=valid-test-code' ), - }, - } ); - } else { - request.continue(); - } - } ); - } ); - - beforeEach( async () => { - await activatePlugin( 'e2e-tests-oauth-callback-plugin' ); - await setClientConfig(); - await setAuthToken(); - await setSiteVerification(); - await setSearchConsoleProperty(); - await logoutUser(); - } ); - - afterEach( async () => { - await logoutUser(); - - // Restore the default/admin user - // (switchToAdmin will not work as it is not aware of the current user) - await loginUser(); - } ); - - it( 'allows an editor to connect their Google account from the splash page', async () => { - await loginUser( 'editor', 'password' ); - await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); - - await page.waitForSelector( '.googlesitekit-splash-intro button' ); - await expect( page ).toMatchElement( '.googlesitekit-splash-intro__title', { text: /Welcome to Site Kit/i } ); - - await Promise.all( [ - expect( page ).toClick( '.googlesitekit-splash-intro button', { text: /connect your account/i } ), - page.waitForNavigation(), - ] ); - - await expect( page ).toMatchElement( '#js-googlesitekit-dashboard' ); - } ); -} ); - From a04694d9306fe6dbd9ef8a9db67f1210ea4e85d8 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Tue, 15 Oct 2019 12:24:43 +0200 Subject: [PATCH 038/102] Introduce e2e utility plugin to trick the plugin into bypassing the proxy. --- tests/e2e/plugins/no-proxy.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/e2e/plugins/no-proxy.php diff --git a/tests/e2e/plugins/no-proxy.php b/tests/e2e/plugins/no-proxy.php new file mode 100644 index 00000000000..d75fcd5cf6b --- /dev/null +++ b/tests/e2e/plugins/no-proxy.php @@ -0,0 +1,25 @@ + Date: Tue, 15 Oct 2019 12:47:59 +0200 Subject: [PATCH 039/102] Add PHPUnit tests for new proxy methods on OAuth_Client. --- .../Clients/OAuth_ClientTest.php | 77 ++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php index cc1f73a6358..98fab880a8b 100644 --- a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php +++ b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php @@ -20,6 +20,9 @@ */ class OAuth_ClientTest extends TestCase { + const SITE_ID = '12345678.apps.sitekit.withgoogle.com'; + const CLIENT_ID = 'test-client-id'; + public function test_get_client() { $client = new OAuth_Client( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) ); @@ -194,7 +197,7 @@ public function test_get_authentication_url() { * @see \Google\Site_Kit\Core\Authentication\Authentication::handle_oauth */ $this->assertEquals( add_query_arg( 'oauth2callback', 1, home_url() ), $params['redirect_uri'] ); - $this->assertEquals( 'test-client-id', $params['client_id'] ); + $this->assertEquals( self::CLIENT_ID, $params['client_id'] ); } public function test_authorize_user() { @@ -247,6 +250,65 @@ public function test_authorize_user() { } } + public function test_using_proxy() { + $context = new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ); + + // Use proxy by default. + $client = new OAuth_Client( $context ); + $this->assertTrue( $client->using_proxy() ); + + // Don't use proxy when regular OAuth client ID is used. + $this->fake_authentication(); + $client = new OAuth_Client( $context ); + $this->assertFalse( $client->using_proxy() ); + + // Use proxy when proxy site ID is used. + $this->fake_proxy_authentication(); + $client = new OAuth_Client( $context ); + $this->assertTrue( $client->using_proxy() ); + } + + public function test_get_proxy_setup_url() { + $context = new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ); + + // If no site ID, pass site registration args. + $client = new OAuth_Client( $context ); + $url = $client->get_proxy_setup_url(); + $this->assertTrue( (bool) strpos( $url, 'name=' ) ); + $this->assertTrue( (bool) strpos( $url, 'url=' ) ); + $this->assertTrue( (bool) strpos( $url, 'rest_root=wp-json' ) ); + $this->assertTrue( (bool) strpos( $url, 'admin_root=wp-admin' ) ); + + // Otherwise, pass site ID and given temporary access code. + $this->fake_proxy_authentication(); + $client = new OAuth_Client( $context ); + $url = $client->get_proxy_setup_url( 'temp-code' ); + $this->assertTrue( (bool) strpos( $url, 'site_id=' . self::SITE_ID ) ); + $this->assertTrue( (bool) strpos( $url, 'code=temp-code' ) ); + } + + public function test_get_proxy_permissions_url() { + $context = new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ); + + // If no access token, this does not work. + $client = new OAuth_Client( $context ); + $url = $client->get_proxy_permissions_url(); + $this->assertEmpty( $url ); + + // The URL has to include the access token. + $encrypted_user_options = $this->force_get_property( $client, 'encrypted_user_options' ); + $encrypted_user_options->set( OAuth_Client::OPTION_ACCESS_TOKEN, 'test-access-token' ); + $url = $client->get_proxy_permissions_url(); + $this->assertTrue( (bool) strpos( $url, 'token=test-access-token' ) ); + + // If there is a site ID, it should also include that. + $this->fake_proxy_authentication(); + $client = new OAuth_Client( $context ); + $url = $client->get_proxy_permissions_url(); + $this->assertTrue( (bool) strpos( $url, 'token=test-access-token' ) ); + $this->assertTrue( (bool) strpos( $url, 'site_id=' . self::SITE_ID ) ); + } + public function test_get_error_message_unknown() { $client = new OAuth_Client( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) ); @@ -282,7 +344,18 @@ protected function fake_authentication() { add_filter( 'googlesitekit_oauth_secret', function () { return json_encode( array( 'web' => array( - 'client_id' => 'test-client-id', + 'client_id' => self::CLIENT_ID, + 'client_secret' => 'test-client-secret', + ), + ) ); + } ); + } + + protected function fake_proxy_authentication() { + add_filter( 'googlesitekit_oauth_secret', function () { + return json_encode( array( + 'web' => array( + 'client_id' => self::SITE_ID, 'client_secret' => 'test-client-secret', ), ) ); From 624271819cbc11fbb38a5fed391f25cb2c068c54 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Tue, 15 Oct 2019 14:53:24 +0200 Subject: [PATCH 040/102] Trigger Travis. From 25424005a90452a795415f7cd9ece2d08bad0fe1 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Tue, 15 Oct 2019 15:02:49 +0200 Subject: [PATCH 041/102] Include auth proxy branch in Travis builds. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 6d28968ade1..50612ef4f7e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,6 +35,7 @@ branches: - master - develop - datapoint-refactoring + - feature/auth-proxy # Before install, failures in this section will result in build status 'errored' before_install: From a83d6921e3ed08b7d147a5037897bf4f70041cdf Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Tue, 15 Oct 2019 16:21:01 +0200 Subject: [PATCH 042/102] Fix failing PHPUnit tests. --- .../Authentication/Clients/OAuth_ClientTest.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php index 98fab880a8b..ac4904e4d5c 100644 --- a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php +++ b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php @@ -272,16 +272,16 @@ public function test_get_proxy_setup_url() { $context = new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ); // If no site ID, pass site registration args. - $client = new OAuth_Client( $context ); + $client = new OAuth_Client( $context ); $url = $client->get_proxy_setup_url(); $this->assertTrue( (bool) strpos( $url, 'name=' ) ); $this->assertTrue( (bool) strpos( $url, 'url=' ) ); - $this->assertTrue( (bool) strpos( $url, 'rest_root=wp-json' ) ); - $this->assertTrue( (bool) strpos( $url, 'admin_root=wp-admin' ) ); + $this->assertTrue( (bool) strpos( $url, 'rest_root=' ) ); + $this->assertTrue( (bool) strpos( $url, 'admin_root=' ) ); // Otherwise, pass site ID and given temporary access code. $this->fake_proxy_authentication(); - $client = new OAuth_Client( $context ); + $client = new OAuth_Client( $context ); $url = $client->get_proxy_setup_url( 'temp-code' ); $this->assertTrue( (bool) strpos( $url, 'site_id=' . self::SITE_ID ) ); $this->assertTrue( (bool) strpos( $url, 'code=temp-code' ) ); @@ -291,19 +291,20 @@ public function test_get_proxy_permissions_url() { $context = new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ); // If no access token, this does not work. - $client = new OAuth_Client( $context ); + $client = new OAuth_Client( $context ); $url = $client->get_proxy_permissions_url(); $this->assertEmpty( $url ); // The URL has to include the access token. - $encrypted_user_options = $this->force_get_property( $client, 'encrypted_user_options' ); - $encrypted_user_options->set( OAuth_Client::OPTION_ACCESS_TOKEN, 'test-access-token' ); + $client = new OAuth_Client( $context ); + $client->set_access_token( 'test-access-token', 3600 ); $url = $client->get_proxy_permissions_url(); $this->assertTrue( (bool) strpos( $url, 'token=test-access-token' ) ); // If there is a site ID, it should also include that. $this->fake_proxy_authentication(); - $client = new OAuth_Client( $context ); + $client = new OAuth_Client( $context ); + $client->set_access_token( 'test-access-token', 3600 ); $url = $client->get_proxy_permissions_url(); $this->assertTrue( (bool) strpos( $url, 'token=test-access-token' ) ); $this->assertTrue( (bool) strpos( $url, 'site_id=' . self::SITE_ID ) ); From 7295928271538f7c3d54056062fad17070fc4354 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 16 Oct 2019 18:27:50 +0200 Subject: [PATCH 043/102] Attempt to update refresh token after refreshing token. --- includes/Core/Authentication/Clients/OAuth_Client.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index d7f5a951d1c..2d5199657a6 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -263,6 +263,9 @@ public function refresh_token() { isset( $authentication_token['expires_in'] ) ? $authentication_token['expires_in'] : '', isset( $authentication_token['created'] ) ? $authentication_token['created'] : 0 ); + + $refresh_token = $this->get_client()->getRefreshToken(); + $this->set_refresh_token( $refresh_token ); } /** From 48d4a1836e4dea49b6c6d0e3c1d5aac245e11ca7 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 16 Oct 2019 19:14:38 +0200 Subject: [PATCH 044/102] Send and check for verification nonce with proxy when necessary. --- .../Core/Authentication/Authentication.php | 5 ++++ .../Authentication/Clients/OAuth_Client.php | 25 +++++++++++-------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index 031df36af5f..c3bf417d2bb 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -547,6 +547,11 @@ private function handle_verification_token() { return; } + $verification_nonce = filter_input( INPUT_GET, 'googlesitekit_verification_nonce' ); + if ( empty( $verification_nonce ) || ! wp_verify_nonce( $verification_nonce, 'googlesitekit_verification' ) ) { + wp_die( esc_html__( 'Invalid nonce.', 'google-site-kit' ) ); + } + $this->verification_tag->set( $verification_token ); $code = (string) filter_input( INPUT_GET, 'googlesitekit_code' ); diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index 2d5199657a6..c48c80580d8 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -481,7 +481,7 @@ public function authorize_user() { try { $authentication_token = $this->get_client()->fetchAccessTokenWithAuthCode( $_GET['code'] ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification } catch ( Google_Proxy_Exception $e ) { - wp_safe_redirect( $this->get_proxy_setup_url( $e->getAccessCode() ) ); + wp_safe_redirect( $this->get_proxy_setup_url( $e->getAccessCode(), $e->getMessage() ) ); exit(); } catch ( Exception $e ) { $this->user_options->set( self::OPTION_ERROR_CODE, 'invalid_code' ); @@ -591,10 +591,13 @@ public function using_proxy() { /** * Returns the setup URL to the authentication proxy. * - * @param string $code Optional. Temporary access code for an undelegated access token. Default empty string. + * @since 1.0.0 + * + * @param string $access_code Optional. Temporary access code for an undelegated access token. Default empty string. + * @param string $error_code Optional. Error code, if the user should be redirected because of an error. Default empty string. * @return string URL to the setup page on the authentication proxy. */ - public function get_proxy_setup_url( $code = '' ) { + public function get_proxy_setup_url( $access_code = '', $error_code = '' ) { $url = self::PROXY_URL . '/site-management/setup/'; $credentials = $this->get_client_credentials(); @@ -627,13 +630,15 @@ public function get_proxy_setup_url( $code = '' ) { ); } - return add_query_arg( - array( - 'site_id' => $credentials->web->client_id, - 'code' => $code, - ), - $url + $query_args = array( + 'site_id' => $credentials->web->client_id, + 'code' => $access_code, ); + if ( 'missing_verification' === $error_code ) { + $query_args['verification_nonce'] = wp_create_nonce( 'googlesitekit_verification' ); + } + + return add_query_arg( $query_args, $url ); } /** @@ -732,7 +737,7 @@ public function get_error_message( $error_code ) { /* translators: 1: error code from API, 2: URL to re-authenticate */ __( 'Setup Error (code: %1$s). Re-authenticate with Google', 'google-site-kit' ), $error_code, - $this->get_proxy_setup_url( $access_code ) + $this->get_proxy_setup_url( $access_code, $error_code ) ); $this->user_options->delete( self::OPTION_PROXY_ACCESS_CODE ); return $message; From cc85ce3a83db6f3eb481712ab4c219848f20dd7d Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 16 Oct 2019 19:22:06 +0200 Subject: [PATCH 045/102] Simplify hack for setting verification flag and Search Console property automatically when proxy is used. --- includes/Core/Authentication/Clients/OAuth_Client.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index c48c80580d8..a2eaeec9037 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -16,6 +16,8 @@ use Google\Site_Kit\Core\Storage\Encrypted_Options; use Google\Site_Kit\Core\Storage\Encrypted_User_Options; use Google\Site_Kit\Core\Authentication\Credentials; +use Google\Site_Kit\Core\Authentication\Verification; +use Google\Site_Kit\Modules\Search_Console; use Google_Client; use Exception; @@ -535,12 +537,8 @@ function( $scope ) { // TODO: In the future, once the old authentication mechanism no longer exists, this should be resolved in // another way. if ( $this->using_proxy() ) { - if ( ! $this->user_options->get( 'googlesitekit_site_verified_meta' ) ) { - $this->user_options->set( 'googlesitekit_site_verified_meta', 'verified' ); - } - if ( ! $this->options->get( 'googlesitekit_search_console_property' ) ) { - $this->options->set( 'googlesitekit_search_console_property', trailingslashit( $this->context->get_reference_site_url() ) ); - } + $this->user_options->set( Verification::OPTION, 'verified' ); + $this->options->set( Search_Console::PROPERTY_OPTION, trailingslashit( $this->context->get_reference_site_url() ) ); } $redirect_url = $this->user_options->get( self::OPTION_REDIRECT_URL ); From 2b470519426e5432bebed01b13c2fc412c374d4e Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 16 Oct 2019 19:25:06 +0200 Subject: [PATCH 046/102] Remove now unnecessary externalCredentialsURL JS param. --- includes/Core/Authentication/Authentication.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index c3bf417d2bb..81c5554d1d0 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -653,13 +653,11 @@ private function inline_js_admin_data( $data ) { if ( strlen( $external_sitename ) < 4 ) { $external_sitename .= ' Site Kit'; } - $external_page_params = array( + $external_page_params = array( 'sitename' => substr( $external_sitename, 0, 30 ), // limit to 30 chars. 'siteurl' => untrailingslashit( home_url() ), ); - - $data['externalCredentialsURL'] = esc_url_raw( add_query_arg( $external_page_params, 'https://developers.google.com/web/site-kit' ) ); - $data['externalAPIKeyURL'] = esc_url_raw( add_query_arg( $external_page_params, 'https://developers.google.com/web/site-kit/apikey' ) ); + $data['externalAPIKeyURL'] = esc_url_raw( add_query_arg( $external_page_params, 'https://developers.google.com/web/site-kit/apikey' ) ); } $data['connectUrl'] = esc_url_raw( $this->get_connect_url() ); From 590c8f5fa1a8d7d7e843a653406819d69d276c42 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 16 Oct 2019 19:29:04 +0200 Subject: [PATCH 047/102] Use esc_url() when displaying proxy setup URL. Co-Authored-By: Evan Mattson --- includes/Core/Authentication/Clients/OAuth_Client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index d7f5a951d1c..ea1ccf6e9b2 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -729,7 +729,7 @@ public function get_error_message( $error_code ) { /* translators: 1: error code from API, 2: URL to re-authenticate */ __( 'Setup Error (code: %1$s). Re-authenticate with Google', 'google-site-kit' ), $error_code, - $this->get_proxy_setup_url( $access_code ) + esc_url( $this->get_proxy_setup_url( $access_code ) ) ); $this->user_options->delete( self::OPTION_PROXY_ACCESS_CODE ); return $message; From fbd9d4fc07997b849eaa127eec00ea731c51904a Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 16 Oct 2019 19:35:12 +0200 Subject: [PATCH 048/102] Remove unused e2e plugin to bypass proxy. --- tests/e2e/plugins/no-proxy.php | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 tests/e2e/plugins/no-proxy.php diff --git a/tests/e2e/plugins/no-proxy.php b/tests/e2e/plugins/no-proxy.php deleted file mode 100644 index d75fcd5cf6b..00000000000 --- a/tests/e2e/plugins/no-proxy.php +++ /dev/null @@ -1,25 +0,0 @@ - Date: Wed, 16 Oct 2019 19:36:20 +0200 Subject: [PATCH 049/102] Simplify some code. --- includes/Core/Authentication/Clients/OAuth_Client.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index a2eaeec9037..17b4a1f7b00 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -604,11 +604,8 @@ public function get_proxy_setup_url( $access_code = '', $error_code = '' ) { $home_url = home_url(); $home_url_no_scheme = str_replace( array( 'http://', 'https://' ), '', $home_url ); - $rest_root = str_replace( array( 'http://', 'https://' ), '', rest_url() ); - $rest_root = str_replace( $home_url_no_scheme, '', $rest_root ); - - $admin_root = str_replace( array( 'http://', 'https://' ), '', admin_url() ); - $admin_root = str_replace( $home_url_no_scheme, '', $admin_root ); + $rest_root = str_replace( array( 'http://', 'https://', $home_url_no_scheme ), '', rest_url() ); + $admin_root = str_replace( array( 'http://', 'https://', $home_url_no_scheme ), '', admin_url() ); $nonce = $this->options->get( self::OPTION_PROXY_NONCE ); if ( empty( $nonce ) ) { From f9bc755cec4fbee9f8debf15ff7af2997fe8fac9 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 16 Oct 2019 19:39:10 +0200 Subject: [PATCH 050/102] Escape URLs before passing to JavaScript. Co-Authored-By: Evan Mattson --- includes/Core/Authentication/Authentication.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index 031df36af5f..c35a5579bbc 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -601,8 +601,8 @@ private function inline_js_admin_data( $data ) { $auth_client = $this->get_oauth_client(); if ( $auth_client->using_proxy() ) { $access_code = (string) $this->user_options->get( Clients\OAuth_Client::OPTION_PROXY_ACCESS_CODE ); - $data['proxySetupURL'] = $auth_client->get_proxy_setup_url( $access_code ); - $data['proxyPermissionsURL'] = $auth_client->get_proxy_permissions_url(); + $data['proxySetupURL'] = esc_url_raw( $auth_client->get_proxy_setup_url( $access_code ) ); + $data['proxyPermissionsURL'] = esc_url_raw( $auth_client->get_proxy_permissions_url() ); // TODO: Remove once related JS functionality is removed. For now, still set these as false-y. $data['clientID'] = ''; @@ -636,7 +636,7 @@ private function inline_js_admin_data( $data ) { // Make GCP project information available only to the creator. if ( ! empty( $gcp_project['id'] ) && (int) get_current_user_id() === $gcp_project['wp_owner_id'] ) { $data['projectId'] = $gcp_project['id']; - $data['projectUrl'] = add_query_arg( 'project', $gcp_project['id'], 'https://console.cloud.google.com/apis/credentials' ); + $data['projectUrl'] = esc_url_raw( add_query_arg( 'project', $gcp_project['id'], 'https://console.cloud.google.com/apis/credentials' ) ); } else { $data['projectId'] = false; $data['projectUrl'] = false; From bfd3cb089e4c60b41f6f54800755244ce7c318e9 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 16 Oct 2019 19:44:08 +0200 Subject: [PATCH 051/102] Use assertContains in proxy unit tests. --- .../Clients/OAuth_ClientTest.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php index ac4904e4d5c..eb63efa07c0 100644 --- a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php +++ b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php @@ -274,17 +274,17 @@ public function test_get_proxy_setup_url() { // If no site ID, pass site registration args. $client = new OAuth_Client( $context ); $url = $client->get_proxy_setup_url(); - $this->assertTrue( (bool) strpos( $url, 'name=' ) ); - $this->assertTrue( (bool) strpos( $url, 'url=' ) ); - $this->assertTrue( (bool) strpos( $url, 'rest_root=' ) ); - $this->assertTrue( (bool) strpos( $url, 'admin_root=' ) ); + $this->assertContains( 'name=', $url ); + $this->assertContains( 'url=', $url ); + $this->assertContains( 'rest_root=', $url ); + $this->assertContains( 'admin_root=', $url ); // Otherwise, pass site ID and given temporary access code. $this->fake_proxy_authentication(); $client = new OAuth_Client( $context ); $url = $client->get_proxy_setup_url( 'temp-code' ); - $this->assertTrue( (bool) strpos( $url, 'site_id=' . self::SITE_ID ) ); - $this->assertTrue( (bool) strpos( $url, 'code=temp-code' ) ); + $this->assertContains( 'site_id=' . self::SITE_ID, $url ); + $this->assertContains( 'code=temp-code', $url ); } public function test_get_proxy_permissions_url() { @@ -299,15 +299,15 @@ public function test_get_proxy_permissions_url() { $client = new OAuth_Client( $context ); $client->set_access_token( 'test-access-token', 3600 ); $url = $client->get_proxy_permissions_url(); - $this->assertTrue( (bool) strpos( $url, 'token=test-access-token' ) ); + $this->assertContains( 'token=test-access-token', $url ); // If there is a site ID, it should also include that. $this->fake_proxy_authentication(); $client = new OAuth_Client( $context ); $client->set_access_token( 'test-access-token', 3600 ); $url = $client->get_proxy_permissions_url(); - $this->assertTrue( (bool) strpos( $url, 'token=test-access-token' ) ); - $this->assertTrue( (bool) strpos( $url, 'site_id=' . self::SITE_ID ) ); + $this->assertContains( 'token=test-access-token', $url ); + $this->assertContains( 'site_id=' . self::SITE_ID, $url ); } public function test_get_error_message_unknown() { From 54e3f15b40aadc63c35e04eba3f83df3f6cb30e2 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 16 Oct 2019 19:46:01 +0200 Subject: [PATCH 052/102] Add assertions to test that no unwanted query vars exist in proxy URL. --- .../Core/Authentication/Clients/OAuth_ClientTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php index eb63efa07c0..6954ddef7dc 100644 --- a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php +++ b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php @@ -278,6 +278,7 @@ public function test_get_proxy_setup_url() { $this->assertContains( 'url=', $url ); $this->assertContains( 'rest_root=', $url ); $this->assertContains( 'admin_root=', $url ); + $this->assertNotContains( 'site_id=', $url ); // Otherwise, pass site ID and given temporary access code. $this->fake_proxy_authentication(); @@ -285,6 +286,10 @@ public function test_get_proxy_setup_url() { $url = $client->get_proxy_setup_url( 'temp-code' ); $this->assertContains( 'site_id=' . self::SITE_ID, $url ); $this->assertContains( 'code=temp-code', $url ); + $this->assertNotContains( 'name=', $url ); + $this->assertNotContains( 'url=', $url ); + $this->assertNotContains( 'rest_root=', $url ); + $this->assertNotContains( 'admin_root=', $url ); } public function test_get_proxy_permissions_url() { From a3408ce7a14fb5451e92e5a3e22ea94806b3abbc Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 16 Oct 2019 19:59:45 +0200 Subject: [PATCH 053/102] Consistently use regular HTTP client from Google_Client in Google_Proxy_Client. --- .../Clients/Google_Proxy_Client.php | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/includes/Core/Authentication/Clients/Google_Proxy_Client.php b/includes/Core/Authentication/Clients/Google_Proxy_Client.php index 9429d0e2bd8..35c7656478f 100644 --- a/includes/Core/Authentication/Clients/Google_Proxy_Client.php +++ b/includes/Core/Authentication/Clients/Google_Proxy_Client.php @@ -14,6 +14,8 @@ use Google\Auth\OAuth2; use Google\Auth\HttpHandler\HttpHandlerFactory; use Google\Auth\HttpHandler\HttpClientCache; +use GuzzleHttp\Psr7; +use GuzzleHttp\Psr7\Request; use Exception; use InvalidArgumentException; use LogicException; @@ -113,20 +115,29 @@ public function revokeToken( $token = null ) { $token = $token['access_token']; } - $response = wp_remote_get( - add_query_arg( + $body = Psr7\stream_for( + http_build_query( array( 'client_id' => $this->getClientId(), 'token' => $token, - ), - self::OAUTH2_REVOKE_URI + ) ) ); - if ( is_wp_error( $response ) ) { - return false; - } + $request = new Request( + 'POST', + self::OAUTH2_REVOKE_URI, + array( + 'Cache-Control' => 'no-store', + 'Content-Type' => 'application/x-www-form-urlencoded', + ), + $body + ); + + $http_handler = HttpHandlerFactory::build( $this->getHttpClient() ); + + $response = $http_handler( $request ); - return 200 === (int) wp_remote_retrieve_response_code( $response ); + return 200 === (int) $response->getStatusCode(); } /** From 38f8de8dacfcb7c2912550a1113b73584333b9a2 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 16 Oct 2019 11:56:33 -0600 Subject: [PATCH 054/102] Change "API Credentials" to "Plugin Status" --- assets/js/components/settings/settings-admin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/components/settings/settings-admin.js b/assets/js/components/settings/settings-admin.js index 20f37d4f779..0a7563612b9 100644 --- a/assets/js/components/settings/settings-admin.js +++ b/assets/js/components/settings/settings-admin.js @@ -120,7 +120,7 @@ class SettingsAdmin extends Component { googlesitekit-settings-module__title "> { moduleIcon( 'logo-google-cloud', false, '24', '26', 'googlesitekit-settings-module__title-icon' ) } - { __( 'API Credentials', 'google-site-kit' ) } + { __( 'Plugin Status', 'google-site-kit' ) }

- { moduleIcon( 'logo-google-cloud', false, '24', '26', 'googlesitekit-settings-module__title-icon' ) } { __( 'Plugin Status', 'google-site-kit' ) }
From 795f06b4f86fc21b148f66fa5e5d4e8c5ab67a26 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 16 Oct 2019 12:05:01 -0600 Subject: [PATCH 056/102] remove key information and replace with connected message --- .../js/components/settings/settings-admin.js | 93 ++----------------- 1 file changed, 10 insertions(+), 83 deletions(-) diff --git a/assets/js/components/settings/settings-admin.js b/assets/js/components/settings/settings-admin.js index 77e81bf9c0a..69e8653b41b 100644 --- a/assets/js/components/settings/settings-admin.js +++ b/assets/js/components/settings/settings-admin.js @@ -87,13 +87,6 @@ class SettingsAdmin extends Component { const { dialogActive, } = this.state; - const { - clientID, - clientSecret, - apikey, - projectId, - projectUrl, - } = googlesitekit.admin; return ( @@ -129,90 +122,24 @@ class SettingsAdmin extends Component { mdc-layout-grid__cell--align-middle mdc-layout-grid__cell--align-right-tablet "> -

- { __( 'Site Kit is connected', 'google-site-kit' ) } - - - { __( 'Connected', 'google-site-kit' ) } - - -

-
-

- { __( 'Client ID', 'google-site-kit' ) } -

-
- { clientID } -
-
-
-

- { __( 'Client Secret', 'google-site-kit' ) } -

-
+ { __( 'Site Kit is connected', 'google-site-kit' ) } + - { clientSecret } -
-
+ + { __( 'Connected', 'google-site-kit' ) } + + +

- { apikey && -
-
-

- { __( 'API Key', 'google-site-kit' ) } -

-
- { apikey } -
-
-
- } - { ( projectId && projectUrl ) && -
-
-

- { __( 'Project ID', 'google-site-kit' ) } -

-
- { projectId + ' ' } - - - { __( 'Open in Google Cloud Platform', 'google-site-kit' ) } - - -
-
-
- }
From 1605454be73a7a900ec63d0c4fb917e9924dcefc Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Wed, 16 Oct 2019 12:46:08 -0600 Subject: [PATCH 057/102] update visual regression test images --- ...ings_Admin_Settings_0_document_0_small.png | Bin 40519 -> 17289 bytes ...ngs_Admin_Settings_0_document_1_medium.png | Bin 43962 -> 21242 bytes ...ings_Admin_Settings_0_document_2_large.png | Bin 45179 -> 22687 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/backstop/reference/google-site-kit_Settings_Admin_Settings_0_document_0_small.png b/tests/backstop/reference/google-site-kit_Settings_Admin_Settings_0_document_0_small.png index 631753a7f1d629e450c963af77667091189eab94..b7fc8ac668e38f268a8ce728a33af0b718e19767 100644 GIT binary patch literal 17289 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 literal 40519 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 literal 43962 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 Nma?W&_Kio+{|`YDC^G;6 diff --git a/tests/backstop/reference/google-site-kit_Settings_Admin_Settings_0_document_2_large.png b/tests/backstop/reference/google-site-kit_Settings_Admin_Settings_0_document_2_large.png index faf9e684acab01dd7226e8f7974b69b5c120006c..2eb2e8cca50f442d06e8cae9eb4a50732cc6a039 100644 GIT binary patch literal 22687 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 ARR910 literal 45179 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 Date: Thu, 17 Oct 2019 09:54:20 +0300 Subject: [PATCH 058/102] whitelist feature/auth-proxy branch for travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6d28968ade1..a356450e430 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,7 @@ branches: only: - master - develop - - datapoint-refactoring + - feature/auth-proxy # Before install, failures in this section will result in build status 'errored' before_install: From 7dc993b4d6c62d8904278cb8dc30e5c5f90eaf17 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Thu, 17 Oct 2019 11:36:55 +0300 Subject: [PATCH 059/102] add permissions link to user menu --- assets/js/components/user-menu.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/assets/js/components/user-menu.js b/assets/js/components/user-menu.js index 43e4d398a36..fe11b272c5f 100644 --- a/assets/js/components/user-menu.js +++ b/assets/js/components/user-menu.js @@ -78,6 +78,8 @@ class UserMenu extends Component { } handleMenuItemSelect( index, e ) { + const { proxyPermissionsURL } = googlesitekit.admin; + if ( ( ( 'keydown' === e.type && ( 13 === e.keyCode || // Enter @@ -89,6 +91,9 @@ class UserMenu extends Component { case 0: this.handleDialog(); break; + case 1: + window.location.assign( proxyPermissionsURL ); + break; default: this.handleMenu(); } @@ -136,7 +141,10 @@ class UserMenu extends Component { } render() { - const { userData: { email = '', picture = '' } } = googlesitekit.admin; + const { + userData: { email = '', picture = '' }, + proxyPermissionsURL, + } = googlesitekit.admin; const { dialogActive, menuOpen } = this.state; return ( @@ -160,7 +168,15 @@ class UserMenu extends Component { From 3b4286204fa00d1a93af38dd14e7fb1b453821ab Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Thu, 17 Oct 2019 10:44:08 +0200 Subject: [PATCH 060/102] Clarify comment about authentication permission. Co-Authored-By: Evan Mattson --- includes/Core/Permissions/Permissions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Core/Permissions/Permissions.php b/includes/Core/Permissions/Permissions.php index be33956c7a8..6ab559c6c23 100644 --- a/includes/Core/Permissions/Permissions.php +++ b/includes/Core/Permissions/Permissions.php @@ -104,7 +104,7 @@ public function __construct( Context $context, Authentication $authentication = $this->authentication = $authentication; $this->primitive_to_core = array( - // By default, only allow administrators and up to authenticate. + // By default, only allow administrators to authenticate. self::AUTHENTICATE => 'manage_options', // Allow contributors and up to view their own post's insights. From f16f1b278b279f88c4055c6ad1c87fcf4bf5e8d9 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Thu, 17 Oct 2019 10:49:20 +0200 Subject: [PATCH 061/102] Remove temporary links to proxy URLs that were used for testing. --- .../Core/Authentication/Authentication.php | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index b445de915a3..60ce1c98041 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -197,28 +197,6 @@ function() { } ); - // TODO: Remove this after testing. - add_action( - 'admin_notices', - function() { - if ( ! $this->get_oauth_client()->using_proxy() ) { - return; - } - $setup_url = $this->get_oauth_client()->get_proxy_setup_url(); - $permissions_url = $this->get_oauth_client()->get_proxy_permissions_url(); - ?> - - Date: Thu, 17 Oct 2019 11:21:44 +0200 Subject: [PATCH 062/102] Remove now unnecessary parts of PSI e2e test. --- .../specs/modules/pagespeed-insights/activation.test.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/e2e/specs/modules/pagespeed-insights/activation.test.js b/tests/e2e/specs/modules/pagespeed-insights/activation.test.js index 1a3d754a8c3..f8d6e8579e1 100644 --- a/tests/e2e/specs/modules/pagespeed-insights/activation.test.js +++ b/tests/e2e/specs/modules/pagespeed-insights/activation.test.js @@ -50,14 +50,5 @@ describe( 'PageSpeed Insights Activation', () => { await expect( page ).toClick( 'button.mdc-button', { text: 'Proceed' } ); await page.waitForSelector( 'h3.googlesitekit-heading-3' ); - - // Check that the correct key is saved on the settings page. - await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' ); - - await expect( page ).toClick( 'button.mdc-tab', { text: 'Admin Settings' } ); - - // Check the API Key text, verifying the submitted value has been stored. - await expect( page ).toMatchElement( '.googlesitekit-settings-module__meta-item-type', { text: 'API Key' } ); - await expect( page ).toMatchElement( 'h5.googlesitekit-settings-module__meta-item-data', { text: 'PSIKEYTOSUBMITANDTEST' } ); } ); } ); From 02bcc94b63f977803bbabf84ff2d7dd252b35be9 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Thu, 17 Oct 2019 12:05:19 +0200 Subject: [PATCH 063/102] Remove now unused JS data. --- .../Core/Authentication/Authentication.php | 30 ++----------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index 60ce1c98041..cfbfcf1a389 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -588,27 +588,10 @@ private function inline_js_admin_data( $data ) { $data['proxyPermissionsURL'] = esc_url_raw( $auth_client->get_proxy_permissions_url() ); // TODO: Remove once related JS functionality is removed. For now, still set these as false-y. - $data['clientID'] = ''; - $data['clientSecret'] = ''; - $data['apikey'] = false; - $data['projectId'] = false; - $data['projectUrl'] = false; + $data['apikey'] = false; } else { // TODO: Remove once related JS functionality is removed. - $client_data = $this->credentials->get(); - $apikey = $this->get_api_key_client()->get_api_key(); - $gcp_project = $this->gcp_project->get(); - - if ( current_user_can( Permissions::MANAGE_OPTIONS ) && isset( $client_data['oauth2_client_id'] ) ) { - $data['clientID'] = $client_data['oauth2_client_id']; - } else { - $data['clientID'] = ''; - } - if ( current_user_can( Permissions::MANAGE_OPTIONS ) && isset( $client_data['oauth2_client_secret'] ) ) { - $data['clientSecret'] = str_repeat( '•', strlen( $client_data['oauth2_client_secret'] ) ); - } else { - $data['clientSecret'] = ''; - } + $apikey = $this->get_api_key_client()->get_api_key(); if ( current_user_can( Permissions::MANAGE_OPTIONS ) && $apikey ) { $data['apikey'] = $apikey; @@ -616,15 +599,6 @@ private function inline_js_admin_data( $data ) { $data['apikey'] = false; } - // Make GCP project information available only to the creator. - if ( ! empty( $gcp_project['id'] ) && (int) get_current_user_id() === $gcp_project['wp_owner_id'] ) { - $data['projectId'] = $gcp_project['id']; - $data['projectUrl'] = esc_url_raw( add_query_arg( 'project', $gcp_project['id'], 'https://console.cloud.google.com/apis/credentials' ) ); - } else { - $data['projectId'] = false; - $data['projectUrl'] = false; - } - $external_sitename = html_entity_decode( get_bloginfo( 'name' ), ENT_QUOTES ); $external_sitename = str_replace( '&', 'and', $external_sitename ); $external_sitename = trim( preg_replace( '/([^A-Za-z0-9 ]+|google)/i', '', $external_sitename ) ); From ed23e4c51ea80cee27080d350fac2a88f40049d1 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Thu, 17 Oct 2019 12:10:16 +0200 Subject: [PATCH 064/102] Remove now unused GCP_Project functionality. --- .../Core/Authentication/Authentication.php | 20 ---- includes/Core/Authentication/GCP_Project.php | 110 ------------------ includes/Core/REST_API/REST_Routes.php | 38 ------ includes/Core/Util/Reset.php | 3 +- .../Core/Authentication/GCP_ProjectTest.php | 90 -------------- .../integration/Core/Util/ResetTest.php | 2 - 6 files changed, 1 insertion(+), 262 deletions(-) delete mode 100644 includes/Core/Authentication/GCP_Project.php delete mode 100644 tests/phpunit/integration/Core/Authentication/GCP_ProjectTest.php diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index cfbfcf1a389..f9fe830734a 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -95,14 +95,6 @@ final class Authentication { */ protected $api_key; - /** - * GCP project instance. - * - * @since 1.0.0 - * @var GCP_Project - */ - protected $gcp_project; - /** * Verification instance. * @@ -170,7 +162,6 @@ public function __construct( $this->credentials = new Credentials( $this->options ); $this->api_key = new API_Key( $this->options ); - $this->gcp_project = new GCP_Project( $this->options ); $this->verification = new Verification( $this->user_options ); $this->verification_tag = new Verification_Tag( $this->user_options, $this->transients ); $this->profile = new Profile( $user_options, $this->get_oauth_client() ); @@ -287,17 +278,6 @@ public function api_key() { return $this->api_key; } - /** - * Gets the GCP project instance. - * - * @since 1.0.0 - * - * @return GCP_Project Project ID instance. - */ - public function gcp_project() { - return $this->gcp_project; - } - /** * Gets the verification instance. * diff --git a/includes/Core/Authentication/GCP_Project.php b/includes/Core/Authentication/GCP_Project.php deleted file mode 100644 index de243936978..00000000000 --- a/includes/Core/Authentication/GCP_Project.php +++ /dev/null @@ -1,110 +0,0 @@ -options = $options; - } - - /** - * Checks whether a GCP project is set. - * - * @since 1.0.0 - * - * @return bool True if a project is set. - */ - public function has() { - $data = $this->get(); - return ! empty( $data['id'] ); - } - - /** - * Retrieves the GCP project. - * - * @since 1.0.0 - * - * @return array Project data. - */ - public function get() { - $data = $this->options->get( self::OPTION ); - - return $this->parse_defaults( $data ); - } - - /** - * Saves the GCP project. - * - * @since 1.0.0 - * - * @param array $data { - * Project data. - * - * @type string $id The project ID. - * @type int $wp_owner_id The WordPress user ID of the owner. - * } - * @return bool True on success, false on failure. - */ - public function set( $data ) { - $data = $this->parse_defaults( $data ); - - return $this->options->set( self::OPTION, $data ); - } - - /** - * Parses GCP project data with its defaults. - * - * @since 1.0.0 - * - * @param mixed $data Project data. - * @return array Parsed $data. - */ - private function parse_defaults( $data ) { - $defaults = array( - 'id' => '', - 'wp_owner_id' => 0, - ); - - if ( ! is_array( $data ) ) { - return $defaults; - } - - $data = wp_parse_args( $data, $defaults ); - $data['wp_owner_id'] = (int) $data['wp_owner_id']; - - return $data; - } -} diff --git a/includes/Core/REST_API/REST_Routes.php b/includes/Core/REST_API/REST_Routes.php index 41a9e646dfa..d80f82f5cfc 100644 --- a/includes/Core/REST_API/REST_Routes.php +++ b/includes/Core/REST_API/REST_Routes.php @@ -196,44 +196,6 @@ private function get_routes() { ) ), // This route is forward-compatible with a potential 'core/(?P[a-z\-]+)/data/(?P[a-z\-]+)'. - new REST_Route( - 'core/site/data/gcpproject', - array( - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => function() { - return new WP_REST_Response( $this->authentication->gcp_project()->get() ); - }, - 'permission_callback' => $can_setup, - ), - array( - 'methods' => WP_REST_Server::EDITABLE, - 'callback' => function( WP_REST_Request $request ) { - $data = isset( $request['data'] ) ? $request['data'] : array(); - if ( ! isset( $data['projectID'] ) ) { - /* translators: %s: Missing parameter name */ - return new WP_Error( 'missing_required_param', sprintf( __( 'Request parameter is empty: %s.', 'google-site-kit' ), 'projectID' ), array( 'status' => 400 ) ); - } - $data = array( - 'id' => sanitize_text_field( $data['projectID'] ), - 'wp_owner_id' => get_current_user_id(), - ); - return new WP_REST_Response( $this->authentication->gcp_project()->set( $data ) ); - }, - 'permission_callback' => $can_setup, - 'args' => array( - 'data' => array( - 'type' => 'object', - 'description' => __( 'Data to set.', 'google-site-kit' ), - 'validate_callback' => function( $value ) { - return is_array( $value ); - }, - ), - ), - ), - ) - ), - // This route is forward-compatible with a potential 'core/(?P[a-z\-]+)/data/(?P[a-z\-]+)'. new REST_Route( 'core/site/data/apikey', array( diff --git a/includes/Core/Util/Reset.php b/includes/Core/Util/Reset.php index b8f8a42273d..f587d2988c5 100644 --- a/includes/Core/Util/Reset.php +++ b/includes/Core/Util/Reset.php @@ -17,7 +17,6 @@ use Google\Site_Kit\Core\Authentication\Credentials; use Google\Site_Kit\Core\Authentication\API_Key; use Google\Site_Kit\Core\Authentication\First_Admin; -use Google\Site_Kit\Core\Authentication\GCP_Project; use Google\Site_Kit\Core\Authentication\Verification; use Google\Site_Kit\Core\Authentication\Verification_Tag; use Google\Site_Kit\Core\Authentication\Profile; @@ -111,7 +110,6 @@ private function delete_all_plugin_options() { $this->options->delete( Activation::OPTION_NEW_SITE_POSTS ); $this->options->delete( Credentials::OPTION ); $this->options->delete( API_Key::OPTION ); - $this->options->delete( GCP_Project::OPTION ); $this->options->delete( 'googlesitekit-active-modules' ); $this->options->delete( Search_Console::PROPERTY_OPTION ); $this->options->delete( AdSense::OPTION ); @@ -131,6 +129,7 @@ private function delete_all_plugin_options() { $this->options->delete( 'googlesitekit_available_modules' ); $this->options->delete( 'googlesitekit_secret_token' ); $this->options->delete( 'googlesitekit_project_id' ); + $this->options->delete( 'googlesitekit_gcp_project' ); } /** diff --git a/tests/phpunit/integration/Core/Authentication/GCP_ProjectTest.php b/tests/phpunit/integration/Core/Authentication/GCP_ProjectTest.php deleted file mode 100644 index a75c2fce688..00000000000 --- a/tests/phpunit/integration/Core/Authentication/GCP_ProjectTest.php +++ /dev/null @@ -1,90 +0,0 @@ -gcp_project = new GCP_Project( $options ); - } - - /** - * Test get() method. - */ - public function test_get() { - $defaults = array( - 'id' => '', - 'wp_owner_id' => 0, - ); - - $this->assertEqualSetsWithIndex( $defaults, $this->gcp_project->get() ); - - $data = $defaults; - $data['id'] = 'fake-gcp-project-id'; - - $this->gcp_project->set( array( 'id' => $data['id'] ) ); - $this->assertEqualSetsWithIndex( $data, $this->gcp_project->get() ); - } - - /** - * Test set() method. - */ - public function test_set() { - $defaults = array( - 'id' => '', - 'wp_owner_id' => 0, - ); - - $data = $defaults; - $data['id'] = 'fake-gcp-project-id'; - $data['wp_owner_id'] = 3; - - $this->assertTrue( $this->gcp_project->set( $data ) ); - $this->assertEqualSetsWithIndex( $data, $this->gcp_project->get() ); - - $this->assertTrue( $this->gcp_project->set( array() ) ); - $this->assertEqualSetsWithIndex( $defaults, $this->gcp_project->get() ); - } - - /** - * Test has() method. - */ - public function test_has() { - $this->assertFalse( $this->gcp_project->has() ); - - $this->gcp_project->set( array( 'id' => 'fake-gcp-project-id' ) ); - $this->assertTrue( $this->gcp_project->has() ); - } -} diff --git a/tests/phpunit/integration/Core/Util/ResetTest.php b/tests/phpunit/integration/Core/Util/ResetTest.php index 6bb4ef1aaaa..6812fe08fef 100644 --- a/tests/phpunit/integration/Core/Util/ResetTest.php +++ b/tests/phpunit/integration/Core/Util/ResetTest.php @@ -15,7 +15,6 @@ use Google\Site_Kit\Core\Authentication\Clients\OAuth_Client; use Google\Site_Kit\Core\Authentication\Credentials; use Google\Site_Kit\Core\Authentication\First_Admin; -use Google\Site_Kit\Core\Authentication\GCP_Project; use Google\Site_Kit\Core\Authentication\Profile; use Google\Site_Kit\Core\Authentication\Verification; use Google\Site_Kit\Core\Authentication\Verification_Tag; @@ -82,7 +81,6 @@ protected function get_option_keys() { API_Key::OPTION, Credentials::OPTION, First_Admin::OPTION, - GCP_Project::OPTION, Optimize::OPTION, PageSpeed_Insights::OPTION, Search_Console::PROPERTY_OPTION, From fdf74ba75d2145da82ccc6e246505727d4d6dd59 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Thu, 17 Oct 2019 13:46:35 +0200 Subject: [PATCH 065/102] Fix failing tests. --- .../integration/Core/Authentication/AuthenticationTest.php | 4 ---- tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php | 1 - 2 files changed, 5 deletions(-) diff --git a/tests/phpunit/integration/Core/Authentication/AuthenticationTest.php b/tests/phpunit/integration/Core/Authentication/AuthenticationTest.php index 606528163c1..984573b0d08 100644 --- a/tests/phpunit/integration/Core/Authentication/AuthenticationTest.php +++ b/tests/phpunit/integration/Core/Authentication/AuthenticationTest.php @@ -69,14 +69,10 @@ protected function assertAdminDataExtended() { $this->assertEqualSets( array( 'apikey', - 'clientID', - 'clientSecret', 'connectUrl', 'disconnectUrl', 'proxySetupURL', 'proxyPermissionsURL', - 'projectId', - 'projectUrl', 'userData', ), array_keys( $data ) diff --git a/tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php b/tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php index 0075d3607bf..fadf1f7d2b3 100644 --- a/tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php +++ b/tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php @@ -43,7 +43,6 @@ public function test_register() { '/' . REST_Routes::REST_ROOT . '/core/site/data/reset', '/' . REST_Routes::REST_ROOT . '/core/site/data/apikey', '/' . REST_Routes::REST_ROOT . '/core/site/data/credentials', - '/' . REST_Routes::REST_ROOT . '/core/site/data/gcpproject', '/' . REST_Routes::REST_ROOT . '/core/user/data/disconnect', '/' . REST_Routes::REST_ROOT . '/core/user/data/authentication', '/' . REST_Routes::REST_ROOT . '/modules', From 152db2aa6ac1bce6d1ae1ecfde4f63c213fd5917 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Thu, 17 Oct 2019 14:02:52 +0200 Subject: [PATCH 066/102] Fix failing test after merge. --- tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php b/tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php index fb848d8ad79..b343aa7640b 100644 --- a/tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php +++ b/tests/phpunit/integration/Core/REST_API/REST_RoutesTest.php @@ -41,7 +41,6 @@ public function test_register() { '/', '/' . REST_Routes::REST_ROOT, '/' . REST_Routes::REST_ROOT . '/core/site/data/reset', - '/' . REST_Routes::REST_ROOT . '/core/site/data/credentials', '/' . REST_Routes::REST_ROOT . '/core/user/data/disconnect', '/' . REST_Routes::REST_ROOT . '/core/user/data/authentication', '/' . REST_Routes::REST_ROOT . '/modules', From 469c9210a0481bf75f3a838ac407726b9fa713e5 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Thu, 17 Oct 2019 15:20:03 +0200 Subject: [PATCH 067/102] Add temporary setup link to proxy. --- includes/Core/Admin/Screens.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/includes/Core/Admin/Screens.php b/includes/Core/Admin/Screens.php index a1c7391a574..e0c24c99119 100644 --- a/includes/Core/Admin/Screens.php +++ b/includes/Core/Admin/Screens.php @@ -334,6 +334,20 @@ private function get_screens() { $assets->enqueue_asset( 'googlesitekit_dashboard_splash' ); }, 'render_callback' => function( Context $context ) { + $auth_client = new \Google\Site_Kit\Core\Authentication\Clients\OAuth_Client( $this->context ); + if ( $auth_client->using_proxy() ) { + $setup_url = $auth_client->get_proxy_setup_url(); + ?> +
+

Temporary Setup

+ +

+ Go To Setup +

+
+
Date: Thu, 17 Oct 2019 15:22:08 +0200 Subject: [PATCH 068/102] Fix potentially incorrect site title as URL query parameter. --- includes/Core/Authentication/Clients/OAuth_Client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index ee4a8bbf1b2..c247497ffd8 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -623,7 +623,7 @@ public function get_proxy_setup_url( $access_code = '', $error_code = '' ) { return add_query_arg( array( 'nonce' => $nonce, - 'name' => rawurlencode( get_bloginfo( 'name' ) ), + 'name' => rawurlencode( wp_specialchars_decode( get_bloginfo( 'name' ) ) ), 'url' => rawurlencode( $home_url ), 'rest_root' => rawurlencode( $rest_root ), 'admin_root' => rawurlencode( $admin_root ), From 5706d6251293cadfbad5f6aed039300412cd14da Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Thu, 17 Oct 2019 18:26:18 +0300 Subject: [PATCH 069/102] initial Beta_Migration class --- includes/Core/Util/Beta_Migration.php | 196 ++++++++++++++++++++++++++ includes/Plugin.php | 1 + 2 files changed, 197 insertions(+) create mode 100644 includes/Core/Util/Beta_Migration.php diff --git a/includes/Core/Util/Beta_Migration.php b/includes/Core/Util/Beta_Migration.php new file mode 100644 index 00000000000..d082e775019 --- /dev/null +++ b/includes/Core/Util/Beta_Migration.php @@ -0,0 +1,196 @@ +options = new Options( $context ); + $this->credentials = new Credentials( $this->options ); + $this->oauth_client = new OAuth_Client( $context ); + } + + /** + * Registers hooks. + */ + public function register() { + $notice = new Notice( + 'beta-migration', + array( + 'content' => function () { + return $this->get_notice_content(); + }, + 'active_callback' => function () { + return $this->options->get( self::OPTION_IS_PRE_PROXY_INSTALL ) && current_user_can( Permissions::SETUP ); + }, + ) + ); + + add_action( 'admin_init', array( $this, 'handle_action' ) ); + add_action( 'admin_init', array( $this, 'maybe_run_upgrade' ) ); + add_action( 'admin_notices', array( $notice, 'render' ) ); + add_action( 'network_admin_notices', array( $notice, 'render' ) ); + } + + /** + * Runs the upgrade based on the current DB version. + */ + public function maybe_run_upgrade() { + if ( version_compare( get_option( 'googlesitekit_db_version', '0' ), self::DB_VERSION, '<' ) ) { + $this->run_upgrade(); + } + } + + /** + * Handles the pre-proxy action chosen by the user. + */ + public function handle_action() { + $action = filter_input( INPUT_GET, self::PARAM_PRE_PROXY_ACTION ); + + if ( ! $action ) { + return; + } + + if ( ! check_admin_referer( self::ACTION ) || ! in_array( $action, array( 'reconnect', 'ignore' ), true ) ) { + return; + } + + $this->options->delete( self::OPTION_IS_PRE_PROXY_INSTALL ); + + if ( 'reconnect' === $action ) { + wp_safe_redirect( $this->oauth_client->get_proxy_setup_url() ); + } elseif ( 'ignore' === $action ) { + // Redirect to the current URL without the action params. + wp_safe_redirect( + add_query_arg( + array( + self::PARAM_PRE_PROXY_ACTION => false, + '_wpnonce' => false, + ) + ) + ); + } + + exit; + } + + /** + * Runs the upgrade. + */ + private function run_upgrade() { + $credentials = $this->credentials->get(); + + if ( ! strpos( $credentials['oauth2_client_id'], '.apps.sitekit.withgoogle.com' ) ) { + $this->options->delete( Credentials::OPTION ); + $this->options->set( self::OPTION_IS_PRE_PROXY_INSTALL, 1 ); + } + + update_option( 'googlesitekit_db_version', self::DB_VERSION ); + } + + /** + * Gets the content to render in the reconnect notice. + * + * @return string + */ + private function get_notice_content() { + ob_start(); + ?> +

+ +

+

+ + + + + + + +

+ $action, + '_wpnonce' => wp_create_nonce( self::ACTION ), + ) + ); + } +} diff --git a/includes/Plugin.php b/includes/Plugin.php index 560c807409e..77723493103 100644 --- a/includes/Plugin.php +++ b/includes/Plugin.php @@ -151,6 +151,7 @@ function( $username, $user ) use ( $user_options ) { $reset = new Core\Util\Reset( $this->context, $options ); ( new Core\Util\Activation( $this->context, $options, $assets ) )->register(); + ( new Core\Util\Beta_Migration( $this->context ) )->register(); ( new Core\Util\Uninstallation( $reset ) )->register(); ( new Core\Util\Updater() )->register(); ( new Core\Util\Deactivation() )->register(); From 7ca4bfc5ed5a4d8e66f32c9b800273305399aa5c Mon Sep 17 00:00:00 2001 From: "Matthew Riley MacPherson (tofumatt)" Date: Thu, 17 Oct 2019 17:04:40 +0100 Subject: [PATCH 070/102] feat: Add a login page for use with the proxy --- .../dashboard-splash/dashboard-splash-app.js | 7 +- assets/js/components/setup/setup-proxy.js | 138 ++++++++++++++++++ includes/Core/Admin/Screens.php | 14 -- includes/Core/Assets/Assets.php | 4 + 4 files changed, 148 insertions(+), 15 deletions(-) create mode 100644 assets/js/components/setup/setup-proxy.js diff --git a/assets/js/components/dashboard-splash/dashboard-splash-app.js b/assets/js/components/dashboard-splash/dashboard-splash-app.js index 25c1210e70c..025ef88e5d5 100644 --- a/assets/js/components/dashboard-splash/dashboard-splash-app.js +++ b/assets/js/components/dashboard-splash/dashboard-splash-app.js @@ -114,6 +114,8 @@ class DashboardSplashApp extends Component { __webpack_public_path__ = window.googlesitekit.publicPath; } + const { proxySetupURL } = googlesitekit.admin; + if ( ! this.state.showAuthenticationSetupWizard && ! this.state.showModuleSetupWizard ) { let introDescription, outroDescription, buttonLabel, onButtonClick; @@ -150,7 +152,10 @@ class DashboardSplashApp extends Component { let Setup = null; - if ( this.state.showAuthenticationSetupWizard ) { + // proxySetupURL is only set if the proxy is in use. + if ( proxySetupURL ) { + Setup = lazy( () => import( /* webpackChunkName: "chunk-googlesitekit-setup-wizard-proxy" */'../setup/setup-proxy' ) ); + } else if ( this.state.showAuthenticationSetupWizard ) { Setup = lazy( () => import( /* webpackChunkName: "chunk-googlesitekit-setup-wizard" */'../setup' ) ); } else { Setup = lazy( () => import( /* webpackChunkName: "chunk-googlesitekit-setup-wrapper" */'../setup/setup-wrapper' ) ); diff --git a/assets/js/components/setup/setup-proxy.js b/assets/js/components/setup/setup-proxy.js new file mode 100644 index 00000000000..1e330fb27e8 --- /dev/null +++ b/assets/js/components/setup/setup-proxy.js @@ -0,0 +1,138 @@ +/** + * Setup component. + * + * Site Kit by Google, Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * External dependencies + */ +import Header from 'GoogleComponents/header'; +import Button from 'GoogleComponents/button'; +import Layout from 'GoogleComponents/layout/layout'; +import { sendAnalyticsTrackingEvent } from 'GoogleUtil'; +import { getSiteKitAdminURL } from 'SiteKitCore/util'; + +const { __ } = wp.i18n; +const { Component, Fragment } = wp.element; +const { delay } = lodash; + +class SetupUsingProxy extends Component { + constructor( props ) { + super( props ); + + const { connectUrl } = googlesitekit.admin; + + const { + isAuthenticated, + hasSearchConsoleProperty, + isSiteKitConnected, + isVerified, + needReauthenticate, + } = googlesitekit.setup; + + const { canSetup } = googlesitekit.permissions; + + this.state = { + canSetup, + isAuthenticated, + isVerified, + needReauthenticate, + hasSearchConsoleProperty, + hasSearchConsolePropertyFromTheStart: hasSearchConsoleProperty, + connectUrl, + errorMsg: '', + isSiteKitConnected, + completeSetup: false, + }; + } + + isSetupFinished() { + const { + isSiteKitConnected, + completeSetup, + } = this.state; + + return isSiteKitConnected && completeSetup; + } + + render() { + const { + connectUrl, + } = this.state; + + if ( this.isSetupFinished() ) { + const redirectUrl = getSiteKitAdminURL( + 'googlesitekit-dashboard', + { + notification: 'authentication_success', + }, + ); + + delay( function() { + window.location.replace( redirectUrl ); + }, 500, 'later' ); + } + + const { proxySetupURL } = googlesitekit.admin; + + return ( + +
+
+
+
+
+ +
+
+
+
+
+

+ { __( 'Time to set up the Site Kit plugin', 'google-site-kit' ) } +

+

+ { __( 'Site Kit Service will guide you through 3 simple setup steps.', 'google-site-kit' ) } +

+ +
+
+
+
+
+
+
+
+
+
+ + ); + } +} + +export default SetupUsingProxy; diff --git a/includes/Core/Admin/Screens.php b/includes/Core/Admin/Screens.php index e0c24c99119..a1c7391a574 100644 --- a/includes/Core/Admin/Screens.php +++ b/includes/Core/Admin/Screens.php @@ -334,20 +334,6 @@ private function get_screens() { $assets->enqueue_asset( 'googlesitekit_dashboard_splash' ); }, 'render_callback' => function( Context $context ) { - $auth_client = new \Google\Site_Kit\Core\Authentication\Clients\OAuth_Client( $this->context ); - if ( $auth_client->using_proxy() ) { - $setup_url = $auth_client->get_proxy_setup_url(); - ?> -
-

Temporary Setup

- -

- Go To Setup -

-
-
context->get_reference_site_url(); + $auth_client = new \Google\Site_Kit\Core\Authentication\Clients\OAuth_Client( $this->context ); + $admin_data = array( + 'usingProxy' => $auth_client->using_proxy(), 'siteURL' => esc_url_raw( $site_url ), 'siteName' => get_bloginfo( 'name' ), 'siteUserId' => md5( $site_url . $current_user->ID ), From 223d0bfe714dacc3613fd591c924f96fab1eb087 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Thu, 17 Oct 2019 20:01:08 +0300 Subject: [PATCH 071/102] refactor redirects with ajax handler for dismissing --- includes/Core/Util/Beta_Migration.php | 91 ++++++++++++--------------- 1 file changed, 39 insertions(+), 52 deletions(-) diff --git a/includes/Core/Util/Beta_Migration.php b/includes/Core/Util/Beta_Migration.php index d082e775019..6a00e1e9378 100644 --- a/includes/Core/Util/Beta_Migration.php +++ b/includes/Core/Util/Beta_Migration.php @@ -91,6 +91,17 @@ public function register() { ) ); + add_action( + 'wp_ajax_googlesitekit_' . self::ACTION, + function () { + check_ajax_referer( self::ACTION ); + + $this->options->delete( self::OPTION_IS_PRE_PROXY_INSTALL ); + + wp_send_json_success(); + } + ); + add_action( 'admin_init', array( $this, 'handle_action' ) ); add_action( 'admin_init', array( $this, 'maybe_run_upgrade' ) ); add_action( 'admin_notices', array( $notice, 'render' ) ); @@ -106,39 +117,6 @@ public function maybe_run_upgrade() { } } - /** - * Handles the pre-proxy action chosen by the user. - */ - public function handle_action() { - $action = filter_input( INPUT_GET, self::PARAM_PRE_PROXY_ACTION ); - - if ( ! $action ) { - return; - } - - if ( ! check_admin_referer( self::ACTION ) || ! in_array( $action, array( 'reconnect', 'ignore' ), true ) ) { - return; - } - - $this->options->delete( self::OPTION_IS_PRE_PROXY_INSTALL ); - - if ( 'reconnect' === $action ) { - wp_safe_redirect( $this->oauth_client->get_proxy_setup_url() ); - } elseif ( 'ignore' === $action ) { - // Redirect to the current URL without the action params. - wp_safe_redirect( - add_query_arg( - array( - self::PARAM_PRE_PROXY_ACTION => false, - '_wpnonce' => false, - ) - ) - ); - } - - exit; - } - /** * Runs the upgrade. */ @@ -156,6 +134,10 @@ private function run_upgrade() { /** * Gets the content to render in the reconnect notice. * + * Mirrors behavior of core's dismissible notices, while dismissing DB flag asynchronously. + * + * @link https://github.com/WordPress/WordPress/blob/956725990f075cb6b8b5a0b8a480c4c823a3fd99/wp-admin/js/common.js#L765-L770 + * * @return string */ private function get_notice_content() { @@ -165,32 +147,37 @@ private function get_notice_content() {

- + - - + +

+ + $action, - '_wpnonce' => wp_create_nonce( self::ACTION ), - ) - ); - } } From 6bf4b81f7d7f9dbf033e352819c2b4f9fd2fccfc Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Thu, 17 Oct 2019 20:01:37 +0300 Subject: [PATCH 072/102] Notice: remove # from id attribute value --- includes/Core/Admin/Notice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Core/Admin/Notice.php b/includes/Core/Admin/Notice.php index 3ee3a23321f..cc4fd67c590 100644 --- a/includes/Core/Admin/Notice.php +++ b/includes/Core/Admin/Notice.php @@ -124,7 +124,7 @@ public function render() { } ?> -
+
Date: Thu, 17 Oct 2019 20:03:11 +0300 Subject: [PATCH 073/102] PHPUnit: add Beta_MigrationTest --- .../Core/Util/Beta_MigrationTest.php | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 tests/phpunit/integration/Core/Util/Beta_MigrationTest.php diff --git a/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php b/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php new file mode 100644 index 00000000000..b2bf5ee18b0 --- /dev/null +++ b/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php @@ -0,0 +1,107 @@ +register(); + + $this->assertTrue( has_action( 'admin_init' ) ); + $this->assertTrue( has_action( 'admin_notices' ) ); + $this->assertTrue( has_action( 'network_admin_notices' ) ); + $this->assertTrue( has_action( 'wp_ajax_googlesitekit_' . Beta_Migration::ACTION ) ); + } + + public function test_maybe_run_upgrade() { + $context = new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ); + $options = new Options( $context ); + $credentials = new Credentials( $options ); + $migration = new Beta_Migration( $context ); + + // Upgrade will update the DB version if run. + $this->delete_db_version(); + $this->delete_credentials(); + + $migration->maybe_run_upgrade(); + + $this->assertEquals( Beta_Migration::DB_VERSION, $options->get( 'googlesitekit_db_version' ) ); + $this->assertFalse( $credentials->has() ); + + // The upgrade will delete old GCP credentials if present. + $this->delete_db_version(); + $this->set_gcp_credentials(); + $this->assertTrue( $credentials->has() ); + + $migration->maybe_run_upgrade(); + + $this->assertFalse( $credentials->has() ); + $this->assertEquals( Beta_Migration::DB_VERSION, $options->get( 'googlesitekit_db_version' ) ); + + // The upgrade will not delete proxy credentials if present. + $this->delete_db_version(); + $this->set_proxy_credentials(); + $this->assertTrue( $credentials->has() ); + + $migration->maybe_run_upgrade(); + + $this->assertTrue( $credentials->has() ); + $this->assertEquals( Beta_Migration::DB_VERSION, $options->get( 'googlesitekit_db_version' ) ); + + // The upgrade will not run if the DB version is greater than or equal to DB_VERSION. + $options->set( 'googlesitekit_db_version', Beta_Migration::DB_VERSION ); + // Set GCP credentials which would be deleted if the upgrade were to run. + $this->set_gcp_credentials(); + $this->assertTrue( $credentials->has() ); + $credentials_before = $credentials->get(); + + $migration->maybe_run_upgrade(); + + $this->assertTrue( $credentials->has() ); + // Credentials are the same as before. + $this->assertEquals( $credentials_before, $credentials->get() ); + $this->assertEquals( Beta_Migration::DB_VERSION, $options->get( 'googlesitekit_db_version' ) ); + } + + private function delete_db_version() { + ( new Options( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) ) )->delete( 'googlesitekit_db_version' ); + } + + private function delete_credentials() { + ( new Options( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) ) )->delete( Credentials::OPTION ); + } + + private function set_gcp_credentials() { + ( new Credentials( new Options( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) ) ) )->set( array( + 'oauth2_client_id' => 'test-client-id.apps.googleusercontent.com', + 'oauth2_client_secret' => 'test-client-secret', + ) ); + } + + private function set_proxy_credentials() { + ( new Credentials( new Options( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) ) ) )->set( array( + 'oauth2_client_id' => 'test-site-id.apps.sitekit.withgoogle.com', + 'oauth2_client_secret' => 'test-site-secret', + ) ); + } +} From 45eac8f3faffdf2787aa06faaded11be2cf007c7 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Thu, 17 Oct 2019 20:06:32 +0300 Subject: [PATCH 074/102] rename action and clean up removed query param --- includes/Core/Util/Beta_Migration.php | 17 ++++++----------- .../Core/Util/Beta_MigrationTest.php | 4 ++-- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/includes/Core/Util/Beta_Migration.php b/includes/Core/Util/Beta_Migration.php index 6a00e1e9378..2d447a6c65b 100644 --- a/includes/Core/Util/Beta_Migration.php +++ b/includes/Core/Util/Beta_Migration.php @@ -34,14 +34,9 @@ class Beta_Migration { const OPTION_IS_PRE_PROXY_INSTALL = 'googlesitekit_pre_proxy_install'; /** - * Query parameter for identifying a pre-proxy action. + * WP Ajax Dismiss Action. */ - const PARAM_PRE_PROXY_ACTION = 'googlesitekit_pre_proxy_action'; - - /** - * WP Nonce Action. - */ - const ACTION = 'dismiss_reconnect_notice'; + const ACTION_DISMISS = 'googlesitekit_dismiss'; /** * Options instance. @@ -92,9 +87,9 @@ public function register() { ); add_action( - 'wp_ajax_googlesitekit_' . self::ACTION, + 'wp_ajax_' . self::ACTION_DISMISS, function () { - check_ajax_referer( self::ACTION ); + check_ajax_referer( self::ACTION_DISMISS ); $this->options->delete( self::OPTION_IS_PRE_PROXY_INSTALL ); @@ -162,8 +157,8 @@ private function get_notice_content() { $notice .on( 'click', 'a', function () { $.post( ajaxurl, { - action: "", - _wpnonce: "" + action: "", + _wpnonce: "" } ); } ) .on( 'click', '[data-dismiss]', function( event ) { diff --git a/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php b/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php index b2bf5ee18b0..3567f14cbdc 100644 --- a/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php +++ b/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php @@ -23,14 +23,14 @@ public function test_register() { remove_all_actions( 'admin_init' ); remove_all_actions( 'admin_notices' ); remove_all_actions( 'network_admin_notices' ); - remove_all_actions( 'wp_ajax_googlesitekit_' . Beta_Migration::ACTION ); + remove_all_actions( 'wp_ajax_' . Beta_Migration::ACTION_DISMISS ); $migration->register(); $this->assertTrue( has_action( 'admin_init' ) ); $this->assertTrue( has_action( 'admin_notices' ) ); $this->assertTrue( has_action( 'network_admin_notices' ) ); - $this->assertTrue( has_action( 'wp_ajax_googlesitekit_' . Beta_Migration::ACTION ) ); + $this->assertTrue( has_action( 'wp_ajax_' . Beta_Migration::ACTION_DISMISS ) ); } public function test_maybe_run_upgrade() { From ce90c702a17426980c07f6b6adc85cb89a2968d0 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Thu, 17 Oct 2019 20:17:43 +0300 Subject: [PATCH 075/102] add hook notice in via googlesitekit_admin_notices required for active_callback to work --- includes/Core/Util/Beta_Migration.php | 29 +++++++++++-------- .../Core/Util/Beta_MigrationTest.php | 6 ++-- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/includes/Core/Util/Beta_Migration.php b/includes/Core/Util/Beta_Migration.php index 2d447a6c65b..97e5d4556ed 100644 --- a/includes/Core/Util/Beta_Migration.php +++ b/includes/Core/Util/Beta_Migration.php @@ -74,16 +74,23 @@ public function __construct( Context $context ) { * Registers hooks. */ public function register() { - $notice = new Notice( - 'beta-migration', - array( - 'content' => function () { - return $this->get_notice_content(); - }, - 'active_callback' => function () { - return $this->options->get( self::OPTION_IS_PRE_PROXY_INSTALL ) && current_user_can( Permissions::SETUP ); - }, - ) + add_filter( + 'googlesitekit_admin_notices', + function ( $notices ) { + $notices[] = new Notice( + 'beta-migration', + array( + 'content' => function () { + return $this->get_notice_content(); + }, + 'active_callback' => function () { + return $this->options->get( self::OPTION_IS_PRE_PROXY_INSTALL ) && current_user_can( Permissions::SETUP ); + }, + ) + ); + + return $notices; + } ); add_action( @@ -99,8 +106,6 @@ function () { add_action( 'admin_init', array( $this, 'handle_action' ) ); add_action( 'admin_init', array( $this, 'maybe_run_upgrade' ) ); - add_action( 'admin_notices', array( $notice, 'render' ) ); - add_action( 'network_admin_notices', array( $notice, 'render' ) ); } /** diff --git a/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php b/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php index 3567f14cbdc..43934539126 100644 --- a/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php +++ b/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php @@ -21,15 +21,13 @@ class Beta_MigrationTest extends TestCase { public function test_register() { $migration = new Beta_Migration( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) ); remove_all_actions( 'admin_init' ); - remove_all_actions( 'admin_notices' ); - remove_all_actions( 'network_admin_notices' ); + remove_all_filters( 'googlesitekit_admin_notices' ); remove_all_actions( 'wp_ajax_' . Beta_Migration::ACTION_DISMISS ); $migration->register(); $this->assertTrue( has_action( 'admin_init' ) ); - $this->assertTrue( has_action( 'admin_notices' ) ); - $this->assertTrue( has_action( 'network_admin_notices' ) ); + $this->assertTrue( has_filter( 'googlesitekit_admin_notices' ) ); $this->assertTrue( has_action( 'wp_ajax_' . Beta_Migration::ACTION_DISMISS ) ); } From ec2a7d03c3dddf85495e192303afc6b880aa0e31 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Thu, 17 Oct 2019 20:32:44 +0300 Subject: [PATCH 076/102] add beta migration related options to Reset + test --- includes/Core/Util/Reset.php | 2 ++ tests/phpunit/integration/Core/Util/ResetTest.php | 3 +++ 2 files changed, 5 insertions(+) diff --git a/includes/Core/Util/Reset.php b/includes/Core/Util/Reset.php index eb6c69708aa..4e2245b564c 100644 --- a/includes/Core/Util/Reset.php +++ b/includes/Core/Util/Reset.php @@ -117,6 +117,8 @@ private function delete_all_plugin_options() { $this->options->delete( TagManager::OPTION ); $this->options->delete( First_Admin::OPTION ); $this->options->delete( OAuth_Client::OPTION_PROXY_NONCE ); + $this->options->delete( Beta_Migration::OPTION_IS_PRE_PROXY_INSTALL ); + $this->options->delete( 'googlesitekit_db_version' ); // Clean up old site verification data, moved to user options. // Also clean up other old unused options. diff --git a/tests/phpunit/integration/Core/Util/ResetTest.php b/tests/phpunit/integration/Core/Util/ResetTest.php index 5dc9f179fb4..450ae13ff19 100644 --- a/tests/phpunit/integration/Core/Util/ResetTest.php +++ b/tests/phpunit/integration/Core/Util/ResetTest.php @@ -18,6 +18,7 @@ use Google\Site_Kit\Core\Authentication\Verification; use Google\Site_Kit\Core\Authentication\Verification_Tag; use Google\Site_Kit\Core\Util\Activation; +use Google\Site_Kit\Core\Util\Beta_Migration; use Google\Site_Kit\Core\Util\Reset; use Google\Site_Kit\Modules\AdSense; use Google\Site_Kit\Modules\Analytics; @@ -83,6 +84,8 @@ protected function get_option_keys() { PageSpeed_Insights::OPTION, Search_Console::PROPERTY_OPTION, TagManager::OPTION, + Beta_Migration::OPTION_IS_PRE_PROXY_INSTALL, + 'googlesitekit_db_version', ); } From 27766da50794dfee8784e114657c49d4cbd34117 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Fri, 18 Oct 2019 08:09:00 +0200 Subject: [PATCH 077/102] Fix undefined property warnings in Google_Proxy_Client class. --- .../Core/Authentication/Clients/Google_Proxy_Client.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/Core/Authentication/Clients/Google_Proxy_Client.php b/includes/Core/Authentication/Clients/Google_Proxy_Client.php index 35c7656478f..5b4c57e2487 100644 --- a/includes/Core/Authentication/Clients/Google_Proxy_Client.php +++ b/includes/Core/Authentication/Clients/Google_Proxy_Client.php @@ -153,9 +153,9 @@ protected function createOAuth2Service() { 'authorizationUri' => self::OAUTH2_AUTH_URL, 'tokenCredentialUri' => self::OAUTH2_TOKEN_URI, 'redirectUri' => $this->getRedirectUri(), - 'issuer' => $this->config['client_id'], - 'signingKey' => $this->config['signing_key'], - 'signingAlgorithm' => $this->config['signing_algorithm'], + 'issuer' => $this->getClientId(), + 'signingKey' => null, + 'signingAlgorithm' => null, ) ); From e548942dad45b2a4a809df5320be04e98015e549 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Fri, 18 Oct 2019 12:22:20 +0300 Subject: [PATCH 078/102] remove action for old action handler used when redirects were handling reconnect/ignore actions --- includes/Core/Util/Beta_Migration.php | 1 - 1 file changed, 1 deletion(-) diff --git a/includes/Core/Util/Beta_Migration.php b/includes/Core/Util/Beta_Migration.php index 97e5d4556ed..d64af99f3e7 100644 --- a/includes/Core/Util/Beta_Migration.php +++ b/includes/Core/Util/Beta_Migration.php @@ -104,7 +104,6 @@ function () { } ); - add_action( 'admin_init', array( $this, 'handle_action' ) ); add_action( 'admin_init', array( $this, 'maybe_run_upgrade' ) ); } From 09cb33676dc2d79baebca0c3be5a8ea6c87d290c Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Fri, 18 Oct 2019 12:23:07 +0300 Subject: [PATCH 079/102] remove googlesitekit_db_version option usage --- includes/Core/Util/Beta_Migration.php | 25 ++++------------ includes/Core/Util/Reset.php | 1 - .../Core/Util/Beta_MigrationTest.php | 30 ++----------------- .../integration/Core/Util/ResetTest.php | 1 - 4 files changed, 9 insertions(+), 48 deletions(-) diff --git a/includes/Core/Util/Beta_Migration.php b/includes/Core/Util/Beta_Migration.php index d64af99f3e7..4720b1edc27 100644 --- a/includes/Core/Util/Beta_Migration.php +++ b/includes/Core/Util/Beta_Migration.php @@ -23,11 +23,6 @@ * @package Google\Site_Kit\Core\Util */ class Beta_Migration { - /** - * Target database version. - */ - const DB_VERSION = '1.0.0'; - /** * Option name to identify a site which was previously configured without the proxy. */ @@ -104,30 +99,22 @@ function () { } ); - add_action( 'admin_init', array( $this, 'maybe_run_upgrade' ) ); - } - - /** - * Runs the upgrade based on the current DB version. - */ - public function maybe_run_upgrade() { - if ( version_compare( get_option( 'googlesitekit_db_version', '0' ), self::DB_VERSION, '<' ) ) { - $this->run_upgrade(); - } + add_action( 'admin_init', array( $this, 'migrate_old_credentials' ) ); } /** - * Runs the upgrade. + * Migrates old GCP credentials if saved in the option. + * + * GCP credentials are still possible to use (for now), but only via filter + * so they should never be present in the option / Credentials anymore. */ - private function run_upgrade() { + public function migrate_old_credentials() { $credentials = $this->credentials->get(); if ( ! strpos( $credentials['oauth2_client_id'], '.apps.sitekit.withgoogle.com' ) ) { $this->options->delete( Credentials::OPTION ); $this->options->set( self::OPTION_IS_PRE_PROXY_INSTALL, 1 ); } - - update_option( 'googlesitekit_db_version', self::DB_VERSION ); } /** diff --git a/includes/Core/Util/Reset.php b/includes/Core/Util/Reset.php index 4e2245b564c..b7a7a6b252d 100644 --- a/includes/Core/Util/Reset.php +++ b/includes/Core/Util/Reset.php @@ -118,7 +118,6 @@ private function delete_all_plugin_options() { $this->options->delete( First_Admin::OPTION ); $this->options->delete( OAuth_Client::OPTION_PROXY_NONCE ); $this->options->delete( Beta_Migration::OPTION_IS_PRE_PROXY_INSTALL ); - $this->options->delete( 'googlesitekit_db_version' ); // Clean up old site verification data, moved to user options. // Also clean up other old unused options. diff --git a/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php b/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php index 43934539126..79b4a0d2458 100644 --- a/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php +++ b/tests/phpunit/integration/Core/Util/Beta_MigrationTest.php @@ -38,51 +38,27 @@ public function test_maybe_run_upgrade() { $migration = new Beta_Migration( $context ); // Upgrade will update the DB version if run. - $this->delete_db_version(); $this->delete_credentials(); - $migration->maybe_run_upgrade(); + $migration->migrate_old_credentials(); - $this->assertEquals( Beta_Migration::DB_VERSION, $options->get( 'googlesitekit_db_version' ) ); $this->assertFalse( $credentials->has() ); // The upgrade will delete old GCP credentials if present. - $this->delete_db_version(); $this->set_gcp_credentials(); $this->assertTrue( $credentials->has() ); - $migration->maybe_run_upgrade(); + $migration->migrate_old_credentials(); $this->assertFalse( $credentials->has() ); - $this->assertEquals( Beta_Migration::DB_VERSION, $options->get( 'googlesitekit_db_version' ) ); // The upgrade will not delete proxy credentials if present. - $this->delete_db_version(); $this->set_proxy_credentials(); $this->assertTrue( $credentials->has() ); - $migration->maybe_run_upgrade(); + $migration->migrate_old_credentials(); $this->assertTrue( $credentials->has() ); - $this->assertEquals( Beta_Migration::DB_VERSION, $options->get( 'googlesitekit_db_version' ) ); - - // The upgrade will not run if the DB version is greater than or equal to DB_VERSION. - $options->set( 'googlesitekit_db_version', Beta_Migration::DB_VERSION ); - // Set GCP credentials which would be deleted if the upgrade were to run. - $this->set_gcp_credentials(); - $this->assertTrue( $credentials->has() ); - $credentials_before = $credentials->get(); - - $migration->maybe_run_upgrade(); - - $this->assertTrue( $credentials->has() ); - // Credentials are the same as before. - $this->assertEquals( $credentials_before, $credentials->get() ); - $this->assertEquals( Beta_Migration::DB_VERSION, $options->get( 'googlesitekit_db_version' ) ); - } - - private function delete_db_version() { - ( new Options( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) ) )->delete( 'googlesitekit_db_version' ); } private function delete_credentials() { diff --git a/tests/phpunit/integration/Core/Util/ResetTest.php b/tests/phpunit/integration/Core/Util/ResetTest.php index 450ae13ff19..dce71e6c6da 100644 --- a/tests/phpunit/integration/Core/Util/ResetTest.php +++ b/tests/phpunit/integration/Core/Util/ResetTest.php @@ -85,7 +85,6 @@ protected function get_option_keys() { Search_Console::PROPERTY_OPTION, TagManager::OPTION, Beta_Migration::OPTION_IS_PRE_PROXY_INSTALL, - 'googlesitekit_db_version', ); } From 33889e2f9fec5bac622c09a696f7c358df91699f Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Fri, 18 Oct 2019 12:46:12 +0300 Subject: [PATCH 080/102] only migrate creds if client id exists & non-proxy --- includes/Core/Util/Beta_Migration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Core/Util/Beta_Migration.php b/includes/Core/Util/Beta_Migration.php index 4720b1edc27..bb593b67961 100644 --- a/includes/Core/Util/Beta_Migration.php +++ b/includes/Core/Util/Beta_Migration.php @@ -111,7 +111,7 @@ function () { public function migrate_old_credentials() { $credentials = $this->credentials->get(); - if ( ! strpos( $credentials['oauth2_client_id'], '.apps.sitekit.withgoogle.com' ) ) { + if ( $credentials['oauth2_client_id'] && ! strpos( $credentials['oauth2_client_id'], '.apps.sitekit.withgoogle.com' ) ) { $this->options->delete( Credentials::OPTION ); $this->options->set( self::OPTION_IS_PRE_PROXY_INSTALL, 1 ); } From 42b4135cd9bb15c522b051c23c917e849d526706 Mon Sep 17 00:00:00 2001 From: Matthew Riley MacPherson Date: Fri, 18 Oct 2019 14:12:43 +0100 Subject: [PATCH 081/102] Update assets/js/components/setup/setup-proxy.js Co-Authored-By: Evan Mattson --- assets/js/components/setup/setup-proxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/components/setup/setup-proxy.js b/assets/js/components/setup/setup-proxy.js index 1e330fb27e8..f81e9df0ca6 100644 --- a/assets/js/components/setup/setup-proxy.js +++ b/assets/js/components/setup/setup-proxy.js @@ -81,7 +81,7 @@ class SetupUsingProxy extends Component { }, ); - delay( function() { + delay( () => { window.location.replace( redirectUrl ); }, 500, 'later' ); } From 93282659edf3fa2469cbecfab59e19ca947e0bdc Mon Sep 17 00:00:00 2001 From: "Matthew Riley MacPherson (tofumatt)" Date: Fri, 18 Oct 2019 14:42:36 +0100 Subject: [PATCH 082/102] chore: Tweak variable usage --- assets/js/components/setup/setup-proxy.js | 31 +++++------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/assets/js/components/setup/setup-proxy.js b/assets/js/components/setup/setup-proxy.js index f81e9df0ca6..2e5c8145189 100644 --- a/assets/js/components/setup/setup-proxy.js +++ b/assets/js/components/setup/setup-proxy.js @@ -33,29 +33,15 @@ class SetupUsingProxy extends Component { constructor( props ) { super( props ); - const { connectUrl } = googlesitekit.admin; - - const { - isAuthenticated, - hasSearchConsoleProperty, - isSiteKitConnected, - isVerified, - needReauthenticate, - } = googlesitekit.setup; - + const { proxySetupURL } = googlesitekit.admin; + const { isSiteKitConnected } = googlesitekit.setup; const { canSetup } = googlesitekit.permissions; this.state = { canSetup, - isAuthenticated, - isVerified, - needReauthenticate, - hasSearchConsoleProperty, - hasSearchConsolePropertyFromTheStart: hasSearchConsoleProperty, - connectUrl, - errorMsg: '', isSiteKitConnected, completeSetup: false, + proxySetupURL, }; } @@ -69,10 +55,6 @@ class SetupUsingProxy extends Component { } render() { - const { - connectUrl, - } = this.state; - if ( this.isSetupFinished() ) { const redirectUrl = getSiteKitAdminURL( 'googlesitekit-dashboard', @@ -86,7 +68,7 @@ class SetupUsingProxy extends Component { }, 500, 'later' ); } - const { proxySetupURL } = googlesitekit.admin; + const { proxySetupURL } = this.state; return ( @@ -117,9 +99,10 @@ class SetupUsingProxy extends Component { href={ proxySetupURL } onClick={ () => { sendAnalyticsTrackingEvent( 'plugin_setup', 'signin_with_google' ); - document.location = connectUrl; } } - >{ __( 'Start setup', 'google-site-kit' ) } + > + { __( 'Start setup', 'google-site-kit' ) } +
From 9e4231323119491457e03317dfcd8c32c39c56b8 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Fri, 18 Oct 2019 18:06:03 +0300 Subject: [PATCH 083/102] update test client config to use proxy credentials --- tests/e2e/utils/test-client-config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/utils/test-client-config.js b/tests/e2e/utils/test-client-config.js index 57ffffa0c2d..c4743fd56fe 100644 --- a/tests/e2e/utils/test-client-config.js +++ b/tests/e2e/utils/test-client-config.js @@ -1,7 +1,7 @@ /* eslint-disable camelcase */ export const testClientConfig = { web: { - client_id: '1234567890-asdfasdfasdfasdfzxcvzxcvzxcvzxcv.apps.googleusercontent.com', + client_id: '1234567890-asdfasdfasdfasdfzxcvzxcvzxcvzxcv.apps.sitekit.withgoogle.com', client_secret: 'x_xxxxxxxxxxxxxxxxxxxxxx', project_id: 'test-project-id', auth_uri: 'https://accounts.google.com/o/oauth2/auth', From 96b17a4d67027c9226d19de103e4c661775717a9 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Fri, 18 Oct 2019 20:15:42 +0300 Subject: [PATCH 084/102] extract client credentials filter to new plugin --- tests/e2e/plugins/auth.php | 11 +-------- tests/e2e/plugins/gcp-credentials.php | 32 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 tests/e2e/plugins/gcp-credentials.php diff --git a/tests/e2e/plugins/auth.php b/tests/e2e/plugins/auth.php index ee32f61d26b..b67b6f7c645 100644 --- a/tests/e2e/plugins/auth.php +++ b/tests/e2e/plugins/auth.php @@ -19,16 +19,7 @@ /** * Provide dummy client configuration, normally provided in step 1 of the set up. */ -add_filter( 'pre_option_googlesitekit_credentials', function () { - return ( new Data_Encryption() )->encrypt( - serialize( - array( - 'oauth2_client_id' => '1234567890-asdfasdfasdfasdfzxcvzxcvzxcvzxcv.apps.googleusercontent.com', - 'oauth2_client_secret' => 'x_xxxxxxxxxxxxxxxxxxxxxx', - ) - ) - ); -} ); +require_once __DIR__ . '/gcp-credentials.php'; /** * Provide a dummy access token to fake an authenticated state. diff --git a/tests/e2e/plugins/gcp-credentials.php b/tests/e2e/plugins/gcp-credentials.php new file mode 100644 index 00000000000..ec2ed7c2313 --- /dev/null +++ b/tests/e2e/plugins/gcp-credentials.php @@ -0,0 +1,32 @@ +encrypt( + serialize( + array( + 'oauth2_client_id' => '1234567890-asdfasdfasdfasdfzxcvzxcvzxcvzxcv.apps.googleusercontent.com', + 'oauth2_client_secret' => 'x_xxxxxxxxxxxxxxxxxxxxxx', + ) + ) + ); +} ); From f01b68f428876dfcd49d52605f342413d0e54408 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Fri, 18 Oct 2019 20:22:27 +0300 Subject: [PATCH 085/102] refactor auth-* tests with gcp-credentials plugin --- tests/e2e/specs/auth-flow-admin-2.test.js | 3 +-- tests/e2e/specs/auth-flow.test.js | 10 +++++----- tests/e2e/specs/auth-setup-search-console.test.js | 4 +--- tests/e2e/specs/auth-setup-verification.test.js | 4 +--- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/tests/e2e/specs/auth-flow-admin-2.test.js b/tests/e2e/specs/auth-flow-admin-2.test.js index a7e205f7d0e..baa52000997 100644 --- a/tests/e2e/specs/auth-flow-admin-2.test.js +++ b/tests/e2e/specs/auth-flow-admin-2.test.js @@ -14,7 +14,6 @@ import { import { logoutUser, setAuthToken, - setClientConfig, setSearchConsoleProperty, setSiteVerification, useRequestInterception, @@ -39,9 +38,9 @@ describe( 'the set up flow for the second administrator', () => { } ); beforeEach( async () => { + await activatePlugin( 'e2e-tests-gcp-credentials-plugin' ); await activatePlugin( 'e2e-tests-oauth-callback-plugin' ); await activatePlugin( 'e2e-tests-site-verification-api-mock' ); - await setClientConfig(); await setAuthToken(); await setSiteVerification(); await setSearchConsoleProperty(); diff --git a/tests/e2e/specs/auth-flow.test.js b/tests/e2e/specs/auth-flow.test.js index 69e29d47065..91cf75dfdd8 100644 --- a/tests/e2e/specs/auth-flow.test.js +++ b/tests/e2e/specs/auth-flow.test.js @@ -11,7 +11,6 @@ import { resetSiteKit, setSearchConsoleProperty, useRequestInterception, - setClientConfig, setAuthToken, setSiteVerification, } from '../utils'; @@ -53,19 +52,21 @@ const signOut = async () => { describe( 'Site Kit set up flow for the first time', () => { beforeAll( async () => { - await activatePlugin( 'e2e-tests-oauth-callback-plugin' ); await setSearchConsoleProperty(); } ); + beforeEach( async () => { + await activatePlugin( 'e2e-tests-gcp-credentials-plugin' ); + } ); + afterEach( async () => { await deactivateUtilityPlugins(); await resetSiteKit(); } ); it( 'authenticates from splash page', async () => { - await setClientConfig(); + await activatePlugin( 'e2e-tests-oauth-callback-plugin' ); await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); - // Sign in with Google await page.setRequestInterception( true ); useRequestInterception( stubGoogleSignIn ); @@ -77,7 +78,6 @@ describe( 'Site Kit set up flow for the first time', () => { } ); it( 'disconnects user from Site Kit', async () => { - await setClientConfig(); await setAuthToken(); await setSiteVerification(); await setSearchConsoleProperty(); diff --git a/tests/e2e/specs/auth-setup-search-console.test.js b/tests/e2e/specs/auth-setup-search-console.test.js index 1f9f04c1244..5cb31baa4eb 100644 --- a/tests/e2e/specs/auth-setup-search-console.test.js +++ b/tests/e2e/specs/auth-setup-search-console.test.js @@ -9,7 +9,6 @@ import { activatePlugin, createURL, visitAdminPage } from '@wordpress/e2e-test-u import { deactivateUtilityPlugins, resetSiteKit, - setClientConfig, useRequestInterception, wpApiFetch, } from '../utils'; @@ -36,6 +35,7 @@ describe( 'Site Kit set up flow for the first time with search console setup', ( } ); beforeEach( async () => { + await activatePlugin( 'e2e-tests-gcp-credentials-plugin' ); await activatePlugin( 'e2e-tests-oauth-callback-plugin' ); await activatePlugin( 'e2e-tests-site-verification-api-mock' ); @@ -52,7 +52,6 @@ describe( 'Site Kit set up flow for the first time with search console setup', ( } ); it( 'inserts property to search console when site does not exist', async () => { - await setClientConfig(); await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); await expect( page ).toClick( '.googlesitekit-wizard-step button', { text: /sign in with Google/i } ); @@ -71,7 +70,6 @@ describe( 'Site Kit set up flow for the first time with search console setup', ( } ); it( 'saves search console property when site exists', async () => { - await setClientConfig(); await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); await expect( page ).toClick( '.googlesitekit-wizard-step button', { text: /sign in with Google/i } ); diff --git a/tests/e2e/specs/auth-setup-verification.test.js b/tests/e2e/specs/auth-setup-verification.test.js index e5247e0c9b7..02700ccd685 100644 --- a/tests/e2e/specs/auth-setup-verification.test.js +++ b/tests/e2e/specs/auth-setup-verification.test.js @@ -9,7 +9,6 @@ import { activatePlugin, createURL, visitAdminPage } from '@wordpress/e2e-test-u import { deactivateUtilityPlugins, resetSiteKit, - setClientConfig, useRequestInterception, wpApiFetch, } from '../utils'; @@ -36,6 +35,7 @@ describe( 'Site Kit set up flow for the first time with site verification', () = } ); beforeEach( async () => { + await activatePlugin( 'e2e-tests-gcp-credentials-plugin' ); await activatePlugin( 'e2e-tests-oauth-callback-plugin' ); await activatePlugin( 'e2e-tests-site-verification-api-mock' ); } ); @@ -50,7 +50,6 @@ describe( 'Site Kit set up flow for the first time with site verification', () = } ); it( 'prompts for confirmation if user is not verified for the site', async () => { - await setClientConfig(); await visitAdminPage( 'admin.php', 'page=googlesitekit-splash' ); await expect( page ).toClick( '.googlesitekit-wizard-step button', { text: /sign in with Google/i } ); @@ -73,7 +72,6 @@ describe( 'Site Kit set up flow for the first time with site verification', () = } ); it( 'does not prompt for verification if the user is already verified for the site', async () => { - await setClientConfig(); // Simulate that the user is already verified. await wpApiFetch( { path: 'google-site-kit/v1/e2e/verify-site', From e2fcd903726c0e12946debb738a78b625888f48e Mon Sep 17 00:00:00 2001 From: "Matthew Riley MacPherson (tofumatt)" Date: Mon, 21 Oct 2019 10:17:24 +0100 Subject: [PATCH 086/102] chore: Remove 'using_proxy' variable --- includes/Core/Assets/Assets.php | 1 - 1 file changed, 1 deletion(-) diff --git a/includes/Core/Assets/Assets.php b/includes/Core/Assets/Assets.php index 7afe23ce232..512d9a97793 100644 --- a/includes/Core/Assets/Assets.php +++ b/includes/Core/Assets/Assets.php @@ -447,7 +447,6 @@ private function get_inline_data() { $auth_client = new \Google\Site_Kit\Core\Authentication\Clients\OAuth_Client( $this->context ); $admin_data = array( - 'usingProxy' => $auth_client->using_proxy(), 'siteURL' => esc_url_raw( $site_url ), 'siteName' => get_bloginfo( 'name' ), 'siteUserId' => md5( $site_url . $current_user->ID ), From a349b995fc05ff626d99d04e77f28939c63fb2b2 Mon Sep 17 00:00:00 2001 From: "Matthew Riley MacPherson (tofumatt)" Date: Mon, 21 Oct 2019 10:17:48 +0100 Subject: [PATCH 087/102] chore: Change header to AC text --- assets/js/components/setup/setup-proxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/components/setup/setup-proxy.js b/assets/js/components/setup/setup-proxy.js index 2e5c8145189..29b863f0b44 100644 --- a/assets/js/components/setup/setup-proxy.js +++ b/assets/js/components/setup/setup-proxy.js @@ -90,7 +90,7 @@ class SetupUsingProxy extends Component { mdc-layout-grid__cell--span-12 ">

- { __( 'Time to set up the Site Kit plugin', 'google-site-kit' ) } + { __( 'The Site Kit plugin is active but requires setup', 'google-site-kit' ) }

{ __( 'Site Kit Service will guide you through 3 simple setup steps.', 'google-site-kit' ) } From e365594fee24ede92a47bf8eec9edcb9bf0f925d Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Mon, 21 Oct 2019 15:41:51 +0300 Subject: [PATCH 088/102] reAuthUrl: add temp special case handling for PSI --- assets/js/util/index.js | 14 +++++++++++--- tests/qunit/assets/js/util/index.js | 9 ++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/assets/js/util/index.js b/assets/js/util/index.js index 6e7871af73a..fb3a100a201 100644 --- a/assets/js/util/index.js +++ b/assets/js/util/index.js @@ -364,13 +364,21 @@ export const getReAuthUrl = ( slug, status ) => { const { screenId } = googlesitekit.modules[ slug ]; - let redirect = addQueryArgs( - adminRoot, { + // Special case handling for PageSpeed Insights. + // TODO: Refactor this out. + const pageSpeedQueryArgs = 'pagespeed-insights' === slug ? { + notification: 'authentication_success', + reAuth: undefined, + } : {}; + let redirect = addQueryArgs( + adminRoot, + { // If the module has a submenu page, and is being activated, redirect back to the module page. page: ( slug && status && screenId ) ? screenId : 'googlesitekit-dashboard', - reAuth: status, slug, + reAuth: status, + ...pageSpeedQueryArgs, } ); diff --git a/tests/qunit/assets/js/util/index.js b/tests/qunit/assets/js/util/index.js index 8d37f358dcc..473562027d0 100644 --- a/tests/qunit/assets/js/util/index.js +++ b/tests/qunit/assets/js/util/index.js @@ -407,30 +407,29 @@ QUnit.test( 'fillFilterWithComponent::', function ( assert ) { * Test getReAuthUrl. */ valuesToTest = [ - { slug: 'pagespeed-insights', status: false, apikey: false, - expected: 'http://sitekit.withgoogle.com/wp-admin/admin.php?page=googlesitekit-dashboard&reAuth=false&slug=pagespeed-insights' + expected: 'http://sitekit.withgoogle.com/wp-admin/admin.php?page=googlesitekit-dashboard&slug=pagespeed-insights¬ification=authentication_success' }, { slug: 'pagespeed-insights', status: true, apikey: false, - expected: 'http://sitekit.withgoogle.com/wp-admin/admin.php?page=googlesitekit-module-pagespeed-insights&reAuth=true&slug=pagespeed-insights' + expected: 'http://sitekit.withgoogle.com/wp-admin/admin.php?page=googlesitekit-module-pagespeed-insights&slug=pagespeed-insights¬ification=authentication_success' }, { slug: 'pagespeed-insights', status: false, apikey: 'abc123', - expected: 'http://sitekit.withgoogle.com/wp-admin/admin.php?page=googlesitekit-dashboard&reAuth=false&slug=pagespeed-insights' + expected: 'http://sitekit.withgoogle.com/wp-admin/admin.php?page=googlesitekit-dashboard&slug=pagespeed-insights¬ification=authentication_success' }, { slug: 'pagespeed-insights', status: true, apikey: 'abc123', - expected: 'http://sitekit.withgoogle.com/wp-admin/admin.php?page=googlesitekit-module-pagespeed-insights&reAuth=true&slug=pagespeed-insights' + expected: 'http://sitekit.withgoogle.com/wp-admin/admin.php?page=googlesitekit-module-pagespeed-insights&slug=pagespeed-insights¬ification=authentication_success' }, ]; From 603d91e7565c8794e7ff1ef494026307a2a4e6a2 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Mon, 21 Oct 2019 15:42:49 +0300 Subject: [PATCH 089/102] refactor PageSpeedInsightsCTA to use reAuthUrl for consistency --- .../pagespeed-insights/dashboard/dashboard-cta.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/assets/js/modules/pagespeed-insights/dashboard/dashboard-cta.js b/assets/js/modules/pagespeed-insights/dashboard/dashboard-cta.js index be88e2b65dd..dd5c46c373f 100644 --- a/assets/js/modules/pagespeed-insights/dashboard/dashboard-cta.js +++ b/assets/js/modules/pagespeed-insights/dashboard/dashboard-cta.js @@ -11,7 +11,7 @@ import { /** * Internal dependencies */ -import { getSiteKitAdminURL } from '../../../util'; +import { getReAuthUrl } from '../../../util'; const { __ } = wp.i18n; @@ -30,16 +30,7 @@ const PageSpeedInsightsCTA = () => { const handleSetUpClick = async () => { try { await activateOrDeactivateModule( data, 'pagespeed-insights', true ); - - window.location.assign( - getSiteKitAdminURL( - 'googlesitekit-dashboard', - { - notification: 'authentication_success', - slug: 'pagespeed-insights', - }, - ) - ); + window.location = getReAuthUrl( 'pagespeed-insights' ); } catch ( err ) { showErrorNotification( GenericError, { id: 'pagespeed-insights-setup-error', From 10cc5b106e06a994a48ef9006d0cac465a2b54b6 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Mon, 21 Oct 2019 15:50:08 +0300 Subject: [PATCH 090/102] update PSI e2e test for activation: incl settings --- .../pagespeed-insights/activation.test.js | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/e2e/specs/modules/pagespeed-insights/activation.test.js b/tests/e2e/specs/modules/pagespeed-insights/activation.test.js index e74d958d5a6..cc37c274897 100644 --- a/tests/e2e/specs/modules/pagespeed-insights/activation.test.js +++ b/tests/e2e/specs/modules/pagespeed-insights/activation.test.js @@ -38,11 +38,27 @@ describe( 'PageSpeed Insights Activation', () => { await resetSiteKit(); } ); - it( 'leads you to the Site Kit dashboard after activation', async () => { + it( 'leads you to the Site Kit dashboard after activation via CTA', async () => { await visitAdminPage( 'admin.php', 'page=googlesitekit-dashboard' ); await Promise.all( [ page.waitForNavigation(), - expect( page ).toClick( '.googlesitekit-cta-link', { text: 'Activate PageSpeed Insights' } ), + expect( page ).toClick( '.googlesitekit-cta-link', { text: /Activate PageSpeed Insights/i } ), + ] ); + + await page.waitForSelector( '.googlesitekit-publisher-win__title' ); + await expect( page ).toMatchElement( '.googlesitekit-publisher-win__title', { text: /Congrats on completing the setup for PageSpeed Insights!/i } ); + } ); + + it( 'leads you to the Site Kit dashboard after activation via the settings page', async () => { + await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' ); + + await page.waitForSelector( '.mdc-tab-bar' ); + await expect( page ).toClick( '.mdc-tab', { text: /connect more services/i } ); + await page.waitForSelector( '.googlesitekit-settings-connect-module--pagespeed-insights' ); + + await Promise.all( [ + page.waitForNavigation(), + expect( page ).toClick( '.googlesitekit-cta-link', { text: /Set up PageSpeed Insights/i } ), ] ); await page.waitForSelector( '.googlesitekit-publisher-win__title' ); From 90a154887dec63882d9c6ef18b97504332de66f7 Mon Sep 17 00:00:00 2001 From: "Matthew Riley MacPherson (tofumatt)" Date: Mon, 21 Oct 2019 14:12:25 +0100 Subject: [PATCH 091/102] fix: Plugin activation test --- tests/e2e/specs/plugin-activation.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/e2e/specs/plugin-activation.test.js b/tests/e2e/specs/plugin-activation.test.js index 70bc552c18a..1de0d7cc067 100644 --- a/tests/e2e/specs/plugin-activation.test.js +++ b/tests/e2e/specs/plugin-activation.test.js @@ -6,9 +6,11 @@ import { deactivatePlugin, activatePlugin } from '@wordpress/e2e-test-utils'; describe( 'Plugin Activation Notice', () => { beforeEach( async () => { await deactivatePlugin( 'google-site-kit' ); + await activatePlugin( 'e2e-tests-gcp-credentials-plugin' ); } ); afterEach( async () => { + await deactivatePlugin( 'e2e-tests-gcp-credentials-plugin' ); await activatePlugin( 'google-site-kit' ); } ); From 51b79594037c5cb05e1ee0a72a767c0b12935765 Mon Sep 17 00:00:00 2001 From: "Matthew Riley MacPherson (tofumatt)" Date: Mon, 21 Oct 2019 15:11:19 +0100 Subject: [PATCH 092/102] fix: E2E tests for proxy --- tests/e2e/specs/plugin-activation.test.js | 2 -- tests/e2e/specs/plugin-reset.test.js | 8 +++++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/e2e/specs/plugin-activation.test.js b/tests/e2e/specs/plugin-activation.test.js index 1de0d7cc067..b24ea617033 100644 --- a/tests/e2e/specs/plugin-activation.test.js +++ b/tests/e2e/specs/plugin-activation.test.js @@ -36,7 +36,5 @@ describe( 'Plugin Activation Notice', () => { // Ensure we're on the first step. await expect( page ).toMatchElement( '.googlesitekit-wizard-progress-step__number--inprogress', { text: '1' } ); - - await deactivatePlugin( 'google-site-kit' ); } ); } ); diff --git a/tests/e2e/specs/plugin-reset.test.js b/tests/e2e/specs/plugin-reset.test.js index 81bf4627210..cc93a8a4357 100644 --- a/tests/e2e/specs/plugin-reset.test.js +++ b/tests/e2e/specs/plugin-reset.test.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { visitAdminPage } from '@wordpress/e2e-test-utils'; +import { activatePlugin, deactivatePlugin, visitAdminPage } from '@wordpress/e2e-test-utils'; /** * Internal dependencies @@ -19,6 +19,7 @@ describe( 'Plugin Reset', () => { await setAuthToken(); await setSiteVerification(); await setSearchConsoleProperty(); + await activatePlugin( 'e2e-tests-gcp-credentials-plugin' ); } ); beforeEach( async () => { @@ -32,6 +33,10 @@ describe( 'Plugin Reset', () => { await page.waitForSelector( '.googlesitekit-settings-module__footer' ); } ); + afterAll( async () => { + await deactivatePlugin( 'e2e-tests-gcp-credentials-plugin' ); + } ); + it( 'displays a confirmation dialog when clicking the "Reset Site Kit" link', async () => { await expect( page ).toClick( 'button.googlesitekit-cta-link', { text: 'Reset Site Kit' } ); await page.waitForSelector( '.mdc-dialog--open .mdc-button' ); @@ -47,6 +52,7 @@ describe( 'Plugin Reset', () => { } ); it( 'disconnects Site Kit by clicking the "Reset" button in the confirmation dialog', async () => { + await page.waitForSelector( 'button.googlesitekit-cta-link' ); await expect( page ).toClick( 'button.googlesitekit-cta-link', { text: 'Reset Site Kit' } ); await page.waitForSelector( '.mdc-dialog--open .mdc-button' ); From 36aaca31cc9e09b5e2a0edca3d0824f8af60a3cb Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Mon, 21 Oct 2019 18:26:17 +0300 Subject: [PATCH 093/102] update credentials checks to include oauth filter --- includes/Core/Authentication/Authentication.php | 3 ++- includes/Core/Authentication/Clients/OAuth_Client.php | 3 ++- includes/Core/Permissions/Permissions.php | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index 18dd81d4701..bc5ab7f393f 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -544,7 +544,8 @@ private function inline_js_setup_data( $data ) { $access_token = $auth_client->get_client()->getAccessToken(); - $data['isSiteKitConnected'] = $this->credentials->has(); + // Site Kit is connected if it has credentials or if it is not using the proxy (only possible via filter). + $data['isSiteKitConnected'] = $this->credentials->has() || ! $auth_client->using_proxy(); $data['isAuthenticated'] = ! empty( $access_token ); $data['requiredScopes'] = $auth_client->get_required_scopes(); diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index c247497ffd8..3d3a445a180 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -478,7 +478,8 @@ public function authorize_user() { exit(); } - if ( ! $this->credentials->has() ) { + // Assume Site Kit has credentials if it is not using the proxy (only possible via filter). + if ( ! $this->credentials->has() && $this->using_proxy() ) { $this->user_options->set( self::OPTION_ERROR_CODE, 'oauth_credentials_not_exist' ); wp_safe_redirect( admin_url() ); exit(); diff --git a/includes/Core/Permissions/Permissions.php b/includes/Core/Permissions/Permissions.php index 6ab559c6c23..3b8a1981cb7 100644 --- a/includes/Core/Permissions/Permissions.php +++ b/includes/Core/Permissions/Permissions.php @@ -272,7 +272,7 @@ private function grant_additional_caps( array $allcaps ) { * @return bool True if setup is completed, false otherwise. */ private function is_setup_complete() { - if ( ! $this->authentication->credentials()->has() ) { + if ( ! $this->authentication->credentials()->has() && $this->authentication->get_oauth_client()->using_proxy() ) { return false; } From 738d72b03c13027e8745055725941f4ed972e4e2 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Mon, 21 Oct 2019 19:01:56 +0300 Subject: [PATCH 094/102] Revert "update credentials checks to include oauth filter" This reverts commit 36aaca31cc9e09b5e2a0edca3d0824f8af60a3cb. --- includes/Core/Authentication/Authentication.php | 3 +-- includes/Core/Authentication/Clients/OAuth_Client.php | 3 +-- includes/Core/Permissions/Permissions.php | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/includes/Core/Authentication/Authentication.php b/includes/Core/Authentication/Authentication.php index bc5ab7f393f..18dd81d4701 100644 --- a/includes/Core/Authentication/Authentication.php +++ b/includes/Core/Authentication/Authentication.php @@ -544,8 +544,7 @@ private function inline_js_setup_data( $data ) { $access_token = $auth_client->get_client()->getAccessToken(); - // Site Kit is connected if it has credentials or if it is not using the proxy (only possible via filter). - $data['isSiteKitConnected'] = $this->credentials->has() || ! $auth_client->using_proxy(); + $data['isSiteKitConnected'] = $this->credentials->has(); $data['isAuthenticated'] = ! empty( $access_token ); $data['requiredScopes'] = $auth_client->get_required_scopes(); diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index 3d3a445a180..c247497ffd8 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -478,8 +478,7 @@ public function authorize_user() { exit(); } - // Assume Site Kit has credentials if it is not using the proxy (only possible via filter). - if ( ! $this->credentials->has() && $this->using_proxy() ) { + if ( ! $this->credentials->has() ) { $this->user_options->set( self::OPTION_ERROR_CODE, 'oauth_credentials_not_exist' ); wp_safe_redirect( admin_url() ); exit(); diff --git a/includes/Core/Permissions/Permissions.php b/includes/Core/Permissions/Permissions.php index 3b8a1981cb7..6ab559c6c23 100644 --- a/includes/Core/Permissions/Permissions.php +++ b/includes/Core/Permissions/Permissions.php @@ -272,7 +272,7 @@ private function grant_additional_caps( array $allcaps ) { * @return bool True if setup is completed, false otherwise. */ private function is_setup_complete() { - if ( ! $this->authentication->credentials()->has() && $this->authentication->get_oauth_client()->using_proxy() ) { + if ( ! $this->authentication->credentials()->has() ) { return false; } From bca2a8606ac911ac91560fa820a155ba469af039 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Mon, 21 Oct 2019 18:30:13 +0200 Subject: [PATCH 095/102] Pass currently required scopes to proxy setup URL. --- includes/Core/Authentication/Clients/OAuth_Client.php | 4 ++++ .../Core/Authentication/Clients/OAuth_ClientTest.php | 2 ++ 2 files changed, 6 insertions(+) diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index c247497ffd8..5436c1e5863 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -607,6 +607,8 @@ public function get_proxy_setup_url( $access_code = '', $error_code = '' ) { $credentials = $this->get_client_credentials(); + $scope = implode( ' ', $this->get_required_scopes() ); + if ( ! is_object( $credentials ) || empty( $credentials->web->client_id ) ) { $home_url = home_url(); $home_url_no_scheme = str_replace( array( 'http://', 'https://' ), '', $home_url ); @@ -627,6 +629,7 @@ public function get_proxy_setup_url( $access_code = '', $error_code = '' ) { 'url' => rawurlencode( $home_url ), 'rest_root' => rawurlencode( $rest_root ), 'admin_root' => rawurlencode( $admin_root ), + 'scope' => rawurlencode( $scope ), ), $url ); @@ -635,6 +638,7 @@ public function get_proxy_setup_url( $access_code = '', $error_code = '' ) { $query_args = array( 'site_id' => $credentials->web->client_id, 'code' => $access_code, + 'scope' => rawurlencode( $scope ), ); if ( 'missing_verification' === $error_code ) { $query_args['verification_nonce'] = wp_create_nonce( 'googlesitekit_verification' ); diff --git a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php index a09dc41d9fd..7daa3ca1738 100644 --- a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php +++ b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php @@ -279,6 +279,7 @@ public function test_get_proxy_setup_url() { $this->assertContains( 'url=', $url ); $this->assertContains( 'rest_root=', $url ); $this->assertContains( 'admin_root=', $url ); + $this->assertContains( 'scope=', $url ); $this->assertNotContains( 'site_id=', $url ); // Otherwise, pass site ID and given temporary access code. @@ -287,6 +288,7 @@ public function test_get_proxy_setup_url() { $url = $client->get_proxy_setup_url( 'temp-code' ); $this->assertContains( 'site_id=' . self::SITE_ID, $url ); $this->assertContains( 'code=temp-code', $url ); + $this->assertContains( 'scope=', $url ); $this->assertNotContains( 'name=', $url ); $this->assertNotContains( 'url=', $url ); $this->assertNotContains( 'rest_root=', $url ); From ea1d1e87263f76ef4a03cd13fa83e2b0ad476e72 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Mon, 21 Oct 2019 19:36:15 +0300 Subject: [PATCH 096/102] move googlesitekit_oauth_secret to Credentials get --- .../Authentication/Clients/OAuth_Client.php | 39 +++++++------------ includes/Core/Authentication/Credentials.php | 23 +++++++++++ .../Clients/OAuth_ClientTest.php | 3 -- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index c247497ffd8..029c6506bd2 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -772,32 +772,19 @@ private function get_client_credentials() { return $this->client_credentials; } - /** - * Site Kit oAuth Secret is a string of the JSON for the Google Cloud Platform web application used for Site Kit - * that will be associated with this account. This is meant to be a temporary way to specify the client secret - * until the authentication proxy has been completed. This filter can be specified from a separate theme or plugin. - * - * To retrieve the JSON secret, use the following instructions: - * - Go to the Google Cloud Platform and create a new project or use an existing one - * - In the APIs & Services section, enable the APIs that are used within Site Kit - * - Under 'credentials' either create new oAuth Client ID credentials or use an existing set of credentials - * - Set the authorizes redirect URIs to be the URL to the oAuth callback for Site Kit, eg. https://?oauth2callback=1 (this must be public) - * - Click the 'Download JSON' button to download the JSON file that can be copied and pasted into the filter - */ - $credentials = trim( apply_filters( 'googlesitekit_oauth_secret', '' ) ); - - if ( empty( $credentials ) && $this->credentials->has() ) { - $redirect_uri = $this->get_redirect_uri(); - $credentials = $this->credentials->get(); - $credentials = '{"web":{"client_id":"' . $credentials['oauth2_client_id'] . '","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"' . $credentials['oauth2_client_secret'] . '","redirect_uris":["' . $redirect_uri . '"]}}'; - } - - if ( ! empty( $credentials ) ) { - $this->client_credentials = json_decode( $credentials ); - } - - if ( ! is_object( $this->client_credentials ) || empty( $this->client_credentials->web ) ) { - $this->client_credentials = null; + if ( $this->credentials->has() ) { + $credentials = $this->credentials->get(); + + $this->client_credentials = (object) array( + 'web' => (object) array( + 'client_id' => $credentials['oauth2_client_id'], + 'client_secret' => $credentials['oauth2_client_secret'], + 'auth_uri' => 'https://accounts.google.com/o/oauth2/auth', + 'token_uri' => 'https://oauth2.googleapis.com/token', + 'auth_provider_x509_cert_url' => 'https://www.googleapis.com/oauth2/v1/certs', + 'redirect_uris' => array( $this->get_redirect_uri() ), + ), + ); } return $this->client_credentials; diff --git a/includes/Core/Authentication/Credentials.php b/includes/Core/Authentication/Credentials.php index b90b7b719c0..70c79f59c35 100644 --- a/includes/Core/Authentication/Credentials.php +++ b/includes/Core/Authentication/Credentials.php @@ -54,6 +54,29 @@ public function __construct( Options $options ) { * @return array|bool Value set for the credentials, or false if not set. */ public function get() { + /** + * Site Kit oAuth Secret is a JSON string of the Google Cloud Platform web application used for Site Kit + * that will be associated with this account. This is meant to be a temporary way to specify the client secret + * until the authentication proxy has been completed. This filter can be specified from a separate theme or plugin. + * + * To retrieve the JSON secret, use the following instructions: + * - Go to the Google Cloud Platform and create a new project or use an existing one + * - In the APIs & Services section, enable the APIs that are used within Site Kit + * - Under 'credentials' either create new oAuth Client ID credentials or use an existing set of credentials + * - Set the authorizes redirect URIs to be the URL to the oAuth callback for Site Kit, eg. https://?oauth2callback=1 (this must be public) + * - Click the 'Download JSON' button to download the JSON file that can be copied and pasted into the filter + */ + $credentials = json_decode( apply_filters( 'googlesitekit_oauth_secret', '' ), true ); + + if ( isset( $credentials['web']['client_id'], $credentials['web']['client_secret'] ) ) { + return $this->parse_defaults( + array( + 'oauth2_client_id' => $credentials['web']['client_id'], + 'oauth2_client_secret' => $credentials['web']['client_secret'], + ) + ); + } + return $this->parse_defaults( $this->encrypted_options->get( self::OPTION ) ); diff --git a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php index a09dc41d9fd..62fad92e6a2 100644 --- a/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php +++ b/tests/phpunit/integration/Core/Authentication/Clients/OAuth_ClientTest.php @@ -232,9 +232,6 @@ public function test_authorize_user() { $_GET['code'] = 'test-code'; $this->fake_authentication(); - $credentials_mock = $this->getMock( 'MockClass', array( 'has' ) ); - $credentials_mock->method( 'has' )->willReturn( true ); - $this->force_set_property( $client, 'credentials', $credentials_mock ); // If all goes smooth, we expect to be redirected to $success_redirect $success_redirect = admin_url( 'success-redirect' ); $client->get_authentication_url( $success_redirect ); From c78f3c8be75507140d1bdad725c0bed95bffe55f Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Mon, 21 Oct 2019 19:36:39 +0300 Subject: [PATCH 097/102] check for credentials option in beta migration --- includes/Core/Util/Beta_Migration.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/includes/Core/Util/Beta_Migration.php b/includes/Core/Util/Beta_Migration.php index bb593b67961..177506a66b0 100644 --- a/includes/Core/Util/Beta_Migration.php +++ b/includes/Core/Util/Beta_Migration.php @@ -111,7 +111,8 @@ function () { public function migrate_old_credentials() { $credentials = $this->credentials->get(); - if ( $credentials['oauth2_client_id'] && ! strpos( $credentials['oauth2_client_id'], '.apps.sitekit.withgoogle.com' ) ) { + // Credentials can be filtered in so we must also check if there is a saved option present. + if ( $this->options->get( Credentials::OPTION ) && $credentials['oauth2_client_id'] && ! strpos( $credentials['oauth2_client_id'], '.apps.sitekit.withgoogle.com' ) ) { $this->options->delete( Credentials::OPTION ); $this->options->set( self::OPTION_IS_PRE_PROXY_INSTALL, 1 ); } From 2fa389b34917495c2b954a89e74399e83ffd6491 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Mon, 21 Oct 2019 18:40:10 +0200 Subject: [PATCH 098/102] Remove unused variable. --- includes/Core/Assets/Assets.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/includes/Core/Assets/Assets.php b/includes/Core/Assets/Assets.php index 512d9a97793..83804aaea6a 100644 --- a/includes/Core/Assets/Assets.php +++ b/includes/Core/Assets/Assets.php @@ -11,7 +11,6 @@ namespace Google\Site_Kit\Core\Assets; use Google\Site_Kit\Context; -use Google\Site_Kit\Core\Authentication\Clients\OAuth_Client; use Google\Site_Kit\Core\Permissions\Permissions; use Google\Site_Kit\Core\Storage\Cache; @@ -444,8 +443,6 @@ private function get_inline_data() { $current_user = wp_get_current_user(); $site_url = $this->context->get_reference_site_url(); - $auth_client = new \Google\Site_Kit\Core\Authentication\Clients\OAuth_Client( $this->context ); - $admin_data = array( 'siteURL' => esc_url_raw( $site_url ), 'siteName' => get_bloginfo( 'name' ), From 1a27660348cf2eaa4ae12bc407ba10ddd3994781 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Mon, 21 Oct 2019 19:41:29 +0300 Subject: [PATCH 099/102] update e2e gcp-credentials plugin with proper filter --- tests/e2e/plugins/gcp-credentials.php | 28 ++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/tests/e2e/plugins/gcp-credentials.php b/tests/e2e/plugins/gcp-credentials.php index ec2ed7c2313..0793a2ace0b 100644 --- a/tests/e2e/plugins/gcp-credentials.php +++ b/tests/e2e/plugins/gcp-credentials.php @@ -12,21 +12,23 @@ * @link https://sitekit.withgoogle.com */ -use Google\Site_Kit\Core\Storage\Data_Encryption; - /** * Provide dummy client configuration, normally provided in step 1 of the set up. - * We need to filter the credentials option here due to `isSiteKitConnected`'s dependence - * on `Credentials` in `\Google\Site_Kit\Core\Authentication\Authentication::inline_js_setup_data` - * which is option-based. */ -add_filter( 'pre_option_googlesitekit_credentials', function () { - return ( new Data_Encryption() )->encrypt( - serialize( +add_filter( + 'googlesitekit_oauth_secret', + function () { + return json_encode( array( - 'oauth2_client_id' => '1234567890-asdfasdfasdfasdfzxcvzxcvzxcvzxcv.apps.googleusercontent.com', - 'oauth2_client_secret' => 'x_xxxxxxxxxxxxxxxxxxxxxx', + 'web' => array( + 'client_id' => '1234567890-asdfasdfasdfasdfzxcvzxcvzxcvzxcv.apps.googleusercontent.com', + 'client_secret' => 'x_xxxxxxxxxxxxxxxxxxxxxx', + 'auth_uri' => 'https://accounts.google.com/o/oauth2/auth', + 'token_uri' => 'https://oauth2.googleapis.com/token', + 'auth_provider_x509_cert_url' => 'https://www.googleapis.com/oauth2/v1/certs', + 'redirect_uris' => array( add_query_arg( 'oauth2callback', '1', home_url() ) ), + ), ) - ) - ); -} ); + ); + } +); From 0522ffb449b8ceab80bb081f02a3cbbb7006c4a5 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Mon, 21 Oct 2019 21:00:32 +0300 Subject: [PATCH 100/102] only json decode if provided by filter --- includes/Core/Authentication/Credentials.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/includes/Core/Authentication/Credentials.php b/includes/Core/Authentication/Credentials.php index 70c79f59c35..250db312127 100644 --- a/includes/Core/Authentication/Credentials.php +++ b/includes/Core/Authentication/Credentials.php @@ -66,7 +66,11 @@ public function get() { * - Set the authorizes redirect URIs to be the URL to the oAuth callback for Site Kit, eg. https://?oauth2callback=1 (this must be public) * - Click the 'Download JSON' button to download the JSON file that can be copied and pasted into the filter */ - $credentials = json_decode( apply_filters( 'googlesitekit_oauth_secret', '' ), true ); + $credentials = apply_filters( 'googlesitekit_oauth_secret', '' ); + + if ( is_string( $credentials ) && trim( $credentials ) ) { + $credentials = json_decode( $credentials, true ); + } if ( isset( $credentials['web']['client_id'], $credentials['web']['client_secret'] ) ) { return $this->parse_defaults( From e3918368956cb0b3c66ae0da31f78f2079288f99 Mon Sep 17 00:00:00 2001 From: Evan Mattson Date: Tue, 22 Oct 2019 09:49:24 +0300 Subject: [PATCH 101/102] update beta migration to only check option No need to include Credentials anymore and Encrypted_Options is only needed in a single method. --- includes/Core/Util/Beta_Migration.php | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/includes/Core/Util/Beta_Migration.php b/includes/Core/Util/Beta_Migration.php index 177506a66b0..b93f05af49e 100644 --- a/includes/Core/Util/Beta_Migration.php +++ b/includes/Core/Util/Beta_Migration.php @@ -15,6 +15,7 @@ use Google\Site_Kit\Core\Authentication\Clients\OAuth_Client; use Google\Site_Kit\Core\Authentication\Credentials; use Google\Site_Kit\Core\Permissions\Permissions; +use Google\Site_Kit\Core\Storage\Encrypted_Options; use Google\Site_Kit\Core\Storage\Options; /** @@ -40,13 +41,6 @@ class Beta_Migration { */ protected $options; - /** - * Credentials instance. - * - * @var Credentials - */ - protected $credentials; - /** * OAuth Client instance. * @@ -61,7 +55,6 @@ class Beta_Migration { */ public function __construct( Context $context ) { $this->options = new Options( $context ); - $this->credentials = new Credentials( $this->options ); $this->oauth_client = new OAuth_Client( $context ); } @@ -109,10 +102,10 @@ function () { * so they should never be present in the option / Credentials anymore. */ public function migrate_old_credentials() { - $credentials = $this->credentials->get(); + $credentials = ( new Encrypted_Options( $this->options ) )->get( Credentials::OPTION ); // Credentials can be filtered in so we must also check if there is a saved option present. - if ( $this->options->get( Credentials::OPTION ) && $credentials['oauth2_client_id'] && ! strpos( $credentials['oauth2_client_id'], '.apps.sitekit.withgoogle.com' ) ) { + if ( isset( $credentials['oauth2_client_id'] ) && ! strpos( $credentials['oauth2_client_id'], '.apps.sitekit.withgoogle.com' ) ) { $this->options->delete( Credentials::OPTION ); $this->options->set( self::OPTION_IS_PRE_PROXY_INSTALL, 1 ); } From f482fcfb1ef699a5639252563bba9367494fca60 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Tue, 22 Oct 2019 10:54:46 +0200 Subject: [PATCH 102/102] Clarify method return value and doc-block for getting client credentials: --- .../Authentication/Clients/OAuth_Client.php | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/includes/Core/Authentication/Clients/OAuth_Client.php b/includes/Core/Authentication/Clients/OAuth_Client.php index df7b3d7aaab..5f138826208 100644 --- a/includes/Core/Authentication/Clients/OAuth_Client.php +++ b/includes/Core/Authentication/Clients/OAuth_Client.php @@ -769,28 +769,34 @@ private function get_redirect_uri() { } /** - * Retrieve the Site Kit oAuth secret. + * Retrieves the OAuth credentials object. + * + * @since 1.0.0 + * + * @return object|null Credentials object with `web` property, or null if no credentials available. */ private function get_client_credentials() { if ( false !== $this->client_credentials ) { return $this->client_credentials; } - if ( $this->credentials->has() ) { - $credentials = $this->credentials->get(); - - $this->client_credentials = (object) array( - 'web' => (object) array( - 'client_id' => $credentials['oauth2_client_id'], - 'client_secret' => $credentials['oauth2_client_secret'], - 'auth_uri' => 'https://accounts.google.com/o/oauth2/auth', - 'token_uri' => 'https://oauth2.googleapis.com/token', - 'auth_provider_x509_cert_url' => 'https://www.googleapis.com/oauth2/v1/certs', - 'redirect_uris' => array( $this->get_redirect_uri() ), - ), - ); + if ( ! $this->credentials->has() ) { + return null; } + $credentials = $this->credentials->get(); + + $this->client_credentials = (object) array( + 'web' => (object) array( + 'client_id' => $credentials['oauth2_client_id'], + 'client_secret' => $credentials['oauth2_client_secret'], + 'auth_uri' => 'https://accounts.google.com/o/oauth2/auth', + 'token_uri' => 'https://oauth2.googleapis.com/token', + 'auth_provider_x509_cert_url' => 'https://www.googleapis.com/oauth2/v1/certs', + 'redirect_uris' => array( $this->get_redirect_uri() ), + ), + ); + return $this->client_credentials; } }