Version Description
- Fixed numerous bugs with access control for media
- Added support for change_own_password capability
- Added support for change_passwords capability
- Added type casting to the Access Policy document
- Added new resource
Role
to the Access Policy - Refactored internal Access Policy implementation
- Improved performance
Download this release
Release Info
Developer | vasyltech |
Plugin | Advanced Access Manager |
Version | 5.8.2 |
Comparing to | |
See all releases |
Code changes from version 5.8.1 to 5.8.2
- Application/Backend/Feature/Main/Capability.php +4 -1
- Application/Backend/Feature/Subject/User.php +3 -3
- Application/Backend/Manager.php +45 -0
- Application/Core/Media.php +41 -24
- Application/Core/Object/Cache.php +1 -1
- Application/Core/Object/Policy.php +45 -397
- Application/Core/Policy/Condition.php +413 -0
- Application/Core/Policy/Token.php +126 -0
- Application/Core/Subject.php +5 -0
- Application/Core/Subject/Role.php +1 -1
- Application/Core/Subject/User.php +40 -22
- Application/Shared/Manager.php +6 -1
- aam.php +3 -6
- readme.txt +10 -1
Application/Backend/Feature/Main/Capability.php
CHANGED
@@ -252,9 +252,12 @@ class AAM_Backend_Feature_Main_Capability extends AAM_Backend_Feature_Abstract {
|
|
252 |
protected function retrieveAllCaps() {
|
253 |
$response = array();
|
254 |
|
|
|
|
|
|
|
255 |
// Load also capabilities defined in policy
|
256 |
$stms = AAM_Core_Policy_Manager::getInstance()->find(
|
257 |
-
"/^Capability:/i",
|
258 |
);
|
259 |
|
260 |
$policyCaps = array();
|
252 |
protected function retrieveAllCaps() {
|
253 |
$response = array();
|
254 |
|
255 |
+
$subject = AAM_Backend_Subject::getInstance()->get();
|
256 |
+
$subject->initialize(true);
|
257 |
+
|
258 |
// Load also capabilities defined in policy
|
259 |
$stms = AAM_Core_Policy_Manager::getInstance()->find(
|
260 |
+
"/^Capability:/i", $subject
|
261 |
);
|
262 |
|
263 |
$policyCaps = array();
|
Application/Backend/Feature/Subject/User.php
CHANGED
@@ -42,9 +42,9 @@ class AAM_Backend_Feature_Subject_User {
|
|
42 |
$response['recordsFiltered'] = $result->get_total();
|
43 |
|
44 |
foreach ($result->get_results() as $row) {
|
45 |
-
$
|
46 |
-
|
47 |
-
);
|
48 |
}
|
49 |
}
|
50 |
|
42 |
$response['recordsFiltered'] = $result->get_total();
|
43 |
|
44 |
foreach ($result->get_results() as $row) {
|
45 |
+
$user = new AAM_Core_Subject_User($row->ID);
|
46 |
+
$user->initialize(true);
|
47 |
+
$response['data'][] = $this->prepareRow($user);
|
48 |
}
|
49 |
}
|
50 |
|
Application/Backend/Manager.php
CHANGED
@@ -114,6 +114,10 @@ class AAM_Backend_Manager {
|
|
114 |
//control admin area
|
115 |
add_action('admin_init', array($this, 'adminInit'));
|
116 |
|
|
|
|
|
|
|
|
|
117 |
//admin toolbar
|
118 |
if (AAM::isAAM()) {
|
119 |
add_action('wp_after_admin_bar_render', array($this, 'cacheAdminBar'));
|
@@ -139,6 +143,47 @@ class AAM_Backend_Manager {
|
|
139 |
}
|
140 |
}
|
141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
/**
|
143 |
*
|
144 |
* @param type $data
|
114 |
//control admin area
|
115 |
add_action('admin_init', array($this, 'adminInit'));
|
116 |
|
117 |
+
//password reset feature
|
118 |
+
add_filter('show_password_fields', array($this, 'canChangePassword'), 10, 2);
|
119 |
+
add_action('check_passwords', array($this, 'canUpdatePassword'), 10, 3);
|
120 |
+
|
121 |
//admin toolbar
|
122 |
if (AAM::isAAM()) {
|
123 |
add_action('wp_after_admin_bar_render', array($this, 'cacheAdminBar'));
|
143 |
}
|
144 |
}
|
145 |
|
146 |
+
/**
|
147 |
+
*
|
148 |
+
* @param boolean $result
|
149 |
+
* @param type $user
|
150 |
+
* @return boolean
|
151 |
+
*/
|
152 |
+
public function canChangePassword($result, $user) {
|
153 |
+
$isProfile = $user->ID === get_current_user_id();
|
154 |
+
if ($isProfile) {
|
155 |
+
if (AAM_Core_API::capabilityExists('change_own_password')
|
156 |
+
&& !AAM::getUser()->hasCapability('change_own_password')) {
|
157 |
+
$result = false;
|
158 |
+
}
|
159 |
+
} elseif (AAM_Core_API::capabilityExists('change_passwords')
|
160 |
+
&& !AAM::getUser()->hasCapability('change_passwords')) {
|
161 |
+
$result = false;
|
162 |
+
}
|
163 |
+
|
164 |
+
return $result;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
*
|
169 |
+
* @param type $login
|
170 |
+
* @param type $password
|
171 |
+
*/
|
172 |
+
public function canUpdatePassword($login, &$password, &$password2) {
|
173 |
+
$userId = AAM_Core_Request::post('user_id');
|
174 |
+
$isProfile = $userId === get_current_user_id();
|
175 |
+
|
176 |
+
if ($isProfile) {
|
177 |
+
if (AAM_Core_API::capabilityExists('change_own_password')
|
178 |
+
&& !AAM::getUser()->hasCapability('change_own_password')) {
|
179 |
+
$password = $password2 = null;
|
180 |
+
}
|
181 |
+
} elseif (AAM_Core_API::capabilityExists('change_passwords')
|
182 |
+
&& !AAM::getUser()->hasCapability('change_passwords')) {
|
183 |
+
$password = $password2 = null;
|
184 |
+
}
|
185 |
+
}
|
186 |
+
|
187 |
/**
|
188 |
*
|
189 |
* @param type $data
|
Application/Core/Media.php
CHANGED
@@ -44,26 +44,6 @@ class AAM_Core_Media {
|
|
44 |
* @access protected
|
45 |
*/
|
46 |
protected function __construct() {
|
47 |
-
if (AAM_Core_Request::get('aam-media')) {
|
48 |
-
$this->initialize();
|
49 |
-
|
50 |
-
if (AAM_Core_Config::get('core.settings.mediaAccessControl', false)) {
|
51 |
-
$area = AAM_Core_Api_Area::get();
|
52 |
-
if (AAM_Core_Config::get("core.settings.{$area}AccessControl", true)) {
|
53 |
-
$this->checkMediaAccess();
|
54 |
-
} else {
|
55 |
-
$this->printMedia();
|
56 |
-
}
|
57 |
-
} else {
|
58 |
-
$this->printMedia();
|
59 |
-
}
|
60 |
-
}
|
61 |
-
}
|
62 |
-
|
63 |
-
/**
|
64 |
-
*
|
65 |
-
*/
|
66 |
-
protected function initialize() {
|
67 |
$media = filter_input(INPUT_GET, 'aam-media', FILTER_VALIDATE_INT);
|
68 |
$request = ($media !== 1 ? $media : urldecode(AAM_Core_Request::server('REQUEST_URI')));
|
69 |
$root = AAM_Core_Request::server('DOCUMENT_ROOT');
|
@@ -72,6 +52,22 @@ class AAM_Core_Media {
|
|
72 |
$this->request_uri = preg_replace('/\?.*$/', '', $request);
|
73 |
}
|
74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
/**
|
76 |
* Check media access
|
77 |
*
|
@@ -161,8 +157,27 @@ class AAM_Core_Media {
|
|
161 |
protected function findMedia() {
|
162 |
global $wpdb;
|
163 |
|
164 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
$id = apply_filters(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
'aam-found-media-filter',
|
167 |
$wpdb->get_var(
|
168 |
$wpdb->prepare(
|
@@ -170,9 +185,11 @@ class AAM_Core_Media {
|
|
170 |
array('%' . $s)
|
171 |
)
|
172 |
),
|
173 |
-
$this->request_uri
|
174 |
-
|
175 |
-
|
|
|
|
|
176 |
return ($id ? AAM::getUser()->getObject('post', $id) : null);
|
177 |
}
|
178 |
|
44 |
* @access protected
|
45 |
*/
|
46 |
protected function __construct() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
$media = filter_input(INPUT_GET, 'aam-media', FILTER_VALIDATE_INT);
|
48 |
$request = ($media !== 1 ? $media : urldecode(AAM_Core_Request::server('REQUEST_URI')));
|
49 |
$root = AAM_Core_Request::server('DOCUMENT_ROOT');
|
52 |
$this->request_uri = preg_replace('/\?.*$/', '', $request);
|
53 |
}
|
54 |
|
55 |
+
/**
|
56 |
+
*
|
57 |
+
*/
|
58 |
+
public function authorize() {
|
59 |
+
if (AAM_Core_Config::get('core.settings.mediaAccessControl', false)) {
|
60 |
+
$area = AAM_Core_Api_Area::get();
|
61 |
+
if (AAM_Core_Config::get("core.settings.{$area}AccessControl", true)) {
|
62 |
+
$this->checkMediaAccess();
|
63 |
+
} else {
|
64 |
+
$this->printMedia();
|
65 |
+
}
|
66 |
+
} else {
|
67 |
+
$this->printMedia();
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
/**
|
72 |
* Check media access
|
73 |
*
|
157 |
protected function findMedia() {
|
158 |
global $wpdb;
|
159 |
|
160 |
+
// 1. replace the cropped extension for images
|
161 |
+
$s = preg_replace('/(-[\d]+x[\d]+)(\.[\w]+)$/', '$2', $this->request);
|
162 |
+
|
163 |
+
// 2. Replace the path to the media
|
164 |
+
$basedir = wp_upload_dir();
|
165 |
+
$s = ltrim(str_replace($basedir['basedir'], '', $s), '/');
|
166 |
+
|
167 |
$id = apply_filters(
|
168 |
+
'aam-found-media-filter',
|
169 |
+
$wpdb->get_var(
|
170 |
+
$wpdb->prepare(
|
171 |
+
"SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value = %s",
|
172 |
+
array('_wp_attached_file', $s)
|
173 |
+
)
|
174 |
+
),
|
175 |
+
$this->request_uri,
|
176 |
+
$this->request
|
177 |
+
);
|
178 |
+
|
179 |
+
if (empty($id)) { // Try to find the image by GUID
|
180 |
+
$id = apply_filters(
|
181 |
'aam-found-media-filter',
|
182 |
$wpdb->get_var(
|
183 |
$wpdb->prepare(
|
185 |
array('%' . $s)
|
186 |
)
|
187 |
),
|
188 |
+
$this->request_uri,
|
189 |
+
$this->request
|
190 |
+
);
|
191 |
+
}
|
192 |
+
|
193 |
return ($id ? AAM::getUser()->getObject('post', $id) : null);
|
194 |
}
|
195 |
|
Application/Core/Object/Cache.php
CHANGED
@@ -50,7 +50,7 @@ class AAM_Core_Object_Cache extends AAM_Core_Object {
|
|
50 |
$triggers = array('edit', 'editpost');
|
51 |
$status = AAM_Core_Config::get('core.cache.status', 'enabled');
|
52 |
|
53 |
-
if (AAM::isAAM() || ($status !== 'enabled') || in_array($action, $triggers)) {
|
54 |
$this->enabled = false;
|
55 |
}
|
56 |
|
50 |
$triggers = array('edit', 'editpost');
|
51 |
$status = AAM_Core_Config::get('core.cache.status', 'enabled');
|
52 |
|
53 |
+
if (AAM::isAAM() || ($status !== 'enabled') || in_array($action, $triggers, true)) {
|
54 |
$this->enabled = false;
|
55 |
}
|
56 |
|
Application/Core/Object/Policy.php
CHANGED
@@ -55,7 +55,11 @@ class AAM_Core_Object_Policy extends AAM_Core_Object {
|
|
55 |
}
|
56 |
|
57 |
/**
|
|
|
58 |
*
|
|
|
|
|
|
|
59 |
*/
|
60 |
public function initialize() {
|
61 |
$subject = $this->getSubject();
|
@@ -81,17 +85,24 @@ class AAM_Core_Object_Policy extends AAM_Core_Object {
|
|
81 |
// Load statements for policies
|
82 |
$subjectId = $subject->getUID();
|
83 |
$subjectId .= ($subject->getId() ? ".{$subject->getId()}" : '');
|
|
|
84 |
$this->load($subjectId, $option);
|
85 |
}
|
86 |
|
87 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
*
|
|
|
89 |
*/
|
90 |
public function load($subjectId, $policies) {
|
91 |
$resources = array();
|
92 |
$features = array();
|
93 |
-
|
94 |
-
$list = $this->parsePolicy($subjectId, $policies);
|
95 |
|
96 |
// Evaluate all Statements first
|
97 |
foreach($list['Statements'] as $statement) {
|
@@ -279,370 +290,12 @@ class AAM_Core_Object_Policy extends AAM_Core_Object {
|
|
279 |
$result = true;
|
280 |
|
281 |
if (!empty($statement['Condition']) && !is_scalar($statement['Condition'])) {
|
282 |
-
|
283 |
-
|
284 |
-
case 'between':
|
285 |
-
$result = $result && $this->evaluateBetweenConditions($conditions);
|
286 |
-
break;
|
287 |
-
|
288 |
-
case 'equals':
|
289 |
-
$result = $result && $this->evaluateEqualsConditions($conditions);
|
290 |
-
break;
|
291 |
-
|
292 |
-
case 'notequals':
|
293 |
-
$result = $result && $this->evaluateNotEqualsConditions($conditions);
|
294 |
-
break;
|
295 |
-
|
296 |
-
case 'greater':
|
297 |
-
$result = $result && $this->evaluateGreaterConditions($conditions);
|
298 |
-
break;
|
299 |
-
|
300 |
-
case 'less':
|
301 |
-
$result = $result && $this->evaluateLessConditions($conditions);
|
302 |
-
break;
|
303 |
-
|
304 |
-
case 'greaterorequals':
|
305 |
-
$result = $result && $this->evaluateGreaterOrEqualsConditions($conditions);
|
306 |
-
break;
|
307 |
-
|
308 |
-
case 'lessorequals':
|
309 |
-
$result = $result && $this->evaluateLessOrEqualsConditions($conditions);
|
310 |
-
break;
|
311 |
-
|
312 |
-
case 'in':
|
313 |
-
$result = $result && $this->evaluateInConditions($conditions);
|
314 |
-
break;
|
315 |
-
|
316 |
-
case 'notin':
|
317 |
-
$result = $result && $this->evaluateNotInConditions($conditions);
|
318 |
-
break;
|
319 |
-
|
320 |
-
case 'like':
|
321 |
-
$result = $result && $this->evaluateLikeConditions($conditions);
|
322 |
-
break;
|
323 |
-
|
324 |
-
case 'notlike':
|
325 |
-
$result = $result && $this->evaluateNotLikeConditions($conditions);
|
326 |
-
break;
|
327 |
-
|
328 |
-
case 'regex':
|
329 |
-
$result = $result && $this->evaluateRegexConditions($conditions);
|
330 |
-
break;
|
331 |
-
|
332 |
-
default:
|
333 |
-
$result = $result && apply_filters('aam-statement-conditions-filter', false, $conditions);
|
334 |
-
break;
|
335 |
-
}
|
336 |
-
}
|
337 |
-
}
|
338 |
-
|
339 |
-
return $result;
|
340 |
-
}
|
341 |
-
|
342 |
-
/**
|
343 |
-
*
|
344 |
-
* @param type $conditions
|
345 |
-
* @return type
|
346 |
-
*/
|
347 |
-
protected function evaluateBetweenConditions($conditions) {
|
348 |
-
$result = false;
|
349 |
-
|
350 |
-
foreach($this->prepareConditions($conditions) as $left => $right) {
|
351 |
-
foreach((array)$right as $subset) {
|
352 |
-
$min = (is_array($subset) ? array_shift($subset) : $subset);
|
353 |
-
$max = (is_array($subset) ? end($subset) : $subset);
|
354 |
-
|
355 |
-
$result = $result || ($left >= $min && $left <= $max);
|
356 |
-
}
|
357 |
-
}
|
358 |
-
|
359 |
-
return $result;
|
360 |
-
}
|
361 |
-
|
362 |
-
/**
|
363 |
-
*
|
364 |
-
* @param type $conditions
|
365 |
-
* @return type
|
366 |
-
*/
|
367 |
-
protected function evaluateEqualsConditions($conditions) {
|
368 |
-
$result = false;
|
369 |
-
|
370 |
-
foreach($this->prepareConditions($conditions) as $left => $right) {
|
371 |
-
$result = $result || ($left === $right);
|
372 |
-
}
|
373 |
-
|
374 |
-
return $result;
|
375 |
-
}
|
376 |
-
|
377 |
-
/**
|
378 |
-
*
|
379 |
-
* @param type $conditions
|
380 |
-
* @return type
|
381 |
-
*/
|
382 |
-
protected function evaluateNotEqualsConditions($conditions) {
|
383 |
-
return !$this->evaluateEqualsConditions($conditions);
|
384 |
-
}
|
385 |
-
|
386 |
-
/**
|
387 |
-
*
|
388 |
-
* @param type $conditions
|
389 |
-
* @return type
|
390 |
-
*/
|
391 |
-
protected function evaluateGreaterConditions($conditions) {
|
392 |
-
$result = false;
|
393 |
-
|
394 |
-
foreach($this->prepareConditions($conditions) as $left => $right) {
|
395 |
-
$result = $result || ($left > $right);
|
396 |
-
}
|
397 |
-
|
398 |
-
return $result;
|
399 |
-
}
|
400 |
-
|
401 |
-
/**
|
402 |
-
*
|
403 |
-
* @param type $conditions
|
404 |
-
* @return type
|
405 |
-
*/
|
406 |
-
protected function evaluateLessConditions($conditions) {
|
407 |
-
$result = false;
|
408 |
-
|
409 |
-
foreach($this->prepareConditions($conditions) as $left => $right) {
|
410 |
-
$result = $result || ($left < $right);
|
411 |
-
}
|
412 |
-
|
413 |
-
return $result;
|
414 |
-
}
|
415 |
-
|
416 |
-
/**
|
417 |
-
*
|
418 |
-
* @param type $conditions
|
419 |
-
* @return type
|
420 |
-
*/
|
421 |
-
protected function evaluateGreaterOrEqualsConditions($conditions) {
|
422 |
-
$result = false;
|
423 |
-
|
424 |
-
foreach($this->prepareConditions($conditions) as $left => $right) {
|
425 |
-
$result = $result || ($left >= $right);
|
426 |
-
}
|
427 |
-
|
428 |
-
return $result;
|
429 |
-
}
|
430 |
-
|
431 |
-
/**
|
432 |
-
*
|
433 |
-
* @param type $conditions
|
434 |
-
* @return type
|
435 |
-
*/
|
436 |
-
protected function evaluateLessOrEqualsConditions($conditions) {
|
437 |
-
$result = false;
|
438 |
-
|
439 |
-
foreach($this->prepareConditions($conditions) as $left => $right) {
|
440 |
-
$result = $result || ($left <= $right);
|
441 |
-
}
|
442 |
-
|
443 |
-
return $result;
|
444 |
-
}
|
445 |
-
|
446 |
-
/**
|
447 |
-
*
|
448 |
-
* @param type $conditions
|
449 |
-
* @return type
|
450 |
-
*/
|
451 |
-
protected function evaluateInConditions($conditions) {
|
452 |
-
$result = false;
|
453 |
-
|
454 |
-
foreach($this->prepareConditions($conditions) as $left => $right) {
|
455 |
-
$result = $result || in_array($left, (array) $right, true);
|
456 |
-
}
|
457 |
-
|
458 |
-
return $result;
|
459 |
-
}
|
460 |
-
|
461 |
-
/**
|
462 |
-
*
|
463 |
-
* @param type $conditions
|
464 |
-
* @return type
|
465 |
-
*/
|
466 |
-
protected function evaluateNotInConditions($conditions) {
|
467 |
-
return !$this->evaluateInConditions($conditions);
|
468 |
-
}
|
469 |
-
|
470 |
-
/**
|
471 |
-
*
|
472 |
-
* @param type $conditions
|
473 |
-
* @return type
|
474 |
-
*/
|
475 |
-
protected function evaluateLikeConditions($conditions) {
|
476 |
-
$result = false;
|
477 |
-
|
478 |
-
foreach($this->prepareConditions($conditions) as $left => $right) {
|
479 |
-
foreach((array)$right as $el) {
|
480 |
-
$result = $result || preg_match('@^' . str_replace('\*', '.*', preg_quote($el)) . '$@', $left);
|
481 |
-
}
|
482 |
-
}
|
483 |
-
|
484 |
-
return $result;
|
485 |
-
}
|
486 |
-
|
487 |
-
/**
|
488 |
-
*
|
489 |
-
* @param type $conditions
|
490 |
-
* @return type
|
491 |
-
*/
|
492 |
-
protected function evaluateNotLikeConditions($conditions) {
|
493 |
-
return !$this->evaluateLikeConditions($conditions);
|
494 |
-
}
|
495 |
-
|
496 |
-
/**
|
497 |
-
*
|
498 |
-
* @param type $conditions
|
499 |
-
* @return type
|
500 |
-
*/
|
501 |
-
protected function evaluateRegexConditions($conditions) {
|
502 |
-
$result = false;
|
503 |
-
|
504 |
-
foreach($this->prepareConditions($conditions) as $left => $right) {
|
505 |
-
$result = $result || preg_match($right, $left);
|
506 |
-
}
|
507 |
-
|
508 |
-
return $result;
|
509 |
-
}
|
510 |
-
|
511 |
-
/**
|
512 |
-
*
|
513 |
-
* @param type $conditions
|
514 |
-
* @return array
|
515 |
-
*/
|
516 |
-
protected function prepareConditions($conditions) {
|
517 |
-
$result = array();
|
518 |
-
|
519 |
-
if (is_array($conditions)) {
|
520 |
-
foreach($conditions as $left => $right) {
|
521 |
-
$left = $this->parseTokens($left);
|
522 |
-
$right = $this->parseTokens($right);
|
523 |
-
|
524 |
-
$result[$left] = $right;
|
525 |
-
}
|
526 |
-
}
|
527 |
-
|
528 |
-
return $result;
|
529 |
-
}
|
530 |
-
|
531 |
-
/**
|
532 |
-
*
|
533 |
-
* @param type $chunk
|
534 |
-
* @return boolean
|
535 |
-
*/
|
536 |
-
protected function parseTokens($chunk) {
|
537 |
-
if (is_scalar($chunk)) {
|
538 |
-
if (preg_match_all('/(\$\{[^}]+\})/', $chunk, $match)) {
|
539 |
-
$chunk = $this->replaceTokens($chunk, $match[1]);
|
540 |
-
}
|
541 |
-
} elseif (is_array($chunk) || is_object($chunk)) {
|
542 |
-
foreach($chunk as &$value) {
|
543 |
-
$value = $this->parseTokens($value);
|
544 |
-
}
|
545 |
-
} else {
|
546 |
-
$chunk = false;
|
547 |
-
}
|
548 |
-
|
549 |
-
return $chunk;
|
550 |
-
}
|
551 |
-
|
552 |
-
/**
|
553 |
-
*
|
554 |
-
* @param type $str
|
555 |
-
* @param type $tokens
|
556 |
-
* @return type
|
557 |
-
*/
|
558 |
-
protected function replaceTokens($str, $tokens) {
|
559 |
-
foreach($tokens as $token) {
|
560 |
-
$str = str_replace(
|
561 |
-
$token,
|
562 |
-
$this->evaluateToken(
|
563 |
-
preg_replace('/^\$\{([^}]+)\}$/', '${1}', $token)
|
564 |
-
),
|
565 |
-
$str
|
566 |
);
|
567 |
}
|
568 |
|
569 |
-
return $
|
570 |
-
}
|
571 |
-
|
572 |
-
/**
|
573 |
-
*
|
574 |
-
* @param type $token
|
575 |
-
* @param type $value
|
576 |
-
*/
|
577 |
-
protected function evaluateToken($token, $value = null) {
|
578 |
-
$parts = explode('.', $token);
|
579 |
-
|
580 |
-
switch($parts[0]) {
|
581 |
-
case 'USER':
|
582 |
-
$value = $this->getUserValue($parts[1], $value);
|
583 |
-
break;
|
584 |
-
|
585 |
-
case 'DATETIME':
|
586 |
-
$value = $this->getDateTimeValue($parts[1], $value);
|
587 |
-
break;
|
588 |
-
|
589 |
-
case 'GET':
|
590 |
-
$value = AAM_Core_Request::get($parts[1], $value);
|
591 |
-
break;
|
592 |
-
|
593 |
-
case 'POST':
|
594 |
-
$value = AAM_Core_Request::post($parts[1], $value);
|
595 |
-
break;
|
596 |
-
|
597 |
-
case 'COOKIE':
|
598 |
-
$value = AAM_Core_Request::cookie($parts[1], $value);
|
599 |
-
break;
|
600 |
-
|
601 |
-
case 'CALLBACK':
|
602 |
-
$value = (is_callable($parts[1]) ? call_user_func($parts[1]) : $value);
|
603 |
-
break;
|
604 |
-
|
605 |
-
default:
|
606 |
-
$value = apply_filters('aam-evaluate-token-filter', $value, $parts[1]);
|
607 |
-
break;
|
608 |
-
}
|
609 |
-
|
610 |
-
return $value;
|
611 |
-
}
|
612 |
-
|
613 |
-
/**
|
614 |
-
*
|
615 |
-
* @param type $prop
|
616 |
-
* @param type $value
|
617 |
-
* @return type
|
618 |
-
*/
|
619 |
-
protected function getUserValue($prop, $value = null) {
|
620 |
-
$user = AAM::api()->getUser();
|
621 |
-
|
622 |
-
switch($prop) {
|
623 |
-
case 'IPAddress':
|
624 |
-
$value = AAM_Core_Request::server('REMOTE_IP');
|
625 |
-
break;
|
626 |
-
|
627 |
-
case 'Authenticated':
|
628 |
-
$value = $user->isVisitor() ? false : true;
|
629 |
-
break;
|
630 |
-
|
631 |
-
default:
|
632 |
-
$value = $user->{$prop};
|
633 |
-
break;
|
634 |
-
}
|
635 |
-
|
636 |
-
return $value;
|
637 |
-
}
|
638 |
-
|
639 |
-
/**
|
640 |
-
*
|
641 |
-
* @param type $prop
|
642 |
-
* @return type
|
643 |
-
*/
|
644 |
-
protected function getDateTimeValue($prop) {
|
645 |
-
return date($prop);
|
646 |
}
|
647 |
|
648 |
/**
|
@@ -758,11 +411,34 @@ class AAM_Core_Object_Policy extends AAM_Core_Object {
|
|
758 |
* @return type
|
759 |
*/
|
760 |
public function getResources(AAM_Core_Subject $subject = null) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
761 |
$response = array();
|
762 |
|
763 |
if (is_null($subject)) {
|
764 |
-
if (!isset(
|
765 |
-
foreach(
|
766 |
foreach ($resources as $id => $props) {
|
767 |
if (!empty($props['Unset'])) {
|
768 |
if (isset($response[$id])) { // Clear the entire chain
|
@@ -773,44 +449,16 @@ class AAM_Core_Object_Policy extends AAM_Core_Object {
|
|
773 |
}
|
774 |
}
|
775 |
}
|
776 |
-
|
777 |
-
} else {
|
778 |
-
$response = self::$resources['__combined'];
|
779 |
-
}
|
780 |
-
} else {
|
781 |
-
$subjectId = $subject->getUID();
|
782 |
-
$subjectId .= ($subject->getId() ? ".{$subject->getId()}" : '');
|
783 |
-
|
784 |
-
if (isset(self::$resources[$subjectId])) {
|
785 |
-
$response = self::$resources[$subjectId];
|
786 |
-
}
|
787 |
-
}
|
788 |
-
|
789 |
-
return $response;
|
790 |
-
}
|
791 |
-
|
792 |
-
/**
|
793 |
-
*
|
794 |
-
* @return type
|
795 |
-
*/
|
796 |
-
public function getFeatures(AAM_Core_Subject $subject = null) {
|
797 |
-
$response = array();
|
798 |
-
|
799 |
-
if (is_null($subject)) {
|
800 |
-
if (!isset(self::$features['__combined'])) {
|
801 |
-
foreach(self::$features as $features) {
|
802 |
-
$response = array_merge($features, $response);
|
803 |
-
}
|
804 |
-
self::$features['__combined'] = $response;
|
805 |
} else {
|
806 |
-
$response =
|
807 |
}
|
808 |
} else {
|
809 |
$subjectId = $subject->getUID();
|
810 |
$subjectId .= ($subject->getId() ? ".{$subject->getId()}" : '');
|
811 |
|
812 |
-
if (isset(
|
813 |
-
$response =
|
814 |
}
|
815 |
}
|
816 |
|
55 |
}
|
56 |
|
57 |
/**
|
58 |
+
* Initialize the policy rules for current subject
|
59 |
*
|
60 |
+
* @return void
|
61 |
+
*
|
62 |
+
* @access public
|
63 |
*/
|
64 |
public function initialize() {
|
65 |
$subject = $this->getSubject();
|
85 |
// Load statements for policies
|
86 |
$subjectId = $subject->getUID();
|
87 |
$subjectId .= ($subject->getId() ? ".{$subject->getId()}" : '');
|
88 |
+
|
89 |
$this->load($subjectId, $option);
|
90 |
}
|
91 |
|
92 |
/**
|
93 |
+
* Load all defined policies for specified subject
|
94 |
+
*
|
95 |
+
* @param string $subjectId
|
96 |
+
* @param array $policies
|
97 |
+
*
|
98 |
+
* @return void
|
99 |
*
|
100 |
+
* @access public
|
101 |
*/
|
102 |
public function load($subjectId, $policies) {
|
103 |
$resources = array();
|
104 |
$features = array();
|
105 |
+
$list = $this->parsePolicy($subjectId, $policies);
|
|
|
106 |
|
107 |
// Evaluate all Statements first
|
108 |
foreach($list['Statements'] as $statement) {
|
290 |
$result = true;
|
291 |
|
292 |
if (!empty($statement['Condition']) && !is_scalar($statement['Condition'])) {
|
293 |
+
$result = AAM_Core_Policy_Condition::getInstance()->evaluate(
|
294 |
+
$statement['Condition']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
295 |
);
|
296 |
}
|
297 |
|
298 |
+
return $result;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
299 |
}
|
300 |
|
301 |
/**
|
411 |
* @return type
|
412 |
*/
|
413 |
public function getResources(AAM_Core_Subject $subject = null) {
|
414 |
+
return $this->getList(self::$resources, $subject);
|
415 |
+
}
|
416 |
+
|
417 |
+
/**
|
418 |
+
*
|
419 |
+
* @return type
|
420 |
+
*/
|
421 |
+
public function getFeatures(AAM_Core_Subject $subject = null) {
|
422 |
+
return $this->getList(self::$features, $subject);
|
423 |
+
}
|
424 |
+
|
425 |
+
/**
|
426 |
+
* Get list from source
|
427 |
+
*
|
428 |
+
* @param array $source
|
429 |
+
* @param AAM_Core_Subject $subject
|
430 |
+
*
|
431 |
+
* @return array
|
432 |
+
*
|
433 |
+
* @access protected
|
434 |
+
* @since v5.8.2
|
435 |
+
*/
|
436 |
+
protected function getList(&$source, AAM_Core_Subject $subject = null) {
|
437 |
$response = array();
|
438 |
|
439 |
if (is_null($subject)) {
|
440 |
+
if (!isset($source['__combined'])) {
|
441 |
+
foreach($source as $resources) {
|
442 |
foreach ($resources as $id => $props) {
|
443 |
if (!empty($props['Unset'])) {
|
444 |
if (isset($response[$id])) { // Clear the entire chain
|
449 |
}
|
450 |
}
|
451 |
}
|
452 |
+
$source['__combined'] = $response;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
453 |
} else {
|
454 |
+
$response = $source['__combined'];
|
455 |
}
|
456 |
} else {
|
457 |
$subjectId = $subject->getUID();
|
458 |
$subjectId .= ($subject->getId() ? ".{$subject->getId()}" : '');
|
459 |
|
460 |
+
if (isset($source[$subjectId])) {
|
461 |
+
$response = $source[$subjectId];
|
462 |
}
|
463 |
}
|
464 |
|
Application/Core/Policy/Condition.php
ADDED
@@ -0,0 +1,413 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
* AAM core policy condition evaluator
|
12 |
+
*
|
13 |
+
* @package AAM
|
14 |
+
* @author Vasyl Martyniuk <vasyl@vasyltech.com>
|
15 |
+
* @since AAM v5.8.2
|
16 |
+
*/
|
17 |
+
final class AAM_Core_Policy_Condition {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Single instance of itself
|
21 |
+
*
|
22 |
+
* @var AAM_Core_Policy_Condition
|
23 |
+
*
|
24 |
+
* @access protected
|
25 |
+
* @static
|
26 |
+
*/
|
27 |
+
protected static $instance = null;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Map between condition type and method that evaluates the
|
31 |
+
* group of conditions
|
32 |
+
*
|
33 |
+
* @var array
|
34 |
+
*
|
35 |
+
* @access protected
|
36 |
+
*/
|
37 |
+
protected $map = array(
|
38 |
+
'between' => 'evaluateBetweenConditions',
|
39 |
+
'equals' => 'evaluateEqualsConditions',
|
40 |
+
'notequals' => 'evaluateNotEqualsConditions',
|
41 |
+
'greater' => 'evaluateGreaterConditions',
|
42 |
+
'less' => 'evaluateLessConditions',
|
43 |
+
'greaterorequals' => 'evaluateGreaterOrEqualsConditions',
|
44 |
+
'lessorequals' => 'evaluateLessOrEqualsConditions',
|
45 |
+
'in' => 'evaluateInConditions',
|
46 |
+
'notin' => 'evaluateNotInConditions',
|
47 |
+
'like' => 'evaluateLikeConditions',
|
48 |
+
'notlike' => 'evaluateNotLikeConditions',
|
49 |
+
'regex' => 'evaluateRegexConditions'
|
50 |
+
);
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Constructor
|
54 |
+
*
|
55 |
+
* @return void
|
56 |
+
*
|
57 |
+
* @access protected
|
58 |
+
*/
|
59 |
+
protected function __construct() {}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Evaluate the group of conditions based on type
|
63 |
+
*
|
64 |
+
* @param array $conditions
|
65 |
+
*
|
66 |
+
* @return boolean
|
67 |
+
*
|
68 |
+
* @access public
|
69 |
+
*/
|
70 |
+
public function evaluate($conditions) {
|
71 |
+
$result = true;
|
72 |
+
|
73 |
+
foreach($conditions as $type => $conditions) {
|
74 |
+
$type = strtolower($type);
|
75 |
+
|
76 |
+
if (isset($this->map[$type])) {
|
77 |
+
$callback = array($this, $this->map[$type]);
|
78 |
+
$result = $result && call_user_func($callback, $conditions);
|
79 |
+
} else {
|
80 |
+
$result = false;
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
return $result;
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Evaluate group of BETWEEN conditions
|
89 |
+
*
|
90 |
+
* @param array $conditions
|
91 |
+
*
|
92 |
+
* @return boolean
|
93 |
+
*
|
94 |
+
* @access protected
|
95 |
+
*/
|
96 |
+
protected function evaluateBetweenConditions($conditions) {
|
97 |
+
$result = false;
|
98 |
+
|
99 |
+
foreach($this->prepareConditions($conditions) as $left => $right) {
|
100 |
+
foreach((array)$right as $subset) {
|
101 |
+
$min = (is_array($subset) ? array_shift($subset) : $subset);
|
102 |
+
$max = (is_array($subset) ? end($subset) : $subset);
|
103 |
+
|
104 |
+
$result = $result || ($left >= $min && $left <= $max);
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
return $result;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Evaluate group of EQUALS conditions
|
113 |
+
*
|
114 |
+
* The values have to be identical
|
115 |
+
*
|
116 |
+
* @param array $conditions
|
117 |
+
*
|
118 |
+
* @return boolean
|
119 |
+
*
|
120 |
+
* @access protected
|
121 |
+
*/
|
122 |
+
protected function evaluateEqualsConditions($conditions) {
|
123 |
+
$result = false;
|
124 |
+
|
125 |
+
foreach($this->prepareConditions($conditions) as $left => $right) {
|
126 |
+
$result = $result || ($left === $right);
|
127 |
+
}
|
128 |
+
|
129 |
+
return $result;
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Evaluate group of NOT EQUALs conditions
|
134 |
+
*
|
135 |
+
* @param array $conditions
|
136 |
+
*
|
137 |
+
* @return boolean
|
138 |
+
*
|
139 |
+
* @access protected
|
140 |
+
*/
|
141 |
+
protected function evaluateNotEqualsConditions($conditions) {
|
142 |
+
return !$this->evaluateEqualsConditions($conditions);
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Evaluate group of GREATER THEN conditions
|
147 |
+
*
|
148 |
+
* @param array $conditions
|
149 |
+
*
|
150 |
+
* @return boolean
|
151 |
+
*
|
152 |
+
* @access protected
|
153 |
+
*/
|
154 |
+
protected function evaluateGreaterConditions($conditions) {
|
155 |
+
$result = false;
|
156 |
+
|
157 |
+
foreach($this->prepareConditions($conditions) as $left => $right) {
|
158 |
+
$result = $result || ($left > $right);
|
159 |
+
}
|
160 |
+
|
161 |
+
return $result;
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Evaluate group of LESS THEN conditions
|
166 |
+
*
|
167 |
+
* @param array $conditions
|
168 |
+
*
|
169 |
+
* @return boolean
|
170 |
+
*
|
171 |
+
* @access protected
|
172 |
+
*/
|
173 |
+
protected function evaluateLessConditions($conditions) {
|
174 |
+
$result = false;
|
175 |
+
|
176 |
+
foreach($this->prepareConditions($conditions) as $left => $right) {
|
177 |
+
$result = $result || ($left < $right);
|
178 |
+
}
|
179 |
+
|
180 |
+
return $result;
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Evaluate group of GREATER OR EQUALS THEN conditions
|
185 |
+
*
|
186 |
+
* @param array $conditions
|
187 |
+
*
|
188 |
+
* @return boolean
|
189 |
+
*
|
190 |
+
* @access protected
|
191 |
+
*/
|
192 |
+
protected function evaluateGreaterOrEqualsConditions($conditions) {
|
193 |
+
$result = false;
|
194 |
+
|
195 |
+
foreach($this->prepareConditions($conditions) as $left => $right) {
|
196 |
+
$result = $result || ($left >= $right);
|
197 |
+
}
|
198 |
+
|
199 |
+
return $result;
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Evaluate group of LESS OR EQUALS THEN conditions
|
204 |
+
*
|
205 |
+
* @param array $conditions
|
206 |
+
*
|
207 |
+
* @return boolean
|
208 |
+
*
|
209 |
+
* @access protected
|
210 |
+
*/
|
211 |
+
protected function evaluateLessOrEqualsConditions($conditions) {
|
212 |
+
$result = false;
|
213 |
+
|
214 |
+
foreach($this->prepareConditions($conditions) as $left => $right) {
|
215 |
+
$result = $result || ($left <= $right);
|
216 |
+
}
|
217 |
+
|
218 |
+
return $result;
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Evaluate group of IN conditions
|
223 |
+
*
|
224 |
+
* @param array $conditions
|
225 |
+
*
|
226 |
+
* @return boolean
|
227 |
+
*
|
228 |
+
* @access protected
|
229 |
+
*/
|
230 |
+
protected function evaluateInConditions($conditions) {
|
231 |
+
$result = false;
|
232 |
+
|
233 |
+
foreach($this->prepareConditions($conditions) as $left => $right) {
|
234 |
+
$result = $result || in_array($left, (array) $right, true);
|
235 |
+
}
|
236 |
+
|
237 |
+
return $result;
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Evaluate group of NOT IN conditions
|
242 |
+
*
|
243 |
+
* @param array $conditions
|
244 |
+
*
|
245 |
+
* @return boolean
|
246 |
+
*
|
247 |
+
* @access protected
|
248 |
+
*/
|
249 |
+
protected function evaluateNotInConditions($conditions) {
|
250 |
+
return !$this->evaluateInConditions($conditions);
|
251 |
+
}
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Evaluate group of LIKE conditions
|
255 |
+
*
|
256 |
+
* @param array $conditions
|
257 |
+
*
|
258 |
+
* @return boolean
|
259 |
+
*
|
260 |
+
* @access protected
|
261 |
+
*/
|
262 |
+
protected function evaluateLikeConditions($conditions) {
|
263 |
+
$result = false;
|
264 |
+
|
265 |
+
foreach($this->prepareConditions($conditions) as $left => $right) {
|
266 |
+
foreach((array)$right as $el) {
|
267 |
+
$sub = str_replace('\*', '.*', preg_quote($el));
|
268 |
+
$result = $result || preg_match('@^' . $sub . '$@', $left);
|
269 |
+
}
|
270 |
+
}
|
271 |
+
|
272 |
+
return $result;
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* Evaluate group of NOT LIKE conditions
|
277 |
+
*
|
278 |
+
* @param array $conditions
|
279 |
+
*
|
280 |
+
* @return boolean
|
281 |
+
*
|
282 |
+
* @access protected
|
283 |
+
*/
|
284 |
+
protected function evaluateNotLikeConditions($conditions) {
|
285 |
+
return !$this->evaluateLikeConditions($conditions);
|
286 |
+
}
|
287 |
+
|
288 |
+
/**
|
289 |
+
* Evaluate group of REGEX conditions
|
290 |
+
*
|
291 |
+
* @param array $conditions
|
292 |
+
*
|
293 |
+
* @return boolean
|
294 |
+
*
|
295 |
+
* @access protected
|
296 |
+
*/
|
297 |
+
protected function evaluateRegexConditions($conditions) {
|
298 |
+
$result = false;
|
299 |
+
|
300 |
+
foreach($this->prepareConditions($conditions) as $left => $right) {
|
301 |
+
$result = $result || preg_match($right, $left);
|
302 |
+
}
|
303 |
+
|
304 |
+
return $result;
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Prepare conditions by replacing all defined tokens
|
309 |
+
*
|
310 |
+
* @param array $conditions
|
311 |
+
*
|
312 |
+
* @return array
|
313 |
+
*
|
314 |
+
* @access protected
|
315 |
+
*/
|
316 |
+
protected function prepareConditions($conditions) {
|
317 |
+
$result = array();
|
318 |
+
|
319 |
+
if (is_array($conditions)) {
|
320 |
+
foreach($conditions as $left => $right) {
|
321 |
+
$left = $this->parseExpression($left);
|
322 |
+
$right = $this->parseExpression($right);
|
323 |
+
|
324 |
+
if ($left !== false) { // Do not include any failed conditions
|
325 |
+
$result[$left] = $right;
|
326 |
+
}
|
327 |
+
}
|
328 |
+
}
|
329 |
+
|
330 |
+
return $result;
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Parse condition and try to replace all defined tokens
|
335 |
+
*
|
336 |
+
* @param mixed $exp Part of the condition (either left or right)
|
337 |
+
*
|
338 |
+
* @return mixed Prepared part of the condition or false on failure
|
339 |
+
*
|
340 |
+
* @access protected
|
341 |
+
*/
|
342 |
+
protected function parseExpression($exp) {
|
343 |
+
if (is_scalar($exp)) {
|
344 |
+
if (preg_match_all('/(\$\{[^}]+\})/', $exp, $match)) {
|
345 |
+
$exp = AAM_Core_Policy_Token::evaluate($exp, $match[1]);
|
346 |
+
}
|
347 |
+
// If there is type scaling, perform it too
|
348 |
+
if (preg_match('/^\(\*(string|ip|int|boolean|bool)\)(.*)/i', $exp, $scale)) {
|
349 |
+
$exp = str_replace(
|
350 |
+
"(*{$scale[1]}", '', $this->scaleValue($scale[2], $scale[1])
|
351 |
+
);
|
352 |
+
}
|
353 |
+
} elseif (is_array($exp) || is_object($exp)) {
|
354 |
+
foreach($exp as &$value) {
|
355 |
+
$value = $this->parseExpression($value);
|
356 |
+
}
|
357 |
+
} else {
|
358 |
+
$exp = false;
|
359 |
+
}
|
360 |
+
|
361 |
+
return $exp;
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Scale value to specific type
|
366 |
+
*
|
367 |
+
* @param mixed $value
|
368 |
+
* @param string $type
|
369 |
+
*
|
370 |
+
* @return mixed
|
371 |
+
*
|
372 |
+
* @access protected
|
373 |
+
*/
|
374 |
+
protected function scaleValue($value, $type) {
|
375 |
+
switch(strtolower($type)) {
|
376 |
+
case 'string':
|
377 |
+
$value = (string)$value;
|
378 |
+
break;
|
379 |
+
|
380 |
+
case 'ip':
|
381 |
+
$value = inet_pton($value);
|
382 |
+
break;
|
383 |
+
|
384 |
+
case 'int':
|
385 |
+
$value = (int)$value;
|
386 |
+
break;
|
387 |
+
|
388 |
+
case 'boolean':
|
389 |
+
case 'bool':
|
390 |
+
$value = (bool)$value;
|
391 |
+
break;
|
392 |
+
}
|
393 |
+
|
394 |
+
return $value;
|
395 |
+
}
|
396 |
+
|
397 |
+
/**
|
398 |
+
* Get single instance of itself
|
399 |
+
*
|
400 |
+
* @return AAM_Core_Policy_Condition
|
401 |
+
*
|
402 |
+
* @access public
|
403 |
+
* @static
|
404 |
+
*/
|
405 |
+
public static function getInstance() {
|
406 |
+
if (is_null(self::$instance)) {
|
407 |
+
self::$instance = new self;
|
408 |
+
}
|
409 |
+
|
410 |
+
return self::$instance;
|
411 |
+
}
|
412 |
+
|
413 |
+
}
|
Application/Core/Policy/Token.php
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
* AAM core policy token evaluator
|
12 |
+
*
|
13 |
+
* @package AAM
|
14 |
+
* @author Vasyl Martyniuk <vasyl@vasyltech.com>
|
15 |
+
* @since AAM v5.8.2
|
16 |
+
*/
|
17 |
+
final class AAM_Core_Policy_Token {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Literal map token's type to the executable method that returns actual value
|
21 |
+
*
|
22 |
+
* @var array
|
23 |
+
*
|
24 |
+
* @access protected
|
25 |
+
* @static
|
26 |
+
*/
|
27 |
+
protected static $map = array(
|
28 |
+
'USER' => 'AAM_Core_Policy_Token::getUserValue',
|
29 |
+
'DATETIME' => 'AAM_Core_Policy_Token::getDateTimeValue',
|
30 |
+
'GET' => 'AAM_Core_Request::get',
|
31 |
+
'POST' => 'AAM_Core_Request::post',
|
32 |
+
'COOKIE' => 'AAM_Core_Request::cookie'
|
33 |
+
);
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Evaluate collection of tokens and replace them with values
|
37 |
+
*
|
38 |
+
* @param string $part String with tokens
|
39 |
+
* @param array $tokens Extracted token
|
40 |
+
*
|
41 |
+
* @return string
|
42 |
+
*
|
43 |
+
* @access public
|
44 |
+
* @static
|
45 |
+
*/
|
46 |
+
public static function evaluate($part, array $tokens) {
|
47 |
+
foreach($tokens as $token) {
|
48 |
+
$part = str_replace(
|
49 |
+
$token,
|
50 |
+
self::getValue(preg_replace('/^\$\{([^}]+)\}$/', '${1}', $token)),
|
51 |
+
$part
|
52 |
+
);
|
53 |
+
}
|
54 |
+
|
55 |
+
return $part;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Get token value
|
60 |
+
*
|
61 |
+
* @param string $token
|
62 |
+
* @param mixed $value
|
63 |
+
*
|
64 |
+
* @return mixed
|
65 |
+
*
|
66 |
+
* @access protected
|
67 |
+
* @static
|
68 |
+
*/
|
69 |
+
protected static function getValue($token, $value = null) {
|
70 |
+
$parts = explode('.', $token);
|
71 |
+
|
72 |
+
if (isset(self::$map[$parts[0]])) {
|
73 |
+
$value = call_user_func(self::$map[$parts[0]], $parts[1], $value);
|
74 |
+
} elseif ($parts[0] === 'CALLBACK' && is_callable($parts[1])) {
|
75 |
+
$value = call_user_func($parts[1], $value);
|
76 |
+
}
|
77 |
+
|
78 |
+
return $value;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Get USER's value
|
83 |
+
*
|
84 |
+
* @param string $prop
|
85 |
+
*
|
86 |
+
* @return mixed
|
87 |
+
*
|
88 |
+
* @access protected
|
89 |
+
* @static
|
90 |
+
*/
|
91 |
+
protected static function getUserValue($prop) {
|
92 |
+
$user = AAM::api()->getUser();
|
93 |
+
|
94 |
+
switch(strtolower($prop)) {
|
95 |
+
case 'ip':
|
96 |
+
case 'ipaddress':
|
97 |
+
$value = AAM_Core_Request::server('REMOTE_ADDR');
|
98 |
+
break;
|
99 |
+
|
100 |
+
case 'authenticated':
|
101 |
+
$value = $user->isVisitor() ? false : true;
|
102 |
+
break;
|
103 |
+
|
104 |
+
default:
|
105 |
+
$value = $user->{$prop};
|
106 |
+
break;
|
107 |
+
}
|
108 |
+
|
109 |
+
return $value;
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Get current datetime value
|
114 |
+
*
|
115 |
+
* @param string $prop
|
116 |
+
*
|
117 |
+
* @return string
|
118 |
+
*
|
119 |
+
* @access protected
|
120 |
+
* @static
|
121 |
+
*/
|
122 |
+
protected static function getDateTimeValue($prop) {
|
123 |
+
return date($prop);
|
124 |
+
}
|
125 |
+
|
126 |
+
}
|
Application/Core/Subject.php
CHANGED
@@ -75,6 +75,11 @@ abstract class AAM_Core_Subject {
|
|
75 |
$this->setSubject($this->retrieveSubject());
|
76 |
}
|
77 |
|
|
|
|
|
|
|
|
|
|
|
78 |
/**
|
79 |
* Trigger Subject native methods
|
80 |
*
|
75 |
$this->setSubject($this->retrieveSubject());
|
76 |
}
|
77 |
|
78 |
+
/**
|
79 |
+
*
|
80 |
+
*/
|
81 |
+
public function initialize() { }
|
82 |
+
|
83 |
/**
|
84 |
* Trigger Subject native methods
|
85 |
*
|
Application/Core/Subject/Role.php
CHANGED
@@ -39,7 +39,7 @@ class AAM_Core_Subject_Role extends AAM_Core_Subject {
|
|
39 |
|
40 |
return $role;
|
41 |
}
|
42 |
-
|
43 |
/**
|
44 |
* Delete User Role
|
45 |
*
|
39 |
|
40 |
return $role;
|
41 |
}
|
42 |
+
|
43 |
/**
|
44 |
* Delete User Role
|
45 |
*
|
Application/Core/Subject/User.php
CHANGED
@@ -226,12 +226,14 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
|
|
226 |
/**
|
227 |
*
|
228 |
*/
|
229 |
-
public function
|
230 |
$subject = $this->getSubject();
|
231 |
|
232 |
// Retrieve all capabilities set in Access Policy
|
233 |
// Load Capabilities from the policy
|
234 |
-
$stms = AAM_Core_Policy_Manager::getInstance()->find(
|
|
|
|
|
235 |
|
236 |
$policyCaps = array();
|
237 |
|
@@ -242,9 +244,42 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
|
|
242 |
}
|
243 |
}
|
244 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
//reset the user capabilities
|
246 |
-
$subject->allcaps = array_merge($subject->allcaps, $policyCaps, $this->aamCaps);
|
247 |
-
$subject->caps = array_merge($subject->caps, $policyCaps, $this->aamCaps);
|
248 |
}
|
249 |
|
250 |
/**
|
@@ -268,24 +303,7 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
|
|
268 |
* @access public
|
269 |
*/
|
270 |
public function hasCapability($capability) {
|
271 |
-
|
272 |
-
if (isset($this->aamCaps[$capability])) {
|
273 |
-
$result = !empty($this->aamCaps[$capability]);
|
274 |
-
} else {
|
275 |
-
// Priority #2: capability that has been defined in policy
|
276 |
-
// Override by policy if is set
|
277 |
-
$stm = AAM::api()->getPolicyManager()->find(
|
278 |
-
"/^Capability:{$capability}$/i", $this
|
279 |
-
);
|
280 |
-
if (!empty($stm)) {
|
281 |
-
$val = end($stm);
|
282 |
-
$result = ($val['Effect'] === 'allow' ? 1 : 0);
|
283 |
-
} else {
|
284 |
-
$result = user_can($this->getSubject(), $capability);
|
285 |
-
}
|
286 |
-
}
|
287 |
-
|
288 |
-
return $result;
|
289 |
}
|
290 |
|
291 |
/**
|
226 |
/**
|
227 |
*
|
228 |
*/
|
229 |
+
public function initialize($isolated = false) {
|
230 |
$subject = $this->getSubject();
|
231 |
|
232 |
// Retrieve all capabilities set in Access Policy
|
233 |
// Load Capabilities from the policy
|
234 |
+
$stms = AAM_Core_Policy_Manager::getInstance()->find(
|
235 |
+
"/^Capability:/i", ($isolated ? $this : null)
|
236 |
+
);
|
237 |
|
238 |
$policyCaps = array();
|
239 |
|
244 |
}
|
245 |
}
|
246 |
|
247 |
+
// Load Roles from the policy
|
248 |
+
$stms = AAM_Core_Policy_Manager::getInstance()->find(
|
249 |
+
"/^Role:/i", ($isolated ? $this : null)
|
250 |
+
);
|
251 |
+
|
252 |
+
$roles = (array) $subject->roles;
|
253 |
+
|
254 |
+
$allRoles = AAM_Core_API::getRoles();
|
255 |
+
$roleCaps = array();
|
256 |
+
|
257 |
+
foreach($stms as $key => $stm) {
|
258 |
+
$chunks = explode(':', $key);
|
259 |
+
|
260 |
+
if ($stm['Effect'] === 'allow') {
|
261 |
+
if (!in_array($chunks[1], $roles, true)) {
|
262 |
+
if ($allRoles->is_role($chunks[1])) {
|
263 |
+
$roleCaps = array_merge($roleCaps, $allRoles->get_role($chunks[1])->capabilities);
|
264 |
+
$roleCaps[] = $chunks[1];
|
265 |
+
}
|
266 |
+
$roles[] = $chunks[1];
|
267 |
+
}
|
268 |
+
} elseif (in_array($chunks[1], $roles, true)) {
|
269 |
+
// Make sure that we delete all instanses of the role
|
270 |
+
foreach($roles as $i => $role){
|
271 |
+
if ($role === $chunks[1]) {
|
272 |
+
unset($roles[$i]);
|
273 |
+
}
|
274 |
+
}
|
275 |
+
}
|
276 |
+
}
|
277 |
+
|
278 |
+
$subject->roles = $roles;
|
279 |
+
|
280 |
//reset the user capabilities
|
281 |
+
$subject->allcaps = array_merge($subject->allcaps, $roleCaps, $policyCaps, $this->aamCaps);
|
282 |
+
$subject->caps = array_merge($subject->caps, $roleCaps, $policyCaps, $this->aamCaps);
|
283 |
}
|
284 |
|
285 |
/**
|
303 |
* @access public
|
304 |
*/
|
305 |
public function hasCapability($capability) {
|
306 |
+
return user_can($this->getSubject(), $capability);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
307 |
}
|
308 |
|
309 |
/**
|
Application/Shared/Manager.php
CHANGED
@@ -113,7 +113,12 @@ class AAM_Shared_Manager {
|
|
113 |
*/
|
114 |
public function init() {
|
115 |
//check URI
|
116 |
-
|
|
|
|
|
|
|
|
|
|
|
117 |
|
118 |
//register CPT AAM_E_Product
|
119 |
register_post_type('aam_policy', array(
|
113 |
*/
|
114 |
public function init() {
|
115 |
//check URI
|
116 |
+
$this->checkURIAccess();
|
117 |
+
|
118 |
+
//check Media Access if needed
|
119 |
+
if (AAM_Core_Request::get('aam-media')) {
|
120 |
+
AAM_Core_Media::bootstrap()->authorize();
|
121 |
+
}
|
122 |
|
123 |
//register CPT AAM_E_Product
|
124 |
register_post_type('aam_policy', array(
|
aam.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
/**
|
4 |
Plugin Name: Advanced Access Manager
|
5 |
Description: All you need to manage access to your WordPress website
|
6 |
-
Version: 5.8.
|
7 |
Author: Vasyl Martyniuk <vasyl@vasyltech.com>
|
8 |
Author URI: https://vasyltech.com
|
9 |
|
@@ -128,7 +128,7 @@ class AAM {
|
|
128 |
// Load AAM
|
129 |
AAM::getInstance();
|
130 |
|
131 |
-
|
132 |
if (AAM_Core_Config::get('core.settings.extensionSupport', true)) {
|
133 |
AAM_Extension_Repository::getInstance()->load();
|
134 |
}
|
@@ -149,9 +149,6 @@ class AAM {
|
|
149 |
* @static
|
150 |
*/
|
151 |
public static function onInit() {
|
152 |
-
//load media control
|
153 |
-
AAM_Core_Media::bootstrap();
|
154 |
-
|
155 |
//bootstrap the correct interface
|
156 |
if (AAM_Core_Api_Area::isBackend()) {
|
157 |
AAM_Backend_Manager::bootstrap();
|
@@ -173,7 +170,7 @@ class AAM {
|
|
173 |
self::$_instance = new self;
|
174 |
|
175 |
// Load user capabilities
|
176 |
-
self::$_instance->getUser()->
|
177 |
|
178 |
// Logout user if he/she is blocked
|
179 |
self::$_instance->getUser()->validateUserStatus();
|
3 |
/**
|
4 |
Plugin Name: Advanced Access Manager
|
5 |
Description: All you need to manage access to your WordPress website
|
6 |
+
Version: 5.8.2
|
7 |
Author: Vasyl Martyniuk <vasyl@vasyltech.com>
|
8 |
Author URI: https://vasyltech.com
|
9 |
|
128 |
// Load AAM
|
129 |
AAM::getInstance();
|
130 |
|
131 |
+
//load all installed extension
|
132 |
if (AAM_Core_Config::get('core.settings.extensionSupport', true)) {
|
133 |
AAM_Extension_Repository::getInstance()->load();
|
134 |
}
|
149 |
* @static
|
150 |
*/
|
151 |
public static function onInit() {
|
|
|
|
|
|
|
152 |
//bootstrap the correct interface
|
153 |
if (AAM_Core_Api_Area::isBackend()) {
|
154 |
AAM_Backend_Manager::bootstrap();
|
170 |
self::$_instance = new self;
|
171 |
|
172 |
// Load user capabilities
|
173 |
+
self::$_instance->getUser()->initialize();
|
174 |
|
175 |
// Logout user if he/she is blocked
|
176 |
self::$_instance->getUser()->validateUserStatus();
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: vasyltech
|
|
3 |
Tags: access control, membership, backend menu, user role, restricted content, security, jwt
|
4 |
Requires at least: 4.0
|
5 |
Tested up to: 5.0.3
|
6 |
-
Stable tag: 5.8.
|
7 |
|
8 |
All you need to manage access to you WordPress websites on frontend, backend and API levels for any role, user or visitors.
|
9 |
|
@@ -79,6 +79,15 @@ https://www.youtube.com/watch?v=mj5Xa_Wc16Y
|
|
79 |
|
80 |
== Changelog ==
|
81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
= 5.8.1 =
|
83 |
* Fixed bug that causes fatal error with Policy editor on Linux servers
|
84 |
* Profiled and improved several bottlenecks that may speed-up website load up to 300 milliseconds
|
3 |
Tags: access control, membership, backend menu, user role, restricted content, security, jwt
|
4 |
Requires at least: 4.0
|
5 |
Tested up to: 5.0.3
|
6 |
+
Stable tag: 5.8.2
|
7 |
|
8 |
All you need to manage access to you WordPress websites on frontend, backend and API levels for any role, user or visitors.
|
9 |
|
79 |
|
80 |
== Changelog ==
|
81 |
|
82 |
+
= 5.8.2 =
|
83 |
+
* Fixed numerous bugs with access control for media
|
84 |
+
* Added support for change_own_password capability
|
85 |
+
* Added support for change_passwords capability
|
86 |
+
* Added type casting to the Access Policy document
|
87 |
+
* Added new resource `Role` to the Access Policy
|
88 |
+
* Refactored internal Access Policy implementation
|
89 |
+
* Improved performance
|
90 |
+
|
91 |
= 5.8.1 =
|
92 |
* Fixed bug that causes fatal error with Policy editor on Linux servers
|
93 |
* Profiled and improved several bottlenecks that may speed-up website load up to 300 milliseconds
|