Your IP : 216.73.216.1
<?php
/**
* API Auth
*
* @package Pinterest_For_Woocommerce/API
* @version 1.0.0
*/
namespace Automattic\WooCommerce\Pinterest\API;
use Automattic\WooCommerce\Pinterest\Logger;
use Pinterest_For_Woocommerce;
use Throwable;
use WP_HTTP_Response;
use WP_REST_Request;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Registers the endpoint to which we are returned to, after being authorized by Pinterest.
*/
class Auth extends VendorAPI {
/**
* Initiate class.
*/
public function __construct() {
$this->base = \PINTEREST_FOR_WOOCOMMERCE_API_AUTH_ENDPOINT;
$this->endpoint_callback = 'connect_callback';
$this->methods = 'GET';
$this->register_routes();
}
/**
* Authenticate request
*
* @since 1.0.0
*
* @param WP_REST_Request $request The request.
*
* @return boolean
*/
public function permissions_check( WP_REST_Request $request ) {
$nonce = $request->get_param( 'state' ) ?? '';
/*
* Check if the nonce is valid. We grab the nonce from the transient because wp_verify_nonce() in REST API call
* is generated for user 0 and therefore it always returns false.
*/
return get_transient( \PINTEREST_FOR_WOOCOMMERCE_CONNECT_NONCE ) === $nonce;
}
/**
* When we got a permissions check failure, Hijack the rest_pre_serve_request filter
* to sent the user to the settings page instead of showing a white page with the printed REST response
*
* @param bool $served Whether the request has already been served. Default false.
* @param WP_HTTP_Response $result Result to send to the client. Usually a `WP_REST_Response`.
* @param WP_REST_Request $request Request used to generate the response.
* @return bool
*/
public function redirect_to_settings_page( $served, $result, $request ) {
if ( 401 === $result->get_status() ) {
$error_message = esc_html__( 'Something went wrong with your attempt to authorize this App. Please try again.', 'pinterest-for-woocommerce' );
wp_safe_redirect( add_query_arg( 'error', rawurlencode( $error_message ), $this->get_redirect_url( $request->get_param( 'view' ), true ) ) );
exit;
}
return $served;
}
/**
* REST Route callback function for POST requests.
*
* @since 1.0.0
*
* @param WP_REST_Request $request The request.
*/
public function connect_callback( WP_REST_Request $request ) {
$error = $request->has_param( 'error' ) ? sanitize_text_field( $request->get_param( 'error' ) ) : '';
$token_data = $request->get_param( 'token_data' );
$info = $request->get_param( 'info' );
// Check if there is an error.
if ( ! empty( $error ) ) {
$this->log_error_and_redirect( $request, $error );
}
if ( empty( $token_data ) ) {
$error = esc_html__( 'Token data missing, please try again later.', 'pinterest-for-woocommerce' );
$this->log_error_and_redirect( $request, $error );
}
if ( empty( $info ) ) {
$error = esc_html__( 'Connection information missing, please try again later.', 'pinterest-for-woocommerce' );
$this->log_error_and_redirect( $request, $error );
}
$token_string = base64_decode( $token_data ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
$token_data = (array) json_decode( urldecode( $token_string ) );
Pinterest_For_Woocommerce()::save_token_data( $token_data );
$info_string = base64_decode( $info ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
$info_data = (array) json_decode( urldecode( $info_string ) );
$features = (array) $info_data['feature_flags'] ?? array();
$this->apply_oauth_flow_features( $features );
unset( $info_data['feature_flags'] );
Pinterest_For_Woocommerce()::save_connection_info_data( $info_data );
Pinterest_For_Woocommerce::save_setting( 'tracking_advertiser', $info_data['advertiser_id'] );
Pinterest_For_Woocommerce::save_setting( 'tracking_tag', $info_data['tag_id'] ?? '' );
try {
/**
* Actions to perform after getting the authorization token.
*
* @since 1.4.0
*/
do_action( 'pinterest_for_woocommerce_token_saved' );
} catch ( Throwable $th ) {
$error = esc_html__( 'There was an error getting the account data. Please try again later.', 'pinterest-for-woocommerce' );
$this->log_error_and_redirect( $request, $error );
}
wp_safe_redirect( $this->get_redirect_url( $request->get_param( 'view' ) ) );
exit;
}
/**
* Applies the features from the OAuth flow to the plugin settings.
*
* @param array $features {
* The features selected by the merchant during the OAuth flow.
*
* @type bool $tags Whether Pinterest Tag was enabled.
* @type bool $CAPI Whether Conversions API was enabled.
* @type bool $catalog Whether Catalog synchronisation was enabled.
* }
*/
private function apply_oauth_flow_features( array $features ): void {
Pinterest_For_Woocommerce()::save_setting( 'track_conversions', $features['tags'] ?? false );
Pinterest_For_Woocommerce()::save_setting( 'track_conversions_capi', $features['CAPI'] ?? false );
Pinterest_For_Woocommerce()::save_setting( 'product_sync_enabled', $features['catalog'] ?? false );
}
/**
* Logs the error and redirects to the settings page.
*
* @param WP_REST_Request $request The request.
* @param string $error The error message.
*/
public function log_error_and_redirect( WP_REST_Request $request, $error ) {
$error_args = '&error=' . $error;
Logger::log( wp_json_encode( $error ), 'error', null, true );
wp_safe_redirect( $this->get_redirect_url( $request->get_param( 'view' ), ! empty( $error ) ) . $error_args );
exit;
}
/**
* Returns the redirect URI based on the current request's parameters and plugin settings.
*
* @param string $view The context of the view.
* @param boolean $has_error Whether there was an error with the auth process.
*
* @return string
*/
private function get_redirect_url( $view = null, $has_error = false ) {
$query_args = array(
'page' => 'wc-admin',
'path' => '/pinterest/onboarding',
'step' => $has_error || ! Pinterest_For_Woocommerce()::is_business_connected() ? 'setup-account' : 'claim-website',
);
if ( ! empty( $view ) ) {
$query_args['view'] = sanitize_key( $view );
}
// phpcs:ignore Squiz.Commenting.InlineComment.InvalidEndChar
// nosemgrep: audit.php.wp.security.xss.query-arg
return add_query_arg(
$query_args,
admin_url( 'admin.php' )
);
}
}