296 lines
6.6 KiB
PHP
296 lines
6.6 KiB
PHP
<?php
|
|
/**
|
|
* Base Rest API Class, extend this if implementing a RestApi class.
|
|
* Most of the code was migrated from OMAPI_RestApi.
|
|
*
|
|
* @since 2.8.0
|
|
*
|
|
* @package OMAPI
|
|
* @author Gabriel Oliveira and Eduardo Nakatsuka
|
|
*/
|
|
|
|
// Exit if accessed directly.
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Base Rest Api class.
|
|
*
|
|
* @since 2.8.0
|
|
*/
|
|
abstract class OMAPI_BaseRestApi {
|
|
/**
|
|
* The Base OMAPI Object
|
|
*
|
|
* @since 2.8.0
|
|
*
|
|
* @var OMAPI
|
|
*/
|
|
protected $base;
|
|
|
|
/**
|
|
* The REST API Namespace
|
|
*
|
|
* @since 2.8.0
|
|
*
|
|
* @var string The namespace
|
|
*/
|
|
protected $namespace = 'omapp/v1';
|
|
|
|
/**
|
|
* Whether request was given a valid api key.
|
|
*
|
|
* @since 2.8.0
|
|
*
|
|
* @var null|bool
|
|
*/
|
|
protected $has_valid_api_key = null;
|
|
|
|
/**
|
|
* Build our object.
|
|
*
|
|
* @since 2.8.0
|
|
*/
|
|
public function __construct() {
|
|
$this->base = OMAPI::get_instance();
|
|
$this->register_rest_routes();
|
|
}
|
|
|
|
/**
|
|
* Registers the Rest API routes for this class
|
|
*
|
|
* @since 2.8.0
|
|
*
|
|
* @return void
|
|
*/
|
|
abstract public function register_rest_routes();
|
|
|
|
/**
|
|
* Determine if we can store settings.
|
|
*
|
|
* @since 2.0.0
|
|
* @since 2.8.0 Migrated from OMAPI_RestApi
|
|
*
|
|
* @param WP_REST_Request $request The REST Request.
|
|
*
|
|
* @return WP_Error|bool
|
|
*/
|
|
public function can_update_settings( $request ) {
|
|
try {
|
|
|
|
$this->verify_request_nonce( $request );
|
|
|
|
} catch ( Exception $e ) {
|
|
return $this->exception_to_response( $e );
|
|
}
|
|
|
|
return OMAPI::get_instance()->can_access( 'settings_update' );
|
|
}
|
|
|
|
/**
|
|
* Determine if OM API key is provided and valid.
|
|
*
|
|
* @since 1.9.10
|
|
* @since 2.8.0 Migrated from OMAPI_RestApi
|
|
*
|
|
* @param WP_REST_Request $request The REST Request.
|
|
*
|
|
* @return WP_Error|bool
|
|
*/
|
|
public function has_valid_api_key( $request ) {
|
|
$header = $request->get_header( 'X-OptinMonster-ApiKey' );
|
|
|
|
// Use this API Key to validate.
|
|
if ( ! $this->validate_api_key( $header ) ) {
|
|
return new WP_Error(
|
|
'omapp_rest_forbidden',
|
|
esc_html__( 'Could not verify your API Key.', 'optin-monster-api' ),
|
|
array(
|
|
'status' => rest_authorization_required_code(),
|
|
)
|
|
);
|
|
}
|
|
|
|
return $this->has_valid_api_key;
|
|
}
|
|
|
|
/**
|
|
* Determine if logged in or OM API key is provided and valid.
|
|
*
|
|
* @since 1.9.10
|
|
* @since 2.8.0 Migrated from OMAPI_RestApi
|
|
*
|
|
* @param WP_REST_Request $request The REST Request.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function logged_in_or_has_api_key( $request ) {
|
|
return $this->logged_in_and_can_access_route( $request )
|
|
|| true === $this->has_valid_api_key( $request );
|
|
}
|
|
|
|
/**
|
|
* Determine if logged in user can access this route (calls current_user_can).
|
|
*
|
|
* @since 2.6.4
|
|
*
|
|
* @param WP_REST_Request $request The REST Request.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function logged_in_and_can_access_route( $request ) {
|
|
return OMAPI::get_instance()->can_access( $request->get_route() );
|
|
}
|
|
|
|
/**
|
|
* Determine if the passed connection token is valid.
|
|
*
|
|
* @since 2.16.6
|
|
*
|
|
* @param WP_REST_Request $request The REST Request.
|
|
*
|
|
* @return WP_Error|bool
|
|
*/
|
|
public function has_connection_token( $request ) {
|
|
$request_connection_token = $request->get_param( 'connectionToken' );
|
|
|
|
$connection_token = $this->base->get_option( 'connectionToken' );
|
|
|
|
if ( 'omwpoct_' . $connection_token !== $request_connection_token ) {
|
|
return new WP_Error(
|
|
'omapp_rest_forbidden',
|
|
esc_html__( 'Could not verify your connection token.', 'optin-monster-api' ),
|
|
array(
|
|
'status' => rest_authorization_required_code(),
|
|
)
|
|
);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Validate this API Key
|
|
* We validate an API Key by fetching the Sites this key can fetch
|
|
* And then confirming that this key has access to at least one of these sites
|
|
*
|
|
* @since 1.8.0
|
|
* @since 2.8.0 Migrated from OMAPI_RestApi
|
|
*
|
|
* @param string $apikey The OM api key.
|
|
*
|
|
* @return bool True if the Key can be validated
|
|
*/
|
|
public function validate_api_key( $apikey ) {
|
|
$this->has_valid_api_key = OMAPI_ApiKey::validate( $apikey );
|
|
|
|
return $this->has_valid_api_key;
|
|
}
|
|
|
|
/**
|
|
* Convert an exception to a REST API WP_Error object.
|
|
*
|
|
* @since 2.0.0
|
|
* @since 2.8.0 Migrated from OMAPI_RestApi
|
|
*
|
|
* @param Exception $e The exception.
|
|
*
|
|
* @return WP_Error
|
|
*/
|
|
protected function exception_to_response( Exception $e ) {
|
|
// Return WP_Error objects directly.
|
|
if ( $e instanceof OMAPI_WpErrorException && $e->getWpError() ) {
|
|
return $e->getWpError();
|
|
}
|
|
|
|
$code = $e->getCode();
|
|
if ( empty( $code ) || $code < 400 ) {
|
|
$code = 400;
|
|
}
|
|
|
|
$data = ! empty( $e->data ) ? $e->data : array();
|
|
$data = wp_parse_args(
|
|
$data,
|
|
array(
|
|
'status' => $code,
|
|
)
|
|
);
|
|
|
|
$error_code = rest_authorization_required_code() === $code
|
|
? 'omapp_rest_forbidden'
|
|
: 'omapp_rest_error';
|
|
|
|
return new WP_Error( $error_code, $e->getMessage(), $data );
|
|
}
|
|
|
|
/**
|
|
* Convert a WP_Error to a proper REST API WP_Error object.
|
|
*
|
|
* @since 2.6.5
|
|
* @since 2.8.0 Migrated from OMAPI_RestApi
|
|
*
|
|
* @param WP_Error $e The WP_Error object.
|
|
* @param mixed $data Data to include in the error data.
|
|
*
|
|
* @return WP_Error
|
|
*/
|
|
protected function wp_error_to_response( WP_Error $e, $data = array() ) {
|
|
$api = OMAPI_Api::instance();
|
|
|
|
$data = is_array( $data ) || is_object( $data ) ? (array) $data : array();
|
|
$error_data = $e->get_error_data();
|
|
$error_message = $e->get_error_message();
|
|
$error_code = $e->get_error_code();
|
|
|
|
if ( empty( $error_data['status'] ) ) {
|
|
|
|
$status = is_numeric( $error_data ) ? $error_data : 400;
|
|
$error_code = (string) rest_authorization_required_code() === (string) $status
|
|
? 'omapp_rest_forbidden'
|
|
: 'omapp_rest_error';
|
|
|
|
$error_data = wp_parse_args(
|
|
array(
|
|
'status' => $status,
|
|
),
|
|
$data
|
|
);
|
|
|
|
} else {
|
|
$error_data = wp_parse_args( $error_data, $data );
|
|
}
|
|
|
|
return new WP_Error( $error_code, $error_message, $error_data );
|
|
}
|
|
|
|
/**
|
|
* Verify the request nonce and throw an exception if verification fails.
|
|
*
|
|
* @since 2.0.0
|
|
* @since 2.8.0 Migrated from OMAPI_RestApi
|
|
*
|
|
* @param WP_REST_Request $request The REST request.
|
|
*
|
|
* @return void
|
|
*
|
|
* @throws Exception If the nonce is missing or invalid.
|
|
*/
|
|
public function verify_request_nonce( $request ) {
|
|
$nonce = $request->get_param( 'nonce' );
|
|
if ( empty( $nonce ) ) {
|
|
$nonce = $request->get_header( 'X-WP-Nonce' );
|
|
}
|
|
|
|
if ( empty( $nonce ) ) {
|
|
throw new Exception( esc_html__( 'Missing security token!', 'optin-monster-api' ), rest_authorization_required_code() );
|
|
}
|
|
|
|
// Check the nonce.
|
|
$result = wp_verify_nonce( $nonce, 'wp_rest' );
|
|
if ( ! $result ) {
|
|
throw new Exception( esc_html__( 'Security token invalid!', 'optin-monster-api' ), rest_authorization_required_code() );
|
|
}
|
|
}
|
|
}
|