API Security
- added APIAccess class to define access levels of API Endpoints (permissions) - use "mailpoet_token" for all nonce (just as before) - merged setupPublic/setupAdmin methods in API in order to avoid duplication - check permission if access level is not all - fixed ABSPATH check in some classes
This commit is contained in:
@ -13,26 +13,25 @@ class API {
|
|||||||
private $_data = array();
|
private $_data = array();
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
// Admin API (Ajax only)
|
// Admin Security token
|
||||||
|
add_action(
|
||||||
|
'admin_head',
|
||||||
|
array($this, 'setToken')
|
||||||
|
);
|
||||||
|
|
||||||
|
// ajax (logged in users)
|
||||||
add_action(
|
add_action(
|
||||||
'wp_ajax_mailpoet',
|
'wp_ajax_mailpoet',
|
||||||
array($this, 'setupAdmin')
|
array($this, 'setupAjax')
|
||||||
);
|
);
|
||||||
|
// ajax (logged out users)
|
||||||
// Public API (Ajax)
|
|
||||||
add_action(
|
add_action(
|
||||||
'wp_ajax_nopriv_mailpoet',
|
'wp_ajax_nopriv_mailpoet',
|
||||||
array($this, 'setupPublic')
|
array($this, 'setupAjax')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupAdmin() {
|
function setupAjax() {
|
||||||
$this->getRequestData();
|
|
||||||
$this->checkPermissions();
|
|
||||||
$this->processRoute();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupPublic() {
|
|
||||||
$this->getRequestData();
|
$this->getRequestData();
|
||||||
$this->checkToken();
|
$this->checkToken();
|
||||||
$this->processRoute();
|
$this->processRoute();
|
||||||
@ -88,6 +87,18 @@ class API {
|
|||||||
function processRoute() {
|
function processRoute() {
|
||||||
try {
|
try {
|
||||||
$endpoint = new $this->_endpoint_class();
|
$endpoint = new $this->_endpoint_class();
|
||||||
|
|
||||||
|
// check the accessibility of the requested endpoint's action
|
||||||
|
// by default, an endpoint's action is considered "private"
|
||||||
|
$permissions = $endpoint->permissions;
|
||||||
|
if(
|
||||||
|
array_key_exists($this->_method, $permissions) === false
|
||||||
|
||
|
||||||
|
$permissions[$this->_method] !== Access::ALL
|
||||||
|
) {
|
||||||
|
$this->checkPermissions();
|
||||||
|
}
|
||||||
|
|
||||||
$response = $endpoint->{$this->_method}($this->_data);
|
$response = $endpoint->{$this->_method}($this->_data);
|
||||||
$response->send();
|
$response->send();
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
@ -117,9 +128,7 @@ class API {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function checkToken() {
|
function checkToken() {
|
||||||
$action = $this->_endpoint.'_'.$this->_method;
|
$is_valid_token = wp_verify_nonce($this->_token, 'mailpoet_token');
|
||||||
|
|
||||||
$is_valid_token = wp_verify_nonce($this->_token, $action);
|
|
||||||
|
|
||||||
if($is_valid_token === false) {
|
if($is_valid_token === false) {
|
||||||
$error_response = new ErrorResponse(
|
$error_response = new ErrorResponse(
|
||||||
@ -132,4 +141,13 @@ class API {
|
|||||||
$error_response->send();
|
$error_response->send();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setToken() {
|
||||||
|
$global = '<script type="text/javascript">';
|
||||||
|
$global .= 'var mailpoet_token = "';
|
||||||
|
$global .= Security::generateToken();
|
||||||
|
$global .= '";';
|
||||||
|
$global .= '</script>';
|
||||||
|
echo $global;
|
||||||
|
}
|
||||||
}
|
}
|
12
lib/API/Access.php
Normal file
12
lib/API/Access.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\API;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
final class Access {
|
||||||
|
const ALL = 'all';
|
||||||
|
|
||||||
|
private function __construct() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,8 @@ if(!defined('ABSPATH')) exit;
|
|||||||
|
|
||||||
abstract class Endpoint {
|
abstract class Endpoint {
|
||||||
|
|
||||||
|
public $permissions = array();
|
||||||
|
|
||||||
function successResponse(
|
function successResponse(
|
||||||
$data = array(), $meta = array(), $status = Response::STATUS_OK
|
$data = array(), $meta = array(), $status = Response::STATUS_OK
|
||||||
) {
|
) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
namespace MailPoet\API\Endpoints;
|
namespace MailPoet\API\Endpoints;
|
||||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||||
use \MailPoet\API\Error as APIError;
|
use \MailPoet\API\Error as APIError;
|
||||||
|
use \MailPoet\API\Access as APIAccess;
|
||||||
|
|
||||||
use MailPoet\Listing;
|
use MailPoet\Listing;
|
||||||
use MailPoet\Models\Subscriber;
|
use MailPoet\Models\Subscriber;
|
||||||
@ -15,6 +16,11 @@ use MailPoet\Models\StatisticsForms;
|
|||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class Subscribers extends APIEndpoint {
|
class Subscribers extends APIEndpoint {
|
||||||
|
|
||||||
|
public $permissions = array(
|
||||||
|
'subscribe' => APIAccess::ALL
|
||||||
|
);
|
||||||
|
|
||||||
function get($data = array()) {
|
function get($data = array()) {
|
||||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||||
$subscriber = Subscriber::findOne($id);
|
$subscriber = Subscriber::findOne($id);
|
||||||
|
@ -6,6 +6,8 @@ use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
|
|||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||||
|
|
||||||
|
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||||
|
|
||||||
class Daemon {
|
class Daemon {
|
||||||
public $daemon;
|
public $daemon;
|
||||||
public $request_data;
|
public $request_data;
|
||||||
|
@ -13,6 +13,8 @@ use MailPoet\Newsletter\Scheduler\Scheduler as NewsletterScheduler;
|
|||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||||
|
|
||||||
|
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||||
|
|
||||||
class Scheduler {
|
class Scheduler {
|
||||||
public $timer;
|
public $timer;
|
||||||
const UNCONFIRMED_SUBSCRIBER_RESCHEDULE_TIMEOUT = 5;
|
const UNCONFIRMED_SUBSCRIBER_RESCHEDULE_TIMEOUT = 5;
|
||||||
|
@ -161,7 +161,7 @@ class Widget extends \WP_Widget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// generate security token
|
// generate security token
|
||||||
$data['token'] = Security::generateToken('subscribers_subscribe');
|
$data['token'] = Security::generateToken();
|
||||||
|
|
||||||
// render form
|
// render form
|
||||||
$renderer = new Renderer();
|
$renderer = new Renderer();
|
||||||
|
@ -5,6 +5,8 @@ use MailPoet\Models\Setting;
|
|||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||||
|
|
||||||
|
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||||
|
|
||||||
class Mailer {
|
class Mailer {
|
||||||
public $mailer_config;
|
public $mailer_config;
|
||||||
public $sender;
|
public $sender;
|
||||||
|
Reference in New Issue
Block a user