File: /home/lesanew/anestetues2/web/app/plugins/advanced-access-manager/application/Restful/Urls.php
<?php
/**
* ======================================================================
* LICENSE: This file is subject to the terms and conditions defined in *
* file 'license.txt', which is part of this source code package. *
* ======================================================================
*/
/**
* RESTful API for the URL Access service
*
* @package AAM
* @version 7.0.0
*/
class AAM_Restful_Urls
{
use AAM_Restful_ServiceTrait;
/**
* Necessary permissions to access endpoint
*
* @version 7.0.0
*/
const PERMISSIONS = [
'aam_manager',
'aam_manage_url_access'
];
/**
* Constructor
*
* @return void
* @access protected
*
* @version 7.0.6
*/
protected function __construct()
{
// Register API endpoint
add_action('rest_api_init', function() {
// Get the list of define URL permissions
$this->_register_route('/urls', [
'methods' => WP_REST_Server::READABLE,
'callback' => [ $this, 'get_rules' ]
], self::PERMISSIONS);
// Define new URL permission
$this->_register_route('/urls', [
'methods' => WP_REST_Server::CREATABLE,
'callback' => [ $this, 'create_rule' ],
'args' => array(
'url_schema' => array(
'description' => 'URL schema',
'type' => 'string',
'required' => true
),
'effect' => array(
'description' => 'Wether allow or deny access to URL',
'type' => 'string',
'required' => true,
'enum' => [ 'allow', 'deny' ]
),
'redirect' => [
'type' => 'object',
'required' => false,
'properties' => [
'type' => [
'description' => 'Redirect type',
'type' => 'string',
'required' => true
],
'message' => [
'description' => 'Custom access denied message',
'type' => 'string',
'validate_callback' => function ($value, $request) {
return $this->_validate_message(
$value, $request
);
}
],
'redirect_page_id' => [
'description' => 'Existing page ID to redirect to',
'type' => 'number',
'validate_callback' => function ($value, $request) {
return $this->_validate_redirect_page_id(
$value, $request
);
}
],
'redirect_url' => [
'description' => 'Valid URL to redirect to',
'type' => 'string',
'validate_callback' => function ($value, $request) {
return $this->_validate_redirect_url(
$value, $request
);
}
],
'callback' => array(
'description' => 'Custom callback function',
'type' => 'string',
'validate_callback' => function ($value, $request) {
return $this->_validate_callback(
$value, $request
);
}
),
'http_status_code' => [
'description' => 'HTTP Status Code',
'type' => 'number'
]
]
]
)
], self::PERMISSIONS);
// Get a permission
$this->_register_route('/url/(?P<id>[A-Za-z0-9\/\+=]+)', [
'methods' => WP_REST_Server::READABLE,
'callback' => [ $this, 'get_rule' ],
'args' => array(
'id' => array(
'description' => 'Base64 encoded URL schema',
'type' => 'string',
'required' => true
)
)
], self::PERMISSIONS);
// Update an existing permission
$this->_register_route('/url/(?P<id>[A-Za-z0-9\/\+=]+)', [
'methods' => WP_REST_Server::EDITABLE,
'callback' => array($this, 'update_rule'),
'args' => array(
'id' => array(
'description' => 'Based64 encoded URL schema',
'type' => 'string',
'required' => true
),
'url_schema' => array(
'description' => 'New URL schema',
'type' => 'string',
'required' => false
),
'effect' => array(
'description' => 'Wether allow or deny access to URL',
'type' => 'string',
'required' => true,
'enum' => [ 'allow', 'deny' ]
),
'redirect' => [
'type' => 'object',
'required' => false,
'properties' => [
'type' => [
'description' => 'Redirect type',
'type' => 'string'
],
'message' => [
'description' => 'Custom access denied message',
'type' => 'string',
'validate_callback' => function ($value, $request) {
return $this->_validate_message(
$value, $request
);
}
],
'redirect_page_id' => [
'description' => 'Existing page ID to redirect to',
'type' => 'number',
'validate_callback' => function ($value, $request) {
return $this->_validate_redirect_page_id(
$value, $request
);
}
],
'redirect_url' => [
'description' => 'Valid URL to redirect to',
'type' => 'string',
'validate_callback' => function ($value, $request) {
return $this->_validate_redirect_url(
$value, $request
);
}
],
'callback' => array(
'description' => 'Custom callback function',
'type' => 'string',
'validate_callback' => function ($value, $request) {
return $this->_validate_callback(
$value, $request
);
}
),
'http_status_code' => [
'description' => 'HTTP Status Code',
'type' => 'number'
]
]
]
)
], self::PERMISSIONS);
// Delete a permission
$this->_register_route('/url/(?P<id>[A-Za-z0-9\/\+=]+)', [
'methods' => WP_REST_Server::DELETABLE,
'callback' => [ $this, 'delete_rule' ],
'args' => array(
'id' => array(
'description' => 'Base64 encoded URL schema',
'type' => 'string',
'required' => true
)
)
], self::PERMISSIONS);
// Reset all permissions
$this->_register_route('/urls', [
'methods' => WP_REST_Server::DELETABLE,
'callback' => [ $this, 'reset' ]
], self::PERMISSIONS);
});
}
/**
* Get list of all defined URL permissions
*
* @param WP_REST_Request $request
*
* @return WP_REST_Response
* @access public
*
* @version 7.0.6
*/
public function get_rules(WP_REST_Request $request)
{
try {
$result = $this->_get_permissions($request);
} catch(Exception $e) {
$result = $this->_prepare_error_response($e);
}
return rest_ensure_response($result);
}
/**
* Create new permission for given URL
*
* @param WP_REST_Request $request
*
* @return WP_REST_Response
* @access public
*
* @version 7.0.6
*/
public function create_rule(WP_REST_Request $request)
{
try {
$service = $this->_get_service($request);
// Grab all the necessary permission attributes
$url_schema = AAM::api()->misc->sanitize_url(
$request->get_param('url_schema')
);
$effect = strtolower($request->get_param('effect'));
$redirect = $request->get_param('redirect');
// Persist the permission
if ($effect === 'allow') {
$service->allow($url_schema);
} else {
$service->deny($url_schema, $redirect);
}
// Prepare the response
$result = $this->_prepare_output(
$url_schema,
$this->_find_permission_by_id(base64_encode($url_schema), $request),
true
);
} catch (Exception $e) {
$result = $this->_prepare_error_response($e);
}
return rest_ensure_response($result);
}
/**
* Get a rule
*
* @param WP_REST_Request $request
*
* @return WP_REST_Response
* @access public
*
* @version 7.0.6
*/
public function get_rule(WP_REST_Request $request)
{
try {
// Prepare result
$result = $this->_prepare_output(
base64_decode($request->get_param('id')),
$this->_find_permission_by_id($request->get_param('id'), $request),
true
);
} catch (Exception $e) {
$result = $this->_prepare_error_response($e);
}
return rest_ensure_response($result);
}
/**
* Update permissions for a specific URL
*
* @param WP_REST_Request $request
*
* @return WP_REST_Response
* @access public
*
* @version 7.0.6
*/
public function update_rule(WP_REST_Request $request)
{
try {
$service = $this->_get_service($request);
// Get all the necessary attributes
$original_url = base64_decode($request->get_param('id'));
$new_url = $request->get_param('url_schema');
$redirect = $request->get_param('redirect');
$effect = strtolower($request->get_param('effect'));
// If we are updating URL, then first, let's delete the original rule
if (!empty($new_url) && ($original_url !== $new_url)) {
$service->reset($original_url);
}
// Now we are settings permission for the given URL
$url_schema = AAM::api()->misc->sanitize_url(
!empty($new_url) ? $new_url : $original_url
);
if ($effect === 'allow') {
$service->allow($url_schema);
} else {
$service->deny($url_schema, $redirect);
}
// Prepare the response
$result = $this->_prepare_output(
$url_schema,
$this->_find_permission_by_id(base64_encode($url_schema), $request),
true
);
} catch (Exception $e) {
$result = $this->_prepare_error_response($e);
}
return rest_ensure_response($result);
}
/**
* Delete permission for a given URL
*
* @param WP_REST_Request $request
*
* @return WP_REST_Response
* @access public
*
* @version 7.0.6
*/
public function delete_rule(WP_REST_Request $request)
{
try {
$service = $this->_get_service($request);
$url_schema = base64_decode($request->get_param('id'));
// Reset the permission
$service->reset($url_schema);
// Prepare the result
$result = [ 'success' => true ];
} catch (Exception $e) {
$result = $this->_prepare_error_response($e);
}
return rest_ensure_response($result);
}
/**
* Reset permissions to all URLs
*
* @param WP_REST_Request $request
*
* @return WP_REST_Response
* @access public
*
* @version 7.0.6
*/
public function reset(WP_REST_Request $request)
{
try {
$service = $this->_get_service($request);
// Reset all permissions
$service->reset();
// Prepare the result
$result = [ 'success' => true ];
} catch (Exception $e) {
$result = $this->_prepare_error_response($e);
}
return rest_ensure_response($result);
}
/**
* Get complete list of defined permissions
*
* @param WP_REST_Request $request
*
* @return array
* @access private
*
* @version 7.0.0
*/
private function _get_permissions($request)
{
$result = [];
$access_level = $this->_determine_access_level($request);
$resource = $access_level->get_resource(
AAM_Framework_Type_Resource::URL
);
foreach($resource->get_permissions() as $url => $permissions) {
array_push($result, $this->_prepare_output(
$url, $permissions['access'], $resource->is_customized($url)
));
}
return $result;
}
/**
* Find permission by ID
*
* @param string $id
* @param WP_REST_Request $request
*
* @return array
* @access private
*
* @version 7.0.0
*/
private function _find_permission_by_id($id, $request)
{
$permissions = array_filter(
$this->_get_permissions($request),
function($p) use ($id) {
return $p['id'] === $id;
}
);
if (empty($permissions)) {
throw new OutOfRangeException('Permission does not exist');
}
return array_shift($permissions);
}
/**
* Validate custom message
*
* @param string $value
* @param WP_REST_Request $request
*
* @return boolean|WP_Error
* @access private
*
* @version 7.0.6
*/
private function _validate_message($value, $request)
{
$response = true;
$redirect = $request->get_param('redirect');
$rule_type = !empty($redirect['type']) ? $redirect['type'] : null;
$message = esc_js(trim($value));
if ($rule_type === 'custom_message' && strlen($message) === 0) {
$response = new WP_Error(
'rest_invalid_param',
'The custom_message cannot be empty or be unsafe',
[ 'status' => 400 ]
);
}
return $response;
}
/**
* Validate redirect page ID
*
* @param int $value
* @param WP_REST_Request $request
*
* @return boolean|WP_Error
* @access private
*
* @version 7.0.6
*/
private function _validate_redirect_page_id($value, $request)
{
$response = true;
$redirect = $request->get_param('redirect');
$rule_type = !empty($redirect['type']) ? $redirect['type'] : null;
$page_id = intval($value);
if ($rule_type === 'page_redirect') {
if ($page_id === 0 || get_post($page_id) === null) {
$response = new WP_Error(
'rest_invalid_param',
'The redirect_page_id refers to non-existing page',
[ 'status' => 400 ]
);
}
}
return $response;
}
/**
* Validate redirect URL
*
* @param string $value
* @param WP_REST_Request $request
*
* @return boolean|WP_Error
* @access private
*
* @version 7.0.6
*/
private function _validate_redirect_url($value, $request)
{
$response = true;
$redirect = $request->get_param('redirect');
$rule_type = !empty($redirect['type']) ? $redirect['type'] : null;
$url = AAM::api()->misc->sanitize_url($value);
if ($rule_type === 'url_redirect' && empty($url)) {
$response = new WP_Error(
'rest_invalid_param',
'The redirect_url is not valid URL',
array('status' => 400)
);
}
return $response;
}
/**
* Validate the callback value
*
* @param string $value
* @param WP_REST_Request $request
*
* @return boolean|WP_Error
* @access private
*
* @version 7.0.6
*/
private function _validate_callback($value, $request)
{
$response = true;
$redirect = $request->get_param('redirect');
$rule_type = !empty($redirect['type']) ? $redirect['type'] : null;
if ($rule_type === 'trigger_callback'
&& is_callable($value, true) === false
) {
$response = new WP_Error(
'rest_invalid_param',
'The callback is not valid PHP callback',
[ 'status' => 400 ]
);
}
return $response;
}
/**
* Prepare the URL permission model
*
* This method prepares the URL model so it can be effectively used by RESTful
* API
*
* @param string $url_schema
* @param array $permission
* @param bool $is_customized
*
* @return array
* @access private
*
* @version 7.0.0
*/
private function _prepare_output($url_schema, $permission, $is_customized)
{
return array_merge([
'id' => base64_encode($url_schema),
'url_schema' => $url_schema,
'is_customized' => $is_customized
], $permission);
}
/**
* Get service
*
* @param WP_REST_Request $request
*
* @return AAM_Framework_Service_Urls
* @access private
*
* @version 7.0.0
*/
private function _get_service(WP_REST_Request $request)
{
return AAM::api()->urls(
$this->_determine_access_level($request),
[ 'error_handling' => 'exception' ]
);
}
}