Your IP : 216.73.216.44


Current Path : /home/krobertfnz/www/wp-content/plugins/wpmudev-updates/includes/
Upload File :
Current File : /home/krobertfnz/www/wp-content/plugins/wpmudev-updates/includes/class-wpmudev-dashboard-ajax.php

<?php
/**
 * Class that handles ajax requests.
 *
 * @link    https://wpmudev.com
 * @since   4.11.6
 * @author  Joel James <joel@incsub.com>
 * @package WPMUDEV_Dashboard_Ajax
 */

// If this file is called directly, abort.
defined( 'WPINC' ) || die;

/**
 * Class WPMUDEV_Dashboard_Ajax
 */
class WPMUDEV_Dashboard_Ajax {

	/**
	 * Available action names.
	 *
	 * @var string[] $actions
	 */
	private array $actions = array();

	/**
	 * Available nopriv action names.
	 *
	 * @var string[] $nopriv_actions
	 */
	private array $nopriv_actions
		= array(
			'wdpunauth',
			'wdpsso_step1',
			'wdpsso_step2',
		);

	/**
	 * Available action names which can be bypassed.
	 *
	 * @var string[] $bypass_actions
	 */
	private array $bypass_actions = array();

	/**
	 * WPMUDEV_Dashboard_Ajax constructor.
	 *
	 * @since 4.11.6
	 */
	public function __construct() {
		// Register all ajax requests.
		foreach ( $this->get_actions() as $action ) {
			add_action( "wp_ajax_$action", array( $this, 'process' ) );
		}

		// Register nopriv ajax actions.
		foreach ( $this->get_nopriv_actions() as $action ) {
			add_action( "wp_ajax_$action", array( $this, 'nopriv_process' ) );
			add_action( "wp_ajax_nopriv_$action", array( $this, 'nopriv_process' ) );
		}

		// AUTO login ajax (nonce protected, it's called by our auto install server).
		add_action( 'wp_ajax_wdp-dashboard-autologin', array( $this, 'dashboard_autologin' ) );
	}

	/**
	 * Get available actions.
	 *
	 * @since 5.0.0
	 *
	 * @return array
	 */
	private function get_actions(): array {
		/**
		 * Override available ajax actions.
		 *
		 * @since 5.0.0
		 *
		 * @param $actions
		 */
		return apply_filters( 'wpmudev_dashboard_ajax_actions', $this->actions );
	}

	/**
	 * Get available nopriv actions.
	 *
	 * @since 5.0.0
	 *
	 * @return array
	 */
	private function get_nopriv_actions(): array {
		/**
		 * Override available ajax nopriv actions.
		 *
		 * @since 5.0.0
		 *
		 * @param $nopriv_actions
		 */
		return apply_filters( 'wpmudev_dashboard_ajax_nopriv_actions', $this->nopriv_actions );
	}

	/**
	 * Entry point for all ajax requests of the plugin.
	 *
	 * All ajax handlers point to this function instead of an individual
	 * callback function; this function validates the user before processing the
	 * actual request.
	 *
	 * @since  4.0.0
	 * @since  4.11.6
	 * @internal
	 */
	public function process() {
		// Make sure required items are found.
		if ( empty( $_REQUEST['action'] ) || empty( $_REQUEST['hash'] ) ) {
			wp_send_json_error(
				array( 'message' => __( 'Required field missing', 'wpmudev' ) )
			);
		}

		// Get action name.
		$action = str_replace( 'wdp-', '', $_REQUEST['action'] ); // phpcs:ignore
		// Get nonce.
		$nonce = $_REQUEST['hash']; // phpcs:ignore

		// Do nothing if the nonce is invalid.
		if ( ! wp_verify_nonce( $nonce, $action ) ) {
			wp_send_json_error(
				array( 'message' => __( 'Something went wrong, please refresh the page and try again.', 'wpmudev' ) )
			);
		}

		// Do nothing if the user is not allowed to use the Dashboard. Exception for specific ajax actions.
		if ( ! in_array( $action, $this->bypass_actions, true ) && ! WPMUDEV_Dashboard::$site->allowed_user() ) {
			wp_send_json_error(
				array( 'message' => __( 'Sorry, you are not allowed to do this.', 'wpmudev' ) )
			);
		}

		// Method names should contain only underscores.
		$method = str_replace( '-', '_', $action );

		if ( method_exists( $this, $method ) ) {
			// Execute request action.
			call_user_func( array( $this, $method ) );
		} else {
			$this->send_json_error(
				array(
					'message' => sprintf(
					/* translators: %s action name. */
						__( 'Unknown action: %s', 'wpmudev' ),
						esc_html( $action )
					),
				)
			);
		}

		// When the method did not send a response assume error.
		wp_send_json_error(
			array( 'message' => __( 'Unexpected action, we could not handle it.', 'wpmudev' ) )
		);
	}

	/**
	 * Entry point for all public ajax requests of the plugin.
	 *
	 * All Ajax handlers point to this function instead of an individual
	 * callback function; These functions are available even when logged out.
	 *
	 * @since  4.0.0
	 * @internal
	 */
	public function nopriv_process() {
		// Do nothing if function was called incorrectly.
		if ( empty( $_REQUEST['action'] ) ) { // phpcs:ignore
			wp_send_json_error(
				array( 'message' => __( 'Required field missing', 'wpmudev' ) )
			);
		}

		// Get action name.
		$method = str_replace( '-', '_', $_REQUEST['action'] ); // phpcs:ignore

		if ( method_exists( $this, $method ) ) {
			// Execute request action.
			call_user_func( array( $this, $method ) );
		} else {
			$this->send_json_error(
				array(
					'message' => sprintf(
					/* translators: %s action name. */
						__( 'Unknown action: %s', 'wpmudev' ),
						esc_html( $_REQUEST['action'] ) // phpcs:ignore
					),
				)
			);
		}

		// When the method did not send a response assume error.
		wp_send_json_error();
	}

	/**
	 * Start authentication.
	 *
	 * Required POST params:
	 * - wdpunkey .. Temporary Auth Key from the DB.
	 * - staff    .. Name of the user who loggs in.
	 *
	 * @since 4.11.6
	 *
	 * @return void
	 */
	public function wdpunauth() {
		WPMUDEV_Dashboard::$api->authenticate_remote_access();
	}

	/**
	 * Process authentication step 1.
	 *
	 * @since 4.11.6
	 *
	 * @return void
	 */
	public function wdpsso_step1() {
		// nonce verify method is using state + hmac.
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		$redirect = rawurlencode( wp_unslash( $_REQUEST['redirect'] ?? '' ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- this is encoded value.
		$nonce    = sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ?? '' ) );
		$jwttoken = sanitize_text_field( wp_unslash( $_REQUEST['jwttoken'] ?? '' ) );
		$apikey   = sanitize_text_field( wp_unslash( $_REQUEST['apikey'] ?? '' ) );
		$hubteam  = (int) sanitize_text_field( wp_unslash( $_REQUEST['hubteam'] ?? '' ) );
		// phpcs:enable WordPress.Security.NonceVerification.Recommended
		WPMUDEV_Dashboard::$api->authenticate_sso_access_step1( $redirect, $nonce, $jwttoken, $apikey, $hubteam );
	}

	/**
	 * Process authentication step 2.
	 *
	 * @since 4.11.6
	 *
	 * @return void
	 */
	public function wdpsso_step2() {
		// nonce verify method is using state + hmac.
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		$data = array(
			'incoming_hmac'  => sanitize_text_field( wp_unslash( $_REQUEST['outgoing_hmac'] ?? '' ) ),
			'token'          => sanitize_text_field( wp_unslash( $_REQUEST['token'] ?? '' ) ),
			'pre_sso_state'  => sanitize_text_field( wp_unslash( $_REQUEST['pre_sso_state'] ?? '' ) ),
			'redirect'       => wp_unslash( $_REQUEST['redirect'] ?? '' ), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- this is encoded value.
			'dev_user_id'    => (int) sanitize_text_field( ( wp_unslash( $_REQUEST['dev_user_id'] ?? '' ) ) ),
			'dev_user_email' => sanitize_email( wp_unslash( $_REQUEST['dev_user_email'] ?? '' ) ),
		);
		// phpcs:enable WordPress.Security.NonceVerification.Recommended

		WPMUDEV_Dashboard::$api->authenticate_sso_access_step2( $data );
	}

	/**
	 * Autologin to dashboard plugin.
	 * - Hub sync
	 * - Auto upgrade free plugins to pro
	 *
	 * @since 4.11.6
	 */
	public function dashboard_autologin() {
		// nonce verifier.
		$auth_verify_nonce = wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['auth_nonce'] ?? '' ) ), 'auth_nonce' );
		if ( ! $auth_verify_nonce ) {
			$this->send_json_error(
				array(
					'type'    => 'invalid_auth',
					'message' => __( 'Invalid Authentication.', 'wpmudev' ),
				)
			);
		}

		// basic permissions ( even allowed_user have to have this cap anyway ).
		if ( ! current_user_can( ( is_multisite() ? 'manage_network_options' : 'manage_options' ) ) ) {
			$this->send_json_error(
				array(
					'type'    => 'invalid_permission',
					'message' => __( 'Invalid Permission.', 'wpmudev' ),
				)
			);
		}

		// Dash Allowed users only.
		if ( ! WPMUDEV_Dashboard::$site->allowed_user() ) {
			$this->send_json_error(
				array(
					'type'    => 'invalid_allow',
					'message' => __( 'Invalid Permission.', 'wpmudev' ),
				)
			);
		}

		$key               = isset( $_REQUEST['apikey'] ) ? trim( sanitize_text_field( wp_unslash( $_REQUEST['apikey'] ) ) ) : false;
		$skip_free_upgrade = isset( $_REQUEST['skip_upgrade_free_plugins'] );

		if ( ! $key ) {
			$this->send_json_error(
				array(
					'type'    => 'invalid_key',
					'message' => __( 'Your API Key was invalid.', 'wpmudev' ),
				)
			);
		}

		$previous_key = '';
		if ( WPMUDEV_Dashboard::$api->has_key() ) {
			$previous_key = WPMUDEV_Dashboard::$api->get_key();
		}

		WPMUDEV_Dashboard::$api->set_key( $key );

		// When we auto install, we will also have the hub_sso_status param available to enable/disable SSO.
		if ( isset( $_REQUEST['hub_sso_status'] ) ) {
			WPMUDEV_Dashboard::$settings->set( 'enabled', absint( $_REQUEST['hub_sso_status'] ), 'sso' );
			if ( 1 === absint( $_REQUEST['hub_sso_status'] ) ) {
				WPMUDEV_Dashboard::$settings->set( 'userid', get_current_user_id(), 'sso' );
			}
		}

		// always get projects on first login / sync.
		WPMUDEV_Dashboard::$api->refresh_projects_data();

		$result = WPMUDEV_Dashboard::$api->hub_sync( false, true );
		if ( ! $result || empty( $result['membership'] ) ) {
			// Return to previous key to avoid logout.
			WPMUDEV_Dashboard::$api->set_key( $previous_key );

			if ( false === $result ) {
				$this->send_json_error(
					array(
						'type'    => 'connection_error',
						'message' => __( 'Your server had a problem connecting to WPMU DEV.', 'wpmudev' ),
					)
				);
			}
			$this->send_json_error(
				array(
					'type'    => 'invalid_key',
					'message' => __( 'Your API Key was invalid.', 'wpmudev' ),
				)
			);
		}

		// Valid key.
		global $current_user;
		WPMUDEV_Dashboard::$settings->set( 'limit_to_user', array( $current_user->ID ), 'general' );
		WPMUDEV_Dashboard::$api->refresh_profile();

		// In case timeout use ?skip_upgrade_free_plugins.
		if ( $skip_free_upgrade ) {
			$this->send_json_success(
				array(
					'skip_upgrade_free_plugins' => true,
				)
			);
		}

		// Sync free plugins!, time execution will vary depends on installed plugins and server connection.
		$upgraded_plugins = array();
		$type             = WPMUDEV_Dashboard::$api->get_membership_status();
		if ( 'full' === $type || 'unit' === $type ) {
			$installed_free_projects = WPMUDEV_Dashboard::$site->get_installed_free_projects();

			foreach ( $installed_free_projects as $installed_free_project ) {
				$upgraded_plugin = array(
					'pid'         => $installed_free_project['id'],
					'name'        => $installed_free_project['name'],
					'is_upgraded' => false,
				);
				if ( WPMUDEV_Dashboard::$site->maybe_replace_free_with_pro( $installed_free_project['id'], false ) ) {
					$upgraded_plugin['is_upgraded'] = true;
				}

				$upgraded_plugins[] = $upgraded_plugin;
			}
		}

		$this->send_json_success(
			array(
				'skip_upgrade_free_plugins' => false,
				'upgrade_free_plugins'      => $upgraded_plugins,
			)
		);
	}

	/**
	 * Clear all output buffers and send an JSON success response.
	 *
	 * @since 4.11.6
	 *
	 * @param mixed $data Data to return.
	 */
	private function send_json_success( $data = null ) {
		$this->send_json( true, $data );
	}

	/**
	 * Clear all output buffers and send an JSON error response.
	 *
	 * @since 4.11.6
	 *
	 * @param mixed $data Data to return.
	 */
	private function send_json_error( $data = null ) {
		$this->send_json( false, $data );
	}

	/**
	 * Clear all output buffers and send an JSON response.
	 *
	 * @since 4.11.6
	 *
	 * @param bool  $success Is success.
	 * @param mixed $data    Optional data to return to the Ajax request.
	 */
	private function send_json( bool $success = true, $data = null ) {
		while ( ob_get_level() ) {
			ob_get_clean();
		}

		$success ? wp_send_json_success( $data ) : wp_send_json_error( $data );
	}
}