Advanced Access Manager - Version 5.8.2

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 Icon 128x128 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 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", AAM_Backend_Subject::getInstance()->get()
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
- $response['data'][] = $this->prepareRow(
46
- new AAM_Core_Subject_User($row->ID)
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
- $s = preg_replace('/(-[\d]+x[\d]+)(\.[\w]+)$/', '$2', $this->request_uri);
 
 
 
 
 
 
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
- foreach($statement['Condition'] as $type => $conditions) {
283
- switch(strtolower($type)) {
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 $str;
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(self::$resources['__combined'])) {
765
- foreach(self::$resources as $resources) {
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
- self::$resources['__combined'] = $response;
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 = self::$features['__combined'];
807
  }
808
  } else {
809
  $subjectId = $subject->getUID();
810
  $subjectId .= ($subject->getId() ? ".{$subject->getId()}" : '');
811
 
812
- if (isset(self::$features[$subjectId])) {
813
- $response = self::$features[$subjectId];
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 loadCapabilities() {
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("/^Capability:/i");
 
 
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
- // Priority #1: capability that has been explicitely set
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
- self::$_instance->checkURIAccess();
 
 
 
 
 
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.1
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
- //load all installed extension
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()->loadCapabilities();
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.1
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