Advanced Access Manager - Version 5.8

Version Description

  • Fixed the bug with Access Policy settings inheritance mechanism
  • Fixed numerous of bugs with JWT authentication and improved time expiration handling
  • Enhanced temporary user access management functionality
  • Added Logout action when user access expired
  • Added ability to login user with URL
Download this release

Release Info

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

Code changes from version 5.7.3 to 5.8

Application/Api/Rest/Resource/User.php CHANGED
@@ -55,7 +55,7 @@ class AAM_Api_Rest_Resource_User {
55
  */
56
  public function userQuery($args) {
57
  //current user max level
58
- $max = AAM_Core_API::maxLevel(AAM::getUser()->allcaps);
59
  $exclude = isset($args['role__not_in']) ? $args['role__not_in'] : array();
60
  $roles = AAM_Core_API::getRoles();
61
 
55
  */
56
  public function userQuery($args) {
57
  //current user max level
58
+ $max = AAM::getUser()->getMaxLevel();
59
  $exclude = isset($args['role__not_in']) ? $args['role__not_in'] : array();
60
  $roles = AAM_Core_API::getRoles();
61
 
Application/Backend/Feature/Subject/User.php CHANGED
@@ -73,7 +73,7 @@ class AAM_Backend_Feature_Subject_User {
73
  if ($userId != get_current_user_id()) {
74
  if ($this->isAllowed(new AAM_Core_Subject_User($userId))) {
75
  $this->updateUserExpiration($userId, $expires, $action, $role);
76
- $response['status'] = 'success';
77
  }
78
  } else {
79
  $response['reason'] = __('You cannot set expiration to yourself', AAM_KEY);
@@ -83,6 +83,22 @@ class AAM_Backend_Feature_Subject_User {
83
  return wp_json_encode($response);
84
  }
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  /**
87
  * Query database for list of users
88
  *
@@ -146,7 +162,7 @@ class AAM_Backend_Feature_Subject_User {
146
 
147
  if ($this->isAllowed($subject->get())) {
148
  //user is not allowed to lock himself
149
- if ($subject->getId() != get_current_user_id()) {
150
  $result = $subject->block();
151
  }
152
  }
@@ -170,7 +186,7 @@ class AAM_Backend_Feature_Subject_User {
170
  implode(', ', $this->getUserRoles($user->roles)),
171
  ($user->display_name ? $user->display_name : $user->user_nicename),
172
  implode(',', $this->prepareRowActions($user)),
173
- AAM_Core_API::maxLevel($user->allcaps),
174
  $this->getUserExpiration($user)
175
  );
176
  }
@@ -210,7 +226,7 @@ class AAM_Backend_Feature_Subject_User {
210
  * @access protected
211
  */
212
  protected function prepareRowActions(AAM_Core_Subject_User $user) {
213
- if ($this->isAllowed($user) || ($user->ID == get_current_user_id())) {
214
  $ui = AAM_Core_Request::post('ui', 'main');
215
  $id = AAM_Core_Request::post('id');
216
 
@@ -227,10 +243,8 @@ class AAM_Backend_Feature_Subject_User {
227
 
228
  if (current_user_can('edit_users')) {
229
  $actions[] = 'edit';
230
- $actions[] = 'ttl';
231
  } else {
232
  $actions[] = 'no-edit';
233
- $actions[] = 'no-ttl';
234
  }
235
 
236
  if (current_user_can('aam_switch_users')) {
@@ -293,7 +307,7 @@ class AAM_Backend_Feature_Subject_User {
293
  * @access protected
294
  */
295
  protected function isAllowed(AAM_Core_Subject_User $user) {
296
- $max = AAM_Core_API::maxLevel(AAM::getUser()->allcaps);
297
 
298
  return $max >= AAM_Core_API::maxLevel($user->allcaps);
299
  }
73
  if ($userId != get_current_user_id()) {
74
  if ($this->isAllowed(new AAM_Core_Subject_User($userId))) {
75
  $this->updateUserExpiration($userId, $expires, $action, $role);
76
+ $response = array('status' => 'success');
77
  }
78
  } else {
79
  $response['reason'] = __('You cannot set expiration to yourself', AAM_KEY);
83
  return wp_json_encode($response);
84
  }
85
 
86
+ /**
87
+ *
88
+ * @return type
89
+ */
90
+ public function generateJWT() {
91
+ $userId = filter_input(INPUT_POST, 'user');
92
+ $expires = filter_input(INPUT_POST, 'expires');
93
+
94
+ $jwt = AAM_Core_JwtAuth::generateJWT($userId, $expires);
95
+
96
+ return wp_json_encode(array(
97
+ 'status' => 'success',
98
+ 'jwt' => $jwt->token
99
+ ));
100
+ }
101
+
102
  /**
103
  * Query database for list of users
104
  *
162
 
163
  if ($this->isAllowed($subject->get())) {
164
  //user is not allowed to lock himself
165
+ if (intval($subject->getId()) !== get_current_user_id()) {
166
  $result = $subject->block();
167
  }
168
  }
186
  implode(', ', $this->getUserRoles($user->roles)),
187
  ($user->display_name ? $user->display_name : $user->user_nicename),
188
  implode(',', $this->prepareRowActions($user)),
189
+ AAM_Core_API::maxLevel($user->getMaxLevel()),
190
  $this->getUserExpiration($user)
191
  );
192
  }
226
  * @access protected
227
  */
228
  protected function prepareRowActions(AAM_Core_Subject_User $user) {
229
+ if ($this->isAllowed($user) || ($user->ID === get_current_user_id())) {
230
  $ui = AAM_Core_Request::post('ui', 'main');
231
  $id = AAM_Core_Request::post('id');
232
 
243
 
244
  if (current_user_can('edit_users')) {
245
  $actions[] = 'edit';
 
246
  } else {
247
  $actions[] = 'no-edit';
 
248
  }
249
 
250
  if (current_user_can('aam_switch_users')) {
307
  * @access protected
308
  */
309
  protected function isAllowed(AAM_Core_Subject_User $user) {
310
+ $max = AAM::getUser()->getMaxLevel();
311
 
312
  return $max >= AAM_Core_API::maxLevel($user->allcaps);
313
  }
Application/Backend/Filter.php CHANGED
@@ -218,7 +218,7 @@ class AAM_Backend_Filter {
218
  * @return array
219
  */
220
  public function filterRoles($roles) {
221
- $userLevel = AAM_Core_API::maxLevel(AAM::getUser()->allcaps);
222
 
223
  //filter roles
224
  foreach($roles as $id => $role) {
@@ -262,7 +262,7 @@ class AAM_Backend_Filter {
262
  */
263
  public function filterUserQuery($query) {
264
  //current user max level
265
- $max = AAM_Core_API::maxLevel(AAM::getUser()->allcaps);
266
  $exclude = array();
267
  $roles = AAM_Core_API::getRoles();
268
 
@@ -288,7 +288,7 @@ class AAM_Backend_Filter {
288
  * @access public
289
  */
290
  public function filterViews($views) {
291
- $max = AAM_Core_API::maxLevel(AAM::getUser()->allcaps);
292
  $roles = AAM_Core_API::getRoles();
293
 
294
  foreach($roles->role_objects as $id => $role) {
218
  * @return array
219
  */
220
  public function filterRoles($roles) {
221
+ $userLevel = AAM::getUser()->getMaxLevel();
222
 
223
  //filter roles
224
  foreach($roles as $id => $role) {
262
  */
263
  public function filterUserQuery($query) {
264
  //current user max level
265
+ $max = AAM::getUser()->getMaxLevel();
266
  $exclude = array();
267
  $roles = AAM_Core_API::getRoles();
268
 
288
  * @access public
289
  */
290
  public function filterViews($views) {
291
+ $max = AAM::getUser()->getMaxLevel();
292
  $roles = AAM_Core_API::getRoles();
293
 
294
  foreach($roles->role_objects as $id => $role) {
Application/Backend/Manager.php CHANGED
@@ -737,7 +737,7 @@ class AAM_Backend_Manager {
737
  public function printJavascript() {
738
  if (AAM::isAAM()) {
739
  wp_enqueue_script('aam-vendor', AAM_MEDIA . '/js/vendor.js');
740
- wp_enqueue_script('aam-main', AAM_MEDIA . '/js/aam-5.7.3.js');
741
 
742
  //add plugin localization
743
  $this->printLocalization('aam-main');
@@ -788,7 +788,7 @@ class AAM_Backend_Manager {
788
  'addUser' => esc_url(admin_url('user-new.php')),
789
  'addPolicy' => esc_url(admin_url('post-new.php?post_type=aam_policy'))
790
  ),
791
- 'level' => AAM_Core_API::maxLevel(wp_get_current_user()->allcaps),
792
  'subject' => array(
793
  'type' => $subject->getUID(),
794
  'id' => $subject->getId(),
737
  public function printJavascript() {
738
  if (AAM::isAAM()) {
739
  wp_enqueue_script('aam-vendor', AAM_MEDIA . '/js/vendor.js');
740
+ wp_enqueue_script('aam-main', AAM_MEDIA . '/js/aam-5.8.js');
741
 
742
  //add plugin localization
743
  $this->printLocalization('aam-main');
788
  'addUser' => esc_url(admin_url('user-new.php')),
789
  'addPolicy' => esc_url(admin_url('post-new.php?post_type=aam_policy'))
790
  ),
791
+ 'level' => AAM::getUser()->getMaxLevel(),
792
  'subject' => array(
793
  'type' => $subject->getUID(),
794
  'id' => $subject->getId(),
Application/Backend/View.php CHANGED
@@ -290,7 +290,7 @@ class AAM_Backend_View {
290
 
291
  if (current_user_can('aam_switch_users')) {
292
  $user = new WP_User(AAM_Core_Request::post('user'));
293
- $max = AAM_Core_API::maxLevel(wp_get_current_user()->allcaps);
294
 
295
  if ($max >= AAM_Core_API::maxLevel($user->allcaps)) {
296
  AAM_Core_API::updateOption(
290
 
291
  if (current_user_can('aam_switch_users')) {
292
  $user = new WP_User(AAM_Core_Request::post('user'));
293
+ $max = AAM::getUser()->getMaxLevel();
294
 
295
  if ($max >= AAM_Core_API::maxLevel($user->allcaps)) {
296
  AAM_Core_API::updateOption(
Application/Backend/phtml/index.phtml CHANGED
@@ -335,33 +335,67 @@
335
  <tbody></tbody>
336
  </table>
337
 
338
- <div class="modal fade" id="edit-user-expiration-modal" tabindex="-1" role="dialog">
339
  <div class="modal-dialog" role="document">
340
  <div class="modal-content">
341
  <div class="modal-header">
342
  <button type="button" class="close" data-dismiss="modal" aria-label="<?php echo __('Close', AAM_KEY); ?>"><span aria-hidden="true">&times;</span></button>
343
- <h4 class="modal-title"><?php echo __('Manage User Expiration', AAM_KEY); ?></h4>
344
  </div>
345
  <div class="modal-body">
346
- <p class="aam-info">To learn more about setting up temporary user accounts, please refer to <a href="https://aamplugin.com/help/how-to-create-temporary-wordpress-user-account" target="_blank">How to create temporary WordPress user account</a> article.</p>
347
- <div class="form-group">
348
- <div id="user-expiration-datapicker"></div>
349
- <input type="hidden" id="user-expires" />
350
- </div>
351
- <div class="form-group">
352
- <label><?php echo __('Action After Expiration', AAM_KEY); ?> </label>
353
- <select class="form-control" id="action-after-expiration">
354
- <option value=""><?php echo __('Select Action', AAM_KEY); ?></option>
355
- <option value="delete"><?php echo __('Delete Account', AAM_KEY); ?></option>
356
- <option value="lock"><?php echo __('Lock Account', AAM_KEY); ?></option>
357
- <option value="change-role"><?php echo __('Change User Role', AAM_KEY); ?></option>
358
- </select>
359
- </div>
360
- <div class="form-group hidden" id="expiration-change-role-holder">
361
- <label><?php echo __('Change To Role', AAM_KEY); ?></label>
362
- <select class="form-control" id="expiration-change-role">
363
- <option value=""><?php echo __('Select Role', AAM_KEY); ?></option>
364
- </select>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365
  </div>
366
  </div>
367
  <div class="modal-footer">
335
  <tbody></tbody>
336
  </table>
337
 
338
+ <div class="modal fade" id="edit-user-modal" tabindex="-1" role="dialog">
339
  <div class="modal-dialog" role="document">
340
  <div class="modal-content">
341
  <div class="modal-header">
342
  <button type="button" class="close" data-dismiss="modal" aria-label="<?php echo __('Close', AAM_KEY); ?>"><span aria-hidden="true">&times;</span></button>
343
+ <h4 class="modal-title"><?php echo __('Manage User', AAM_KEY); ?></h4>
344
  </div>
345
  <div class="modal-body">
346
+ <ul class="nav nav-tabs" role="tablist">
347
+ <li role="presentation" class="active"><a href="#edit-user-expiration" aria-controls="edit-user-expiration" role="tab" data-toggle="tab">Temporary Access</a></li>
348
+ <li role="presentation"><a href="#edit-user-jwt" aria-controls="edit-user-jwt" role="tab" data-toggle="tab">JWT Auth Token</a></li>
349
+ <li role="presentation"><a href="#edit-user-profile" aria-controls="edit-user-profile" role="tab" data-toggle="tab">Edit User</a></li>
350
+ </ul>
351
+
352
+ <div class="tab-content">
353
+ <div role="tabpanel" class="tab-pane active" id="edit-user-expiration">
354
+ <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); ?>
355
+ <div class="form-group">
356
+ <div id="user-expiration-datapicker"></div>
357
+ <input type="hidden" id="user-expires" />
358
+ </div>
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
+ <div class="form-group hidden" id="expiration-change-role-holder">
370
+ <label><?php echo __('Change To Role', AAM_KEY); ?></label>
371
+ <select class="form-control" id="expiration-change-role">
372
+ <option value=""><?php echo __('Select Role', AAM_KEY); ?></option>
373
+ </select>
374
+ </div>
375
+ </div>
376
+ <div role="tabpanel" class="tab-pane" id="edit-user-jwt">
377
+ <div class="form-group">
378
+ <p class="aam-info"><?php echo sprintf(__('User JWT token to authentication user without a need for entering username/password. To learn more about JWT authentication, please refer to %sHow to authenticate WordPress user with JWT token%s article.', AAM_KEY), '<a href="https://aamplugin.com/article/how-to-authenticate-wordpress-user-with-jwt-token" target="_blank">', '</a>'); ?></p>
379
+ <div class="form-group">
380
+ <label for="user-auth-url"><?php echo __('JWT Token (for any API calls)', AAM_KEY); ?></label>
381
+ <textarea class="form-control" id="user-auth-jwt" readonly rows="5"></textarea>
382
+ </div>
383
+
384
+ <hr/>
385
+
386
+ <div class="form-group">
387
+ <label for="user-auth-url"><?php echo __('User Login URL (with JWT token)', AAM_KEY); ?></label>
388
+ <textarea class="form-control" id="user-auth-url" data-url="<?php echo add_query_arg('aam-jwt', '%s', site_url()); ?>" readonly rows="5"></textarea>
389
+ <small><?php echo __('With this URL user will be automatically logged in until the time defined on the "Temporary Access" tab.', AAM_KEY); ?></small>
390
+ </div>
391
+ </div>
392
+ </div>
393
+ <div role="tabpanel" class="tab-pane" id="edit-user-profile">
394
+ <p class="aam-info"><?php echo __("To manage user profile, click on the button below.", AAM_KEY); ?></p>
395
+ <p class="text-center">
396
+ <a href="#" id="edit-user-link" class="btn btn-primary" target="_blank"><?php echo __('Edit User Profile', AAM_KEY); ?></a>
397
+ </p>
398
+ </div>
399
  </div>
400
  </div>
401
  <div class="modal-footer">
Application/Core/API.php CHANGED
@@ -193,17 +193,17 @@ final class AAM_Core_API {
193
  * @access public
194
  */
195
  public static function maxLevel($caps, $default = 0) {
196
- $levels = array($default);
197
 
198
  if (is_array($caps)) { //WP Error Fix bug report
199
  foreach($caps as $cap => $granted) {
200
- if ($granted && preg_match('/^level_([0-9]+)$/i', $cap, $match)) {
201
- $levels[] = intval($match[1]);
202
  }
203
  }
204
  }
205
 
206
- return max($levels);
207
  }
208
 
209
  /**
193
  * @access public
194
  */
195
  public static function maxLevel($caps, $default = 0) {
196
+ $max = $default;
197
 
198
  if (is_array($caps)) { //WP Error Fix bug report
199
  foreach($caps as $cap => $granted) {
200
+ if ($granted && preg_match('/^level_([0-9]+)$/', $cap, $match)) {
201
+ $max = ($max < $match[1] ? $match[1] : $max);
202
  }
203
  }
204
  }
205
 
206
+ return intval($max);
207
  }
208
 
209
  /**
Application/Core/JwtAuth.php CHANGED
@@ -100,7 +100,7 @@ class AAM_Core_JwtAuth {
100
 
101
  if ($result['status'] === 'success') { // generate token
102
  try {
103
- $token = $this->generateJWT($result['user']->ID);
104
 
105
  $response->status = 200;
106
  $response->data = array(
@@ -141,14 +141,13 @@ class AAM_Core_JwtAuth {
141
  $jwt, $key, array_keys(Firebase\JWT\JWT::$supported_algs)
142
  );
143
 
144
- if (isset($claims->userId)) {
145
- $response->status = 200;
146
- $response->data = array (
147
- 'status' => 'valid'
148
- );
149
- }
150
  } catch (Exception $ex) {
151
- // Do nothing
152
  }
153
  }
154
 
@@ -165,34 +164,58 @@ class AAM_Core_JwtAuth {
165
  * @access public
166
  * @throws Exception
167
  */
168
- public function generateJWT($userId, $container = 'header') {
169
- $key = AAM_Core_Config::get('authentication.jwt.secret', SECURE_AUTH_KEY);
170
- $expire = AAM_Core_Config::get('authentication.jwt.expires', 86400);
171
  $container = explode(
172
- ',', AAM_Core_Config::get('authentication.jwt.container', $container)
173
  );
174
- $alg = AAM_Core_Config::get('authentication.jwt.algorithm', 'HS256');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
  if ($key) {
177
  $claims = apply_filters('aam-jwt-claims-filter', array(
178
- "iat" => time(),
179
- 'exp' => time() + $expire, // by default expires in 1 day
180
- 'userId' => $userId,
181
  ));
182
 
183
  $token = Firebase\JWT\JWT::encode($claims, $key, $alg);
184
-
185
- if (in_array('cookie', $container, true)) {
186
- setcookie(
187
- 'aam-jwt',
188
- $token,
189
- time() + $expire,
190
- '/',
191
- parse_url(get_bloginfo('url'), PHP_URL_HOST),
192
- is_ssl(),
193
- AAM_Core_Config::get('authentication.jwt.cookie.httpOnly', false)
194
- );
195
- }
196
  } else {
197
  Throw new Exception(
198
  __('JWT Authentication is enabled but secret key is not defined', AAM_KEY)
@@ -213,14 +236,32 @@ class AAM_Core_JwtAuth {
213
  $token = $this->extractJwt();
214
  $key = AAM_Core_Config::get('authentication.jwt.secret', SECURE_AUTH_KEY);
215
 
216
- if ($token) {
217
  try {
218
  $claims = Firebase\JWT\JWT::decode(
219
- $token, $key, array_keys(Firebase\JWT\JWT::$supported_algs)
220
  );
221
 
222
  if (isset($claims->userId)) {
223
  $result = $claims->userId;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  }
225
  } catch (Exception $ex) {
226
  // Do nothing
@@ -236,7 +277,7 @@ class AAM_Core_JwtAuth {
236
  */
237
  protected function extractJwt() {
238
  $container = explode(',', AAM_Core_Config::get(
239
- 'authentication.jwt.container', 'header'
240
  ));
241
 
242
  $jwt = null;
@@ -269,7 +310,10 @@ class AAM_Core_JwtAuth {
269
  }
270
  }
271
 
272
- return (!empty($jwt) ? preg_replace('/^Bearer /', '', $jwt) : null);
 
 
 
273
  }
274
 
275
  /**
100
 
101
  if ($result['status'] === 'success') { // generate token
102
  try {
103
+ $token = $this->issueJWT($result['user']->ID);
104
 
105
  $response->status = 200;
106
  $response->data = array(
141
  $jwt, $key, array_keys(Firebase\JWT\JWT::$supported_algs)
142
  );
143
 
144
+ $response->status = 200;
145
+ $response->data = array(
146
+ 'status' => 'valid',
147
+ 'token_expires' => date('m/d/Y H:i:s O', $claims->exp)
148
+ );
 
149
  } catch (Exception $ex) {
150
+ $response->data['reason'] = $ex->getMessage();
151
  }
152
  }
153
 
164
  * @access public
165
  * @throws Exception
166
  */
167
+ public function issueJWT($userId, $container = 'header') {
 
 
168
  $container = explode(
169
+ ',', AAM_Core_Config::get('authentication.jwt.container', $container)
170
  );
171
+
172
+ $token = $this->generateJWT($userId);
173
+
174
+ if (in_array('cookie', $container, true)) {
175
+ setcookie(
176
+ 'aam-jwt',
177
+ $token->token,
178
+ $token->claims['exp'],
179
+ '/',
180
+ parse_url(get_bloginfo('url'), PHP_URL_HOST),
181
+ is_ssl(),
182
+ AAM_Core_Config::get('authentication.jwt.cookie.httpOnly', false)
183
+ );
184
+ }
185
+
186
+ return $token;
187
+ }
188
+
189
+ /**
190
+ * Generate the token
191
+ *
192
+ * @param int $userId
193
+ * @param int $expires
194
+ *
195
+ * @return stdObject
196
+ *
197
+ * @access public
198
+ * @throws Exception
199
+ */
200
+ public static function generateJWT($userId, $expires = null) {
201
+ $key = AAM_Core_Config::get('authentication.jwt.secret', SECURE_AUTH_KEY);
202
+ $expire = AAM_Core_Config::get('authentication.jwt.expires', $expires);
203
+ $alg = AAM_Core_Config::get('authentication.jwt.algorithm', 'HS256');
204
+
205
+ if (!empty($expire)) {
206
+ $time = DateTime::createFromFormat('m/d/Y, H:i O', $expires);
207
+ } else {
208
+ $time = new DateTime('+24 hours');
209
+ }
210
 
211
  if ($key) {
212
  $claims = apply_filters('aam-jwt-claims-filter', array(
213
+ "iat" => time(),
214
+ 'exp' => $time->format('U'),
215
+ 'userId' => $userId
216
  ));
217
 
218
  $token = Firebase\JWT\JWT::encode($claims, $key, $alg);
 
 
 
 
 
 
 
 
 
 
 
 
219
  } else {
220
  Throw new Exception(
221
  __('JWT Authentication is enabled but secret key is not defined', AAM_KEY)
236
  $token = $this->extractJwt();
237
  $key = AAM_Core_Config::get('authentication.jwt.secret', SECURE_AUTH_KEY);
238
 
239
+ if (!empty($token['jwt'])) {
240
  try {
241
  $claims = Firebase\JWT\JWT::decode(
242
+ $token['jwt'], $key, array_keys(Firebase\JWT\JWT::$supported_algs)
243
  );
244
 
245
  if (isset($claims->userId)) {
246
  $result = $claims->userId;
247
+
248
+ // Also login user if REQUEST_METHOD is GET
249
+ if ($token['method'] === 'query'
250
+ && AAM_Core_Request::server('REQUEST_METHOD') === 'GET') {
251
+ wp_set_current_user($claims->userId);
252
+ wp_set_auth_cookie($claims->userId);
253
+
254
+ $exp = get_user_meta($claims->userId, 'aam_user_expiration', true);
255
+ if (empty($exp)) {
256
+ update_user_meta(
257
+ $claims->userId,
258
+ 'aam_user_expiration',
259
+ date('m/d/Y, H:i O', $claims->exp) . '|logout|'
260
+ );
261
+ }
262
+
263
+ do_action('wp_login', '', wp_get_current_user());
264
+ }
265
  }
266
  } catch (Exception $ex) {
267
  // Do nothing
277
  */
278
  protected function extractJwt() {
279
  $container = explode(',', AAM_Core_Config::get(
280
+ 'authentication.jwt.container', 'header,post,query,cookie'
281
  ));
282
 
283
  $jwt = null;
310
  }
311
  }
312
 
313
+ return array(
314
+ 'jwt' => preg_replace('/^Bearer /', '', $jwt),
315
+ 'method' => $method
316
+ );
317
  }
318
 
319
  /**
Application/Core/Login.php CHANGED
@@ -92,7 +92,7 @@ class AAM_Core_Login {
92
  }
93
 
94
  if (AAM::api()->getConfig('core.settings.setJwtCookieAfterLogin', false)) {
95
- AAM_Core_JwtAuth::getInstance()->generateJWT($user->ID, 'cookie');
96
  }
97
 
98
  if ($this->aamLogin === false) {
92
  }
93
 
94
  if (AAM::api()->getConfig('core.settings.setJwtCookieAfterLogin', false)) {
95
+ AAM_Core_JwtAuth::getInstance()->issueJWT($user->ID, 'cookie');
96
  }
97
 
98
  if ($this->aamLogin === false) {
Application/Core/Object/Policy.php CHANGED
@@ -128,19 +128,17 @@ class AAM_Core_Object_Policy extends AAM_Core_Object {
128
  );
129
 
130
  foreach($policies as $id => $effect) {
131
- if ($effect) {
132
- $policy = get_post($id);
133
-
134
- if (is_a($policy, 'WP_Post')) {
135
- $obj = json_decode($policy->post_content, true);
136
- if (json_last_error() === JSON_ERROR_NONE) {
137
- $list['Statements'] = array_merge(
138
- $list['Statements'], $this->extractStatements($obj)
139
- );
140
- $list['Features'] = array_merge(
141
- $list['Features'], $this->extractFeatures($obj)
142
- );
143
- }
144
  }
145
  }
146
  }
@@ -155,7 +153,7 @@ class AAM_Core_Object_Policy extends AAM_Core_Object {
155
  * @param type $policy
156
  * @return type
157
  */
158
- protected function extractStatements($policy) {
159
  $statements = array();
160
 
161
  if (isset($policy['Statement'])) {
@@ -175,6 +173,12 @@ class AAM_Core_Object_Policy extends AAM_Core_Object {
175
  }
176
  }
177
 
 
 
 
 
 
 
178
  return $statements;
179
  }
180
 
@@ -188,7 +192,7 @@ class AAM_Core_Object_Policy extends AAM_Core_Object {
188
  * @access protected
189
  * @since v5.7.3
190
  */
191
- protected function extractFeatures($policy) {
192
  $features = array();
193
 
194
  if (isset($policy['Feature'])) {
@@ -199,6 +203,12 @@ class AAM_Core_Object_Policy extends AAM_Core_Object {
199
  }
200
  }
201
 
 
 
 
 
 
 
202
  return $features;
203
  }
204
 
@@ -753,7 +763,15 @@ class AAM_Core_Object_Policy extends AAM_Core_Object {
753
  if (is_null($subject)) {
754
  if (!isset(self::$resources['__combined'])) {
755
  foreach(self::$resources as $resources) {
756
- $response = array_merge($resources, $response);
 
 
 
 
 
 
 
 
757
  }
758
  self::$resources['__combined'] = $response;
759
  } else {
128
  );
129
 
130
  foreach($policies as $id => $effect) {
131
+ $policy = get_post($id);
132
+
133
+ if (is_a($policy, 'WP_Post')) {
134
+ $obj = json_decode($policy->post_content, true);
135
+ if (json_last_error() === JSON_ERROR_NONE) {
136
+ $list['Statements'] = array_merge(
137
+ $list['Statements'], $this->extractStatements($obj, empty($effect))
138
+ );
139
+ $list['Features'] = array_merge(
140
+ $list['Features'], $this->extractFeatures($obj, empty($effect))
141
+ );
 
 
142
  }
143
  }
144
  }
153
  * @param type $policy
154
  * @return type
155
  */
156
+ protected function extractStatements($policy, $unset = false) {
157
  $statements = array();
158
 
159
  if (isset($policy['Statement'])) {
173
  }
174
  }
175
 
176
+ if ($unset === true) {
177
+ foreach($statements as &$statement) {
178
+ $statement['Unset'] = true;
179
+ }
180
+ }
181
+
182
  return $statements;
183
  }
184
 
192
  * @access protected
193
  * @since v5.7.3
194
  */
195
+ protected function extractFeatures($policy, $unset = false) {
196
  $features = array();
197
 
198
  if (isset($policy['Feature'])) {
203
  }
204
  }
205
 
206
+ if ($unset === true) {
207
+ foreach($features as &$feature) {
208
+ $feature['Unset'] = true;
209
+ }
210
+ }
211
+
212
  return $features;
213
  }
214
 
763
  if (is_null($subject)) {
764
  if (!isset(self::$resources['__combined'])) {
765
  foreach(self::$resources as $resources) {
766
+ foreach ($resources as $id => $props) {
767
+ if (!empty($props['Unset'])) {
768
+ if (isset($response[$id])) { // Clear the entire chain
769
+ unset($response[$id]);
770
+ }
771
+ } else {
772
+ $response[$id] = $props;
773
+ }
774
+ }
775
  }
776
  self::$resources['__combined'] = $response;
777
  } else {
Application/Core/Subject/User.php CHANGED
@@ -41,6 +41,12 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
41
  */
42
  protected $parent = null;
43
 
 
 
 
 
 
 
44
  /**
45
  *
46
  * @param type $id
@@ -66,10 +72,23 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
66
  }
67
 
68
  //check if user is expired
69
- $expired = get_user_option('aam_user_expiration', $this->ID);
70
  if (!empty($expired)) {
71
- $parts = explode('|', $expired);
72
- if ($parts[0] <= date('Y-m-d H:i:s')) {
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  $this->triggerExpiredUserAction($parts);
74
  }
75
  }
@@ -116,6 +135,10 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
116
  $this->block();
117
  break;
118
 
 
 
 
 
119
  case 'change-role':
120
  if (AAM_Core_API::getRoles()->is_role($config[2])) {
121
  $this->getSubject()->set_role($config[2]);
@@ -209,7 +232,7 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
209
  // Retrieve all capabilities set in Access Policy
210
  // Load Capabilities from the policy
211
  $stms = AAM_Core_Policy_Manager::getInstance()->find("/^Capability:/i");
212
-
213
  $policyCaps = array();
214
 
215
  foreach($stms as $key => $stm) {
@@ -444,7 +467,11 @@ class AAM_Core_Subject_User extends AAM_Core_Subject {
444
  * @return type
445
  */
446
  public function getMaxLevel() {
447
- return AAM_Core_API::maxLevel($this->allcaps);
 
 
 
 
448
  }
449
 
450
  }
41
  */
42
  protected $parent = null;
43
 
44
+ /**
45
+ *
46
+ * @var type
47
+ */
48
+ protected $maxLevel = null;
49
+
50
  /**
51
  *
52
  * @param type $id
72
  }
73
 
74
  //check if user is expired
75
+ $expired = get_user_meta($this->ID, 'aam_user_expiration', true);
76
  if (!empty($expired)) {
77
+ $parts = explode('|', $expired);
78
+
79
+ // Set time
80
+ // TODO: Remove in Jan 2020
81
+ if (preg_match('/^[\d]{4}-/', $parts[0])) {
82
+ $expires = DateTime::createFromFormat('Y-m-d H:i:s', $parts[0]);
83
+ } else {
84
+ $expires = DateTime::createFromFormat('m/d/Y, H:i O', $parts[0]);
85
+ }
86
+
87
+ $compare = new DateTime();
88
+ //TODO - PHP Warning: DateTime::setTimezone(): Can only do this for zones with ID for now in
89
+ @$compare->setTimezone($expires->getTimezone());
90
+
91
+ if ($expires <= $compare) {
92
  $this->triggerExpiredUserAction($parts);
93
  }
94
  }
135
  $this->block();
136
  break;
137
 
138
+ case 'logout':
139
+ wp_logout();
140
+ break;
141
+
142
  case 'change-role':
143
  if (AAM_Core_API::getRoles()->is_role($config[2])) {
144
  $this->getSubject()->set_role($config[2]);
232
  // Retrieve all capabilities set in Access Policy
233
  // Load Capabilities from the policy
234
  $stms = AAM_Core_Policy_Manager::getInstance()->find("/^Capability:/i");
235
+
236
  $policyCaps = array();
237
 
238
  foreach($stms as $key => $stm) {
467
  * @return type
468
  */
469
  public function getMaxLevel() {
470
+ if (is_null($this->maxLevel)) {
471
+ $this->maxLevel = AAM_Core_API::maxLevel($this->allcaps);
472
+ }
473
+
474
+ return $this->maxLevel;
475
  }
476
 
477
  }
Application/Shared/Manager.php CHANGED
@@ -513,7 +513,7 @@ class AAM_Shared_Manager {
513
  * @return type
514
  */
515
  protected function checkPluginsAction($action, $caps, $cap) {
516
- $allow = AAM::api()->isAllowed("Plugin", "WP:{$action}");
517
 
518
  if ($allow !== null) {
519
  $caps[] = $allow ? $cap : 'do_not_allow';
@@ -534,7 +534,7 @@ class AAM_Shared_Manager {
534
  $parts = explode('/', $plugin);
535
  $slug = (!empty($parts[0]) ? $parts[0] : null);
536
 
537
- $allow = AAM::api()->isAllowed("Plugin:{$slug}", "WP:{$action}");
538
  if ($allow !== null) {
539
  $caps[] = $allow ? $cap : 'do_not_allow';
540
  }
@@ -620,7 +620,7 @@ class AAM_Shared_Manager {
620
  $user = new WP_User($userId);
621
 
622
  //current user max level
623
- $maxLevel = AAM_Core_API::maxLevel(AAM::getUser()->allcaps);
624
  //userLevel
625
  $userLevel = AAM_Core_API::maxLevel($user->allcaps);
626
 
513
  * @return type
514
  */
515
  protected function checkPluginsAction($action, $caps, $cap) {
516
+ $allow = AAM::api()->isAllowed("Plugin:WP:{$action}");
517
 
518
  if ($allow !== null) {
519
  $caps[] = $allow ? $cap : 'do_not_allow';
534
  $parts = explode('/', $plugin);
535
  $slug = (!empty($parts[0]) ? $parts[0] : null);
536
 
537
+ $allow = AAM::api()->isAllowed("Plugin:{$slug}:WP:{$action}");
538
  if ($allow !== null) {
539
  $caps[] = $allow ? $cap : 'do_not_allow';
540
  }
620
  $user = new WP_User($userId);
621
 
622
  //current user max level
623
+ $maxLevel = AAM::getUser()->getMaxLevel();
624
  //userLevel
625
  $userLevel = AAM_Core_API::maxLevel($user->allcaps);
626
 
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.7.3
7
  Author: Vasyl Martyniuk <vasyl@vasyltech.com>
8
  Author URI: https://vasyltech.com
9
 
3
  /**
4
  Plugin Name: Advanced Access Manager
5
  Description: All you need to manage access to your WordPress website
6
+ Version: 5.8
7
  Author: Vasyl Martyniuk <vasyl@vasyltech.com>
8
  Author URI: https://vasyltech.com
9
 
media/js/{aam-5.7.3.js → aam-5.8.js} RENAMED
@@ -742,6 +742,44 @@
742
  }
743
  });
744
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
745
 
746
  //initialize the user list table
747
  $('#user-list').DataTable({
@@ -836,9 +874,10 @@
836
  }
837
 
838
  //add subtitle
 
839
  $('td:eq(0)', row).append(
840
  $('<i/>', {'class': 'aam-row-subtitle'}).html(
841
- getAAM().__('Role') + ': ' + data[1] + '; ID: <b>' + data[0] + '</b>'
842
  )
843
  );
844
 
@@ -881,20 +920,26 @@
881
  })).prop('disabled', (isCurrent(data[0]) ? true: false));
882
  break;
883
 
884
- case 'ttl':
885
  if (getAAM().isUI('main')) {
886
  $(container).append($('<i/>', {
887
- 'class': 'aam-row-action icon-clock text-' + (data[5] ? 'danger' : 'warning')
888
  }).bind('click', function () {
 
 
 
 
 
 
889
  $('#edit-user-expiration-btn').attr('data-user-id', data[0]);
890
  $('#reset-user-expiration-btn').attr('data-user-id', data[0]);
891
-
892
  if (data[5]) {
893
  $('#reset-user-expiration-btn').removeClass('hidden');
894
  var settings = data[5].split('|');
895
  $('#user-expires').val(settings[0]);
896
  $('#action-after-expiration').val(settings[1]);
897
-
898
  if (settings[1] === 'change-role') {
899
  $('#expiration-change-role-holder').removeClass('hidden');
900
  loadRoleList(settings[2]);
@@ -907,31 +952,9 @@
907
  $('#user-expires, #action-after-expiration').val('');
908
  loadRoleList();
909
  }
 
 
910
 
911
- $('#edit-user-expiration-modal').modal('show');
912
- }).attr({
913
- 'data-toggle': "tooltip",
914
- 'title': getAAM().__('User Expiration')
915
- }));
916
- }
917
- break;
918
-
919
- case 'no-ttl':
920
- if (getAAM().isUI('main')) {
921
- $(container).append($('<i/>', {
922
- 'class': 'aam-row-action icon-clock text-muted'
923
- }));
924
- }
925
- break;
926
-
927
- case 'edit':
928
- if (getAAM().isUI('main')) {
929
- $(container).append($('<i/>', {
930
- 'class': 'aam-row-action icon-pencil text-info'
931
- }).bind('click', function () {
932
- window.open(
933
- getLocal().url.editUser + '?user_id=' + data[0], '_blank'
934
- );
935
  }).attr({
936
  'data-toggle': "tooltip",
937
  'title': getAAM().__('Edit User')
@@ -1064,15 +1087,17 @@
1064
  sideBySide: true
1065
  });
1066
 
1067
- $('#edit-user-expiration-modal').on('show.bs.modal', function() {
1068
  try{
1069
  if ($.trim($('#user-expires').val())) {
1070
  $('#user-expiration-datapicker').data('DateTimePicker').defaultDate(
1071
  $('#user-expires').val()
1072
  );
1073
  } else {
 
 
1074
  $('#user-expiration-datapicker').data('DateTimePicker').defaultDate(
1075
- new Date()
1076
  );
1077
  }
1078
  } catch(e) {
@@ -1082,7 +1107,11 @@
1082
 
1083
  $('#user-expiration-datapicker').on('dp.change', function(res) {
1084
  $('#user-expires').val(
1085
- res.date.format('MM/DD/YYYY, h:mm a')
 
 
 
 
1086
  );
1087
  });
1088
 
@@ -1116,7 +1145,7 @@
1116
  getAAM().notification('danger', getAAM().__('Application error'));
1117
  },
1118
  complete: function () {
1119
- $('#edit-user-expiration-modal').modal('hide');
1120
  $(_this).text(getAAM().__('Save')).attr('disabled', false);
1121
  }
1122
  });
@@ -1149,7 +1178,7 @@
1149
  getAAM().notification('danger', getAAM().__('Application error'));
1150
  },
1151
  complete: function () {
1152
- $('#edit-user-expiration-modal').modal('hide');
1153
  $(_this).text(getAAM().__('Reset')).attr('disabled', false);
1154
  }
1155
  });
@@ -1486,7 +1515,7 @@
1486
  save({
1487
  type: getAAM().getSubject().type,
1488
  id: getAAM().getSubject().id
1489
- }, data[0], 1, this);
1490
  }).attr({
1491
  'data-toggle': "tooltip",
1492
  'title': getAAM().__('Apply Policy')
@@ -1500,7 +1529,7 @@
1500
  save({
1501
  type: getAAM().getSubject().type,
1502
  id: getAAM().getSubject().id
1503
- }, data[0], 0, this);
1504
  }).attr({
1505
  'data-toggle': "tooltip",
1506
  'title': getAAM().__('Revoke Policy')
742
  }
743
  });
744
  }
745
+
746
+ /**
747
+ *
748
+ * @param {type} id
749
+ * @param {type} expires
750
+ * @returns {undefined}
751
+ */
752
+ function generateJWT(id, expires) {
753
+ $.ajax(getLocal().ajaxurl, {
754
+ type: 'POST',
755
+ dataType: 'json',
756
+ data: {
757
+ action: 'aam',
758
+ sub_action: 'Subject_User.generateJWT',
759
+ _ajax_nonce: getLocal().nonce,
760
+ user: id,
761
+ expires: expires
762
+ },
763
+ beforeSend: function () {
764
+ $('#user-auth-jwt').val(getAAM().__('Generating token...'));
765
+ },
766
+ success: function (response) {
767
+ if (response.status === 'success') {
768
+ $('#user-auth-jwt').val(response.jwt);
769
+ $('#user-auth-url').val(
770
+ $('#user-auth-url').data('url').replace('%s', response.jwt)
771
+ );
772
+ } else {
773
+ getAAM().notification(
774
+ 'danger', getAAM().__('Failed to generate JWT token')
775
+ );
776
+ }
777
+ },
778
+ error: function () {
779
+ getAAM().notification('danger', getAAM().__('Application error'));
780
+ }
781
+ });
782
+ }
783
 
784
  //initialize the user list table
785
  $('#user-list').DataTable({
874
  }
875
 
876
  //add subtitle
877
+ var expire = (data[5] ? '; <i class="icon-clock"></i>' : '');
878
  $('td:eq(0)', row).append(
879
  $('<i/>', {'class': 'aam-row-subtitle'}).html(
880
+ getAAM().__('Role') + ': ' + data[1] + '; ID: <b>' + data[0] + '</b>' + expire
881
  )
882
  );
883
 
920
  })).prop('disabled', (isCurrent(data[0]) ? true: false));
921
  break;
922
 
923
+ case 'edit':
924
  if (getAAM().isUI('main')) {
925
  $(container).append($('<i/>', {
926
+ 'class': 'aam-row-action icon-pencil text-info'
927
  }).bind('click', function () {
928
+ // Update user's edit profile
929
+ $('#edit-user-link').attr(
930
+ 'href',
931
+ getLocal().url.editUser + '?user_id=' + data[0]
932
+ );
933
+
934
  $('#edit-user-expiration-btn').attr('data-user-id', data[0]);
935
  $('#reset-user-expiration-btn').attr('data-user-id', data[0]);
936
+
937
  if (data[5]) {
938
  $('#reset-user-expiration-btn').removeClass('hidden');
939
  var settings = data[5].split('|');
940
  $('#user-expires').val(settings[0]);
941
  $('#action-after-expiration').val(settings[1]);
942
+
943
  if (settings[1] === 'change-role') {
944
  $('#expiration-change-role-holder').removeClass('hidden');
945
  loadRoleList(settings[2]);
952
  $('#user-expires, #action-after-expiration').val('');
953
  loadRoleList();
954
  }
955
+
956
+ $('#edit-user-modal').modal('show');
957
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
958
  }).attr({
959
  'data-toggle': "tooltip",
960
  'title': getAAM().__('Edit User')
1087
  sideBySide: true
1088
  });
1089
 
1090
+ $('#edit-user-modal').on('show.bs.modal', function() {
1091
  try{
1092
  if ($.trim($('#user-expires').val())) {
1093
  $('#user-expiration-datapicker').data('DateTimePicker').defaultDate(
1094
  $('#user-expires').val()
1095
  );
1096
  } else {
1097
+ var tomorrow = new Date();
1098
+ tomorrow.setDate(tomorrow.getDate() + 1);
1099
  $('#user-expiration-datapicker').data('DateTimePicker').defaultDate(
1100
+ tomorrow
1101
  );
1102
  }
1103
  } catch(e) {
1107
 
1108
  $('#user-expiration-datapicker').on('dp.change', function(res) {
1109
  $('#user-expires').val(
1110
+ res.date.format('MM/DD/YYYY, H:mm Z')
1111
+ );
1112
+ generateJWT(
1113
+ $('#edit-user-expiration-btn').attr('data-user-id'),
1114
+ $('#user-expires').val()
1115
  );
1116
  });
1117
 
1145
  getAAM().notification('danger', getAAM().__('Application error'));
1146
  },
1147
  complete: function () {
1148
+ $('#edit-user-modal').modal('hide');
1149
  $(_this).text(getAAM().__('Save')).attr('disabled', false);
1150
  }
1151
  });
1178
  getAAM().notification('danger', getAAM().__('Application error'));
1179
  },
1180
  complete: function () {
1181
+ $('#edit-user-modal').modal('hide');
1182
  $(_this).text(getAAM().__('Reset')).attr('disabled', false);
1183
  }
1184
  });
1515
  save({
1516
  type: getAAM().getSubject().type,
1517
  id: getAAM().getSubject().id
1518
+ }, data[0], ($(this).hasClass('icon-check-empty') ? 1 : 0), this);
1519
  }).attr({
1520
  'data-toggle': "tooltip",
1521
  'title': getAAM().__('Apply Policy')
1529
  save({
1530
  type: getAAM().getSubject().type,
1531
  id: getAAM().getSubject().id
1532
+ }, data[0], ($(this).hasClass('icon-check') ? 0 : 1), this);
1533
  }).attr({
1534
  'data-toggle': "tooltip",
1535
  'title': getAAM().__('Revoke Policy')
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: vasyltech
3
  Tags: access control, membership, backend menu, user role, restricted content, security, jwt
4
  Requires at least: 4.0
5
- Tested up to: 5.0.2
6
- Stable tag: 5.7.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
 
@@ -78,6 +78,13 @@ https://www.youtube.com/watch?v=mj5Xa_Wc16Y
78
 
79
  == Changelog ==
80
 
 
 
 
 
 
 
 
81
  = 5.7.3 =
82
  * Fixed the bug with JWT authentication
83
  * Fixed the PHP bug in policy metabox when no errors with JSON is detected
2
  Contributors: vasyltech
3
  Tags: access control, membership, backend menu, user role, restricted content, security, jwt
4
  Requires at least: 4.0
5
+ Tested up to: 5.0.3
6
+ Stable tag: 5.8
7
 
8
  All you need to manage access to you WordPress websites on frontend, backend and API levels for any role, user or visitors.
9
 
78
 
79
  == Changelog ==
80
 
81
+ = 5.8 =
82
+ * Fixed the bug with Access Policy settings inheritance mechanism
83
+ * Fixed numerous of bugs with JWT authentication and improved time expiration handling
84
+ * Enhanced temporary user access management functionality
85
+ * Added Logout action when user access expired
86
+ * Added ability to login user with URL
87
+
88
  = 5.7.3 =
89
  * Fixed the bug with JWT authentication
90
  * Fixed the PHP bug in policy metabox when no errors with JSON is detected