From f1c6ccbc92e07d809363272448133d7efd22fe23 Mon Sep 17 00:00:00 2001 From: Emanuele Buccelli Date: Wed, 28 Feb 2024 02:38:33 +0100 Subject: [PATCH] User Management: Tracking events (#35773) Co-authored-by: Anthony Grullon Co-authored-by: Kosta Co-authored-by: heavyweight --- .../changelog/update-user-management-tracking | 4 + .../sso/class.jetpack-sso-user-admin.php | 236 ++++++++++++++---- 2 files changed, 195 insertions(+), 45 deletions(-) create mode 100644 projects/plugins/jetpack/changelog/update-user-management-tracking diff --git a/projects/plugins/jetpack/changelog/update-user-management-tracking b/projects/plugins/jetpack/changelog/update-user-management-tracking new file mode 100644 index 0000000000000..b9cb7ebbfb9c3 --- /dev/null +++ b/projects/plugins/jetpack/changelog/update-user-management-tracking @@ -0,0 +1,4 @@ +Significance: minor +Type: other + +Adding tracking for user management events diff --git a/projects/plugins/jetpack/modules/sso/class.jetpack-sso-user-admin.php b/projects/plugins/jetpack/modules/sso/class.jetpack-sso-user-admin.php index d5bcd954cd478..f19d991409dfe 100644 --- a/projects/plugins/jetpack/modules/sso/class.jetpack-sso-user-admin.php +++ b/projects/plugins/jetpack/modules/sso/class.jetpack-sso-user-admin.php @@ -1,6 +1,7 @@ record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => 'invalid-revoke-api-error', + ) + ); + return $response; + } + + $body = json_decode( $response['body'] ); + + if ( ! $body->deleted ) { + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => 'invalid-invite-revoke', + ) + ); + } else { + self::$tracking->record_user_event( $event, array( 'success' => 'true' ) ); + } + + return $response; } } catch ( Exception $e ) { return false; @@ -115,6 +154,8 @@ public function handle_invitation_results() { return wp_admin_notice( __( 'Attempted to send a new invitation to a user using an invite that doesn’t exist.', 'jetpack' ), array( 'type' => 'error' ) ); case 'error-revoke': return wp_admin_notice( __( 'An error has occurred when revoking the invite for the user.', 'jetpack' ), array( 'type' => 'error' ) ); + case 'invalid-revoke-api-error': + return wp_admin_notice( __( 'An error has occurred when revoking the user invite.', 'jetpack' ), array( 'type' => 'error' ) ); default: return wp_admin_notice( __( 'An error has occurred when inviting the user to the site.', 'jetpack' ), array( 'type' => 'error' ) ); } @@ -127,11 +168,13 @@ public function handle_invitation_results() { public function invite_user_to_wpcom() { check_admin_referer( 'jetpack-sso-invite-user', 'invite_nonce' ); $nonce = wp_create_nonce( 'jetpack-sso-invite-user' ); + $event = 'sso_user_invite_sent'; if ( ! current_user_can( 'create_users' ) ) { + $error = 'invalid-user-permissions'; $query_params = array( 'jetpack-sso-invite-user' => 'failed', - 'jetpack-sso-invite-error' => 'invalid-user-permissions', + 'jetpack-sso-invite-error' => $error, '_wpnonce' => $nonce, ); return self::create_error_notice_and_redirect( $query_params ); @@ -148,6 +191,13 @@ public function invite_user_to_wpcom() { '_wpnonce' => $nonce, ); + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => $reason, + ) + ); return self::create_error_notice_and_redirect( $query_params ); } @@ -173,14 +223,21 @@ public function invite_user_to_wpcom() { 'wpcom' ); - $status_code = wp_remote_retrieve_response_code( $response ); - - if ( is_wp_error( $response ) || 200 !== $status_code ) { + if ( 200 !== wp_remote_retrieve_response_code( $response ) ) { + $error = 'invalid-invite-api-error'; $query_params = array( 'jetpack-sso-invite-user' => 'failed', - 'jetpack-sso-invite-error' => 'invalid_request', + 'jetpack-sso-invite-error' => $error, '_wpnonce' => $nonce, ); + + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => $error, + ) + ); return self::create_error_notice_and_redirect( $query_params ); } @@ -195,15 +252,32 @@ public function invite_user_to_wpcom() { if ( ! $body->success && $body->errors ) { $response_error = array_keys( (array) $body->errors ); $query_params['jetpack-sso-invite-error'] = $response_error[0]; + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => $response_error[0], + ) + ); + } else { + self::$tracking->record_user_event( $event, array( 'success' => 'true' ) ); } return self::create_error_notice_and_redirect( $query_params ); } else { + $error = 'invalid-user'; $query_params = array( 'jetpack-sso-invite-user' => 'failed', - 'jetpack-sso-invite-error' => 'invalid-user', + 'jetpack-sso-invite-error' => $error, '_wpnonce' => $nonce, ); + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => $error, + ) + ); return self::create_error_notice_and_redirect( $query_params ); } wp_die(); @@ -214,11 +288,11 @@ public function invite_user_to_wpcom() { * * @param string $invite_id The ID of the invite to revoke. */ - public function revoke_wpcom_invite( $invite_id ) { + public function send_revoke_wpcom_invite( $invite_id ) { $blog_id = Jetpack_Options::get_option( 'id' ); - $url = '/sites/' . $blog_id . '/invites/delete'; - $response = Client::wpcom_json_api_request_as_user( + $url = '/sites/' . $blog_id . '/invites/delete'; + return Client::wpcom_json_api_request_as_user( $url, 'v2', array( @@ -229,16 +303,6 @@ public function revoke_wpcom_invite( $invite_id ) { ), 'wpcom' ); - - $status_code = wp_remote_retrieve_response_code( $response ); - if ( is_wp_error( $response ) || 200 !== $status_code ) { - return $response; - } - - return array( - 'body' => json_decode( $response['body'] ), - 'status_code' => json_decode( $status_code ), - ); } /** @@ -247,11 +311,12 @@ public function revoke_wpcom_invite( $invite_id ) { public function handle_request_revoke_invite() { check_admin_referer( 'jetpack-sso-revoke-user-invite', 'revoke_invite_nonce' ); $nonce = wp_create_nonce( 'jetpack-sso-invite-user' ); - + $event = 'sso_user_invite_revoked'; if ( ! current_user_can( 'promote_users' ) ) { + $error = 'invalid-revoke-permissions'; $query_params = array( 'jetpack-sso-invite-user' => 'failed', - 'jetpack-sso-invite-error' => 'invalid-revoke-permissions', + 'jetpack-sso-invite-error' => $error, '_wpnonce' => $nonce, ); @@ -259,58 +324,97 @@ public function handle_request_revoke_invite() { } elseif ( isset( $_GET['user_id'] ) ) { $user_id = intval( wp_unslash( $_GET['user_id'] ) ); $user = get_user_by( 'id', $user_id ); - if ( ! $user ) { - + $error = 'invalid-user-revoke'; $query_params = array( 'jetpack-sso-invite-user' => 'failed', - 'jetpack-sso-invite-error' => 'invalid-user-revoke', + 'jetpack-sso-invite-error' => $error, '_wpnonce' => $nonce, ); + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => $error, + ) + ); return self::create_error_notice_and_redirect( $query_params ); } if ( ! isset( $_GET['invite_id'] ) ) { + $error = 'invalid-invite-revoke'; $query_params = array( 'jetpack-sso-invite-user' => 'failed', - 'jetpack-sso-invite-error' => 'invalid-invite-revoke', + 'jetpack-sso-invite-error' => $error, '_wpnonce' => $nonce, ); + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => $error, + ) + ); return self::create_error_notice_and_redirect( $query_params ); } $invite_id = sanitize_text_field( wp_unslash( $_GET['invite_id'] ) ); - $response = self::revoke_wpcom_invite( $invite_id ); - - $status_code = wp_remote_retrieve_response_code( $response ); + $response = self::send_revoke_wpcom_invite( $invite_id ); - if ( is_wp_error( $response ) || 200 !== $status_code ) { + if ( 200 !== wp_remote_retrieve_response_code( $response ) ) { + $error = 'invalid-revoke-api-error'; $query_params = array( 'jetpack-sso-invite-user' => 'failed', - 'jetpack-sso-invite-error' => 'error-revoke', + 'jetpack-sso-invite-error' => $error, // general error message '_wpnonce' => $nonce, ); + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => $error, + ) + ); return self::create_error_notice_and_redirect( $query_params ); } - $body = $response['body']; + $body = json_decode( $response['body'] ); $query_params = array( 'jetpack-sso-invite-user' => $body->deleted ? 'successful-revoke' : 'failed', '_wpnonce' => $nonce, ); if ( ! $body->deleted ) { // no invite was deleted, probably it does not exist - $query_params['jetpack-sso-invite-error'] = 'invalid-invite-revoke'; + $error = 'invalid-invite-revoke'; + $query_params['jetpack-sso-invite-error'] = $error; + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => $error, + ) + ); + } else { + self::$tracking->record_user_event( $event, array( 'success' => 'true' ) ); } return self::create_error_notice_and_redirect( $query_params ); } else { + $error = 'invalid-user-revoke'; $query_params = array( 'jetpack-sso-invite-user' => 'failed', - 'jetpack-sso-invite-error' => 'invalid-user-revoke', + 'jetpack-sso-invite-error' => $error, '_wpnonce' => $nonce, ); + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => $error, + ) + ); return self::create_error_notice_and_redirect( $query_params ); } + wp_die(); } @@ -320,7 +424,7 @@ public function handle_request_revoke_invite() { public function handle_request_resend_invite() { check_admin_referer( 'jetpack-sso-resend-user-invite', 'resend_invite_nonce' ); $nonce = wp_create_nonce( 'jetpack-sso-invite-user' ); - + $event = 'sso_user_invite_resend'; if ( ! current_user_can( 'create_users' ) ) { $query_params = array( 'jetpack-sso-invite-user' => 'failed', @@ -346,29 +450,57 @@ public function handle_request_resend_invite() { $status_code = wp_remote_retrieve_response_code( $response ); - if ( is_wp_error( $response ) || 200 !== $status_code ) { + if ( 200 !== $status_code ) { $message_type = $status_code === 404 ? 'invalid-invite' : ''; // empty is the general error message $query_params = array( 'jetpack-sso-invite-user' => 'failed', 'jetpack-sso-invite-error' => $message_type, '_wpnonce' => $nonce, ); + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => $message_type, + ) + ); return self::create_error_notice_and_redirect( $query_params ); } - $body = json_decode( $response['body'] ); - $query_params = array( - 'jetpack-sso-invite-user' => $body->success ? 'reinvited-success' : 'failed', + $body = json_decode( $response['body'] ); + $invite_response_message = $body->success ? 'reinvited-success' : 'failed'; + $query_params = array( + 'jetpack-sso-invite-user' => $invite_response_message, '_wpnonce' => $nonce, ); + if ( ! $body->success ) { + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => $invite_response_message, + ) + ); + } else { + self::$tracking->record_user_event( $event, array( 'success' => 'true' ) ); + } + return self::create_error_notice_and_redirect( $query_params ); } else { + $error = 'empty-invite'; $query_params = array( 'jetpack-sso-invite-user' => 'failed', 'jetpack-sso-invite-error' => 'empty-invite', '_wpnonce' => $nonce, ); + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + 'error_message' => $error, + ) + ); return self::create_error_notice_and_redirect( $query_params ); } } @@ -624,9 +756,25 @@ public function send_wpcom_mail_user_invite( $errors, $update, $user ) { ) ); - $status_code = wp_remote_retrieve_response_code( $response ); - if ( is_wp_error( $response ) || 200 !== $status_code ) { + $event = 'sso_new_user_invite_sent'; + $custom_message_sent = isset( $new_user_request['message'] ) ? 'true' : 'false'; + + if ( 200 !== wp_remote_retrieve_response_code( $response ) ) { $errors->add( 'invitation_not_sent', __( 'Error: The user invitation email could not be sent, the user account was not created.', 'jetpack' ) ); + self::$tracking->record_user_event( + $event, + array( + 'success' => 'false', + ) + ); + } else { + self::$tracking->record_user_event( + $event, + array( + 'success' => 'true', + 'custom_message_sent' => $custom_message_sent, + ) + ); } } @@ -694,7 +842,7 @@ function ( $current, $item ) { 'wpcom' ); - if ( ! is_wp_error( $response ) && 200 === $response['response']['code'] ) { + if ( 200 === wp_remote_retrieve_response_code( $response ) ) { $body = json_decode( $response['body'], true ); self::$cached_invites = array_merge( self::$cached_invites, $body ); } @@ -758,9 +906,7 @@ private static function has_pending_wpcom_invite( $user_id ) { 'wpcom' ); - $status_code = wp_remote_retrieve_response_code( $response ); - - if ( is_wp_error( $response ) || 200 !== $status_code ) { + if ( 200 !== wp_remote_retrieve_response_code( $response ) ) { return false; }