Advanced Access Manager - Version 5.9.4

Version Description

  • Fixed the bug with incorrectly identifying CPT capabilities
  • Fixed the bug with URI Access where there where no way to override wildcard rule
  • Fixed multiple bugs related to JWT authentication
  • Fixed the bug with Access Policy that triggers PHP Notice for visitors
  • Removed support for ConfigPress option core.settings.setJwtCookieAfterLogin
  • Added the ability to obtain Login URL from the "Manage User" modal
  • Added the ability to control AAM cache size https://aamplugin.com/reference/plugin#core-cache-limit
  • Refactored Capabilities feature to follow the best practices for integration with WP Core
  • Refactored JWT authentication so it can be more seamlessly integrated with user status
Download this release

Release Info

Developer vasyltech
Plugin Icon 128x128 Advanced Access Manager
Version 5.9.4
Comparing to
See all releases

Code changes from version 5.9.3 to 5.9.4

Application/Backend/Feature/Main/Capability.php CHANGED
@@ -74,104 +74,69 @@ class AAM_Backend_Feature_Main_Capability extends AAM_Backend_Feature_Abstract {
74
  }
75
 
76
  /**
77
- * Undocumented function
78
  *
79
- * @return void
 
 
80
  */
81
  public function save() {
82
  $cap = AAM_Core_Request::post('capability');
83
  $status = AAM_Core_Request::post('status');
84
 
85
  $object = AAM_Backend_Subject::getInstance()->getObject('capability');
 
86
 
87
- $object->save($cap, $status);
88
-
89
- return wp_json_encode(array('status' => 'success'));
90
- }
91
-
92
- /**
93
- *
94
- * @return type
95
- */
96
- public function reset() {
97
- return AAM_Backend_Subject::getInstance()->resetObject('capability');
98
- }
99
-
100
- /**
101
- *
102
- * @return type
103
- */
104
- public function getTable() {
105
- $response = array('data' => $this->retrieveAllCaps());
106
-
107
- return wp_json_encode($response);
108
  }
109
 
110
  /**
111
- * Update capability tag
112
  *
113
  * @return string
114
  *
115
  * @access public
116
  */
117
- public function update() {
118
- $capability = AAM_Core_Request::post('capability');
119
- $updated = AAM_Core_Request::post('updated');
120
- $roles = AAM_Core_API::getRoles();
121
-
122
- if ($this->isAllowedToEdit($capability) === false) {
123
- $response = array(
124
- 'status' => 'failure',
125
- 'message' => __('Permission denied to update this capability', AAM_KEY)
126
- );
127
- } elseif (AAM_Core_API::capabilityExists($updated) === false) {
128
- foreach($roles->role_objects as $role) {
129
- //check if capability is present for current role! Note, we
130
- //can not use the native WP_Role::has_cap function because it will
131
- //return false if capability exists but not checked
132
- if (is_array($role->capabilities)
133
- && array_key_exists($capability, $role->capabilities)) {
134
- $role->add_cap($updated, $role->capabilities[$capability]);
135
- $role->remove_cap($capability);
136
- }
137
- }
138
- $response = array('status' => 'success');
139
- } else {
140
- $response = array(
141
- 'status' => 'failure',
142
- 'message' => __('Capability already exists', AAM_KEY)
143
- );
144
- }
145
-
146
- return wp_json_encode($response);
147
  }
148
-
149
  /**
150
- * Delete capability
151
- *
152
- * This function delete capability in all roles.
153
  *
154
  * @return string
155
  *
156
  * @access public
157
  */
158
- public function delete() {
159
- $capability = AAM_Core_Request::post('capability');
160
- $roles = AAM_Core_API::getRoles();
161
-
162
- if ($this->isAllowedToDelete($capability) === false) {
163
- $response = array(
164
- 'status' => 'failure',
165
- 'message' => __('Permission denied to delete this capability', AAM_KEY)
166
- );
167
- } else {
168
- foreach($roles->role_objects as $role) {
169
- $role->remove_cap($capability);
 
 
 
 
 
 
 
170
  }
171
- $response = array('status' => 'success');
172
  }
173
-
174
- return wp_json_encode($response);
175
  }
176
 
177
  /**
@@ -182,17 +147,25 @@ class AAM_Backend_Feature_Main_Capability extends AAM_Backend_Feature_Abstract {
182
  }
183
 
184
  /**
 
 
 
 
185
  *
186
- * @param type $cap
187
- * @return type
 
 
 
188
  */
189
  protected function prepareActionList($cap) {
190
  $subject = AAM_Backend_Subject::getInstance();
191
  $actions = array();
192
 
193
- $toggle = ($subject->hasCapability($cap) ? 'checked' : 'unchecked');
194
-
195
- if (AAM::api()->getPolicyManager()->isAllowed("Capability:{$cap}:AAM:toggle") === false) {
 
196
  $toggle = 'no-' . $toggle;
197
  }
198
 
@@ -215,12 +188,15 @@ class AAM_Backend_Feature_Main_Capability extends AAM_Backend_Feature_Abstract {
215
 
216
  return implode(',', $actions);
217
  }
218
-
219
  /**
 
 
 
220
  *
221
- * @param type $subject
222
- * @param type $cap
223
  * @return boolean
 
 
224
  */
225
  protected function isAllowedToEdit($cap) {
226
  $allowed = false;
@@ -230,18 +206,29 @@ class AAM_Backend_Feature_Main_Capability extends AAM_Backend_Feature_Abstract {
230
  }
231
 
232
  // Access & Security policy has higher priority
233
- if (AAM::api()->getPolicyManager()->isAllowed("Capability:{$cap}:AAM:update") === false) {
 
234
  $allowed = false;
235
  }
 
 
 
 
 
 
 
236
 
237
  return $allowed;
238
  }
239
 
240
  /**
 
 
 
241
  *
242
- * @param type $subject
243
- * @param type $cap
244
  * @return boolean
 
 
245
  */
246
  protected function isAllowedToDelete($cap) {
247
  $allowed = false;
@@ -251,33 +238,19 @@ class AAM_Backend_Feature_Main_Capability extends AAM_Backend_Feature_Abstract {
251
  }
252
 
253
  // Access & Security policy has higher priority
254
- if (AAM::api()->getPolicyManager()->isAllowed("Capability:{$cap}:AAM:delete") === false) {
 
255
  $allowed = false;
256
  }
257
-
258
- return $allowed;
259
- }
260
 
261
- /**
262
- *
263
- * @return type
264
- */
265
- protected function retrieveAllCaps() {
266
- $response = array();
267
- $manager = AAM::api()->getPolicyManager();
268
-
269
- foreach (array_keys(AAM_Core_API::getAllCapabilities()) as $cap) {
270
- if ($manager->isAllowed("Capability:{$cap}:AAM:list") !== false) {
271
- $response[] = array(
272
- $cap,
273
- $this->getGroup($cap),
274
- $cap,
275
- $this->prepareActionList($cap)
276
- );
277
- }
278
- }
279
 
280
- return $response;
281
  }
282
 
283
  /**
@@ -308,10 +281,9 @@ class AAM_Backend_Feature_Main_Capability extends AAM_Backend_Feature_Abstract {
308
  $capability = sanitize_text_field(AAM_Core_Request::post('capability'));
309
 
310
  if ($capability) {
311
- //add the capability to administrator's role as default behavior
312
- AAM_Core_API::getRoles()->add_cap('administrator', $capability);
313
- AAM_Backend_Subject::getInstance()->addCapability($capability);
314
- $response = array('status' => 'success');
315
  } else {
316
  $response = array('status' => 'failure');
317
  }
@@ -319,6 +291,60 @@ class AAM_Backend_Feature_Main_Capability extends AAM_Backend_Feature_Abstract {
319
  return wp_json_encode($response);
320
  }
321
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
  /**
323
  * Get capability group name
324
  *
74
  }
75
 
76
  /**
77
+ * Save capability status
78
  *
79
+ * @return string
80
+ *
81
+ * @access public
82
  */
83
  public function save() {
84
  $cap = AAM_Core_Request::post('capability');
85
  $status = AAM_Core_Request::post('status');
86
 
87
  $object = AAM_Backend_Subject::getInstance()->getObject('capability');
88
+ $result = $object->save($cap, $status);
89
 
90
+ return wp_json_encode(array(
91
+ 'status' => ($result ? 'success' : 'failure')
92
+ ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  }
94
 
95
  /**
96
+ * Reset capabilities
97
  *
98
  * @return string
99
  *
100
  * @access public
101
  */
102
+ public function reset() {
103
+ $result = AAM_Backend_Subject::getInstance()->resetObject('capability');
104
+
105
+ return wp_json_encode(array(
106
+ 'status' => ($result ? 'success' : 'failure')
107
+ ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  }
109
+
110
  /**
111
+ * Get list of capabilities for table view
 
 
112
  *
113
  * @return string
114
  *
115
  * @access public
116
  */
117
+ public function getTable() {
118
+ $data = array();
119
+ $subject = AAM_Backend_Subject::getInstance();
120
+ $manager = AAM::api()->getPolicyManager();
121
+
122
+ // Compile the complete list of capabilities
123
+ $caps = AAM_Core_API::getAllCapabilities();
124
+
125
+ // Add also subject specific capabilities
126
+ $caps = array_merge($caps, $subject->getCapabilities());
127
+
128
+ foreach (array_keys($caps) as $cap) {
129
+ if ($manager->isAllowed("Capability:{$cap}:AAM:list") !== false) {
130
+ $data[] = array(
131
+ $cap,
132
+ $this->getGroup($cap),
133
+ $cap,
134
+ $this->prepareActionList($cap)
135
+ );
136
  }
 
137
  }
138
+
139
+ return wp_json_encode(array('data' => $data));
140
  }
141
 
142
  /**
147
  }
148
 
149
  /**
150
+ * Prepare row actions
151
+ *
152
+ * Based on current user permissions and subject's capability ownership, prepare
153
+ * the correct list of actions
154
  *
155
+ * @param string $cap
156
+ *
157
+ * @return string
158
+ *
159
+ * @access protected
160
  */
161
  protected function prepareActionList($cap) {
162
  $subject = AAM_Backend_Subject::getInstance();
163
  $actions = array();
164
 
165
+ $toggle = ($subject->hasCapability($cap) ? 'checked' : 'unchecked');
166
+ $manager = AAM::api()->getPolicyManager();
167
+
168
+ if ($manager->isAllowed("Capability:{$cap}:AAM:toggle") === false) {
169
  $toggle = 'no-' . $toggle;
170
  }
171
 
188
 
189
  return implode(',', $actions);
190
  }
191
+
192
  /**
193
+ * Check if current user can edit capability
194
+ *
195
+ * @param string $cap
196
  *
 
 
197
  * @return boolean
198
+ *
199
+ * @access protected
200
  */
201
  protected function isAllowedToEdit($cap) {
202
  $allowed = false;
206
  }
207
 
208
  // Access & Security policy has higher priority
209
+ $manager = AAM::api()->getPolicyManager();
210
+ if ($manager->isAllowed("Capability:{$cap}:AAM:update") === false) {
211
  $allowed = false;
212
  }
213
+
214
+ // Check if current subject contains the capability and if so, allow to
215
+ // edit it
216
+ $subject = AAM_Backend_Subject::getInstance();
217
+ if ($allowed) {
218
+ $allowed = array_key_exists($cap, $subject->getCapabilities());
219
+ }
220
 
221
  return $allowed;
222
  }
223
 
224
  /**
225
+ * Check if current user can delete capability
226
+ *
227
+ * @param string $cap
228
  *
 
 
229
  * @return boolean
230
+ *
231
+ * @access protected
232
  */
233
  protected function isAllowedToDelete($cap) {
234
  $allowed = false;
238
  }
239
 
240
  // Access & Security policy has higher priority
241
+ $manager = AAM::api()->getPolicyManager();
242
+ if ($manager->isAllowed("Capability:{$cap}:AAM:delete") === false) {
243
  $allowed = false;
244
  }
 
 
 
245
 
246
+ // Check if current subject contains the capability and if so, allow to
247
+ // delete it
248
+ $subject = AAM_Backend_Subject::getInstance();
249
+ if ($allowed) {
250
+ $allowed = array_key_exists($cap, $subject->getCapabilities());
251
+ }
 
 
 
 
 
 
 
 
 
 
 
 
252
 
253
+ return $allowed;
254
  }
255
 
256
  /**
281
  $capability = sanitize_text_field(AAM_Core_Request::post('capability'));
282
 
283
  if ($capability) {
284
+ $result = AAM_Backend_Subject::getInstance()->addCapability($capability);
285
+
286
+ $response = array('status' => ($result ? 'success' : 'failure'));
 
287
  } else {
288
  $response = array('status' => 'failure');
289
  }
291
  return wp_json_encode($response);
292
  }
293
 
294
+ /**
295
+ * Update capability tag
296
+ *
297
+ * @return string
298
+ *
299
+ * @access public
300
+ */
301
+ public function update() {
302
+ $capability = AAM_Core_Request::post('capability');
303
+ $updated = AAM_Core_Request::post('updated');
304
+ $subject = AAM_Backend_Subject::getInstance();
305
+
306
+ if ($this->isAllowedToEdit($capability) === false) {
307
+ $response = array(
308
+ 'status' => 'failure',
309
+ 'message' => __('Permission denied to update this capability', AAM_KEY)
310
+ );
311
+ } else {
312
+ if ($subject->removeCapability($capability)) {
313
+ $result = $subject->addCapability($updated);
314
+ }
315
+
316
+ $response = array('status' => (!empty($result) ? 'success' : 'failure'));
317
+ }
318
+
319
+ return wp_json_encode($response);
320
+ }
321
+
322
+ /**
323
+ * Delete capability
324
+ *
325
+ * This function delete capability in all roles.
326
+ *
327
+ * @return string
328
+ *
329
+ * @access public
330
+ */
331
+ public function delete() {
332
+ $capability = AAM_Core_Request::post('capability');
333
+ $subject = AAM_Backend_Subject::getInstance();
334
+
335
+ if ($this->isAllowedToDelete($capability) === false) {
336
+ $response = array(
337
+ 'status' => 'failure',
338
+ 'message' => __('Permission denied to delete this capability', AAM_KEY)
339
+ );
340
+ } else {
341
+ $result = $subject->removeCapability($capability);
342
+ $response = array('status' => ($result ? 'success' : 'failure'));
343
+ }
344
+
345
+ return wp_json_encode($response);
346
+ }
347
+
348
  /**
349
  * Get capability group name
350
  *
Application/Backend/Feature/Main/Jwt.php CHANGED
@@ -40,15 +40,20 @@ class AAM_Backend_Feature_Main_Jwt extends AAM_Backend_Feature_Abstract {
40
  * @return type
41
  */
42
  public function generate() {
43
- $user = AAM_Backend_Subject::getInstance()->get();
44
- $expires = filter_input(INPUT_POST, 'expires');
 
45
 
46
  try {
47
  $max = AAM::getUser()->getMaxLevel();
48
  if ($max >= AAM_Core_API::maxLevel($user->allcaps)) {
49
  $issuer = new AAM_Core_Jwt_Issuer();
50
  $jwt = $issuer->issueToken(
51
- array('userId' => $user->ID, 'revocable' => true),
 
 
 
 
52
  $expires
53
  );
54
  $result = array(
40
  * @return type
41
  */
42
  public function generate() {
43
+ $user = AAM_Backend_Subject::getInstance()->get();
44
+ $expires = filter_input(INPUT_POST, 'expires');
45
+ $refreshable = filter_input(INPUT_POST, 'refreshable', FILTER_VALIDATE_BOOLEAN);
46
 
47
  try {
48
  $max = AAM::getUser()->getMaxLevel();
49
  if ($max >= AAM_Core_API::maxLevel($user->allcaps)) {
50
  $issuer = new AAM_Core_Jwt_Issuer();
51
  $jwt = $issuer->issueToken(
52
+ array(
53
+ 'userId' => $user->ID,
54
+ 'revocable' => true,
55
+ 'refreshable' => $refreshable
56
+ ),
57
  $expires
58
  );
59
  $result = array(
Application/Backend/Feature/Subject/Role.php CHANGED
@@ -234,8 +234,9 @@ class AAM_Backend_Feature_Subject_Role {
234
  */
235
  public function edit() {
236
  if (current_user_can('aam_edit_roles')) {
237
- $role = AAM_Backend_Subject::getInstance();
238
- $role->update(trim(filter_input(INPUT_POST, 'name')));
 
239
 
240
  do_action('aam-post-update-role-action', $role->get());
241
 
234
  */
235
  public function edit() {
236
  if (current_user_can('aam_edit_roles')) {
237
+ $role = AAM_Backend_Subject::getInstance();
238
+
239
+ $role->update(esc_js(trim(filter_input(INPUT_POST, 'name'))));
240
 
241
  do_action('aam-post-update-role-action', $role->get());
242
 
Application/Backend/Feature/Subject/User.php CHANGED
@@ -72,11 +72,12 @@ class AAM_Backend_Feature_Subject_User {
72
  $expires = filter_input(INPUT_POST, 'expires');
73
  $action = filter_input(INPUT_POST, 'after');
74
  $role = filter_input(INPUT_POST, 'role');
 
75
 
76
  if (current_user_can('edit_users')) {
77
  if ($userId != get_current_user_id()) {
78
  if ($this->isAllowed(new AAM_Core_Subject_User($userId))) {
79
- $this->updateUserExpiration($userId, $expires, $action, $role);
80
  $response = array('status' => 'success');
81
  }
82
  } else {
@@ -86,6 +87,45 @@ class AAM_Backend_Feature_Subject_User {
86
 
87
  return wp_json_encode($response);
88
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
  /**
91
  *
@@ -207,6 +247,48 @@ class AAM_Backend_Feature_Subject_User {
207
 
208
  return wp_json_encode(array('status' => ($result ? 'success' : 'failure')));
209
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
  /**
212
  * Prepare row
@@ -309,16 +391,12 @@ class AAM_Backend_Feature_Subject_User {
309
  *
310
  * @access protected
311
  */
312
- protected function updateUserExpiration($user, $expires, $action, $role = '') {
313
- if (trim($expires)) {
314
- update_user_meta(
315
- $user,
316
- 'aam_user_expiration',
317
- $expires . "|" . ($action ? $action : 'delete') . '|' . $role
318
- );
319
- } else {
320
- delete_user_meta($user, 'aam_user_expiration');
321
- }
322
  }
323
 
324
  /**
72
  $expires = filter_input(INPUT_POST, 'expires');
73
  $action = filter_input(INPUT_POST, 'after');
74
  $role = filter_input(INPUT_POST, 'role');
75
+ $jwt = filter_input(INPUT_POST, 'jwt');
76
 
77
  if (current_user_can('edit_users')) {
78
  if ($userId != get_current_user_id()) {
79
  if ($this->isAllowed(new AAM_Core_Subject_User($userId))) {
80
+ $this->updateUserExpiration($userId, $expires, $action, $role, $jwt);
81
  $response = array('status' => 'success');
82
  }
83
  } else {
87
 
88
  return wp_json_encode($response);
89
  }
90
+
91
+ /**
92
+ * Undocumented function
93
+ *
94
+ * @return void
95
+ */
96
+ public function resetExpiration() {
97
+ $response = array(
98
+ 'status' => 'failure',
99
+ 'reason' => __('Operation is not permitted', AAM_KEY)
100
+ );
101
+
102
+ $userId = filter_input(INPUT_POST, 'user');
103
+
104
+ if (current_user_can('edit_users')) {
105
+ if ($userId != get_current_user_id()) {
106
+ if ($this->isAllowed(new AAM_Core_Subject_User($userId))) {
107
+ $meta = get_user_meta($userId, 'aam_user_expiration', true);
108
+
109
+ if (!empty($meta)) {
110
+ $parts = explode('|', $meta);
111
+ if (!empty($parts[3])) {
112
+ AAM_Core_Jwt_Manager::getInstance()->revokeToken(
113
+ $userId, $parts[3]
114
+ );
115
+ }
116
+ }
117
+ $result = delete_user_meta($userId, 'aam_user_expiration');
118
+ $response = array(
119
+ 'status' => $result ? 'success' : 'failure'
120
+ );
121
+ }
122
+ } else {
123
+ $response['reason'] = __('You cannot manager expiration to yourself', AAM_KEY);
124
+ }
125
+ }
126
+
127
+ return wp_json_encode($response);
128
+ }
129
 
130
  /**
131
  *
247
 
248
  return wp_json_encode(array('status' => ($result ? 'success' : 'failure')));
249
  }
250
+
251
+ /**
252
+ * Undocumented function
253
+ *
254
+ * @return void
255
+ */
256
+ public function generateJwt() {
257
+ if (current_user_can('aam_manage_jwt')) {
258
+ $user = AAM_Backend_Subject::getInstance()->get();
259
+ $expires = filter_input(INPUT_POST, 'expires');
260
+ $trigger = filter_input(INPUT_POST, 'trigger', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
261
+
262
+ try {
263
+ $max = AAM::getUser()->getMaxLevel();
264
+ if ($max >= AAM_Core_API::maxLevel($user->allcaps)) {
265
+ $issuer = new AAM_Core_Jwt_Issuer();
266
+ $jwt = $issuer->issueToken(
267
+ array(
268
+ 'userId' => $user->ID,
269
+ 'revocable' => true,
270
+ 'refreshable' => false,
271
+ 'trigger' => $trigger
272
+ ),
273
+ $expires
274
+ );
275
+ AAM_Core_Jwt_Manager::getInstance()->registerToken($user->ID, $jwt->token);
276
+ $result = array(
277
+ 'status' => 'success',
278
+ 'jwt' => $jwt->token
279
+ );
280
+ } else {
281
+ $result = array('status' => 'failure', 'reason' => 'User ID has higher level than current user');
282
+ }
283
+ } catch (Exception $ex) {
284
+ $result = array('status' => 'failure', 'reason' => $ex->getMessage());
285
+ }
286
+ } else {
287
+ $result = array('status' => 'failure', 'reason' => 'You are not allowed to manage JWT tokens');
288
+ }
289
+
290
+ return wp_json_encode($result);
291
+ }
292
 
293
  /**
294
  * Prepare row
391
  *
392
  * @access protected
393
  */
394
+ protected function updateUserExpiration($user, $expires, $action, $role = '', $jwt = '') {
395
+ update_user_meta(
396
+ $user,
397
+ 'aam_user_expiration',
398
+ $expires . "|" . ($action ? $action : 'delete') . '|' . $role . '|' . $jwt
399
+ );
 
 
 
 
400
  }
401
 
402
  /**
Application/Backend/Manager.php CHANGED
@@ -798,7 +798,7 @@ class AAM_Backend_Manager {
798
  public function printJavascript() {
799
  if (AAM::isAAM()) {
800
  wp_enqueue_script('aam-vendor', AAM_MEDIA . '/js/vendor.js');
801
- wp_enqueue_script('aam-main', AAM_MEDIA . '/js/aam-5.9.2.js');
802
 
803
  //add plugin localization
804
  $this->printLocalization('aam-main');
798
  public function printJavascript() {
799
  if (AAM::isAAM()) {
800
  wp_enqueue_script('aam-vendor', AAM_MEDIA . '/js/vendor.js');
801
+ wp_enqueue_script('aam-main', AAM_MEDIA . '/js/aam-5.9.4.js');
802
 
803
  //add plugin localization
804
  $this->printLocalization('aam-main');
Application/Backend/phtml/index.phtml CHANGED
@@ -349,26 +349,48 @@
349
  <div class="tab-content">
350
  <div role="tabpanel" class="tab-pane active" id="edit-user-expiration">
351
  <p class="aam-info"><?php echo __('Define for how long user can access the website and what action needs to be taken after access expires.', AAM_KEY); ?>
352
- <div class="form-group">
 
353
  <div id="user-expiration-datapicker"></div>
354
  <input type="hidden" id="user-expires" />
355
  </div>
356
- <div class="form-group">
357
- <label><?php echo __('Action After Expiration', AAM_KEY); ?> </label>
358
- <select class="form-control" id="action-after-expiration">
359
- <option value=""><?php echo __('Select Action', AAM_KEY); ?></option>
360
- <option value="logout"><?php echo __('Logout User', AAM_KEY); ?></option>
361
- <option value="delete"><?php echo __('Delete Account', AAM_KEY); ?></option>
362
- <option value="lock"><?php echo __('Lock Account', AAM_KEY); ?></option>
363
- <option value="change-role"><?php echo __('Change User Role', AAM_KEY); ?></option>
364
- </select>
365
- </div>
366
- <div class="form-group hidden" id="expiration-change-role-holder">
367
- <label><?php echo __('Change To Role', AAM_KEY); ?></label>
368
- <select class="form-control" id="expiration-change-role">
369
- <option value=""><?php echo __('Select Role', AAM_KEY); ?></option>
370
- </select>
 
 
 
 
371
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  </div>
373
  <div role="tabpanel" class="tab-pane" id="edit-user-profile">
374
  <p class="aam-info"><?php echo __("To manage user profile, click on the button below.", AAM_KEY); ?></p>
349
  <div class="tab-content">
350
  <div role="tabpanel" class="tab-pane active" id="edit-user-expiration">
351
  <p class="aam-info"><?php echo __('Define for how long user can access the website and what action needs to be taken after access expires.', AAM_KEY); ?>
352
+
353
+ <div class="form-group aam-bordered">
354
  <div id="user-expiration-datapicker"></div>
355
  <input type="hidden" id="user-expires" />
356
  </div>
357
+
358
+ <div class="aam-bordered">
359
+ <div class="form-group">
360
+ <label><?php echo __('Action After Expiration', AAM_KEY); ?> </label>
361
+ <select class="form-control" id="action-after-expiration">
362
+ <option value=""><?php echo __('Select Action', AAM_KEY); ?></option>
363
+ <option value="logout"><?php echo __('Logout User', AAM_KEY); ?></option>
364
+ <option value="delete"><?php echo __('Delete Account', AAM_KEY); ?></option>
365
+ <option value="lock"><?php echo __('Lock Account', AAM_KEY); ?></option>
366
+ <option value="change-role"><?php echo __('Change User Role', AAM_KEY); ?></option>
367
+ </select>
368
+ </div>
369
+
370
+ <div class="form-group hidden" id="expiration-change-role-holder">
371
+ <label><?php echo __('Change To Role', AAM_KEY); ?></label>
372
+ <select class="form-control" id="expiration-change-role">
373
+ <option value=""><?php echo __('Select Role', AAM_KEY); ?></option>
374
+ </select>
375
+ </div>
376
  </div>
377
+
378
+ <?php if (AAM::api()->getConfig('core.settings.jwtAuthentication', true) && current_user_can('aam_manage_jwt')) { ?>
379
+ <div class="form-group aam-bordered aam-outer-top-xs">
380
+ <label for="login-url-preview" class="aam-block">
381
+ <?php echo __('Login with URL', AAM_KEY); ?>
382
+ <a href="#" class="aam-copy-clipboard" data-clipboard-target="#login-url-preview"><?php echo __('Copy to clipboard', AAM_KEY); ?></a>
383
+ </label>
384
+ <div class="input-group">
385
+ <input type="text" class="form-control" id="login-url-preview" data-url="<?php echo add_query_arg('aam-jwt', '%s', site_url()); ?>" value="<?php echo __('Login URL has not been requested', AAM_KEY); ?>" readonly />
386
+ <span class="input-group-btn">
387
+ <a href="#" class="btn btn-primary" id="request-login-url"><?php echo __('Request URL', AAM_KEY); ?></a>
388
+ </span>
389
+ <input type="hidden" id="login-jwt" />
390
+ </div>
391
+ <small><?php echo AAM_Backend_View_Helper::preparePhrase('With this URL user will be automatically logged in until defined date and time. The JWT token associated with URL is [revokable] however not [refreshable].', 'i', 'i'); ?></small>
392
+ </div>
393
+ <?php } ?>
394
  </div>
395
  <div role="tabpanel" class="tab-pane" id="edit-user-profile">
396
  <p class="aam-info"><?php echo __("To manage user profile, click on the button below.", AAM_KEY); ?></p>
Application/Backend/phtml/main/capability.phtml CHANGED
@@ -5,7 +5,7 @@
5
  <div class="row">
6
  <div class="col-xs-12">
7
  <p class="aam-notification">
8
- <?php echo sprintf(AAM_Backend_View_Helper::preparePhrase('[Be careful!] Manage capabilities for [%s]. For more information about the concept of capabilities check %sWhat is a WordPress capability%s article.', 'b', 'b'), AAM_Backend_Subject::getInstance()->getName(), '<a href="https://aamplugin.com/article/what-is-a-wordpress-capability" target="_blank">', '</a>'); ?>
9
  </p>
10
  </div>
11
  </div>
@@ -98,7 +98,7 @@
98
  <h4 class="modal-title"><?php echo __('Delete Capability', AAM_KEY); ?></h4>
99
  </div>
100
  <div class="modal-body">
101
- <p class="text-center aam-confirm-message alert alert-danger" data-message="<?php echo __('Are you sure that you want to delete %s capability for all roles?', AAM_KEY); ?>"></p>
102
  </div>
103
  <div class="modal-footer">
104
  <button type="button" class="btn btn-danger" id="delete-capability-btn"><?php echo __('Delete', AAM_KEY); ?></button>
5
  <div class="row">
6
  <div class="col-xs-12">
7
  <p class="aam-notification">
8
+ <?php echo sprintf(AAM_Backend_View_Helper::preparePhrase('[Be careful!] On this tab, you can manage capabilities for [%s]. Any changes to the list of capabilities is [permanent]. Consider to backup at least your database tables [_options] and [_usermeta] regularly. For more information about this feature, refer to the %sHow to manage WordPress capabilities%s article.', 'b', 'b', 'b', 'i', 'i'), AAM_Backend_Subject::getInstance()->getName(), '<a href="https://aamplugin.com/article/how-to-manage-wordpress-capabilities" target="_blank">', '</a>'); ?>
9
  </p>
10
  </div>
11
  </div>
98
  <h4 class="modal-title"><?php echo __('Delete Capability', AAM_KEY); ?></h4>
99
  </div>
100
  <div class="modal-body">
101
+ <p class="text-center aam-confirm-message alert alert-danger" data-message="<?php echo __('You are about to delete the %s capability from %n', AAM_KEY); ?>"></p>
102
  </div>
103
  <div class="modal-footer">
104
  <button type="button" class="btn btn-danger" id="delete-capability-btn"><?php echo __('Delete', AAM_KEY); ?></button>
Application/Backend/phtml/main/jwt.phtml CHANGED
@@ -43,12 +43,28 @@
43
  <input type="hidden" id="jwt-expires" />
44
  </div>
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  <div class="form-group aam-outer-top-xs">
47
  <label for="jwt-token-preview" class="aam-block">
48
  <?php echo __('JWT Token (for any API calls)', AAM_KEY); ?>
49
  <a href="#" class="aam-copy-clipboard" data-clipboard-target="#jwt-token-preview"><?php echo __('Copy to clipboard', AAM_KEY); ?></a>
50
  </label>
51
- <textarea class="form-control" id="jwt-token-preview" readonly rows="5"></textarea>
52
  </div>
53
 
54
  <hr/>
@@ -58,8 +74,8 @@
58
  <?php echo __('Account Login URL (with JWT token)', AAM_KEY); ?>
59
  <a href="#" class="aam-copy-clipboard" data-clipboard-target="#jwt-url-preview"><?php echo __('Copy to clipboard', AAM_KEY); ?></a>
60
  </label>
61
- <textarea class="form-control" id="jwt-url-preview" data-url="<?php echo add_query_arg('aam-jwt', '%s', site_url()); ?>" readonly rows="5"></textarea>
62
- <small><?php echo __('With this URL account will be automatically logged in until the time defined on the "Temporary Access" tab.', AAM_KEY); ?></small>
63
  </div>
64
  </div>
65
  <div class="modal-footer">
43
  <input type="hidden" id="jwt-expires" />
44
  </div>
45
 
46
+ <table class="table table-bordered">
47
+ <tbody>
48
+ <tr>
49
+ <td>
50
+ <span class='aam-setting-title'><?php echo __('Is token refreshable?', AAM_KEY); ?></span>
51
+ <p class="aam-setting-description">
52
+ <?php echo __('Whether this token, before expires, can be used to obtain a new token for the same time duration or not.', AAM_KEY); ?>
53
+ </p>
54
+ </td>
55
+ <td class="text-center">
56
+ <input data-toggle="toggle" id="jwt-refreshable" type="checkbox" data-on="Yes" data-off="No" data-size="small" />
57
+ </td>
58
+ </tr>
59
+ </tbody>
60
+ </table>
61
+
62
  <div class="form-group aam-outer-top-xs">
63
  <label for="jwt-token-preview" class="aam-block">
64
  <?php echo __('JWT Token (for any API calls)', AAM_KEY); ?>
65
  <a href="#" class="aam-copy-clipboard" data-clipboard-target="#jwt-token-preview"><?php echo __('Copy to clipboard', AAM_KEY); ?></a>
66
  </label>
67
+ <input type="text" class="form-control" id="jwt-token-preview" readonly />
68
  </div>
69
 
70
  <hr/>
74
  <?php echo __('Account Login URL (with JWT token)', AAM_KEY); ?>
75
  <a href="#" class="aam-copy-clipboard" data-clipboard-target="#jwt-url-preview"><?php echo __('Copy to clipboard', AAM_KEY); ?></a>
76
  </label>
77
+ <input type="text" class="form-control" id="jwt-url-preview" data-url="<?php echo add_query_arg('aam-jwt', '%s', site_url()); ?>" readonly />
78
+ <small><?php echo __('With this URL account will be automatically logged in as long as JWT token is valid.', AAM_KEY); ?></small>
79
  </div>
80
  </div>
81
  <div class="modal-footer">
Application/Core/Compatibility.php CHANGED
@@ -27,7 +27,8 @@ class AAM_Core_Compatibility {
27
  *
28
  * @param [type] $action
29
  * @param [type] $effect
30
- * @return void
 
31
  */
32
  public static function convertPolicyAction($action, $effect, $prefix = '') {
33
  $action = apply_filters('aam-policy-post-resource-action-filter', $action);
@@ -186,9 +187,9 @@ class AAM_Core_Compatibility {
186
 
187
  /**
188
  *
189
- * @param type $option
190
- * @param type $normalizedName
191
- * @param type $config
192
  * @return int
193
  */
194
  protected static function normalizeOption($option, $normalizedName, &$config) {
27
  *
28
  * @param [type] $action
29
  * @param [type] $effect
30
+ *
31
+ * @return array
32
  */
33
  public static function convertPolicyAction($action, $effect, $prefix = '') {
34
  $action = apply_filters('aam-policy-post-resource-action-filter', $action);
187
 
188
  /**
189
  *
190
+ * @param type $option
191
+ * @param type $normalizedName
192
+ * @param array &$config
193
  * @return int
194
  */
195
  protected static function normalizeOption($option, $normalizedName, &$config) {
Application/Core/Jwt/Manager.php CHANGED
@@ -39,6 +39,9 @@ class AAM_Core_Jwt_Manager {
39
 
40
  //register authentication hook
41
  add_filter('determine_current_user', array($this, 'determineUser'), 999);
 
 
 
42
  }
43
 
44
  /**
@@ -174,21 +177,29 @@ class AAM_Core_Jwt_Manager {
174
  $result = $issuer->validateToken($jwt);
175
 
176
  if ($result->status === 'valid') {
177
- // calculate the new expiration
178
- $issuedAt = new DateTime();
179
- $issuedAt->setTimestamp($result->iat);
180
- $expires = DateTime::createFromFormat('m/d/Y, H:i O', $result->exp);
 
181
 
182
- $exp = new DateTime();
183
- $exp->add($issuedAt->diff($expires));
184
 
185
- $new = $this->issueToken($result->userId, $jwt, $exp);
186
 
187
- $response->status = 200;
188
- $response->data = array(
189
- 'token' => $new->token,
190
- 'token_expires' => $new->claims['exp'],
191
- );
 
 
 
 
 
 
 
192
  } else {
193
  $response->status = 400;
194
  $response->data = new WP_Error(
@@ -219,7 +230,6 @@ class AAM_Core_Jwt_Manager {
219
 
220
  if ($result->status === 'valid') {
221
  $userId = $result->userId;
222
- $this->possiblyLoginUser($token->method, $result);
223
  }
224
  }
225
  }
@@ -227,6 +237,51 @@ class AAM_Core_Jwt_Manager {
227
  return $userId;
228
  }
229
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  /**
231
  * Register JWT token to user's registry
232
  *
@@ -308,7 +363,14 @@ class AAM_Core_Jwt_Manager {
308
  protected function issueToken($userId, $replace = null, $expires = null) {
309
  $issuer = new AAM_Core_Jwt_Issuer();
310
  $result = $issuer->issueToken(
311
- array('userId' => $userId, 'revocable' => true), $expires
 
 
 
 
 
 
 
312
  );
313
 
314
  // Finally register token so it can be revoked
@@ -329,7 +391,7 @@ class AAM_Core_Jwt_Manager {
329
  */
330
  protected function extractJwt() {
331
  $container = explode(',', AAM_Core_Config::get(
332
- 'authentication.jwt.container', 'header,post,query,cookie'
333
  ));
334
 
335
  $jwt = null;
@@ -344,10 +406,6 @@ class AAM_Core_Jwt_Manager {
344
  $jwt = AAM_Core_Request::cookie('aam-jwt');
345
  break;
346
 
347
- case 'query':
348
- $jwt = AAM_Core_Request::get('aam-jwt');
349
- break;
350
-
351
  case 'post':
352
  $jwt = AAM_Core_Request::post('aam-jwt');
353
  break;
@@ -374,41 +432,6 @@ class AAM_Core_Jwt_Manager {
374
  return $response;
375
  }
376
 
377
- /**
378
- * Also login user if HTTP request is get and JWT was extracted from query params
379
- *
380
- * @param string $container
381
- * @param object $claims
382
- *
383
- * @return void
384
- *
385
- * @access protected
386
- */
387
- protected function possiblyLoginUser($container, $claims) {
388
- // Also login user if REQUEST_METHOD is GET
389
- $method = AAM_Core_Request::server('REQUEST_METHOD');
390
-
391
- if ($container === 'query' && ($method === 'GET')) {
392
- $exp = get_user_meta($claims->userId, 'aam_user_expiration', true);
393
-
394
- // Do it only once
395
- if (empty($exp)) {
396
- wp_set_current_user($claims->userId);
397
- wp_set_auth_cookie($claims->userId);
398
-
399
- // TODO: Remove June 2020
400
- $exp = (is_numeric($claims->exp) ? date('m/d/Y, H:i O', $claims->exp) : $claims->exp);
401
-
402
- update_user_meta(
403
- $claims->userId,
404
- 'aam_user_expiration',
405
- $exp . '|logout|'
406
- );
407
- do_action('wp_login', '', wp_get_current_user());
408
- }
409
- }
410
- }
411
-
412
  /**
413
  * Get single instance of itself
414
  *
39
 
40
  //register authentication hook
41
  add_filter('determine_current_user', array($this, 'determineUser'), 999);
42
+
43
+ //login user if JWT is in the URL
44
+ add_action('init', array($this, 'loginAccount'), 1);
45
  }
46
 
47
  /**
177
  $result = $issuer->validateToken($jwt);
178
 
179
  if ($result->status === 'valid') {
180
+ if (!empty($result->refreshable)) {
181
+ // calculate the new expiration
182
+ $issuedAt = new DateTime();
183
+ $issuedAt->setTimestamp($result->iat);
184
+ $expires = DateTime::createFromFormat('m/d/Y, H:i O', $result->exp);
185
 
186
+ $exp = new DateTime();
187
+ $exp->add($issuedAt->diff($expires));
188
 
189
+ $new = $this->issueToken($result->userId, $jwt, $exp);
190
 
191
+ $response->status = 200;
192
+ $response->data = array(
193
+ 'token' => $new->token,
194
+ 'token_expires' => $new->claims['exp'],
195
+ );
196
+ } else {
197
+ $response->status = 400;
198
+ $response->data = new WP_Error(
199
+ 'rest_jwt_validation_failure',
200
+ __('Provided JWT token is not refreshable', AAM_KEY)
201
+ );
202
+ }
203
  } else {
204
  $response->status = 400;
205
  $response->data = new WP_Error(
230
 
231
  if ($result->status === 'valid') {
232
  $userId = $result->userId;
 
233
  }
234
  }
235
  }
237
  return $userId;
238
  }
239
 
240
+ /**
241
+ * Undocumented function
242
+ *
243
+ * @return void
244
+ */
245
+ public function loginAccount() {
246
+ $jwt = AAM_Core_Request::get('aam-jwt');
247
+ $method = AAM_Core_Request::server('REQUEST_METHOD');
248
+
249
+ if (!empty($jwt) && ($method === 'GET')) {
250
+ $issuer = new AAM_Core_Jwt_Issuer();
251
+ $token = $issuer->validateToken($jwt);
252
+
253
+
254
+
255
+ // Check that JWT token is valid
256
+ if ($token->status === 'valid') {
257
+ // Check if Account is active
258
+ $user = AAM::api()->getUser($token->userId);
259
+
260
+ if ($user->getUserStatus()->status === 'active') {
261
+ wp_set_current_user($token->userId);
262
+ wp_set_auth_cookie($token->userId);
263
+
264
+ // TODO: Remove June 2020
265
+ $exp = (is_numeric($token->exp) ? date('m/d/Y, H:i O', $token->exp) : $token->exp);
266
+
267
+ // determine correct trigger
268
+ if (!empty($token->trigger)) {
269
+ update_user_meta(
270
+ $token->userId,
271
+ 'aam_user_expiration',
272
+ $exp . "|{$token->trigger->action}|" . (!empty($token->trigger->role) ? $token->trigger->role : '')
273
+ );
274
+ }
275
+
276
+ do_action('wp_login', $user->user_login, $user->getSubject());
277
+
278
+ // finally just redirect user to the homepage
279
+ wp_safe_redirect(get_home_url()); exit;
280
+ }
281
+ }
282
+ }
283
+ }
284
+
285
  /**
286
  * Register JWT token to user's registry
287
  *
363
  protected function issueToken($userId, $replace = null, $expires = null) {
364
  $issuer = new AAM_Core_Jwt_Issuer();
365
  $result = $issuer->issueToken(
366
+ array(
367
+ 'userId' => $userId,
368
+ 'revocable' => true,
369
+ 'refreshable' => AAM::api()->getConfig(
370
+ 'authentication.jwt.refreshable', false
371
+ )
372
+ ),
373
+ $expires
374
  );
375
 
376
  // Finally register token so it can be revoked
391
  */
392
  protected function extractJwt() {
393
  $container = explode(',', AAM_Core_Config::get(
394
+ 'authentication.jwt.container', 'header,post,cookie'
395
  ));
396
 
397
  $jwt = null;
406
  $jwt = AAM_Core_Request::cookie('aam-jwt');
407
  break;
408
 
 
 
 
 
409
  case 'post':
410
  $jwt = AAM_Core_Request::post('aam-jwt');
411
  break;
432
  return $response;
433
  }
434
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
435
  /**
436
  * Get single instance of itself
437
  *
Application/Core/Login.php CHANGED
@@ -77,7 +77,7 @@ class AAM_Core_Login {
77
  $this->updateLoginCounter(-1);
78
  }
79
 
80
- // Delete User Switch flag in case admin is inpersonating user
81
  AAM_Core_API::deleteOption('aam-user-switch-' . $user->ID);
82
 
83
  // Experimental feature. Track user session
@@ -91,20 +91,6 @@ class AAM_Core_Login {
91
  }
92
  }
93
 
94
- if (AAM::api()->getConfig('core.settings.setJwtCookieAfterLogin', false)) {
95
- $issuer = new AAM_Core_Jwt_Issuer();
96
- $token = $issuer->issueToken(array('userId' => $user->ID));
97
- setcookie(
98
- 'aam-jwt',
99
- $token->token,
100
- $token->claims['exp'],
101
- '/',
102
- parse_url(get_bloginfo('url'), PHP_URL_HOST),
103
- is_ssl(),
104
- AAM_Core_Config::get('authentication.jwt.cookie.httpOnly', false)
105
- );
106
- }
107
-
108
  if ($this->aamLogin === false) {
109
  $redirect = $this->getLoginRedirect($user);
110
 
77
  $this->updateLoginCounter(-1);
78
  }
79
 
80
+ // Delete User Switch flag in case admin is impersonating user
81
  AAM_Core_API::deleteOption('aam-user-switch-' . $user->ID);
82
 
83
  // Experimental feature. Track user session
91
  }
92
  }
93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  if ($this->aamLogin === false) {
95
  $redirect = $this->getLoginRedirect($user);
96
 
Application/Core/Object/Cache.php CHANGED
@@ -79,6 +79,12 @@ class AAM_Core_Object_Cache extends AAM_Core_Object {
79
  */
80
  public function add($type, $id, $value) {
81
  $option = $this->getOption();
 
 
 
 
 
 
82
  $option[$type][$id] = $value;
83
  $this->setOption($option);
84
 
@@ -124,5 +130,5 @@ class AAM_Core_Object_Cache extends AAM_Core_Object {
124
  public function reset() {
125
  return $this->getSubject()->deleteOption('cache');
126
  }
127
-
128
  }
79
  */
80
  public function add($type, $id, $value) {
81
  $option = $this->getOption();
82
+
83
+ $limit = AAM_Core_Config::get('core.cache.limit', 1000);
84
+ if (isset($option[$type][$id]) && (count($option[$type][$id]) >= $limit)) {
85
+ array_shift($option[$type][$id]);
86
+ }
87
+
88
  $option[$type][$id] = $value;
89
  $this->setOption($option);
90
 
130
  public function reset() {
131
  return $this->getSubject()->deleteOption('cache');
132
  }
133
+
134
  }
Application/Core/Object/Capability.php CHANGED
@@ -15,44 +15,6 @@
15
  */
16
  class AAM_Core_Object_Capability extends AAM_Core_Object {
17
 
18
- /**
19
- * Constructor
20
- *
21
- * @param AAM_Core_Subject $subject
22
- *
23
- * @return void
24
- *
25
- * @access public
26
- */
27
- public function __construct(AAM_Core_Subject $subject) {
28
- parent::__construct($subject);
29
-
30
- $caps = $this->getSubject()->getCapabilities();
31
-
32
- // Load Capabilities from the policy
33
- $stms = AAM_Core_Policy_Factory::get($subject)->find("/^Capability:/i");
34
-
35
- foreach($stms as $key => $stm) {
36
- $chunks = explode(':', $key);
37
- if (count($chunks) === 2) {
38
- $caps[$chunks[1]] = ($stm['Effect'] === 'allow' ? 1 : 0);
39
- }
40
- }
41
-
42
- //check if capabilities are overwritten but only for user subject
43
- if (is_a($this->getSubject(), 'AAM_Core_Subject_User')) {
44
- $userCaps = get_user_option(
45
- AAM_Core_Subject_User::AAM_CAPKEY, $this->getSubject()->getId()
46
- );
47
- if (!empty($userCaps)) {
48
- $caps = array_merge($caps, $userCaps);
49
- $this->setOverwritten(true);
50
- }
51
- }
52
-
53
- $this->setOption($caps);
54
- }
55
-
56
  /**
57
  * Update subject's capability
58
  *
@@ -111,4 +73,5 @@ class AAM_Core_Object_Capability extends AAM_Core_Object {
111
  public function remove($capability) {
112
  return $this->save($capability, 0);
113
  }
 
114
  }
15
  */
16
  class AAM_Core_Object_Capability extends AAM_Core_Object {
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  /**
19
  * Update subject's capability
20
  *
73
  public function remove($capability) {
74
  return $this->save($capability, 0);
75
  }
76
+
77
  }
Application/Core/Object/Uri.php CHANGED
@@ -35,7 +35,7 @@ class AAM_Core_Object_Uri extends AAM_Core_Object {
35
 
36
  if (empty($option)) {
37
  $stms = AAM_Core_Policy_Factory::get($subject)->find("/^URI:/i");
38
-
39
  foreach($stms as $key => $stm) {
40
  $chunks = explode(':', $key);
41
  $effect = ($stm['Effect'] === 'deny' ? 1 : 0);
@@ -85,7 +85,7 @@ class AAM_Core_Object_Uri extends AAM_Core_Object {
85
  );
86
  }
87
  }
88
-
89
  if (empty($option)) {
90
  $option = $this->getSubject()->inheritFromParent('uri');
91
  }
@@ -117,11 +117,10 @@ class AAM_Core_Object_Uri extends AAM_Core_Object {
117
  if (apply_filters('aam-uri-match-filter', preg_match($regex, $s), $uri, $s)
118
  && (empty($out) || count(array_intersect_assoc($params, $out)) === count($out))) {
119
  $match = $rule;
120
- break;
121
  }
122
  }
123
  }
124
-
125
  return $match;
126
  }
127
 
35
 
36
  if (empty($option)) {
37
  $stms = AAM_Core_Policy_Factory::get($subject)->find("/^URI:/i");
38
+
39
  foreach($stms as $key => $stm) {
40
  $chunks = explode(':', $key);
41
  $effect = ($stm['Effect'] === 'deny' ? 1 : 0);
85
  );
86
  }
87
  }
88
+
89
  if (empty($option)) {
90
  $option = $this->getSubject()->inheritFromParent('uri');
91
  }
117
  if (apply_filters('aam-uri-match-filter', preg_match($regex, $s), $uri, $s)
118
  && (empty($out) || count(array_intersect_assoc($params, $out)) === count($out))) {
119
  $match = $rule;
 
120
  }
121
  }
122
  }
123
+
124
  return $match;
125
  }
126
 
Application/Core/Object/Visibility.php CHANGED
@@ -56,18 +56,14 @@ class AAM_Core_Object_Visibility extends AAM_Core_Object {
56
  $this->pushOptions('post', $row->post_id . '|' . $row->post_type, $settings);
57
  }
58
  }
59
-
60
  // Read all the settings from the Access & Security Policies
61
  $area = AAM_Core_Api_Area::get();
62
- $stms = AAM_Core_Policy_Factory::get($subject)->find(
63
- "/^post:(.*):(list|listtoothers)$/"
64
- );
65
-
66
  foreach($stms as $key => $stm) {
67
  $chunks = explode(':', $key);
68
 
69
- $action = ($chunks[3] === 'listtoothers' ? 'list_others' : 'list');
70
-
71
  if (is_numeric($chunks[2])) {
72
  $postId = $chunks[2];
73
  } else {
@@ -77,15 +73,18 @@ class AAM_Core_Object_Visibility extends AAM_Core_Object {
77
  $postId = (is_a($post, 'WP_Post') ? $post->ID : 0);
78
  }
79
 
80
- $this->pushOptions(
81
- 'post',
82
- "{$postId}|{$chunks[1]}",
83
- array(
84
- "{$area}.{$action}" => ($stm['Effect'] === 'deny' ? 1 : 0)
85
- )
86
- );
 
 
 
87
  }
88
-
89
  do_action('aam-visibility-initialize-action', $this);
90
 
91
  // inherit settings from parent
@@ -128,8 +127,8 @@ class AAM_Core_Object_Visibility extends AAM_Core_Object {
128
 
129
  if (empty($filtered)) {
130
  $filtered = array_combine(
131
- $listOptions,
132
- array_fill(0, count($listOptions), 0)
133
  );
134
  }
135
 
56
  $this->pushOptions('post', $row->post_id . '|' . $row->post_type, $settings);
57
  }
58
  }
59
+
60
  // Read all the settings from the Access & Security Policies
61
  $area = AAM_Core_Api_Area::get();
62
+ $stms = AAM_Core_Policy_Factory::get($subject)->find("/^post:(.*):list$/");
63
+
 
 
64
  foreach($stms as $key => $stm) {
65
  $chunks = explode(':', $key);
66
 
 
 
67
  if (is_numeric($chunks[2])) {
68
  $postId = $chunks[2];
69
  } else {
73
  $postId = (is_a($post, 'WP_Post') ? $post->ID : 0);
74
  }
75
 
76
+ // Cover the case when unknown slug is used
77
+ if (!empty($postId)) {
78
+ $this->pushOptions(
79
+ 'post',
80
+ "{$postId}|{$chunks[1]}",
81
+ array(
82
+ "{$area}.list" => ($stm['Effect'] === 'deny' ? 1 : 0)
83
+ )
84
+ );
85
+ }
86
  }
87
+
88
  do_action('aam-visibility-initialize-action', $this);
89
 
90
  // inherit settings from parent
127
 
128
  if (empty($filtered)) {
129
  $filtered = array_combine(
130
+ $listOptions,
131
+ array_fill(0, count($listOptions), 0)
132
  );
133
  }
134
 
Application/Core/Policy/Condition.php CHANGED
@@ -144,7 +144,7 @@ final class AAM_Core_Policy_Condition {
144
  foreach($this->prepareConditions($conditions, $args) as $condition) {
145
  $result = $result || ($condition['left'] === $condition['right']);
146
  }
147
-
148
  return $result;
149
  }
150
 
144
  foreach($this->prepareConditions($conditions, $args) as $condition) {
145
  $result = $result || ($condition['left'] === $condition['right']);
146
  }
147
+
148
  return $result;
149
  }
150
 
Application/Core/Policy/Token.php CHANGED
@@ -75,7 +75,7 @@ final class AAM_Core_Policy_Token {
75
  */
76
  protected static function getValue($token, $args) {
77
  $parts = explode('.', $token);
78
-
79
  if (isset(self::$map[$parts[0]])) {
80
  $value = call_user_func(self::$map[$parts[0]], $parts[1], $args);
81
  } elseif ($parts[0] === 'CALLBACK' && is_callable($parts[1])) {
75
  */
76
  protected static function getValue($token, $args) {
77
  $parts = explode('.', $token);
78
+
79
  if (isset(self::$map[$parts[0]])) {
80
  $value = call_user_func(self::$map[$parts[0]], $parts[1], $args);
81
  } elseif ($parts[0] === 'CALLBACK' && is_callable($parts[1])) {
Application/Core/Subject/Role.php CHANGED
@@ -20,6 +20,15 @@ class AAM_Core_Subject_Role extends AAM_Core_Subject {
20
  */
21
  const UID = 'role';
22
 
 
 
 
 
 
 
 
 
 
23
  /**
24
  * Retrieve Role based on ID
25
  *
@@ -28,13 +37,13 @@ class AAM_Core_Subject_Role extends AAM_Core_Subject {
28
  * @access protected
29
  */
30
  protected function retrieveSubject() {
31
- $roles = AAM_Core_API::getRoles();
32
- $role = $roles->get_role($this->getId());
33
 
34
- if (!is_null($role) && isset($role->capabilities)) {
35
- //add role capability as role id, weird WordPress behavior
36
- //example is administrator capability
37
- $role->capabilities[$this->getId()] = true;
 
38
  }
39
 
40
  return $role;
@@ -51,14 +60,12 @@ class AAM_Core_Subject_Role extends AAM_Core_Subject {
51
  $status = false;
52
  $roles = AAM_Core_API::getRoles();
53
 
54
- if ($this->getId() !== 'administrator') {
55
- $count = count_users();
56
- $stats = $count['avail_roles'];
57
 
58
- if (empty($stats[$this->getId()])) {
59
- $roles->remove_role($this->getId());
60
- $status = true;
61
- }
62
  }
63
 
64
  return $status;
@@ -75,6 +82,7 @@ class AAM_Core_Subject_Role extends AAM_Core_Subject {
75
  */
76
  public function update($name) {
77
  $roles = AAM_Core_API::getRoles();
 
78
  if ($name) {
79
  $roles->roles[$this->getId()]['name'] = $name;
80
  $status = AAM_Core_API::updateOption($roles->role_key, $roles->roles);
@@ -95,7 +103,7 @@ class AAM_Core_Subject_Role extends AAM_Core_Subject {
95
  * @access public
96
  */
97
  public function removeCapability($capability) {
98
- $this->getSubject()->add_cap($capability, false);
99
 
100
  return true;
101
  }
@@ -213,7 +221,7 @@ class AAM_Core_Subject_Role extends AAM_Core_Subject {
213
  * @return type
214
  */
215
  public function getName() {
216
- return $this->name;
217
  }
218
 
219
  /**
20
  */
21
  const UID = 'role';
22
 
23
+ /**
24
+ * Role name
25
+ *
26
+ * Fix the bug that is in the way WP_Roles is initialized
27
+ *
28
+ * @var string
29
+ */
30
+ protected $name;
31
+
32
  /**
33
  * Retrieve Role based on ID
34
  *
37
  * @access protected
38
  */
39
  protected function retrieveSubject() {
40
+ $wpRoles = AAM_Core_API::getRoles();
 
41
 
42
+ if (isset($wpRoles->roles[$this->getId()])) {
43
+ $role = $wpRoles->get_role($this->getId());
44
+ $this->name = $wpRoles->roles[$this->getId()]['name'];
45
+ } else {
46
+ $role = null;
47
  }
48
 
49
  return $role;
60
  $status = false;
61
  $roles = AAM_Core_API::getRoles();
62
 
63
+ $count = count_users();
64
+ $stats = $count['avail_roles'];
 
65
 
66
+ if (empty($stats[$this->getId()])) {
67
+ $roles->remove_role($this->getId());
68
+ $status = true;
 
69
  }
70
 
71
  return $status;
82
  */
83
  public function update($name) {
84
  $roles = AAM_Core_API::getRoles();
85
+
86
  if ($name) {
87
  $roles->roles[$this->getId()]['name'] = $name;
88
  $status = AAM_Core_API::updateOption($roles->role_key, $roles->roles);
103
  * @access public
104
  */
105
  public function removeCapability($capability) {
106
+ $this->getSubject()->remove_cap($capability);
107
 
108
  return true;
109
  }
221
  * @return type
222
  */
223
  public function getName() {
224
+ return translate_user_role($this->name);
225
  }
226
 
227
  /**
Application/Core/Subject/User.php CHANGED
@@ -31,6 +31,8 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
31
  * It is very important to have all user capability changes be stored in
32
  * separate options from the wp_capabilities usermeta cause if AAM is not
33
  * active as a plugin, it reverts back to the default WordPress settings
 
 
34
  */
35
  const AAM_CAPKEY = 'aam_capability';
36
 
@@ -198,7 +200,7 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
198
  */
199
  public function getUserStatus() {
200
  if (is_null($this->status)) {
201
- $this->status = array('status' => 'active');
202
  $steps = array(
203
  'UserRecordStatus', // Check if user's record states that it is blocked
204
  'UserExpiration', // Check if user's account is expired
@@ -209,7 +211,7 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
209
  foreach($steps as $step) {
210
  $result = call_user_func(array($this, "check{$step}"));
211
  if ($result !== true) {
212
- $this->status = $result;
213
  break;
214
  }
215
  }
@@ -221,23 +223,23 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
221
  /**
222
  * Restrain user account based on status
223
  *
224
- * @param array $status
225
  *
226
  * @return void
227
  * @see AAM_Core_Subject_User::getUserStatus
228
  *
229
  * @access public
230
  */
231
- public function restrainUserAccount(array $status) {
232
- switch($status['action']) {
233
  case 'lock':
234
  $this->block();
235
  break;
236
 
237
  case 'change-role':
238
- $this->getSubject()->set_role(''); // First reset all roles
239
- foreach((array)$status['meta'] as $role) {
240
- $this->getSubject()->add_role($role);
241
  }
242
  break;
243
 
@@ -251,7 +253,7 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
251
  wp_logout();
252
  break;
253
  }
254
-
255
  // Delete `aam_user_expiration`
256
  delete_user_meta($this->getId(), 'aam_user_expiration');
257
  }
@@ -385,9 +387,9 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
385
 
386
  $status = ($this->getSubject()->user_status ? 0 : 1);
387
  $result = $wpdb->update(
388
- $wpdb->users,
389
- array('user_status' => $status),
390
- array('ID' => $this->getId())
391
  );
392
 
393
  if ($result) {
@@ -423,7 +425,16 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
423
  * @access public
424
  */
425
  public function getCapabilities() {
426
- return $this->getSubject()->allcaps;
 
 
 
 
 
 
 
 
 
427
  }
428
 
429
  /**
@@ -449,7 +460,9 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
449
  * @access public
450
  */
451
  public function addCapability($capability) {
452
- return $this->updateCapability($capability, true);
 
 
453
  }
454
 
455
  /**
@@ -462,26 +475,9 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
462
  * @access public
463
  */
464
  public function removeCapability($capability) {
465
- return $this->updateCapability($capability, false);
466
- }
467
 
468
- /**
469
- * Update User's Capability Set
470
- *
471
- * @param string $capability
472
- * @param boolean $grand
473
- *
474
- * @return boolean
475
- *
476
- * @access public
477
- */
478
- public function updateCapability($capability, $grand) {
479
- //update capability
480
- $caps = $this->getSubject()->caps;
481
- $caps[$capability] = $grand;
482
-
483
- //save and return the result of operation
484
- return update_user_option($this->getId(), self::AAM_CAPKEY, $caps);
485
  }
486
 
487
  /**
31
  * It is very important to have all user capability changes be stored in
32
  * separate options from the wp_capabilities usermeta cause if AAM is not
33
  * active as a plugin, it reverts back to the default WordPress settings
34
+ *
35
+ * @todo Remove in June 2020
36
  */
37
  const AAM_CAPKEY = 'aam_capability';
38
 
200
  */
201
  public function getUserStatus() {
202
  if (is_null($this->status)) {
203
+ $this->status = (object) array('status' => 'active');
204
  $steps = array(
205
  'UserRecordStatus', // Check if user's record states that it is blocked
206
  'UserExpiration', // Check if user's account is expired
211
  foreach($steps as $step) {
212
  $result = call_user_func(array($this, "check{$step}"));
213
  if ($result !== true) {
214
+ $this->status = (object) $result;
215
  break;
216
  }
217
  }
223
  /**
224
  * Restrain user account based on status
225
  *
226
+ * @param object $status
227
  *
228
  * @return void
229
  * @see AAM_Core_Subject_User::getUserStatus
230
  *
231
  * @access public
232
  */
233
+ public function restrainUserAccount($status) {
234
+ switch($status->action) {
235
  case 'lock':
236
  $this->block();
237
  break;
238
 
239
  case 'change-role':
240
+ $this->set_role(''); // First reset all roles
241
+ foreach((array)$status->meta as $role) {
242
+ $this->add_role($role);
243
  }
244
  break;
245
 
253
  wp_logout();
254
  break;
255
  }
256
+
257
  // Delete `aam_user_expiration`
258
  delete_user_meta($this->getId(), 'aam_user_expiration');
259
  }
387
 
388
  $status = ($this->getSubject()->user_status ? 0 : 1);
389
  $result = $wpdb->update(
390
+ $wpdb->users,
391
+ array('user_status' => $status),
392
+ array('ID' => $this->getId())
393
  );
394
 
395
  if ($result) {
425
  * @access public
426
  */
427
  public function getCapabilities() {
428
+ $caps = $this->getSubject()->caps;
429
+ $roles = AAM_Core_API::getRoles();
430
+
431
+ foreach($caps as $cap => $effect) {
432
+ if ($roles->is_role($cap)) {
433
+ unset($caps[$cap]);
434
+ }
435
+ }
436
+
437
+ return $caps;
438
  }
439
 
440
  /**
460
  * @access public
461
  */
462
  public function addCapability($capability) {
463
+ $this->getSubject()->add_cap($capability);
464
+
465
+ return true;
466
  }
467
 
468
  /**
475
  * @access public
476
  */
477
  public function removeCapability($capability) {
478
+ $this->getSubject()->remove_cap($capability);
 
479
 
480
+ return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  }
482
 
483
  /**
Application/Extension/List.php CHANGED
@@ -22,7 +22,7 @@ class AAM_Extension_List {
22
  'description' => 'Get the complete list of all premium AAM extensions in one package and all future premium extensions already included for now additional cost.',
23
  'url' => 'https://aamplugin.com/complete-package',
24
  'version' => (defined('AAM_COMPLETE_PACKAGE') ? constant('AAM_COMPLETE_PACKAGE') : null),
25
- 'latest' => '3.8.17'
26
  ),
27
  'AAM_PLUS_PACKAGE' => array(
28
  'title' => 'Plus Package',
@@ -31,7 +31,7 @@ class AAM_Extension_List {
31
  'description' => 'Manage access to your WordPress website posts, pages, media, custom post types, categories and hierarchical taxonomies for any role, individual user, visitors or even define default access for everybody; and do this separately for frontend, backend or API levels. As the bonus, define more granular access to how comments can be managed on the backend by other users.',
32
  'url' => 'https://aamplugin.com/extension/plus-package',
33
  'version' => (defined('AAM_PLUS_PACKAGE') ? constant('AAM_PLUS_PACKAGE') : null),
34
- 'latest' => '3.9.5'
35
  ),
36
  'AAM_IP_CHECK' => array(
37
  'title' => 'IP Check',
22
  'description' => 'Get the complete list of all premium AAM extensions in one package and all future premium extensions already included for now additional cost.',
23
  'url' => 'https://aamplugin.com/complete-package',
24
  'version' => (defined('AAM_COMPLETE_PACKAGE') ? constant('AAM_COMPLETE_PACKAGE') : null),
25
+ 'latest' => '3.8.20'
26
  ),
27
  'AAM_PLUS_PACKAGE' => array(
28
  'title' => 'Plus Package',
31
  'description' => 'Manage access to your WordPress website posts, pages, media, custom post types, categories and hierarchical taxonomies for any role, individual user, visitors or even define default access for everybody; and do this separately for frontend, backend or API levels. As the bonus, define more granular access to how comments can be managed on the backend by other users.',
32
  'url' => 'https://aamplugin.com/extension/plus-package',
33
  'version' => (defined('AAM_PLUS_PACKAGE') ? constant('AAM_PLUS_PACKAGE') : null),
34
+ 'latest' => '3.9.7'
35
  ),
36
  'AAM_IP_CHECK' => array(
37
  'title' => 'IP Check',
Application/Shared/Manager.php CHANGED
@@ -24,15 +24,6 @@ class AAM_Shared_Manager {
24
  */
25
  private static $_instance = null;
26
 
27
- /**
28
- * Undocumented variable
29
- *
30
- * @var array
31
- */
32
- protected $primitiveCaps = array(
33
- 'edit_post', 'delete_post', 'read_post', 'publish_posts'
34
- );
35
-
36
  /**
37
  * Undocumented variable
38
  *
@@ -142,8 +133,13 @@ class AAM_Shared_Manager {
142
  */
143
  public function registerPostType($type, $object) {
144
  if (is_a($object, 'WP_Post_Type')) { // Work only with WP 4.6.0 or higher
 
 
 
 
 
145
  foreach($object->cap as $type => $capability) {
146
- if (in_array($type, $this->primitiveCaps, true)) {
147
  $object->cap->{$type} = "aam|{$type}|{$capability}";
148
  }
149
  }
@@ -203,8 +199,8 @@ class AAM_Shared_Manager {
203
  if (isset($uri['query'])) {
204
  parse_str($uri['query'], $params);
205
  }
206
-
207
- if ($match = $object->findMatch($uri['path'], $params)) {
208
  if ($match['type'] !== 'allow') {
209
  AAM::api()->redirect($match['type'], $match['action']);
210
  }
@@ -299,7 +295,7 @@ class AAM_Shared_Manager {
299
  public function filterPostQuery($clauses, $wpQuery) {
300
  if (!$wpQuery->is_singular && $this->isPostFilterEnabled()) {
301
  $option = AAM::getUser()->getObject('visibility', 0)->getOption();
302
-
303
  if (!empty($option['post'])) {
304
  $query = $this->preparePostQuery($option['post'], $wpQuery);
305
  } else {
@@ -400,7 +396,7 @@ class AAM_Shared_Manager {
400
  } else {
401
  $query = '';
402
  }
403
-
404
  return $query;
405
  }
406
 
@@ -468,18 +464,20 @@ class AAM_Shared_Manager {
468
  * @access public
469
  */
470
  public function mapMetaCaps($caps, $cap, $user_id, $args) {
471
- global $post, $screen;
472
 
473
  $objectId = (isset($args[0]) ? $args[0] : null);
474
 
475
  // First of all delete all artificial capability from the $caps
476
  foreach($caps as $i => $capability) {
477
  if (strpos($capability, 'aam|') === 0) {
478
- $parts = explode('|', $capability);
479
- $capability = $parts[2];
480
- $primitive = $parts[1];
481
- } else {
482
- $primitive = null;
 
 
483
  }
484
 
485
  if (in_array($capability, AAM_Backend_Feature_Main_Capability::$groups['aam'], true)) {
@@ -490,8 +488,7 @@ class AAM_Shared_Manager {
490
  }
491
  }
492
 
493
- // If capability is primitive - then do not include it in the list of meta caps
494
- if (in_array($primitive, $this->primitiveCaps, true)) {
495
  unset($caps[$i]);
496
  } else {
497
  $caps[$i] = $capability;
24
  */
25
  private static $_instance = null;
26
 
 
 
 
 
 
 
 
 
 
27
  /**
28
  * Undocumented variable
29
  *
133
  */
134
  public function registerPostType($type, $object) {
135
  if (is_a($object, 'WP_Post_Type')) { // Work only with WP 4.6.0 or higher
136
+ // The list of capabilities to override
137
+ $override = array(
138
+ 'edit_post', 'delete_post', 'read_post', 'publish_posts'
139
+ );
140
+
141
  foreach($object->cap as $type => $capability) {
142
+ if (in_array($type, $override, true)) {
143
  $object->cap->{$type} = "aam|{$type}|{$capability}";
144
  }
145
  }
199
  if (isset($uri['query'])) {
200
  parse_str($uri['query'], $params);
201
  }
202
+
203
+ if ($match = $object->findMatch(rtrim($uri['path'], '/'), $params)) {
204
  if ($match['type'] !== 'allow') {
205
  AAM::api()->redirect($match['type'], $match['action']);
206
  }
295
  public function filterPostQuery($clauses, $wpQuery) {
296
  if (!$wpQuery->is_singular && $this->isPostFilterEnabled()) {
297
  $option = AAM::getUser()->getObject('visibility', 0)->getOption();
298
+
299
  if (!empty($option['post'])) {
300
  $query = $this->preparePostQuery($option['post'], $wpQuery);
301
  } else {
396
  } else {
397
  $query = '';
398
  }
399
+
400
  return $query;
401
  }
402
 
464
  * @access public
465
  */
466
  public function mapMetaCaps($caps, $cap, $user_id, $args) {
467
+ global $post;
468
 
469
  $objectId = (isset($args[0]) ? $args[0] : null);
470
 
471
  // First of all delete all artificial capability from the $caps
472
  foreach($caps as $i => $capability) {
473
  if (strpos($capability, 'aam|') === 0) {
474
+ $parts = explode('|', $capability);
475
+
476
+ if (in_array($parts[1], array('edit_post', 'delete_post', 'read_post'), true)) {
477
+ $capability = null; //remove primitive from the meta array
478
+ } else {
479
+ $capability = $parts[2];
480
+ }
481
  }
482
 
483
  if (in_array($capability, AAM_Backend_Feature_Main_Capability::$groups['aam'], true)) {
488
  }
489
  }
490
 
491
+ if ($capability === null) {
 
492
  unset($caps[$i]);
493
  } else {
494
  $caps[$i] = $capability;
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.9.3
7
  * Author: Vasyl Martyniuk <vasyl@vasyltech.com>
8
  * Author URI: https://vasyltech.com
9
  *
@@ -114,7 +114,7 @@ class AAM {
114
  public static function onPluginsLoaded() {
115
  //load AAM core config
116
  AAM_Core_Config::bootstrap();
117
-
118
  //login control
119
  if (AAM_Core_Config::get('core.settings.secureLogin', true)) {
120
  AAM_Core_Login::bootstrap();
@@ -171,12 +171,12 @@ class AAM {
171
 
172
  // Load user capabilities
173
  $user->initialize();
174
-
175
  // Logout user if he/she is blocked
176
  $status = $user->getUserStatus();
177
-
178
  // If user is not active, then perform rollback on user
179
- if ($status['status'] !== 'active') {
180
  $user->restrainUserAccount($status);
181
  }
182
 
3
  /**
4
  * Plugin Name: Advanced Access Manager
5
  * Description: All you need to manage access to your WordPress website
6
+ * Version: 5.9.4
7
  * Author: Vasyl Martyniuk <vasyl@vasyltech.com>
8
  * Author URI: https://vasyltech.com
9
  *
114
  public static function onPluginsLoaded() {
115
  //load AAM core config
116
  AAM_Core_Config::bootstrap();
117
+
118
  //login control
119
  if (AAM_Core_Config::get('core.settings.secureLogin', true)) {
120
  AAM_Core_Login::bootstrap();
171
 
172
  // Load user capabilities
173
  $user->initialize();
174
+
175
  // Logout user if he/she is blocked
176
  $status = $user->getUserStatus();
177
+
178
  // If user is not active, then perform rollback on user
179
+ if (!empty($status) && $status->status !== 'active') {
180
  $user->restrainUserAccount($status);
181
  }
182
 
media/css/aam.css CHANGED
@@ -105,6 +105,17 @@
105
  .icon-wrench:before { content: '\e80e' !important; } /* '' */
106
  .icon-ok-circled:before { content: '\e81c' !important; } /* '' */
107
  .icon-cancel-circled:before { content: '\e81d' !important; } /* '' */
 
 
 
 
 
 
 
 
 
 
 
108
 
109
  .animate-spin {
110
  -moz-animation: spin 2s infinite linear;
105
  .icon-wrench:before { content: '\e80e' !important; } /* '' */
106
  .icon-ok-circled:before { content: '\e81c' !important; } /* '' */
107
  .icon-cancel-circled:before { content: '\e81d' !important; } /* '' */
108
+ .icon-info-circled:before { content: '\e81f' !important; } /* '' */
109
+ .icon-attention:before { content: '\e81e' !important; } /* '' */
110
+
111
+ .icon-image-40 {
112
+ font-size: 40px;
113
+ }
114
+
115
+ .icon-image-40:before {
116
+ margin-left: 0 !important;
117
+ margin-right: 0 !important;
118
+ }
119
 
120
  .animate-spin {
121
  -moz-animation: spin 2s infinite linear;
media/font/fontello.eot CHANGED
Binary file
media/font/fontello.svg CHANGED
@@ -66,6 +66,10 @@
66
 
67
  <glyph glyph-name="cancel-circled" unicode="&#xe81d;" d="M641 224q0 14-10 25l-101 101 101 101q10 11 10 25 0 15-10 26l-51 50q-10 11-25 11-15 0-25-11l-101-101-101 101q-11 11-25 11-16 0-26-11l-50-50q-11-11-11-26 0-14 11-25l101-101-101-101q-11-11-11-25 0-15 11-26l50-50q10-11 26-11 14 0 25 11l101 101 101-101q10-11 25-11 15 0 25 11l51 50q10 11 10 26z m216 126q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
68
 
 
 
 
 
69
  <glyph glyph-name="user-plus" unicode="&#xe820;" d="M393 350q-89 0-152 63t-62 151 62 152 152 63 151-63 63-152-63-151-151-63z m536-71h196q7 0 13-6t5-12v-107q0-8-5-13t-13-5h-196v-197q0-7-6-12t-12-6h-107q-8 0-13 6t-5 12v197h-197q-7 0-12 5t-6 13v107q0 7 6 12t12 6h197v196q0 7 5 13t13 5h107q7 0 12-5t6-13v-196z m-411-125q0-29 21-51t50-21h143v-133q-38-28-95-28h-488q-67 0-108 39t-41 106q0 30 2 58t8 61 15 60 24 55 34 45 48 30 62 11q11 0 22-10 44-34 86-51t92-17 92 17 86 51q11 10 22 10 73 0 121-54h-125q-29 0-50-21t-21-50v-107z" horiz-adv-x="1142.9" />
70
 
71
  <glyph glyph-name="box" unicode="&#xe822;" d="M607 386q0 14-10 25t-26 10h-142q-15 0-26-10t-10-25 10-25 26-11h142q15 0 26 11t10 25z m322 107v-536q0-14-11-25t-25-11h-786q-14 0-25 11t-11 25v536q0 14 11 25t25 11h786q14 0 25-11t11-25z m35 250v-143q0-15-10-25t-25-11h-858q-14 0-25 11t-10 25v143q0 14 10 25t25 11h858q14 0 25-11t10-25z" horiz-adv-x="1000" />
66
 
67
  <glyph glyph-name="cancel-circled" unicode="&#xe81d;" d="M641 224q0 14-10 25l-101 101 101 101q10 11 10 25 0 15-10 26l-51 50q-10 11-25 11-15 0-25-11l-101-101-101 101q-11 11-25 11-16 0-26-11l-50-50q-11-11-11-26 0-14 11-25l101-101-101-101q-11-11-11-25 0-15 11-26l50-50q10-11 26-11 14 0 25 11l101 101 101-101q10-11 25-11 15 0 25 11l51 50q10 11 10 26z m216 126q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
68
 
69
+ <glyph glyph-name="attention" unicode="&#xe81e;" d="M571 83v106q0 8-5 13t-12 5h-108q-7 0-12-5t-5-13v-106q0-8 5-13t12-6h108q7 0 12 6t5 13z m-1 208l10 257q0 6-5 10-7 6-14 6h-122q-6 0-14-6-5-4-5-12l9-255q0-5 6-9t13-3h103q8 0 14 3t5 9z m-7 522l428-786q20-35-1-70-9-17-26-26t-35-10h-858q-18 0-35 10t-26 26q-21 35-1 70l429 786q9 17 26 27t36 10 36-10 27-27z" horiz-adv-x="1000" />
70
+
71
+ <glyph glyph-name="info-circled" unicode="&#xe81f;" d="M571 82v89q0 8-5 13t-12 5h-54v286q0 8-5 13t-13 5h-178q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h53v-179h-53q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h250q7 0 12 5t5 13z m-71 500v89q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-89q0-8 5-13t13-5h107q8 0 13 5t5 13z m357-232q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
72
+
73
  <glyph glyph-name="user-plus" unicode="&#xe820;" d="M393 350q-89 0-152 63t-62 151 62 152 152 63 151-63 63-152-63-151-151-63z m536-71h196q7 0 13-6t5-12v-107q0-8-5-13t-13-5h-196v-197q0-7-6-12t-12-6h-107q-8 0-13 6t-5 12v197h-197q-7 0-12 5t-6 13v107q0 7 6 12t12 6h197v196q0 7 5 13t13 5h107q7 0 12-5t6-13v-196z m-411-125q0-29 21-51t50-21h143v-133q-38-28-95-28h-488q-67 0-108 39t-41 106q0 30 2 58t8 61 15 60 24 55 34 45 48 30 62 11q11 0 22-10 44-34 86-51t92-17 92 17 86 51q11 10 22 10 73 0 121-54h-125q-29 0-50-21t-21-50v-107z" horiz-adv-x="1142.9" />
74
 
75
  <glyph glyph-name="box" unicode="&#xe822;" d="M607 386q0 14-10 25t-26 10h-142q-15 0-26-10t-10-25 10-25 26-11h142q15 0 26 11t10 25z m322 107v-536q0-14-11-25t-25-11h-786q-14 0-25 11t-11 25v536q0 14 11 25t25 11h786q14 0 25-11t11-25z m35 250v-143q0-15-10-25t-25-11h-858q-14 0-25 11t-10 25v143q0 14 10 25t25 11h858q14 0 25-11t10-25z" horiz-adv-x="1000" />
media/font/fontello.ttf CHANGED
Binary file
media/font/fontello.woff CHANGED
Binary file
media/font/fontello.woff2 CHANGED
Binary file
media/js/{aam-5.9.2.js → aam-5.9.4.js} RENAMED
@@ -43,7 +43,7 @@
43
  }
44
  },
45
  error: function () {
46
- getAAM().notification('danger', getAAM().__('Application error'));
47
  },
48
  complete: function () {
49
  $(btn).attr(
@@ -103,9 +103,7 @@
103
  }
104
  },
105
  error: function () {
106
- getAAM().notification(
107
- 'danger', getAAM().__('Application Error')
108
- );
109
  }
110
  });
111
  });
@@ -569,7 +567,7 @@
569
  }
570
  },
571
  error: function () {
572
- getAAM().notification('danger', getAAM().__('Application error'));
573
  },
574
  complete: function () {
575
  $('#add-role-modal').modal('hide');
@@ -623,7 +621,7 @@
623
  }
624
  },
625
  error: function () {
626
- getAAM().notification('danger', getAAM().__('Application error'));
627
  },
628
  complete: function () {
629
  $('#edit-role-modal').modal('hide');
@@ -660,7 +658,7 @@
660
  }
661
  },
662
  error: function () {
663
- getAAM().notification('danger', getAAM().__('Application error'));
664
  },
665
  complete: function () {
666
  $('#delete-role-modal').modal('hide');
@@ -753,10 +751,60 @@
753
  }
754
  },
755
  error: function () {
756
- getAAM().notification('danger', getAAM().__('Application error'));
757
  }
758
  });
759
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
760
 
761
  //initialize the user list table
762
  $('#user-list').DataTable({
@@ -924,9 +972,17 @@
924
  loadRoleList();
925
  $('#expiration-change-role-holder').addClass('hidden');
926
  }
 
 
 
 
 
 
 
 
927
  } else {
928
- $('#reset-user-expiration-btn').addClass('hidden');
929
- $('#user-expires, #action-after-expiration').val('');
930
  loadRoleList();
931
  }
932
 
@@ -1050,7 +1106,11 @@
1050
  $('#expiration-change-role-holder').addClass('hidden');
1051
  }
1052
  });
1053
-
 
 
 
 
1054
  $('#user-expiration-datapicker').datetimepicker({
1055
  icons: {
1056
  time: "icon-clock",
@@ -1061,6 +1121,7 @@
1061
  next: "icon-angle-right"
1062
  },
1063
  inline: true,
 
1064
  sideBySide: true
1065
  });
1066
 
@@ -1083,9 +1144,7 @@
1083
  });
1084
 
1085
  $('#user-expiration-datapicker').on('dp.change', function(res) {
1086
- $('#user-expires').val(
1087
- res.date.format('MM/DD/YYYY, H:mm Z')
1088
- );
1089
  });
1090
 
1091
  //edit role button
@@ -1102,7 +1161,8 @@
1102
  user: $(_this).attr('data-user-id'),
1103
  expires: $('#user-expires').val(),
1104
  after: $('#action-after-expiration').val(),
1105
- role: $('#expiration-change-role').val()
 
1106
  },
1107
  beforeSend: function () {
1108
  $(_this).text(getAAM().__('Saving...')).attr('disabled', true);
@@ -1115,7 +1175,7 @@
1115
  }
1116
  },
1117
  error: function () {
1118
- getAAM().notification('danger', getAAM().__('Application error'));
1119
  },
1120
  complete: function () {
1121
  $('#edit-user-modal').modal('hide');
@@ -1133,7 +1193,7 @@
1133
  dataType: 'json',
1134
  data: {
1135
  action: 'aam',
1136
- sub_action: 'Subject_User.saveExpiration',
1137
  _ajax_nonce: getLocal().nonce,
1138
  user: $(_this).attr('data-user-id')
1139
  },
@@ -1148,7 +1208,7 @@
1148
  }
1149
  },
1150
  error: function () {
1151
- getAAM().notification('danger', getAAM().__('Application error'));
1152
  },
1153
  complete: function () {
1154
  $('#edit-user-modal').modal('hide');
@@ -1264,7 +1324,10 @@
1264
  $('#manage-default').bind('click', function () {
1265
  var _this = this;
1266
 
1267
- getAAM().setSubject('default', null, getAAM().__('All Users, Roles and Visitor'), 0);
 
 
 
1268
  $('i.icon-cog', $(this)).attr('class', 'icon-spin4 animate-spin');
1269
  if (getAAM().isUI('main')) {
1270
  getAAM().fetchContent('main');
@@ -1364,10 +1427,7 @@
1364
  }
1365
  },
1366
  error: function () {
1367
- getAAM().notification(
1368
- 'danger',
1369
- getAAM().__('Application error')
1370
- );
1371
  },
1372
  complete: function() {
1373
  cb();
@@ -1589,9 +1649,7 @@
1589
  successCallback(response);
1590
  },
1591
  error: function () {
1592
- getAAM().notification(
1593
- 'danger', getAAM().__('Application Error')
1594
- );
1595
  }
1596
  });
1597
  });
@@ -1713,9 +1771,7 @@
1713
  successCallback(response);
1714
  },
1715
  error: function () {
1716
- getAAM().notification(
1717
- 'danger', getAAM().__('Application Error')
1718
- );
1719
  }
1720
  });
1721
  });
@@ -1839,9 +1895,7 @@
1839
  successCallback(response);
1840
  },
1841
  error: function () {
1842
- getAAM().notification(
1843
- 'danger', getAAM().__('Application Error')
1844
- );
1845
  }
1846
  });
1847
  });
@@ -1868,9 +1922,7 @@
1868
  initialize();
1869
  },
1870
  error: function () {
1871
- getAAM().notification(
1872
- 'danger', getAAM().__('Application error')
1873
- );
1874
  }
1875
  });
1876
  }
@@ -1932,9 +1984,7 @@
1932
  }
1933
  },
1934
  error: function () {
1935
- getAAM().notification(
1936
- 'danger', getAAM().__('Application error')
1937
- );
1938
  $('i', '#refresh-metabox-list').attr(
1939
  'class', 'icon-arrows-cw'
1940
  );
@@ -2046,9 +2096,7 @@
2046
  }
2047
  },
2048
  error: function () {
2049
- getAAM().notification(
2050
- 'danger', getAAM().__('Application Error')
2051
- );
2052
  }
2053
  });
2054
  });
@@ -2142,10 +2190,13 @@
2142
  $(container).append($('<i/>', {
2143
  'class': 'aam-row-action icon-trash-empty text-danger'
2144
  }).bind('click', function () {
2145
- var message = $('.aam-confirm-message', '#delete-capability-modal');
2146
- $(message).html(message.data('message').replace(
2147
- '%s', '"' + data[0] + '"')
2148
- );
 
 
 
2149
  $('#capability-id').val(data[0]);
2150
  $('#delete-capability-btn').attr('data-cap', data[0]);
2151
  $('#delete-capability-modal').modal('show');
@@ -2222,7 +2273,7 @@
2222
  }
2223
  },
2224
  error: function () {
2225
- getAAM().notification('danger', getAAM().__('Application error'));
2226
  },
2227
  complete: function () {
2228
  $(_this).text(getAAM().__('Add Capability')).attr('disabled', false);
@@ -2248,6 +2299,8 @@
2248
  data: {
2249
  action: 'aam',
2250
  sub_action: 'Main_Capability.update',
 
 
2251
  _ajax_nonce: getLocal().nonce,
2252
  capability: $(this).attr('data-cap'),
2253
  updated: cap
@@ -2265,7 +2318,7 @@
2265
  }
2266
  },
2267
  error: function () {
2268
- getAAM().notification('danger', getAAM().__('Application error'));
2269
  },
2270
  complete: function () {
2271
  $('#edit-capability-modal').modal('hide');
@@ -2304,7 +2357,7 @@
2304
  }
2305
  },
2306
  error: function () {
2307
- getAAM().notification('danger', getAAM().__('Application error'));
2308
  },
2309
  complete: function () {
2310
  $('#delete-capability-modal').modal('hide');
@@ -2389,9 +2442,7 @@
2389
  successCallback(response);
2390
  },
2391
  error: function () {
2392
- getAAM().notification(
2393
- 'danger', getAAM().__('Application error')
2394
- );
2395
  }
2396
  });
2397
  });
@@ -2559,7 +2610,7 @@
2559
  });
2560
  },
2561
  error: function () {
2562
- getAAM().notification('danger', getAAM().__('Application error'));
2563
  },
2564
  complete: function () {
2565
  $(btn).attr('class', $(btn).attr('data-class')).removeAttr('data-class');
@@ -2777,7 +2828,7 @@
2777
  $(_btn).attr('class', 'aam-row-action icon-spin4 animate-spin');
2778
  },
2779
  error: function () {
2780
- getAAM().notification('danger', getAAM().__('Application error'));
2781
  },
2782
  complete: function () {
2783
  $('#post-list').DataTable().ajax.reload();
@@ -2951,6 +3002,7 @@
2951
  previous: "icon-angle-left",
2952
  next: "icon-angle-right"
2953
  },
 
2954
  inline: true,
2955
  sideBySide: true
2956
  });
@@ -3013,9 +3065,7 @@
3013
  successCallback(response);
3014
  },
3015
  error: function () {
3016
- getAAM().notification(
3017
- 'danger', getAAM().__('Application Error')
3018
- );
3019
  }
3020
  });
3021
  });
@@ -3109,9 +3159,7 @@
3109
  successCallback(response);
3110
  },
3111
  error: function () {
3112
- getAAM().notification(
3113
- 'danger', getAAM().__('Application Error')
3114
- );
3115
  }
3116
  });
3117
  });
@@ -3211,9 +3259,7 @@
3211
  successCallback(response);
3212
  },
3213
  error: function () {
3214
- getAAM().notification(
3215
- 'danger', getAAM().__('Application Error')
3216
- );
3217
  }
3218
  });
3219
  });
@@ -3303,9 +3349,7 @@
3303
  value: value
3304
  },
3305
  error: function () {
3306
- getAAM().notification(
3307
- 'danger', getAAM().__('Application error')
3308
- );
3309
  }
3310
  });
3311
  });
@@ -3394,9 +3438,7 @@
3394
  },
3395
  error: function () {
3396
  updateBtn(btn, value ? 0 : 1);
3397
- getAAM().notification(
3398
- 'danger', getAAM().__('Application error')
3399
- );
3400
  }
3401
  });
3402
  });
@@ -3565,9 +3607,7 @@
3565
  }
3566
  },
3567
  error: function () {
3568
- getAAM().notification(
3569
- 'danger', getAAM().__('Application error')
3570
- );
3571
  },
3572
  complete: function () {
3573
  $('#uri-model').modal('hide');
@@ -3602,7 +3642,7 @@
3602
  }
3603
  },
3604
  error: function () {
3605
- getAAM().notification('danger', getAAM().__('Application error'));
3606
  },
3607
  complete: function () {
3608
  $('#uri-delete-model').modal('hide');
@@ -3720,7 +3760,7 @@
3720
  * @param {type} expires
3721
  * @returns {undefined}
3722
  */
3723
- function generateJWT(expires) {
3724
  $.ajax(getLocal().ajaxurl, {
3725
  type: 'POST',
3726
  dataType: 'json',
@@ -3730,7 +3770,8 @@
3730
  _ajax_nonce: getLocal().nonce,
3731
  subject: getAAM().getSubject().type,
3732
  subjectId: getAAM().getSubject().id,
3733
- expires: expires
 
3734
  },
3735
  beforeSend: function () {
3736
  $('#jwt-token-preview').val(getAAM().__('Generating token...'));
@@ -3749,7 +3790,7 @@
3749
  }
3750
  },
3751
  error: function () {
3752
- getAAM().notification('danger', getAAM().__('Application error'));
3753
  }
3754
  });
3755
  }
@@ -3793,7 +3834,15 @@
3793
  res.date.format('MM/DD/YYYY, H:mm Z')
3794
  );
3795
  generateJWT(
3796
- $('#jwt-expires').val()
 
 
 
 
 
 
 
 
3797
  );
3798
  });
3799
 
@@ -3915,9 +3964,7 @@
3915
  }
3916
  },
3917
  error: function () {
3918
- getAAM().notification(
3919
- 'danger', getAAM().__('Application error')
3920
- );
3921
  },
3922
  complete: function() {
3923
  $('#create-jwt-btn').html(getAAM().__('Create'));
@@ -3949,15 +3996,15 @@
3949
  }
3950
  },
3951
  error: function () {
3952
- getAAM().notification(
3953
- 'danger', getAAM().__('Application error')
3954
- );
3955
  },
3956
  complete: function() {
3957
  $('#jwt-delete-btn').html(getAAM().__('Delete'));
3958
  }
3959
  });
3960
  });
 
 
3961
  }
3962
  }
3963
 
@@ -4020,10 +4067,7 @@
4020
  }
4021
  },
4022
  error: function () {
4023
- getAAM().notification(
4024
- 'danger',
4025
- getAAM().__('Application error')
4026
- );
4027
  },
4028
  complete: function() {
4029
  cb();
@@ -4063,9 +4107,7 @@
4063
  }
4064
  },
4065
  error: function () {
4066
- getAAM().notification(
4067
- 'danger', getAAM().__('Application error')
4068
- );
4069
  },
4070
  complete: function () {
4071
  location.reload();
@@ -4214,7 +4256,7 @@
4214
  }
4215
  },
4216
  error: function() {
4217
- getAAM().notification('danger', getAAM().__('Application error'));
4218
  },
4219
  complete: function () {
4220
  $('i', '#fix-extension-dir-issue').attr('class', 'icon-wrench');
@@ -4277,9 +4319,7 @@
4277
  location.reload();
4278
  },
4279
  error: function () {
4280
- getAAM().notification(
4281
- 'danger', getAAM().__('Application Error')
4282
- );
4283
  $('#ack-get-started').text(
4284
  getAAM().__('OK, got it')
4285
  );
@@ -4322,9 +4362,7 @@
4322
  value: value
4323
  },
4324
  error: function () {
4325
- getAAM().notification(
4326
- 'danger', getAAM().__('Application Error')
4327
- );
4328
  }
4329
  });
4330
  });
@@ -4373,7 +4411,7 @@
4373
  }
4374
  },
4375
  error: function () {
4376
- getAAM().notification('danger', getAAM().__('Application Error'));
4377
  },
4378
  complete: function() {
4379
  $('#clear-settings').prop('disabled', false);
@@ -4407,7 +4445,7 @@
4407
  }
4408
  },
4409
  error: function () {
4410
- getAAM().notification('danger', getAAM().__('Application Error'));
4411
  },
4412
  complete: function() {
4413
  $('#clear-cache').prop('disabled', false);
@@ -4439,10 +4477,7 @@
4439
  config: editor.getValue()
4440
  },
4441
  error: function () {
4442
- getAAM().notification(
4443
- 'danger',
4444
- getAAM().__('Application error')
4445
- );
4446
  }
4447
  });
4448
  });
@@ -4853,6 +4888,21 @@
4853
  */
4854
  AAM.prototype.notification = function (status, message) {
4855
  var notification = $('<div/>', {'class': 'aam-sticky-note ' + status});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4856
 
4857
  notification.append($('<span/>').text(message));
4858
  $('.wrap').append(notification);
@@ -4888,9 +4938,7 @@
4888
  getAAM().fetchContent('main');
4889
  },
4890
  error: function () {
4891
- getAAM().notification(
4892
- 'danger', getAAM().__('Application error')
4893
- );
4894
  },
4895
  complete: function() {
4896
  btn.text(btn.attr('data-original-label'));
43
  }
44
  },
45
  error: function () {
46
+ getAAM().notification('danger');
47
  },
48
  complete: function () {
49
  $(btn).attr(
103
  }
104
  },
105
  error: function () {
106
+ getAAM().notification('danger');
 
 
107
  }
108
  });
109
  });
567
  }
568
  },
569
  error: function () {
570
+ getAAM().notification('danger');
571
  },
572
  complete: function () {
573
  $('#add-role-modal').modal('hide');
621
  }
622
  },
623
  error: function () {
624
+ getAAM().notification('danger');
625
  },
626
  complete: function () {
627
  $('#edit-role-modal').modal('hide');
658
  }
659
  },
660
  error: function () {
661
+ getAAM().notification('danger');
662
  },
663
  complete: function () {
664
  $('#delete-role-modal').modal('hide');
751
  }
752
  },
753
  error: function () {
754
+ getAAM().notification('danger');
755
  }
756
  });
757
  }
758
+
759
+ /**
760
+ *
761
+ * @param {*} expires
762
+ * @param {*} action
763
+ */
764
+ function generateJWT() {
765
+ if ($('#login-url-preview').length === 1) {
766
+ // Build the trigger
767
+ var trigger = {
768
+ action: $('#action-after-expiration').val()
769
+ }
770
+
771
+ if (trigger.action === 'change-role') {
772
+ trigger.role = $('#expiration-change-role').val();
773
+ }
774
+
775
+ $.ajax(getLocal().ajaxurl, {
776
+ type: 'POST',
777
+ dataType: 'json',
778
+ data: {
779
+ action: 'aam',
780
+ sub_action: 'Subject_User.generateJwt',
781
+ _ajax_nonce: getLocal().nonce,
782
+ subject: 'user',
783
+ subjectId: $('#reset-user-expiration-btn').attr('data-user-id'),
784
+ expires: $('#user-expires').val(),
785
+ trigger: trigger
786
+ },
787
+ beforeSend: function () {
788
+ $('#login-url-preview').val(getAAM().__('Generating URL...'));
789
+ },
790
+ success: function (response) {
791
+ if (response.status === 'success') {
792
+ $('#login-url-preview').val(
793
+ $('#login-url-preview').data('url').replace('%s', response.jwt)
794
+ );
795
+ $('#login-jwt').val(response.jwt);
796
+ } else {
797
+ getAAM().notification(
798
+ 'danger', getAAM().__('Failed to generate JWT token')
799
+ );
800
+ }
801
+ },
802
+ error: function () {
803
+ getAAM().notification('danger');
804
+ }
805
+ });
806
+ }
807
+ }
808
 
809
  //initialize the user list table
810
  $('#user-list').DataTable({
972
  loadRoleList();
973
  $('#expiration-change-role-holder').addClass('hidden');
974
  }
975
+
976
+ // set JWT if defined
977
+ if (settings.length === 4) {
978
+ $('#login-url-preview').val(
979
+ $('#login-url-preview').data('url').replace('%s', settings[3])
980
+ );
981
+ $('#login-jwt').val( settings[3]);
982
+ }
983
  } else {
984
+ $('#reset-user-expiration-btn, #expiration-change-role-holder').addClass('hidden');
985
+ $('#user-expires, #action-after-expiration, #login-url-preview, #login-url').val('');
986
  loadRoleList();
987
  }
988
 
1106
  $('#expiration-change-role-holder').addClass('hidden');
1107
  }
1108
  });
1109
+
1110
+ $('#request-login-url').bind('click', function() {
1111
+ generateJWT();
1112
+ });
1113
+
1114
  $('#user-expiration-datapicker').datetimepicker({
1115
  icons: {
1116
  time: "icon-clock",
1121
  next: "icon-angle-right"
1122
  },
1123
  inline: true,
1124
+ minDate: new Date(),
1125
  sideBySide: true
1126
  });
1127
 
1144
  });
1145
 
1146
  $('#user-expiration-datapicker').on('dp.change', function(res) {
1147
+ $('#user-expires').val(res.date.format('MM/DD/YYYY, H:mm Z'));
 
 
1148
  });
1149
 
1150
  //edit role button
1161
  user: $(_this).attr('data-user-id'),
1162
  expires: $('#user-expires').val(),
1163
  after: $('#action-after-expiration').val(),
1164
+ role: $('#expiration-change-role').val(),
1165
+ jwt: $('#login-jwt').val()
1166
  },
1167
  beforeSend: function () {
1168
  $(_this).text(getAAM().__('Saving...')).attr('disabled', true);
1175
  }
1176
  },
1177
  error: function () {
1178
+ getAAM().notification('danger');
1179
  },
1180
  complete: function () {
1181
  $('#edit-user-modal').modal('hide');
1193
  dataType: 'json',
1194
  data: {
1195
  action: 'aam',
1196
+ sub_action: 'Subject_User.resetExpiration',
1197
  _ajax_nonce: getLocal().nonce,
1198
  user: $(_this).attr('data-user-id')
1199
  },
1208
  }
1209
  },
1210
  error: function () {
1211
+ getAAM().notification('danger');
1212
  },
1213
  complete: function () {
1214
  $('#edit-user-modal').modal('hide');
1324
  $('#manage-default').bind('click', function () {
1325
  var _this = this;
1326
 
1327
+ getAAM().setSubject(
1328
+ 'default', null, getAAM().__('All Users, Roles and Visitor'), 0
1329
+ );
1330
+
1331
  $('i.icon-cog', $(this)).attr('class', 'icon-spin4 animate-spin');
1332
  if (getAAM().isUI('main')) {
1333
  getAAM().fetchContent('main');
1427
  }
1428
  },
1429
  error: function () {
1430
+ getAAM().notification('danger');
 
 
 
1431
  },
1432
  complete: function() {
1433
  cb();
1649
  successCallback(response);
1650
  },
1651
  error: function () {
1652
+ getAAM().notification('danger');
 
 
1653
  }
1654
  });
1655
  });
1771
  successCallback(response);
1772
  },
1773
  error: function () {
1774
+ getAAM().notification('danger');
 
 
1775
  }
1776
  });
1777
  });
1895
  successCallback(response);
1896
  },
1897
  error: function () {
1898
+ getAAM().notification('danger');
 
 
1899
  }
1900
  });
1901
  });
1922
  initialize();
1923
  },
1924
  error: function () {
1925
+ getAAM().notification('danger');
 
 
1926
  }
1927
  });
1928
  }
1984
  }
1985
  },
1986
  error: function () {
1987
+ getAAM().notification('danger');
 
 
1988
  $('i', '#refresh-metabox-list').attr(
1989
  'class', 'icon-arrows-cw'
1990
  );
2096
  }
2097
  },
2098
  error: function () {
2099
+ getAAM().notification('danger');
 
 
2100
  }
2101
  });
2102
  });
2190
  $(container).append($('<i/>', {
2191
  'class': 'aam-row-action icon-trash-empty text-danger'
2192
  }).bind('click', function () {
2193
+ var message = $('.aam-confirm-message', '#delete-capability-modal').data('message');
2194
+
2195
+ // replace some dynamic parts
2196
+ message = message.replace('%s', '<b>' + data[0] + '</b>');
2197
+ message = message.replace('%n', '<b>' + getAAM().getSubject().name + '</b>')
2198
+ $('.aam-confirm-message', '#delete-capability-modal').html(message);
2199
+
2200
  $('#capability-id').val(data[0]);
2201
  $('#delete-capability-btn').attr('data-cap', data[0]);
2202
  $('#delete-capability-modal').modal('show');
2273
  }
2274
  },
2275
  error: function () {
2276
+ getAAM().notification('danger');
2277
  },
2278
  complete: function () {
2279
  $(_this).text(getAAM().__('Add Capability')).attr('disabled', false);
2299
  data: {
2300
  action: 'aam',
2301
  sub_action: 'Main_Capability.update',
2302
+ subject: getAAM().getSubject().type,
2303
+ subjectId: getAAM().getSubject().id,
2304
  _ajax_nonce: getLocal().nonce,
2305
  capability: $(this).attr('data-cap'),
2306
  updated: cap
2318
  }
2319
  },
2320
  error: function () {
2321
+ getAAM().notification('danger');
2322
  },
2323
  complete: function () {
2324
  $('#edit-capability-modal').modal('hide');
2357
  }
2358
  },
2359
  error: function () {
2360
+ getAAM().notification('danger');
2361
  },
2362
  complete: function () {
2363
  $('#delete-capability-modal').modal('hide');
2442
  successCallback(response);
2443
  },
2444
  error: function () {
2445
+ getAAM().notification('danger');
 
 
2446
  }
2447
  });
2448
  });
2610
  });
2611
  },
2612
  error: function () {
2613
+ getAAM().notification('danger');
2614
  },
2615
  complete: function () {
2616
  $(btn).attr('class', $(btn).attr('data-class')).removeAttr('data-class');
2828
  $(_btn).attr('class', 'aam-row-action icon-spin4 animate-spin');
2829
  },
2830
  error: function () {
2831
+ getAAM().notification('danger');
2832
  },
2833
  complete: function () {
2834
  $('#post-list').DataTable().ajax.reload();
3002
  previous: "icon-angle-left",
3003
  next: "icon-angle-right"
3004
  },
3005
+ minDate: new Date(),
3006
  inline: true,
3007
  sideBySide: true
3008
  });
3065
  successCallback(response);
3066
  },
3067
  error: function () {
3068
+ getAAM().notification('danger');
 
 
3069
  }
3070
  });
3071
  });
3159
  successCallback(response);
3160
  },
3161
  error: function () {
3162
+ getAAM().notification('danger');
 
 
3163
  }
3164
  });
3165
  });
3259
  successCallback(response);
3260
  },
3261
  error: function () {
3262
+ getAAM().notification('danger');
 
 
3263
  }
3264
  });
3265
  });
3349
  value: value
3350
  },
3351
  error: function () {
3352
+ getAAM().notification('danger');
 
 
3353
  }
3354
  });
3355
  });
3438
  },
3439
  error: function () {
3440
  updateBtn(btn, value ? 0 : 1);
3441
+ getAAM().notification('danger');
 
 
3442
  }
3443
  });
3444
  });
3607
  }
3608
  },
3609
  error: function () {
3610
+ getAAM().notification('danger');
 
 
3611
  },
3612
  complete: function () {
3613
  $('#uri-model').modal('hide');
3642
  }
3643
  },
3644
  error: function () {
3645
+ getAAM().notification('danger');
3646
  },
3647
  complete: function () {
3648
  $('#uri-delete-model').modal('hide');
3760
  * @param {type} expires
3761
  * @returns {undefined}
3762
  */
3763
+ function generateJWT(expires, refreshable) {
3764
  $.ajax(getLocal().ajaxurl, {
3765
  type: 'POST',
3766
  dataType: 'json',
3770
  _ajax_nonce: getLocal().nonce,
3771
  subject: getAAM().getSubject().type,
3772
  subjectId: getAAM().getSubject().id,
3773
+ expires: expires,
3774
+ refreshable: refreshable
3775
  },
3776
  beforeSend: function () {
3777
  $('#jwt-token-preview').val(getAAM().__('Generating token...'));
3790
  }
3791
  },
3792
  error: function () {
3793
+ getAAM().notification('danger');
3794
  }
3795
  });
3796
  }
3834
  res.date.format('MM/DD/YYYY, H:mm Z')
3835
  );
3836
  generateJWT(
3837
+ $('#jwt-expires').val(),
3838
+ $('#jwt-refreshable').is(':checked')
3839
+ );
3840
+ });
3841
+
3842
+ $('#jwt-refreshable').on('change', function() {
3843
+ generateJWT(
3844
+ $('#jwt-expires').val(),
3845
+ $('#jwt-refreshable').is(':checked')
3846
  );
3847
  });
3848
 
3964
  }
3965
  },
3966
  error: function () {
3967
+ getAAM().notification('danger');
 
 
3968
  },
3969
  complete: function() {
3970
  $('#create-jwt-btn').html(getAAM().__('Create'));
3996
  }
3997
  },
3998
  error: function () {
3999
+ getAAM().notification('danger');
 
 
4000
  },
4001
  complete: function() {
4002
  $('#jwt-delete-btn').html(getAAM().__('Delete'));
4003
  }
4004
  });
4005
  });
4006
+
4007
+ $('[data-toggle="toggle"]', container).bootstrapToggle();
4008
  }
4009
  }
4010
 
4067
  }
4068
  },
4069
  error: function () {
4070
+ getAAM().notification('danger');
 
 
 
4071
  },
4072
  complete: function() {
4073
  cb();
4107
  }
4108
  },
4109
  error: function () {
4110
+ getAAM().notification('danger');
 
 
4111
  },
4112
  complete: function () {
4113
  location.reload();
4256
  }
4257
  },
4258
  error: function() {
4259
+ getAAM().notification('danger');
4260
  },
4261
  complete: function () {
4262
  $('i', '#fix-extension-dir-issue').attr('class', 'icon-wrench');
4319
  location.reload();
4320
  },
4321
  error: function () {
4322
+ getAAM().notification('danger');
 
 
4323
  $('#ack-get-started').text(
4324
  getAAM().__('OK, got it')
4325
  );
4362
  value: value
4363
  },
4364
  error: function () {
4365
+ getAAM().notification('danger');
 
 
4366
  }
4367
  });
4368
  });
4411
  }
4412
  },
4413
  error: function () {
4414
+ getAAM().notification('danger');
4415
  },
4416
  complete: function() {
4417
  $('#clear-settings').prop('disabled', false);
4445
  }
4446
  },
4447
  error: function () {
4448
+ getAAM().notification('danger');
4449
  },
4450
  complete: function() {
4451
  $('#clear-cache').prop('disabled', false);
4477
  config: editor.getValue()
4478
  },
4479
  error: function () {
4480
+ getAAM().notification('danger');
 
 
 
4481
  }
4482
  });
4483
  });
4888
  */
4889
  AAM.prototype.notification = function (status, message) {
4890
  var notification = $('<div/>', {'class': 'aam-sticky-note ' + status});
4891
+
4892
+ if (!message) {
4893
+ switch(status) {
4894
+ case 'success':
4895
+ message = getAAM().__('Operation Completed Successfully');
4896
+ break;
4897
+
4898
+ case 'danger':
4899
+ message = getAAM().__('Unexpected Application Error');
4900
+ break;
4901
+
4902
+ default:
4903
+ break;
4904
+ }
4905
+ }
4906
 
4907
  notification.append($('<span/>').text(message));
4908
  $('.wrap').append(notification);
4938
  getAAM().fetchContent('main');
4939
  },
4940
  error: function () {
4941
+ getAAM().notification('danger');
 
 
4942
  },
4943
  complete: function() {
4944
  btn.text(btn.attr('data-original-label'));
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.1
6
- Stable tag: 5.9.3
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
 
@@ -80,6 +80,17 @@ https://www.youtube.com/watch?v=mj5Xa_Wc16Y
80
 
81
  == Changelog ==
82
 
 
 
 
 
 
 
 
 
 
 
 
83
  = 5.9.3 =
84
  * Fixed the bug with LIST and LIST TO OTHERS options for multiple roles support
85
  * Fixed the bug with managing access to custom post types that contain "-" in name
3
  Tags: access control, membership, backend menu, user role, restricted content, security, jwt
4
  Requires at least: 4.0
5
  Tested up to: 5.1
6
+ Stable tag: 5.9.4
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
 
80
 
81
  == Changelog ==
82
 
83
+ = 5.9.4 =
84
+ * Fixed the bug with incorrectly identifying CPT capabilities
85
+ * Fixed the bug with URI Access where there where no way to override wildcard rule
86
+ * Fixed multiple bugs related to JWT authentication
87
+ * Fixed the bug with Access Policy that triggers PHP Notice for visitors
88
+ * Removed support for ConfigPress option `core.settings.setJwtCookieAfterLogin`
89
+ * Added the ability to obtain Login URL from the "Manage User" modal
90
+ * Added the ability to control AAM cache size https://aamplugin.com/reference/plugin#core-cache-limit
91
+ * Refactored Capabilities feature to follow the best practices for integration with WP Core
92
+ * Refactored JWT authentication so it can be more seamlessly integrated with user status
93
+
94
  = 5.9.3 =
95
  * Fixed the bug with LIST and LIST TO OTHERS options for multiple roles support
96
  * Fixed the bug with managing access to custom post types that contain "-" in name