Passed
Push — master ( 8403c0...3ede7f )
by Chris
08:42
created

MonsterInsights_API_Auth::rauthenticate()   B

Complexity

Conditions 8
Paths 24

Size

Total Lines 31
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 8
eloc 16
c 2
b 0
f 0
nc 24
nop 0
dl 0
loc 31
rs 8.4444
1
<?php
2
/**
3
 * Google Client admin class.
4
 *
5
 * Handles retrieving whether a particular notice has been dismissed or not,
6
 * as well as marking a notice as dismissed.
7
 *
8
 * @since 7.0.0
9
 *
10
 * @package MonsterInsights
11
 * @subpackage GA Client
12
 * @author  Chris Christoff
13
 */
14
15
// Exit if accessed directly
16
if ( ! defined( 'ABSPATH' ) ) {
17
	exit;
18
}
19
20
final class MonsterInsights_API_Auth {
21
22
	/**
23
	 * Primary class constructor.
24
	 *
25
	 * @access public
26
	 * @since 7.0.0
27
	 */
28
	public function __construct() {
29
30
		// Authentication Actions
31
		add_action( 'wp_ajax_monsterinsights_maybe_authenticate',    array( $this, 'maybe_authenticate' ) );
32
		add_action( 'wp_ajax_monsterinsights_maybe_reauthenticate',  array( $this, 'maybe_reauthenticate' ) );
33
		add_action( 'wp_ajax_monsterinsights_maybe_verify',          array( $this, 'maybe_verify' ) );
34
		add_action( 'wp_ajax_monsterinsights_maybe_delete',          array( $this, 'maybe_delete' ) );
35
36
		add_action( 'admin_init',          							 array( $this, 'authenticate_listener' ) );
37
		add_action( 'admin_init',          							 array( $this, 'reauthenticate_listener' ) );
38
39
		add_action( 'wp_ajax_nopriv_monsterinsights_is_installed',    array( $this, 'is_installed' ) );
40
		add_action( 'wp_ajax_nopriv_monsterinsights_rauthenticate',   array( $this, 'rauthenticate' ) );
41
42
		add_filter( 'monsterinsights_maybe_authenticate_siteurl', array( $this, 'before_redirect' ) );
43
44
		add_action( 'wp_ajax_nopriv_monsterinsights_push_mp_token', array( $this, 'handle_relay_mp_token_push' ) );
45
	}
46
47
	public function get_tt(){
48
		$tt = is_network_admin() ? get_site_option( 'monsterinsights_network_tt', '' ) : get_option( 'monsterinsights_site_tt', '' );
49
		if ( empty( $tt ) ) {
50
			// if TT is empty, generate a new one, save it and then return it
51
			$tt = $this->generate_tt();
52
			$this->is_network_admin() ? update_site_option( 'monsterinsights_network_tt', $tt ) : update_option( 'monsterinsights_site_tt', $tt );
53
		}
54
		return $tt;
55
	}
56
57
	public function rotate_tt(){
58
		$tt = $this->generate_tt();
59
		is_network_admin() ? update_site_option( 'monsterinsights_network_tt', $tt ) : update_option( 'monsterinsights_site_tt', $tt );
60
	}
61
62
	public function generate_tt(){
63
		return hash( 'sha512', wp_generate_password( 128, true, true ) . AUTH_SALT . uniqid( "", true ) );
64
	}
65
66
	public function validate_tt( $passed_tt = '' ) {
67
		$tt = $this->get_tt();
68
		return hash_equals( $tt, $passed_tt );
69
	}
70
71
	public function is_installed() {
72
		wp_send_json_success(
73
			array(
74
				'version'   => MONSTERINSIGHTS_VERSION,
75
				'pro'   	=> monsterinsights_is_pro_version(),
76
			)
77
		);
78
	}
79
80
	public function maybe_authenticate(){
81
82
		// Check nonce
83
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
84
85
		// current user can authenticate
86
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
87
			wp_send_json_error( array(	'message' => __( "You don't have permission to authenticate MonsterInsights.", 'google-analytics-for-wordpress' ) ) );
88
		}
89
90
		if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
91
			define( 'WP_NETWORK_ADMIN', true );
92
		}
93
94
		// Only for Pro users, require a license key to be entered first so we can link to things.
95
		if ( monsterinsights_is_pro_version() ) {
96
			$valid = is_network_admin() ? MonsterInsights()->license->is_network_licensed() : MonsterInsights()->license->is_site_licensed();
97
			if ( ! $valid ) {
98
				wp_send_json_error( array( 'message' => __( "Cannot authenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings.", 'google-analytics-for-wordpress' ) ) );
99
			}
100
		}
101
102
		// we do not have a current auth
103
		if ( ! $this->is_network_admin() && MonsterInsights()->auth->is_authed() ) {
104
			wp_send_json_error( array(	'message' => __( "Cannot authenticate. Please re-authenticate.", 'google-analytics-for-wordpress' ) ) );
105
		} else if ( $this->is_network_admin() && MonsterInsights()->auth->is_network_authed() ) {
106
			wp_send_json_error( array(	'message' => __( "Cannot network authenticate. Please re-authenticate on the network settings panel.", 'google-analytics-for-wordpress' ) ) );
107
		}
108
109
		$sitei = $this->get_sitei();
110
		//update_network_option(  get_current_network_id(), 'monsterinsights_network_sitei', $sitei );
111
112
		$siteurl = add_query_arg( array(
113
			'tt'        => $this->get_tt(),
114
			'sitei'     => $sitei,
115
			'miversion' => MONSTERINSIGHTS_VERSION,
116
			'ajaxurl'   => admin_url( 'admin-ajax.php' ),
117
			'network'   => is_network_admin() ? 'network' : 'site',
118
			'siteurl'   => is_network_admin() ? network_admin_url() : site_url(),
119
			'return'    => is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' ),
120
			'testurl'   => 'https://' . monsterinsights_get_api_url() . 'test/',
121
		 ), $this->get_route( 'https://' . monsterinsights_get_api_url() . 'auth/new/{type}' ) );
122
123
		if ( monsterinsights_is_pro_version() ) {
124
			$key     = is_network_admin() ? MonsterInsights()->license->get_network_license_key() : MonsterInsights()->license->get_site_license_key();
125
			$siteurl = add_query_arg( 'license', $key, $siteurl );
126
		}
127
128
		$siteurl = apply_filters( 'monsterinsights_maybe_authenticate_siteurl', $siteurl );
129
		wp_send_json_success( array( 'redirect' => $siteurl ) );
130
	}
131
132
	private function send_missing_args_error( $arg ) {
133
		wp_send_json_error(
134
			array(
135
				'error'   => 'authenticate_missing_arg',
136
				'message' => 'Authenticate missing parameter: ' . $arg,
137
				'version'   => MONSTERINSIGHTS_VERSION,
138
				'pro'   	=> monsterinsights_is_pro_version(),
139
			)
140
		);
141
	}
142
143
	public function rauthenticate() {
144
		// Check for missing params
145
		$reqd_args = array( 'key', 'token', 'miview', 'a', 'w', 'p', 'tt', 'network' );
146
147
		if ( empty( $_REQUEST['ua'] ) && empty( $_REQUEST['v4'] ) ) {
148
			$this->send_missing_args_error( 'ua/v4' );
149
		}
150
151
		foreach ( $reqd_args as $arg ) {
152
			if ( empty( $_REQUEST[$arg] ) ) {
153
				$this->send_missing_args_error( $arg );
154
			}
155
		}
156
157
		if ( ! empty( $_REQUEST['network'] ) && 'network' === $_REQUEST['network'] ) {
158
			define( 'WP_NETWORK_ADMIN', true );
159
		}
160
161
		if ( ! $this->validate_tt( $_REQUEST['tt'] ) ) {
162
			wp_send_json_error(
163
				array(
164
					'error'   => 'authenticate_invalid_tt',
165
					'message' => 'Invalid TT sent',
166
					'version'   => MONSTERINSIGHTS_VERSION,
167
					'pro'   	=> monsterinsights_is_pro_version(),
168
				)
169
			);
170
		}
171
172
		// If the tt is validated, send a success response to trigger the regular auth process.
173
		wp_send_json_success();
174
	}
175
176
	public function authenticate_listener(){
177
		// Make sure it's for us
178
		if ( empty( $_REQUEST['mi-oauth-action'] ) || $_REQUEST['mi-oauth-action'] !== 'auth' ) {
179
			return;
180
		}
181
182
		// User can authenticate
183
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
184
			return;
185
		}
186
187
		// Invalid request
188
		if ( empty( $_REQUEST['tt'] ) || ! $this->validate_tt( $_REQUEST['tt'] ) ) {
189
			return;
190
		}
191
192
		// Make sure has required params
193
		if (
194
			empty( $_REQUEST['key'] )    ||
195
			empty( $_REQUEST['token'] )  ||
196
			empty( $_REQUEST['miview'] ) ||
197
			empty( $_REQUEST['a'] )      ||
198
			empty( $_REQUEST['w'] )      ||
199
			empty( $_REQUEST['p'] )      ||
200
			( empty( $_REQUEST['ua'] ) && empty( $_REQUEST['v4'] ) )
201
		) {
202
			return;
203
		}
204
205
		if ( ! empty( $_REQUEST['ua'] ) ) {
206
			$code_key = 'ua';
207
			$code_value = monsterinsights_is_valid_ua( $_REQUEST['ua'] );
208
		} else if ( ! empty( $_REQUEST['v4'] ) ) {
209
			$code_key = 'v4';
210
			$code_value = monsterinsights_is_valid_v4_id( $_REQUEST['v4'] );
211
		}
212
213
		if ( empty( $code_value ) ) {
214
			return;
215
		}
216
217
		$profile = array(
218
			'key'           => sanitize_text_field( $_REQUEST['key'] ),
219
			'token'         => sanitize_text_field( $_REQUEST['token'] ),
220
			'viewname'      => sanitize_text_field( $_REQUEST['miview'] ),
221
			'a'             => sanitize_text_field( $_REQUEST['a'] ), // AccountID
222
			'w'             => sanitize_text_field( $_REQUEST['w'] ), // PropertyID
223
			'p'             => sanitize_text_field( $_REQUEST['p'] ), // View ID
224
			'siteurl'       => site_url(),
225
			'neturl'        => network_admin_url(),
226
			'connectedtype' => $code_key,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $code_key does not seem to be defined for all execution paths leading up to this point.
Loading history...
227
		);
228
229
		if ( ! empty( $_REQUEST['mp'] ) ) {
230
			$profile['measurement_protocol_secret'] = sanitize_text_field( $_REQUEST['mp'] );
231
		}
232
233
		$profile[ $code_key ] = $code_value;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $code_value does not seem to be defined for all execution paths leading up to this point.
Loading history...
234
235
		$worked = $this->verify_auth( $profile );
236
		if ( ! $worked || is_wp_error( $worked ) ) {
237
			return;
238
		}
239
240
		// Save Profile
241
		$this->is_network_admin() ? MonsterInsights()->auth->set_network_analytics_profile( $profile ) : MonsterInsights()->auth->set_analytics_profile( $profile );
0 ignored issues
show
Bug Best Practice introduced by
The property $auth is declared protected in MonsterInsights_Lite. Since you implement __get, consider adding a @property or @property-read.
Loading history...
242
243
		// Clear cache
244
		$where = $this->is_network_admin() ? 'network' : 'site';
245
		MonsterInsights()->reporting->delete_aggregate_data( $where );
246
247
		$url = $this->is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' )  : admin_url( 'admin.php?page=monsterinsights_settings' ) ;
248
		$url = add_query_arg( array(
249
			 'mi_action' => 'auth',
250
			 'success'   => 'true',
251
			), $url );
252
		$url = apply_filters( 'monsterinsights_auth_success_redirect_url', $url );
253
		wp_safe_redirect( $url );
254
		exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
255
	}
256
257
	public function maybe_reauthenticate(){
258
259
		// Check nonce
260
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
261
262
		// current user can authenticate
263
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
264
			wp_send_json_error( array(	'message' => __( "You don't have permission to re-authenticate MonsterInsights.", 'google-analytics-for-wordpress' ) ) );
265
		}
266
267
		if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
268
			define( 'WP_NETWORK_ADMIN', true );
269
		}
270
271
		// Only for Pro users, require a license key to be entered first so we can link to things.
272
		if ( monsterinsights_is_pro_version() ) {
273
			$valid = is_network_admin() ? MonsterInsights()->license->is_network_licensed() : MonsterInsights()->license->is_site_licensed();
274
			if ( monsterinsights_is_pro_version() && ! $valid ) {
275
				wp_send_json_error( array( 'message' => __( "Cannot re-authenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings.", 'google-analytics-for-wordpress' ) ) );
276
			}
277
		}
278
279
		// we do have a current auth
280
		if ( ! $this->is_network_admin() && ! MonsterInsights()->auth->is_authed() ) {
281
			wp_send_json_error( array(	'message' => __( "Cannot re-authenticate. Please authenticate.", 'google-analytics-for-wordpress' ) ) );
282
		} else if ( $this->is_network_admin() && ! MonsterInsights()->auth->is_network_authed() ) {
283
			wp_send_json_error( array(	'message' => __( "Cannot re-authenticate the network. Please authenticate on the network settings panel.", 'google-analytics-for-wordpress' ) ) );
284
		}
285
286
		$siteurl = add_query_arg( array(
287
			'tt'        => $this->get_tt(),
288
			'sitei'     => $this->get_sitei(),
289
			'miversion' => MONSTERINSIGHTS_VERSION,
290
			'ajaxurl'   => admin_url( 'admin-ajax.php' ),
291
			'network'   => is_network_admin() ? 'network' : 'site',
292
			'siteurl'   => is_network_admin() ? network_admin_url() : site_url(),
293
			'key'       => is_network_admin() ? MonsterInsights()->auth->get_network_key() : MonsterInsights()->auth->get_key(),
294
			'token'     => is_network_admin() ? MonsterInsights()->auth->get_network_token() : MonsterInsights()->auth->get_token(),
295
			'return'    => is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' ),
296
			'testurl'   => 'https://' . monsterinsights_get_api_url() . 'test/',
297
		 ), $this->get_route( 'https://' . monsterinsights_get_api_url() . 'auth/reauth/{type}' ) );
298
299
		if ( monsterinsights_is_pro_version() ) {
300
			$key     = is_network_admin() ? MonsterInsights()->license->get_network_license_key() : MonsterInsights()->license->get_site_license_key();
301
			$siteurl = add_query_arg( 'license', $key, $siteurl );
302
		}
303
304
		$siteurl = apply_filters( 'monsterinsights_maybe_authenticate_siteurl', $siteurl );
305
306
		wp_send_json_success( array( 'redirect' => $siteurl ) );
307
	}
308
309
	public function reauthenticate_listener(){
310
		// Make sure it's for us
311
		if ( empty( $_REQUEST['mi-oauth-action'] ) || $_REQUEST['mi-oauth-action'] !== 'reauth' ) {
312
			return;
313
		}
314
315
		// User can authenticate
316
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
317
			return;
318
		}
319
320
		// Invalid request
321
		if ( empty( $_REQUEST['tt'] ) || ! $this->validate_tt( $_REQUEST['tt'] ) ) {
322
			return;
323
		}
324
325
		// Make sure has required params
326
		if (
327
			( empty( $_REQUEST['ua'] ) && empty( $_REQUEST['v4'] ) ) ||
328
			empty( $_REQUEST['miview'] ) ||
329
			empty( $_REQUEST['a'] ) ||
330
			empty( $_REQUEST['w'] ) ||
331
			empty( $_REQUEST['p'] )
332
		) {
333
			return;
334
		}
335
336
		if ( ! empty( $_REQUEST['ua'] ) ) {
337
			$code_key = 'ua';
338
			$code_value = monsterinsights_is_valid_ua( $_REQUEST['ua'] );
339
		} else if ( ! empty( $_REQUEST['v4'] ) ) {
340
			$code_key = 'v4';
341
			$code_value = monsterinsights_is_valid_v4_id( $_REQUEST['v4'] );
342
		}
343
344
		if ( empty( $code_value ) ) {
345
			return;
346
		}
347
348
		// we do have a current auth
349
		$existing = $this->is_network_admin() ? MonsterInsights()->auth->get_network_analytics_profile() : MonsterInsights()->auth->get_analytics_profile();
0 ignored issues
show
Bug Best Practice introduced by
The property $auth is declared protected in MonsterInsights_Lite. Since you implement __get, consider adding a @property or @property-read.
Loading history...
350
		if ( empty( $existing['key'] ) || empty( $existing['token'] ) ) {
351
			return;
352
		}
353
354
		$profile = array(
355
			'key'      => $existing['key'],
356
			'token'    => $existing['token'],
357
			'viewname' => sanitize_text_field( $_REQUEST['miview'] ),
358
			'a'        => sanitize_text_field( $_REQUEST['a'] ),
359
			'w'        => sanitize_text_field( $_REQUEST['w'] ),
360
			'p'        => sanitize_text_field( $_REQUEST['p'] ),
361
			'ua'       => $existing['ua'],
362
			'v4'       => $existing['v4'],
363
			'siteurl'  => site_url(),
364
			'neturl'   => network_admin_url(),
365
			'connectedtype' => $code_key,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $code_key does not seem to be defined for all execution paths leading up to this point.
Loading history...
366
		);
367
368
		if ( ! empty( $_REQUEST['mp'] ) ) {
369
			$profile['measurement_protocol_secret'] = sanitize_text_field( $_REQUEST['mp'] );
370
		}
371
372
		$profile[ $code_key ] = $code_value;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $code_value does not seem to be defined for all execution paths leading up to this point.
Loading history...
373
374
		// Save Profile
375
		$this->is_network_admin() ? MonsterInsights()->auth->set_network_analytics_profile( $profile ) : MonsterInsights()->auth->set_analytics_profile( $profile );
376
377
		// Clear cache
378
		$where = $this->is_network_admin() ? 'network' : 'site';
379
		MonsterInsights()->reporting->delete_aggregate_data( $where );
380
381
		$url = $this->is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' )  : admin_url( 'admin.php?page=monsterinsights_settings' ) ;
382
		$url = add_query_arg( array(
383
			 'mi_action' => 'reauth',
384
			 'success'   => 'true',
385
			), $url );
386
		$url = apply_filters( 'monsterinsights_reauth_success_redirect_url', $url );
387
388
		wp_safe_redirect( $url );
389
		exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
390
	}
391
392
	public function maybe_verify(){
393
394
		// Check nonce
395
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
396
397
		// current user can verify
398
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
399
			wp_send_json_error( array(	'message' => __( "You don't have permission to verify MonsterInsights.", 'google-analytics-for-wordpress' ) ) );
400
		}
401
402
		if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
403
			define( 'WP_NETWORK_ADMIN', true );
404
		}
405
406
		// we have an auth to verify
407
		if ( $this->is_network_admin() && ! MonsterInsights()->auth->is_network_authed() ) {
408
			wp_send_json_error( array(	'message' => __( "Cannot verify. Please authenticate.", 'google-analytics-for-wordpress' ) ) );
409
		} else if ( ! $this->is_network_admin() && ! MonsterInsights()->auth->is_authed() ) {
410
			wp_send_json_error( array(	'message' => __( "Cannot verify. Please authenticate.", 'google-analytics-for-wordpress' ) ) );
411
		}
412
413
		if ( monsterinsights_is_pro_version() ) {
414
			$valid = is_network_admin() ? MonsterInsights()->license->is_network_licensed() : MonsterInsights()->license->is_site_licensed();
415
			if ( ! $valid ) {
416
				wp_send_json_error( array( 'message' => __( "Cannot verify. Please enter a valid, active license key for MonsterInsights Pro into the settings.", 'google-analytics-for-wordpress' ) ) );
417
			}
418
		}
419
420
		$worked = $this->verify_auth();
421
		if ( $worked && ! is_wp_error(  $worked ) ) {
422
			wp_send_json_success( array( 'message' => __( "Successfully verified.", 'google-analytics-for-wordpress' ) ) );
423
		} else {
424
			wp_send_json_error( array( 'message' => __( "Could not verify.", 'google-analytics-for-wordpress' ) ) );
425
		}
426
	}
427
428
	public function verify_auth( $credentials = array() ){
429
		$creds = ! empty( $credentials ) ? $credentials : ( $this->is_network_admin() ? MonsterInsights()->auth->get_network_analytics_profile( true ) : MonsterInsights()->auth->get_analytics_profile( true ) );
0 ignored issues
show
Bug Best Practice introduced by
The property $auth is declared protected in MonsterInsights_Lite. Since you implement __get, consider adding a @property or @property-read.
Loading history...
430
431
		if ( empty( $creds['key'] ) ) {
432
			return new WP_Error( 'validation-error', sprintf( __( 'Verify auth key not passed', 'google-analytics-for-wordpress' ) ) );
433
		}
434
435
		$network = ! empty( $_REQUEST['network'] ) ? $_REQUEST['network'] === 'network' : $this->is_network_admin();
436
		$api   = new MonsterInsights_API_Request( $this->get_route( 'auth/verify/{type}/' ), array( 'network' => $network, 'tt' => $this->get_tt(), 'key' => $creds['key'], 'token' => $creds['token'], 'testurl'   => 'https://' . monsterinsights_get_api_url() . 'test/' ) );
437
		$ret   = $api->request();
438
439
		$this->rotate_tt();
440
		if ( is_wp_error( $ret ) ) {
441
			return $ret;
442
		} else {
443
			return true;
444
		}
445
	}
446
447
	public function maybe_delete(){
448
449
		// Check nonce
450
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
451
452
		// current user can delete
453
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
454
			wp_send_json_error( array(	'message' => __( "You don't have permission to deauthenticate MonsterInsights.", 'google-analytics-for-wordpress' ) ) );
455
		}
456
457
		if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
458
			define( 'WP_NETWORK_ADMIN', true );
459
		}
460
461
		// we have an auth to delete
462
		if ( $this->is_network_admin() && ! MonsterInsights()->auth->is_network_authed() ) {
463
			wp_send_json_error( array(	'message' => __( "Cannot deauthenticate. You are not currently authed.", 'google-analytics-for-wordpress' ) ) );
464
		} else if ( ! $this->is_network_admin() && ! MonsterInsights()->auth->is_authed() ) {
465
			wp_send_json_error( array(	'message' => __( "Cannot deauthenticate. You are not currently authed.", 'google-analytics-for-wordpress' ) ) );
466
		}
467
468
		if ( monsterinsights_is_pro_version() ) {
469
			$valid = is_network_admin() ? MonsterInsights()->license->is_network_licensed() : MonsterInsights()->license->is_site_licensed();
470
			if ( ! $valid ) {
471
				wp_send_json_error( array( 'message' => __( "Cannot deauthenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings.", 'google-analytics-for-wordpress' ) ) );
472
			}
473
		}
474
475
		$force = ! empty( $_REQUEST['forcedelete'] ) && $_REQUEST['forcedelete'] === 'true';
476
477
		$worked = $this->delete_auth( $force );
478
		if ( $worked && ! is_wp_error(  $worked ) ) {
479
			wp_send_json_success( array( 'message' => __( "Successfully deauthenticated.", 'google-analytics-for-wordpress' ) ) );
480
		} else {
481
			if ( $force ) {
482
				wp_send_json_success( array( 'message' => __( "Successfully force deauthenticated.", 'google-analytics-for-wordpress' ) ) );
483
			} else {
484
				wp_send_json_error( array( 'message' => __( "Could not deauthenticate.", 'google-analytics-for-wordpress' ) ) );
485
			}
486
		}
487
	}
488
489
	public function delete_auth( $force = false ){
490
		if ( $this->is_network_admin() && ! MonsterInsights()->auth->is_network_authed() ) {
0 ignored issues
show
Bug Best Practice introduced by
The property $auth is declared protected in MonsterInsights_Lite. Since you implement __get, consider adding a @property or @property-read.
Loading history...
491
			return false;
492
		} else if ( ! $this->is_network_admin() && ! MonsterInsights()->auth->is_authed() ) {
493
			return false;
494
		}
495
496
		$creds = $this->is_network_admin() ? MonsterInsights()->auth->get_network_analytics_profile( true ) : MonsterInsights()->auth->get_analytics_profile( true );
497
498
		if ( empty( $creds['key'] ) ) {
499
			return false;
500
		}
501
502
		// If we have a new siteurl enabled option and the profile site doesn't match the current site, deactivate anyways
503
		if ( is_network_admin() ) {
504
			$siteurl = network_admin_url();
505
			if ( ! empty( $creds['neturl' ] ) && $creds['neturl'] !== $siteurl ) {
506
				MonsterInsights()->auth->delete_network_analytics_profile( true );
507
				return true;
508
			}
509
		} else {
510
			$siteurl = site_url();
511
			if ( ! empty( $creds['siteurl' ] ) && $creds['siteurl'] !== $siteurl ) {
512
				MonsterInsights()->auth->delete_analytics_profile( true );
513
				return true;
514
			}
515
		}
516
517
		$api   = new MonsterInsights_API_Request( $this->get_route( 'auth/delete/{type}/' ), array( 'network' => $this->is_network_admin(), 'tt' => $this->get_tt(), 'key' => $creds['key'], 'token' => $creds['token'], 'testurl'   => 'https://' . monsterinsights_get_api_url() . 'test/' ) );
518
		$ret   = $api->request();
519
520
		$this->rotate_tt();
521
		if ( is_wp_error( $ret ) && ! $force ) {
522
			return false;
523
		} else {
524
			if ( $this->is_network_admin() ) {
525
				MonsterInsights()->auth->delete_network_analytics_profile( true );
526
			} else {
527
				MonsterInsights()->auth->delete_analytics_profile( true );
528
529
			}
530
			return true;
531
		}
532
	}
533
534
	/**
535
	 * Function to delete network auth in the uninstall process where we can't check if is network admin.
536
	 *
537
	 * @return bool
538
	 */
539
	public function uninstall_network_auth() {
540
541
		if ( ! MonsterInsights()->auth->is_network_authed() ) {
0 ignored issues
show
Bug Best Practice introduced by
The property $auth is declared protected in MonsterInsights_Lite. Since you implement __get, consider adding a @property or @property-read.
Loading history...
542
			return false;
543
		}
544
545
		$creds = MonsterInsights()->auth->get_network_analytics_profile( true );
546
547
		$api = new MonsterInsights_API_Request( $this->get_route( 'auth/delete/{type}/' ), array(
548
			'network' => true,
549
			'tt'      => $this->get_tt(),
550
			'key'     => $creds['key'],
551
			'token'   => $creds['token'],
552
			'testurl'   => 'https://' . monsterinsights_get_api_url() . 'test/'
553
		) );
554
		// Force the network admin url otherwise this will fail not finding the url in relay.
555
		$api->site_url = network_admin_url();
0 ignored issues
show
Bug Best Practice introduced by
The property site_url does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
556
		$ret = $api->request();
557
558
		$this->rotate_tt();
559
		if ( is_wp_error( $ret ) ) {
560
			return false;
561
		} else {
562
			MonsterInsights()->auth->delete_network_analytics_profile( true );
563
			return true;
564
		}
565
	}
566
567
	public function get_type() {
568
		$base = monsterinsights_is_pro_version() ? 'pro' : 'lite';
569
		return apply_filters( 'monsterinsights_api_auth_get_type', $base );
570
	}
571
572
	public function get_route( $route = '' ) {
573
		$route = str_replace( '{type}', $this->get_type(), $route );
574
		$route = trailingslashit( $route );
575
		return $route;
576
	}
577
578
	public function is_network_admin() {
579
		return is_multisite() && is_network_admin();
580
	}
581
582
	public function get_sitei() {
583
		// $sitei = get_network_option(  get_current_network_id(), 'monsterinsights_network_sitei', false );
584
		// if ( ! empty( $sitei ) && strlen( $sitei ) >= 1 ) {
585
		// 	return $sitei;
586
		// }
587
588
		$auth_key        = defined( 'AUTH_KEY' )        ? AUTH_KEY 		  : '';
589
		$secure_auth_key = defined( 'SECURE_AUTH_KEY' ) ? SECURE_AUTH_KEY : '';
590
		$logged_in_key   = defined( 'LOGGED_IN_KEY' )   ? LOGGED_IN_KEY   : '';
591
592
		$sitei = $auth_key . $secure_auth_key . $logged_in_key;
593
		$sitei = preg_replace('/[^a-zA-Z0-9]/', '', $sitei );
594
		$sitei = sanitize_text_field( $sitei );
595
		$sitei = trim( $sitei );
596
		$sitei = ( strlen($sitei) > 30 ) ? substr($sitei, 0, 30 ) : $sitei;
597
		return $sitei;
598
	}
599
600
	/**
601
	 * Logic to run before serving the redirect url during auth.
602
	 *
603
	 * @param string $url
604
	 *
605
	 * @return string
606
	 */
607
	public function before_redirect( $url ) {
608
609
		// If Bad Behavior plugin is installed.
610
		if ( function_exists( 'bb2_read_settings' ) ) {
611
			// Make sure the offsite_forms option is enabled to allow auth.
612
			$bb_settings = get_option( 'bad_behavior_settings' );
613
			if ( empty( $bb_settings['offsite_forms'] ) || false === $bb_settings['offsite_forms'] ) {
614
				$bb_settings['offsite_forms'] = true;
615
				update_option( 'bad_behavior_settings', $bb_settings );
616
			}
617
		}
618
619
		return $url;
620
	}
621
622
	/**
623
	 * Delete auth-related options from the db - should be run at site level.
624
	 */
625
	public function uninstall_auth() {
626
		delete_option( 'monsterinsights_site_profile' );
627
		delete_option( 'monsterinsights_site_tt' );
628
	}
629
630
	/**
631
	 * Save the measurement protocol that Relay pushes to this site
632
	 */
633
	public function handle_relay_mp_token_push() {
634
		$mp_token = sanitize_text_field( $_POST['mp_token'] );
635
		$timestamp = (int) sanitize_text_field( $_POST['timestamp'] );
636
		$signature = sanitize_text_field( $_POST['signature'] );
637
638
		// check if expired
639
		if ( time() > $timestamp + 1000 ) {
640
			wp_send_json_error( new WP_Error( 'monsterinsights_mp_token_timestamp_expired' ) );
641
		}
642
643
		// Check hashed signature
644
		$auth = MonsterInsights()->auth;
0 ignored issues
show
Bug Best Practice introduced by
The property $auth is declared protected in MonsterInsights_Lite. Since you implement __get, consider adding a @property or @property-read.
Loading history...
645
646
		$is_network = is_multisite();
647
		$public_key = $is_network
648
			? $auth->get_network_key()
649
			: $auth->get_key();
650
651
		$hashed_data = array(
652
			'mp_token' => $_POST['mp_token'],
653
			'timestamp' => $timestamp,
654
		);
655
656
		// These `hash_` functions are polyfilled by WP in wp-includes/compat.php
657
		$expected_signature = hash_hmac( 'md5', http_build_query( $hashed_data ), $public_key );
658
		if ( ! hash_equals( $signature, $expected_signature ) ) {
659
			wp_send_json_error( new WP_Error( 'monsterinsights_mp_token_invalid_signature' ) );
660
		}
661
662
		// Save measurement protocol token
663
		if ( $is_network ) {
664
			$auth->set_network_measurement_protocol_secret( $mp_token );
665
		} else {
666
			$auth->set_measurement_protocol_secret( $mp_token );
667
		}
668
		wp_send_json_success();
669
	}
670
}
671