PluginProbe ʕ •ᴥ•ʔ
Advanced Access Manager – Access Governance for WordPress / trunk
Advanced Access Manager – Access Governance for WordPress vtrunk
6.8.4 6.8.5 6.9.0 6.9.1 6.9.10 6.9.11 6.9.12 6.9.13 6.9.14 6.9.15 6.9.16 6.9.17 6.9.18 6.9.19 6.9.2 6.9.20 6.9.21 6.9.22 6.9.23 6.9.24 6.9.25 6.9.26 6.9.27 6.9.28 6.9.29 6.9.3 6.9.30 6.9.31 6.9.32 6.9.33 6.9.34 6.9.35 6.9.36 6.9.37 6.9.38 6.9.39 6.9.4 6.9.41 6.9.42 6.9.43 6.9.44 6.9.45 6.9.46 6.9.47 6.9.48 6.9.49 6.9.5 6.9.51 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.0-alpha.6 7.0.0-alpha.7 7.0.0-beta.1 7.0.0-rc1 7.0.0-rc2 7.0.0-rc3 7.0.1 7.0.10 7.0.11 7.0.2 7.0.3 7.0.4 7.0.5 7.0.6 7.0.7 7.0.8 7.0.9 7.1.0 7.1.1 trunk 3.0 4.0 4.0.1 4.1 4.2 4.3 4.4 4.4.1 4.5 4.6 4.6.1 4.6.2 4.7 4.7.1 4.7.2 4.7.5 4.7.6 4.8 4.8.1 4.9 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 4.9.5.1 4.9.5.2 5.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1 5.1.1 5.10 5.11 5.2 5.2.1 5.2.5 5.2.6 5.2.7 5.3 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.4 5.4.1 5.4.2 5.4.3 5.4.3.1 5.4.3.2 5.5 5.5.1 5.5.2 5.6 5.6.1 5.6.1.1 5.7 5.7.1 5.7.2 5.7.3 5.8 5.8.1 5.8.2 5.8.3 5.9 5.9.1 5.9.1.1 5.9.2 5.9.2.1 5.9.3 5.9.4 5.9.5 5.9.6 5.9.6.1 5.9.6.2 5.9.6.3 5.9.7 5.9.7.1 5.9.7.2 5.9.7.3 5.9.8 5.9.8.1 5.9.9 5.9.9.1 6.0.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.1.0 6.1.1 6.2.0 6.2.1 6.2.2 6.3.0 6.3.1 6.3.2 6.3.3 6.4.0 6.4.1 6.4.2 6.4.3 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.6.0 6.6.1 6.6.2 6.6.3 6.6.4 6.7.0 6.7.1 6.7.2 6.7.3 6.7.4 6.7.5 6.7.6 6.7.7 6.7.8 6.7.9 6.8.0 6.8.1 6.8.2 6.8.3
advanced-access-manager / application / Restful / Urls.php
advanced-access-manager / application / Restful Last commit date
AccessDeniedRedirect.php 1 year ago AdminToolbar.php 1 year ago ApiRoute.php 1 year ago BackendMenu.php 1 year ago BackwardCompatibility.php 1 year ago Capability.php 1 year ago Configs.php 5 months ago Content.php 1 year ago Identity.php 1 year ago Jwt.php 5 months ago LoginRedirect.php 1 year ago LogoutRedirect.php 1 year ago Metabox.php 1 year ago Mu.php 1 year ago NotFoundRedirect.php 1 year ago Policies.php 1 year ago Roles.php 1 year ago SecureLogin.php 1 year ago SecurityAudit.php 1 year ago ServiceTrait.php 1 year ago Settings.php 1 year ago Urls.php 1 year ago Users.php 1 year ago Widgets.php 1 year ago
Urls.php
637 lines
1 <?php
2
3 /**
4 * ======================================================================
5 * LICENSE: This file is subject to the terms and conditions defined in *
6 * file 'license.txt', which is part of this source code package. *
7 * ======================================================================
8 */
9
10 /**
11 * RESTful API for the URL Access service
12 *
13 * @package AAM
14 * @version 7.0.0
15 */
16 class AAM_Restful_Urls
17 {
18
19 use AAM_Restful_ServiceTrait;
20
21 /**
22 * Necessary permissions to access endpoint
23 *
24 * @version 7.0.0
25 */
26 const PERMISSIONS = [
27 'aam_manager',
28 'aam_manage_url_access'
29 ];
30
31 /**
32 * Constructor
33 *
34 * @return void
35 * @access protected
36 *
37 * @version 7.0.6
38 */
39 protected function __construct()
40 {
41 // Register API endpoint
42 add_action('rest_api_init', function() {
43 // Get the list of define URL permissions
44 $this->_register_route('/urls', [
45 'methods' => WP_REST_Server::READABLE,
46 'callback' => [ $this, 'get_rules' ]
47 ], self::PERMISSIONS);
48
49 // Define new URL permission
50 $this->_register_route('/urls', [
51 'methods' => WP_REST_Server::CREATABLE,
52 'callback' => [ $this, 'create_rule' ],
53 'args' => array(
54 'url_schema' => array(
55 'description' => 'URL schema',
56 'type' => 'string',
57 'required' => true
58 ),
59 'effect' => array(
60 'description' => 'Wether allow or deny access to URL',
61 'type' => 'string',
62 'required' => true,
63 'enum' => [ 'allow', 'deny' ]
64 ),
65 'redirect' => [
66 'type' => 'object',
67 'required' => false,
68 'properties' => [
69 'type' => [
70 'description' => 'Redirect type',
71 'type' => 'string',
72 'required' => true
73 ],
74 'message' => [
75 'description' => 'Custom access denied message',
76 'type' => 'string',
77 'validate_callback' => function ($value, $request) {
78 return $this->_validate_message(
79 $value, $request
80 );
81 }
82 ],
83 'redirect_page_id' => [
84 'description' => 'Existing page ID to redirect to',
85 'type' => 'number',
86 'validate_callback' => function ($value, $request) {
87 return $this->_validate_redirect_page_id(
88 $value, $request
89 );
90 }
91 ],
92 'redirect_url' => [
93 'description' => 'Valid URL to redirect to',
94 'type' => 'string',
95 'validate_callback' => function ($value, $request) {
96 return $this->_validate_redirect_url(
97 $value, $request
98 );
99 }
100 ],
101 'callback' => array(
102 'description' => 'Custom callback function',
103 'type' => 'string',
104 'validate_callback' => function ($value, $request) {
105 return $this->_validate_callback(
106 $value, $request
107 );
108 }
109 ),
110 'http_status_code' => [
111 'description' => 'HTTP Status Code',
112 'type' => 'number'
113 ]
114 ]
115 ]
116 )
117 ], self::PERMISSIONS);
118
119 // Get a permission
120 $this->_register_route('/url/(?P<id>[A-Za-z0-9\/\+=]+)', [
121 'methods' => WP_REST_Server::READABLE,
122 'callback' => [ $this, 'get_rule' ],
123 'args' => array(
124 'id' => array(
125 'description' => 'Base64 encoded URL schema',
126 'type' => 'string',
127 'required' => true
128 )
129 )
130 ], self::PERMISSIONS);
131
132 // Update an existing permission
133 $this->_register_route('/url/(?P<id>[A-Za-z0-9\/\+=]+)', [
134 'methods' => WP_REST_Server::EDITABLE,
135 'callback' => array($this, 'update_rule'),
136 'args' => array(
137 'id' => array(
138 'description' => 'Based64 encoded URL schema',
139 'type' => 'string',
140 'required' => true
141 ),
142 'url_schema' => array(
143 'description' => 'New URL schema',
144 'type' => 'string',
145 'required' => false
146 ),
147 'effect' => array(
148 'description' => 'Wether allow or deny access to URL',
149 'type' => 'string',
150 'required' => true,
151 'enum' => [ 'allow', 'deny' ]
152 ),
153 'redirect' => [
154 'type' => 'object',
155 'required' => false,
156 'properties' => [
157 'type' => [
158 'description' => 'Redirect type',
159 'type' => 'string'
160 ],
161 'message' => [
162 'description' => 'Custom access denied message',
163 'type' => 'string',
164 'validate_callback' => function ($value, $request) {
165 return $this->_validate_message(
166 $value, $request
167 );
168 }
169 ],
170 'redirect_page_id' => [
171 'description' => 'Existing page ID to redirect to',
172 'type' => 'number',
173 'validate_callback' => function ($value, $request) {
174 return $this->_validate_redirect_page_id(
175 $value, $request
176 );
177 }
178 ],
179 'redirect_url' => [
180 'description' => 'Valid URL to redirect to',
181 'type' => 'string',
182 'validate_callback' => function ($value, $request) {
183 return $this->_validate_redirect_url(
184 $value, $request
185 );
186 }
187 ],
188 'callback' => array(
189 'description' => 'Custom callback function',
190 'type' => 'string',
191 'validate_callback' => function ($value, $request) {
192 return $this->_validate_callback(
193 $value, $request
194 );
195 }
196 ),
197 'http_status_code' => [
198 'description' => 'HTTP Status Code',
199 'type' => 'number'
200 ]
201 ]
202 ]
203 )
204 ], self::PERMISSIONS);
205
206 // Delete a permission
207 $this->_register_route('/url/(?P<id>[A-Za-z0-9\/\+=]+)', [
208 'methods' => WP_REST_Server::DELETABLE,
209 'callback' => [ $this, 'delete_rule' ],
210 'args' => array(
211 'id' => array(
212 'description' => 'Base64 encoded URL schema',
213 'type' => 'string',
214 'required' => true
215 )
216 )
217 ], self::PERMISSIONS);
218
219 // Reset all permissions
220 $this->_register_route('/urls', [
221 'methods' => WP_REST_Server::DELETABLE,
222 'callback' => [ $this, 'reset' ]
223 ], self::PERMISSIONS);
224 });
225 }
226
227 /**
228 * Get list of all defined URL permissions
229 *
230 * @param WP_REST_Request $request
231 *
232 * @return WP_REST_Response
233 * @access public
234 *
235 * @version 7.0.6
236 */
237 public function get_rules(WP_REST_Request $request)
238 {
239 try {
240 $result = $this->_get_permissions($request);
241 } catch(Exception $e) {
242 $result = $this->_prepare_error_response($e);
243 }
244
245 return rest_ensure_response($result);
246 }
247
248 /**
249 * Create new permission for given URL
250 *
251 * @param WP_REST_Request $request
252 *
253 * @return WP_REST_Response
254 * @access public
255 *
256 * @version 7.0.6
257 */
258 public function create_rule(WP_REST_Request $request)
259 {
260 try {
261 $service = $this->_get_service($request);
262
263 // Grab all the necessary permission attributes
264 $url_schema = AAM::api()->misc->sanitize_url(
265 $request->get_param('url_schema')
266 );
267
268 $effect = strtolower($request->get_param('effect'));
269 $redirect = $request->get_param('redirect');
270
271 // Persist the permission
272 if ($effect === 'allow') {
273 $service->allow($url_schema);
274 } else {
275 $service->deny($url_schema, $redirect);
276 }
277
278 // Prepare the response
279 $result = $this->_prepare_output(
280 $url_schema,
281 $this->_find_permission_by_id(base64_encode($url_schema), $request),
282 true
283 );
284 } catch (Exception $e) {
285 $result = $this->_prepare_error_response($e);
286 }
287
288 return rest_ensure_response($result);
289 }
290
291 /**
292 * Get a rule
293 *
294 * @param WP_REST_Request $request
295 *
296 * @return WP_REST_Response
297 * @access public
298 *
299 * @version 7.0.6
300 */
301 public function get_rule(WP_REST_Request $request)
302 {
303 try {
304 // Prepare result
305 $result = $this->_prepare_output(
306 base64_decode($request->get_param('id')),
307 $this->_find_permission_by_id($request->get_param('id'), $request),
308 true
309 );
310 } catch (Exception $e) {
311 $result = $this->_prepare_error_response($e);
312 }
313
314 return rest_ensure_response($result);
315 }
316
317 /**
318 * Update permissions for a specific URL
319 *
320 * @param WP_REST_Request $request
321 *
322 * @return WP_REST_Response
323 * @access public
324 *
325 * @version 7.0.6
326 */
327 public function update_rule(WP_REST_Request $request)
328 {
329 try {
330 $service = $this->_get_service($request);
331
332 // Get all the necessary attributes
333 $original_url = base64_decode($request->get_param('id'));
334 $new_url = $request->get_param('url_schema');
335 $redirect = $request->get_param('redirect');
336 $effect = strtolower($request->get_param('effect'));
337
338 // If we are updating URL, then first, let's delete the original rule
339 if (!empty($new_url) && ($original_url !== $new_url)) {
340 $service->reset($original_url);
341 }
342
343 // Now we are settings permission for the given URL
344 $url_schema = AAM::api()->misc->sanitize_url(
345 !empty($new_url) ? $new_url : $original_url
346 );
347
348 if ($effect === 'allow') {
349 $service->allow($url_schema);
350 } else {
351 $service->deny($url_schema, $redirect);
352 }
353
354 // Prepare the response
355 $result = $this->_prepare_output(
356 $url_schema,
357 $this->_find_permission_by_id(base64_encode($url_schema), $request),
358 true
359 );
360 } catch (Exception $e) {
361 $result = $this->_prepare_error_response($e);
362 }
363
364 return rest_ensure_response($result);
365 }
366
367 /**
368 * Delete permission for a given URL
369 *
370 * @param WP_REST_Request $request
371 *
372 * @return WP_REST_Response
373 * @access public
374 *
375 * @version 7.0.6
376 */
377 public function delete_rule(WP_REST_Request $request)
378 {
379 try {
380 $service = $this->_get_service($request);
381 $url_schema = base64_decode($request->get_param('id'));
382
383 // Reset the permission
384 $service->reset($url_schema);
385
386 // Prepare the result
387 $result = [ 'success' => true ];
388 } catch (Exception $e) {
389 $result = $this->_prepare_error_response($e);
390 }
391
392 return rest_ensure_response($result);
393 }
394
395 /**
396 * Reset permissions to all URLs
397 *
398 * @param WP_REST_Request $request
399 *
400 * @return WP_REST_Response
401 * @access public
402 *
403 * @version 7.0.6
404 */
405 public function reset(WP_REST_Request $request)
406 {
407 try {
408 $service = $this->_get_service($request);
409
410 // Reset all permissions
411 $service->reset();
412
413 // Prepare the result
414 $result = [ 'success' => true ];
415 } catch (Exception $e) {
416 $result = $this->_prepare_error_response($e);
417 }
418
419 return rest_ensure_response($result);
420 }
421
422 /**
423 * Get complete list of defined permissions
424 *
425 * @param WP_REST_Request $request
426 *
427 * @return array
428 * @access private
429 *
430 * @version 7.0.0
431 */
432 private function _get_permissions($request)
433 {
434 $result = [];
435 $access_level = $this->_determine_access_level($request);
436 $resource = $access_level->get_resource(
437 AAM_Framework_Type_Resource::URL
438 );
439
440 foreach($resource->get_permissions() as $url => $permissions) {
441 array_push($result, $this->_prepare_output(
442 $url, $permissions['access'], $resource->is_customized($url)
443 ));
444 }
445
446 return $result;
447 }
448
449 /**
450 * Find permission by ID
451 *
452 * @param string $id
453 * @param WP_REST_Request $request
454 *
455 * @return array
456 * @access private
457 *
458 * @version 7.0.0
459 */
460 private function _find_permission_by_id($id, $request)
461 {
462 $permissions = array_filter(
463 $this->_get_permissions($request),
464 function($p) use ($id) {
465 return $p['id'] === $id;
466 }
467 );
468
469 if (empty($permissions)) {
470 throw new OutOfRangeException('Permission does not exist');
471 }
472
473 return array_shift($permissions);
474 }
475
476 /**
477 * Validate custom message
478 *
479 * @param string $value
480 * @param WP_REST_Request $request
481 *
482 * @return boolean|WP_Error
483 * @access private
484 *
485 * @version 7.0.6
486 */
487 private function _validate_message($value, $request)
488 {
489 $response = true;
490 $redirect = $request->get_param('redirect');
491 $rule_type = !empty($redirect['type']) ? $redirect['type'] : null;
492 $message = esc_js(trim($value));
493
494 if ($rule_type === 'custom_message' && strlen($message) === 0) {
495 $response = new WP_Error(
496 'rest_invalid_param',
497 'The custom_message cannot be empty or be unsafe',
498 [ 'status' => 400 ]
499 );
500 }
501
502 return $response;
503 }
504
505 /**
506 * Validate redirect page ID
507 *
508 * @param int $value
509 * @param WP_REST_Request $request
510 *
511 * @return boolean|WP_Error
512 * @access private
513 *
514 * @version 7.0.6
515 */
516 private function _validate_redirect_page_id($value, $request)
517 {
518 $response = true;
519 $redirect = $request->get_param('redirect');
520 $rule_type = !empty($redirect['type']) ? $redirect['type'] : null;
521 $page_id = intval($value);
522
523 if ($rule_type === 'page_redirect') {
524 if ($page_id === 0 || get_post($page_id) === null) {
525 $response = new WP_Error(
526 'rest_invalid_param',
527 'The redirect_page_id refers to non-existing page',
528 [ 'status' => 400 ]
529 );
530 }
531 }
532
533 return $response;
534 }
535
536 /**
537 * Validate redirect URL
538 *
539 * @param string $value
540 * @param WP_REST_Request $request
541 *
542 * @return boolean|WP_Error
543 * @access private
544 *
545 * @version 7.0.6
546 */
547 private function _validate_redirect_url($value, $request)
548 {
549 $response = true;
550 $redirect = $request->get_param('redirect');
551 $rule_type = !empty($redirect['type']) ? $redirect['type'] : null;
552 $url = AAM::api()->misc->sanitize_url($value);
553
554 if ($rule_type === 'url_redirect' && empty($url)) {
555 $response = new WP_Error(
556 'rest_invalid_param',
557 'The redirect_url is not valid URL',
558 array('status' => 400)
559 );
560 }
561
562 return $response;
563 }
564
565 /**
566 * Validate the callback value
567 *
568 * @param string $value
569 * @param WP_REST_Request $request
570 *
571 * @return boolean|WP_Error
572 * @access private
573 *
574 * @version 7.0.6
575 */
576 private function _validate_callback($value, $request)
577 {
578 $response = true;
579 $redirect = $request->get_param('redirect');
580 $rule_type = !empty($redirect['type']) ? $redirect['type'] : null;
581
582 if ($rule_type === 'trigger_callback'
583 && is_callable($value, true) === false
584 ) {
585 $response = new WP_Error(
586 'rest_invalid_param',
587 'The callback is not valid PHP callback',
588 [ 'status' => 400 ]
589 );
590 }
591
592 return $response;
593 }
594
595 /**
596 * Prepare the URL permission model
597 *
598 * This method prepares the URL model so it can be effectively used by RESTful
599 * API
600 *
601 * @param string $url_schema
602 * @param array $permission
603 * @param bool $is_customized
604 *
605 * @return array
606 * @access private
607 *
608 * @version 7.0.0
609 */
610 private function _prepare_output($url_schema, $permission, $is_customized)
611 {
612 return array_merge([
613 'id' => base64_encode($url_schema),
614 'url_schema' => $url_schema,
615 'is_customized' => $is_customized
616 ], $permission);
617 }
618
619 /**
620 * Get service
621 *
622 * @param WP_REST_Request $request
623 *
624 * @return AAM_Framework_Service_Urls
625 * @access private
626 *
627 * @version 7.0.0
628 */
629 private function _get_service(WP_REST_Request $request)
630 {
631 return AAM::api()->urls(
632 $this->_determine_access_level($request),
633 [ 'error_handling' => 'exception' ]
634 );
635 }
636
637 }