Advanced Access Manager - Version 6.7.0

Version Description

  • Fixed Bug: Incorrectly merged settings with multi-role enabled https://github.com/aamplugin/advanced-access-manager/issues/152
  • Changed: Simplify the Route service https://github.com/aamplugin/advanced-access-manager/issues/153
  • Changed: Unexpected Application Error Message Misleads https://github.com/aamplugin/advanced-access-manager/issues/151
  • Added New: AAM CLI: Allow the ability import/export settings https://github.com/aamplugin/advanced-access-manager/issues/150
Download this release

Release Info

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

Code changes from version 6.6.4 to 6.7.0

aam.php CHANGED
@@ -3,7 +3,7 @@
3
  /**
4
  * Plugin Name: Advanced Access Manager
5
  * Description: Collection of features to manage your WordPress website authentication, authorization and monitoring
6
- * Version: 6.6.4
7
  * Author: Vasyl Martyniuk <vasyl@vasyltech.com>
8
  * Author URI: https://vasyltech.com
9
  * Text Domain: advanced-access-manager
@@ -264,7 +264,7 @@ if (defined('ABSPATH')) {
264
  //define few common constants
265
  define('AAM_MEDIA', plugins_url('/media', __FILE__));
266
  define('AAM_KEY', 'advanced-access-manager');
267
- define('AAM_VERSION', '6.6.4');
268
  define('AAM_BASEDIR', __DIR__);
269
 
270
  //load vendor
3
  /**
4
  * Plugin Name: Advanced Access Manager
5
  * Description: Collection of features to manage your WordPress website authentication, authorization and monitoring
6
+ * Version: 6.7.0
7
  * Author: Vasyl Martyniuk <vasyl@vasyltech.com>
8
  * Author URI: https://vasyltech.com
9
  * Text Domain: advanced-access-manager
264
  //define few common constants
265
  define('AAM_MEDIA', plugins_url('/media', __FILE__));
266
  define('AAM_KEY', 'advanced-access-manager');
267
+ define('AAM_VERSION', '6.7.0');
268
  define('AAM_BASEDIR', __DIR__);
269
 
270
  //load vendor
application/Backend/Feature/Settings/Manager.php CHANGED
@@ -10,6 +10,7 @@
10
  /**
11
  * Backend Settings area abstract manager
12
  *
 
13
  * @since 6.6.0 https://github.com/aamplugin/advanced-access-manager/issues/130
14
  * @since 6.5.0 https://github.com/aamplugin/advanced-access-manager/issues/109
15
  * https://github.com/aamplugin/advanced-access-manager/issues/106
@@ -17,7 +18,7 @@
17
  * @since 6.0.0 Initial implementation of the class
18
  *
19
  * @package AAM
20
- * @version 6.6.0
21
  */
22
  class AAM_Backend_Feature_Settings_Manager extends AAM_Backend_Feature_Abstract
23
  {
@@ -123,16 +124,19 @@ class AAM_Backend_Feature_Settings_Manager extends AAM_Backend_Feature_Abstract
123
  /**
124
  * Export AAM settings as JSON
125
  *
 
 
126
  * @return string
127
  *
 
128
  * @since 6.6.0 https://github.com/aamplugin/advanced-access-manager/issues/130
129
  * @since 6.3.0 Optimized AAM_Core_API::getOption call
130
  * @since 6.2.0 Initial implementation of the method
131
  *
132
  * @access public
133
- * @version 6.6.0
134
  */
135
- public function exportSettings()
136
  {
137
  $data = array(
138
  'version' => AAM_VERSION,
@@ -180,9 +184,9 @@ class AAM_Backend_Feature_Settings_Manager extends AAM_Backend_Feature_Abstract
180
  }
181
  }
182
 
183
- return wp_json_encode(array(
184
  'result' => base64_encode(wp_json_encode($data))
185
- ));
186
  }
187
 
188
  /**
@@ -287,20 +291,24 @@ class AAM_Backend_Feature_Settings_Manager extends AAM_Backend_Feature_Abstract
287
  *
288
  * @return string
289
  *
 
290
  * @since 6.6.0 https://github.com/aamplugin/advanced-access-manager/issues/130
291
  * @since 6.2.0 Initial implementation of the method
292
  *
293
  * @access public
294
- * @version 6.6.0
295
  */
296
- public function importSettings()
297
  {
298
  $error = __('Invalid data', AAM_KEY);
299
- $data = json_decode($this->getFromPost('payload'), true);
300
 
301
- if ($data) {
302
- if (isset($data['dataset']) && is_array($data['dataset'])) {
303
- foreach($data['dataset'] as $group => $settings) {
 
 
 
 
304
  switch($group) {
305
  case 'settings':
306
  AAM_Core_AccessSettings::getInstance()->replace($settings);
10
  /**
11
  * Backend Settings area abstract manager
12
  *
13
+ * @since 6.7.0 https://github.com/aamplugin/advanced-access-manager/issues/150
14
  * @since 6.6.0 https://github.com/aamplugin/advanced-access-manager/issues/130
15
  * @since 6.5.0 https://github.com/aamplugin/advanced-access-manager/issues/109
16
  * https://github.com/aamplugin/advanced-access-manager/issues/106
18
  * @since 6.0.0 Initial implementation of the class
19
  *
20
  * @package AAM
21
+ * @version 6.7.0
22
  */
23
  class AAM_Backend_Feature_Settings_Manager extends AAM_Backend_Feature_Abstract
24
  {
124
  /**
125
  * Export AAM settings as JSON
126
  *
127
+ * @param boolean $raw
128
+ *
129
  * @return string
130
  *
131
+ * @since 6.7.0 Added `$raw` argument
132
  * @since 6.6.0 https://github.com/aamplugin/advanced-access-manager/issues/130
133
  * @since 6.3.0 Optimized AAM_Core_API::getOption call
134
  * @since 6.2.0 Initial implementation of the method
135
  *
136
  * @access public
137
+ * @version 6.7.0
138
  */
139
+ public function exportSettings($raw = false)
140
  {
141
  $data = array(
142
  'version' => AAM_VERSION,
184
  }
185
  }
186
 
187
+ return ($raw ? $data : wp_json_encode(array(
188
  'result' => base64_encode(wp_json_encode($data))
189
+ )));
190
  }
191
 
192
  /**
291
  *
292
  * @return string
293
  *
294
+ * @since 6.7.0 Added `$payload` argument
295
  * @since 6.6.0 https://github.com/aamplugin/advanced-access-manager/issues/130
296
  * @since 6.2.0 Initial implementation of the method
297
  *
298
  * @access public
299
+ * @version 6.7.0
300
  */
301
+ public function importSettings($payload = null)
302
  {
303
  $error = __('Invalid data', AAM_KEY);
 
304
 
305
+ if (is_null($payload)) {
306
+ $payload = json_decode($this->getFromPost('payload'), true);
307
+ }
308
+
309
+ if ($payload) {
310
+ if (isset($payload['dataset']) && is_array($payload['dataset'])) {
311
+ foreach($payload['dataset'] as $group => $settings) {
312
  switch($group) {
313
  case 'settings':
314
  AAM_Core_AccessSettings::getInstance()->replace($settings);
application/Core/API.php CHANGED
@@ -10,6 +10,7 @@
10
  /**
11
  * AAM core API
12
  *
 
13
  * @since 6.6.4 https://github.com/aamplugin/advanced-access-manager/issues/142
14
  * @since 6.3.1 Fixed bug with setting clearing
15
  * @since 6.3.0 Optimized for Multisite setup
@@ -19,7 +20,7 @@
19
  * @since 6.0.0 Initial implementation of the class
20
  *
21
  * @package AAM
22
- * @version 6.6.4
23
  */
24
  final class AAM_Core_API
25
  {
@@ -62,20 +63,27 @@ final class AAM_Core_API
62
  *
63
  * @return bool
64
  *
 
65
  * @since 6.3.0 Optimized for Multisite setup
66
  * @since 6.0.0 Initial implementation of the method
67
  *
68
  * @access public
69
- * @version 6.3.0
70
  */
71
  public static function updateOption($option, $data, $blog_id = null)
72
  {
73
- if (is_multisite()) {
74
- $result = update_blog_option(
75
- ($blog_id ? $blog_id : get_current_blog_id()), $option, $data
76
- );
 
 
 
 
 
 
77
  } else {
78
- $result = update_option($option, $data);
79
  }
80
 
81
  return $result;
10
  /**
11
  * AAM core API
12
  *
13
+ * @since 6.7.0 https://github.com/aamplugin/advanced-access-manager/issues/151
14
  * @since 6.6.4 https://github.com/aamplugin/advanced-access-manager/issues/142
15
  * @since 6.3.1 Fixed bug with setting clearing
16
  * @since 6.3.0 Optimized for Multisite setup
20
  * @since 6.0.0 Initial implementation of the class
21
  *
22
  * @package AAM
23
+ * @version 6.7.0
24
  */
25
  final class AAM_Core_API
26
  {
63
  *
64
  * @return bool
65
  *
66
+ * @since 6.7.0 https://github.com/aamplugin/advanced-access-manager/issues/151
67
  * @since 6.3.0 Optimized for Multisite setup
68
  * @since 6.0.0 Initial implementation of the method
69
  *
70
  * @access public
71
+ * @version 6.7.0
72
  */
73
  public static function updateOption($option, $data, $blog_id = null)
74
  {
75
+ $old_value = self::getOption($option, null, $blog_id);
76
+
77
+ if (maybe_serialize($old_value) !== maybe_serialize($data)) {
78
+ if (is_multisite()) {
79
+ $result = update_blog_option(
80
+ ($blog_id ? $blog_id : get_current_blog_id()), $option, $data
81
+ );
82
+ } else {
83
+ $result = update_option($option, $data);
84
+ }
85
  } else {
86
+ $result = true;
87
  }
88
 
89
  return $result;
application/Core/Cli.php ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * ======================================================================
5
+ * LICENSE: This file is subject to the terms and conditions defined in *
6
+ * file 'license.txt', which is part of this source code package. *
7
+ * ======================================================================
8
+ */
9
+
10
+ /**
11
+ * AAM CLI commands
12
+ *
13
+ * @package AAM
14
+ * @version 6.7.0
15
+ */
16
+ class AAM_Core_Cli
17
+ {
18
+
19
+ /**
20
+ * Export AAM settings
21
+ *
22
+ * ## OPTIONS
23
+ *
24
+ * [--roles]
25
+ * : Export list of roles and capabilities
26
+ *
27
+ * [--settings]
28
+ * : Export AAM access controls
29
+ *
30
+ * [--policies]
31
+ * : Export defined access policies
32
+ *
33
+ * [--configpress]
34
+ * : Export ConfigPress
35
+ *
36
+ * ## EXAMPLES
37
+ *
38
+ * wp aam export --roles
39
+ * wp aam export --settings --policies
40
+ *
41
+ * @param array $args
42
+ * @param array $assoc_args
43
+ *
44
+ * @return void
45
+ *
46
+ * @access public
47
+ * @subcommand export
48
+ * @version 6.7.0
49
+ */
50
+ public function export($args, $assoc_args)
51
+ {
52
+ $manager = new AAM_Backend_Feature_Settings_Manager();
53
+ $settings = $manager->exportSettings(true);
54
+
55
+ if ($settings) {
56
+ if (is_iterable($assoc_args) && count($assoc_args)) {
57
+ $dataset = array();
58
+
59
+ foreach(array_keys($assoc_args) as $group) {
60
+ if (isset($settings['dataset'][$group])) {
61
+ $dataset[$group] = $settings['dataset'][$group];
62
+ }
63
+ }
64
+
65
+ $settings['dataset'] = $dataset;
66
+ }
67
+
68
+ echo json_encode($settings);
69
+ } else {
70
+ WP_CLI::error('Failed to export settings');
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Import AAM settings
76
+ *
77
+ * ## OPTIONS
78
+ *
79
+ * [<payload>]
80
+ * : JSON-formatted payload if omitted, the payload is taken from STDIN
81
+ *
82
+ * [--roles]
83
+ * : Import list of roles and capabilities
84
+ *
85
+ * [--settings]
86
+ * : Import AAM access controls
87
+ *
88
+ * [--policies]
89
+ * : Import defined access policies
90
+ *
91
+ * [--configpress]
92
+ * : Import ConfigPress
93
+ *
94
+ * ## EXAMPLES
95
+ *
96
+ * wp aam import < /tmp/settings.json
97
+ * wp aam import < ./settings.json --settings --policies
98
+ *
99
+ * @param array $args
100
+ * @param array $assoc_args
101
+ *
102
+ * @return void
103
+ *
104
+ * @access public
105
+ * @subcommand import
106
+ * @version 6.7.0
107
+ */
108
+ public function import($args, $assoc_args)
109
+ {
110
+ $manager = new AAM_Backend_Feature_Settings_Manager();
111
+
112
+ if (isset($args[0])) {
113
+ $payload = json_decode($args[0], true);
114
+ } else {
115
+ $payload = json_decode(
116
+ WP_CLI::get_value_from_arg_or_stdin($args, 1), true
117
+ );
118
+ }
119
+
120
+ if (is_iterable($assoc_args) && count($assoc_args)) {
121
+ $dataset = array();
122
+
123
+ foreach(array_keys($assoc_args) as $group) {
124
+ if (isset($payload['dataset'][$group])) {
125
+ $dataset[$group] = $payload['dataset'][$group];
126
+ }
127
+ }
128
+
129
+ $payload['dataset'] = $dataset;
130
+ }
131
+
132
+ $result = json_decode($manager->importSettings($payload));
133
+
134
+ if ($result->status === 'success') {
135
+ WP_CLI::success('Settings imported successfully');
136
+ } else {
137
+ WP_CLI::error($result->reason);
138
+ }
139
+ }
140
+
141
+ }
application/Core/Subject.php CHANGED
@@ -26,12 +26,13 @@
26
  * Subject principal is underlying WordPress core user or role. Not all Subjects have
27
  * principals (e.g. Visitor or Default).
28
  *
 
29
  * @since 6.3.2 Added new hook `aam_initialized_{$type}_object_filter`
30
  * @since 6.1.0 Fixed bug with incorrectly managed internal cache
31
  * @since 6.0.0 Initial implementation of the class
32
  *
33
  * @package AAM
34
- * @version 6.3.2
35
  */
36
  abstract class AAM_Core_Subject
37
  {
@@ -328,8 +329,11 @@ abstract class AAM_Core_Subject
328
  *
329
  * @return array
330
  *
 
 
 
331
  * @access protected
332
- * @version 6.0.0
333
  */
334
  protected function inheritFromParent(AAM_Core_Object $object)
335
  {
@@ -341,9 +345,6 @@ abstract class AAM_Core_Subject
341
  $object->getId()
342
  )->getOption();
343
 
344
- // Merge access settings while reading hierarchical chain
345
- $option = array_replace_recursive($option, $object->getOption());
346
-
347
  // Merge access settings if multi-roles option is enabled
348
  $multi = AAM::api()->getConfig('core.settings.multiSubject', false);
349
 
@@ -358,6 +359,9 @@ abstract class AAM_Core_Subject
358
  }
359
  }
360
 
 
 
 
361
  // Finally set the option for provided object
362
  $object->setOption($option);
363
  }
26
  * Subject principal is underlying WordPress core user or role. Not all Subjects have
27
  * principals (e.g. Visitor or Default).
28
  *
29
+ * @since 6.7.0 https://github.com/aamplugin/advanced-access-manager/issues/152
30
  * @since 6.3.2 Added new hook `aam_initialized_{$type}_object_filter`
31
  * @since 6.1.0 Fixed bug with incorrectly managed internal cache
32
  * @since 6.0.0 Initial implementation of the class
33
  *
34
  * @package AAM
35
+ * @version 6.7.0
36
  */
37
  abstract class AAM_Core_Subject
38
  {
329
  *
330
  * @return array
331
  *
332
+ * @since 6.7.0 https://github.com/aamplugin/advanced-access-manager/issues/152
333
+ * @since 6.0.0 Initial implementation of the method
334
+ *
335
  * @access protected
336
+ * @version 6.7.0
337
  */
338
  protected function inheritFromParent(AAM_Core_Object $object)
339
  {
345
  $object->getId()
346
  )->getOption();
347
 
 
 
 
348
  // Merge access settings if multi-roles option is enabled
349
  $multi = AAM::api()->getConfig('core.settings.multiSubject', false);
350
 
359
  }
360
  }
361
 
362
+ // Merge access settings while reading hierarchical chain
363
+ $option = array_replace_recursive($option, $object->getOption());
364
+
365
  // Finally set the option for provided object
366
  $object->setOption($option);
367
  }
application/Service/Cli.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * ======================================================================
5
+ * LICENSE: This file is subject to the terms and conditions defined in *
6
+ * file 'license.txt', which is part of this source code package. *
7
+ * ======================================================================
8
+ */
9
+
10
+ /**
11
+ * WP CLI service
12
+ *
13
+ * @package AAM
14
+ *
15
+ * @version 6.7.0
16
+ */
17
+ class AAM_Service_Cli
18
+ {
19
+ use AAM_Core_Contract_ServiceTrait;
20
+
21
+ /**
22
+ * AAM configuration setting that is associated with the service
23
+ *
24
+ * @version 6.7.0
25
+ */
26
+ const FEATURE_FLAG = 'core.service.cli.enabled';
27
+
28
+ /**
29
+ * Constructor
30
+ *
31
+ * @return void
32
+ *
33
+ * @access protected
34
+ * @version 6.7.0
35
+ */
36
+ protected function __construct()
37
+ {
38
+ if (is_admin()) {
39
+ // Hook that returns the detailed information about the nature of the
40
+ // service. This is used to display information about service on the
41
+ // Settings->Services tab
42
+ add_filter('aam_service_list_filter', function ($services) {
43
+ $services[] = array(
44
+ 'title' => __('WP CLI', AAM_KEY),
45
+ 'description' => __('Collection of WP CLI command that facilitate various AAM features.', AAM_KEY),
46
+ 'setting' => self::FEATURE_FLAG
47
+ );
48
+
49
+ return $services;
50
+ }, 30);
51
+ }
52
+
53
+ // Hook into the WP core processes
54
+ if (AAM_Core_Config::get(self::FEATURE_FLAG, true)) {
55
+ $this->initializeHooks();
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Initialize service hooks
61
+ *
62
+ * @return void
63
+ *
64
+ * @access protected
65
+ * @version 6.7.0
66
+ */
67
+ protected function initializeHooks()
68
+ {
69
+ // Register WP-CLI commands
70
+ if (class_exists('WP_CLI')) {
71
+ WP_CLI::add_command('aam', 'AAM_Core_Cli');
72
+ }
73
+ }
74
+
75
+ }
76
+
77
+ if (defined('AAM_KEY')) {
78
+ AAM_Service_Cli::bootstrap();
79
+ }
application/Service/Route.php CHANGED
@@ -10,12 +10,13 @@
10
  /**
11
  * API Route service
12
  *
 
13
  * @since 6.4.0 Enhanced https://github.com/aamplugin/advanced-access-manager/issues/71
14
  * Fixed https://github.com/aamplugin/advanced-access-manager/issues/76
15
  * @since 6.0.0 Initial implementation of the class
16
  *
17
  * @package AAM
18
- * @version 6.4.0
19
  */
20
  class AAM_Service_Route
21
  {
@@ -79,12 +80,13 @@ class AAM_Service_Route
79
  *
80
  * @return void
81
  *
 
82
  * @since 6.4.0 Enhanced https://github.com/aamplugin/advanced-access-manager/issues/71
83
  * Fixed https://github.com/aamplugin/advanced-access-manager/issues/76
84
  * @since 6.0.0 Initial implementation of the method
85
  *
86
  * @access protected
87
- * @version 6.4.0
88
  */
89
  protected function initializeHooks()
90
  {
@@ -136,7 +138,7 @@ class AAM_Service_Route
136
  );
137
 
138
  // Register API manager is applicable
139
- add_action('parse_request', array($this, 'registerRouteControllers'), 1);
140
 
141
  // Policy generation hook
142
  add_filter(
@@ -179,24 +181,6 @@ class AAM_Service_Route
179
  return $policy;
180
  }
181
 
182
- /**
183
- * Register route controllers
184
- *
185
- * @return void
186
- *
187
- * @access public
188
- * @version 6.0.0
189
- */
190
- public function registerRouteControllers()
191
- {
192
- global $wp;
193
-
194
- if (!empty($wp->query_vars['rest_route'])) {
195
- // Manage access to the RESTful endpoints
196
- add_filter('rest_pre_dispatch', array($this, 'authorizeRequest'), 1, 3);
197
- }
198
- }
199
-
200
  /**
201
  * Authorize REST request
202
  *
10
  /**
11
  * API Route service
12
  *
13
+ * @since 6.7.0 https://github.com/aamplugin/advanced-access-manager/issues/153
14
  * @since 6.4.0 Enhanced https://github.com/aamplugin/advanced-access-manager/issues/71
15
  * Fixed https://github.com/aamplugin/advanced-access-manager/issues/76
16
  * @since 6.0.0 Initial implementation of the class
17
  *
18
  * @package AAM
19
+ * @version 6.7.0
20
  */
21
  class AAM_Service_Route
22
  {
80
  *
81
  * @return void
82
  *
83
+ * @since 6.7.0 https://github.com/aamplugin/advanced-access-manager/issues/153
84
  * @since 6.4.0 Enhanced https://github.com/aamplugin/advanced-access-manager/issues/71
85
  * Fixed https://github.com/aamplugin/advanced-access-manager/issues/76
86
  * @since 6.0.0 Initial implementation of the method
87
  *
88
  * @access protected
89
+ * @version 6.7.0
90
  */
91
  protected function initializeHooks()
92
  {
138
  );
139
 
140
  // Register API manager is applicable
141
+ add_filter('rest_pre_dispatch', array($this, 'authorizeRequest'), 1, 3);
142
 
143
  // Policy generation hook
144
  add_filter(
181
  return $policy;
182
  }
183
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  /**
185
  * Authorize REST request
186
  *
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: access control, membership, backend menu, user role, restricted content, s
4
  Requires at least: 4.7.0
5
  Requires PHP: 5.6.0
6
  Tested up to: 5.5.1
7
- Stable tag: 6.6.4
8
 
9
  All you need to manage access to WordPress websites on the frontend, backend and API levels for any role, user or visitors.
10
 
@@ -91,6 +91,12 @@ We take security and privacy very seriously, that is why there are several non-n
91
 
92
  == Changelog ==
93
 
 
 
 
 
 
 
94
  = 6.6.4 =
95
  * Fixed Bug: DataTables warning: table id=post-ipcheck-list - Cannot reinitialise DataTable [https://github.com/aamplugin/advanced-access-manager/issues/149](https://github.com/aamplugin/advanced-access-manager/issues/149)
96
  * Changed: User Level Filter Service: Performance Request by @dannysummerlinjstartorg [https://github.com/aamplugin/advanced-access-manager/issues/142](https://github.com/aamplugin/advanced-access-manager/issues/142)
4
  Requires at least: 4.7.0
5
  Requires PHP: 5.6.0
6
  Tested up to: 5.5.1
7
+ Stable tag: 6.7.0
8
 
9
  All you need to manage access to WordPress websites on the frontend, backend and API levels for any role, user or visitors.
10
 
91
 
92
  == Changelog ==
93
 
94
+ = 6.7.0 =
95
+ * Fixed Bug: Incorrectly merged settings with multi-role enabled [https://github.com/aamplugin/advanced-access-manager/issues/152](https://github.com/aamplugin/advanced-access-manager/issues/152)
96
+ * Changed: Simplify the Route service [https://github.com/aamplugin/advanced-access-manager/issues/153](https://github.com/aamplugin/advanced-access-manager/issues/153)
97
+ * Changed: Unexpected Application Error Message Misleads [https://github.com/aamplugin/advanced-access-manager/issues/151](https://github.com/aamplugin/advanced-access-manager/issues/151)
98
+ * Added New: AAM CLI: Allow the ability import/export settings [https://github.com/aamplugin/advanced-access-manager/issues/150](https://github.com/aamplugin/advanced-access-manager/issues/150)
99
+
100
  = 6.6.4 =
101
  * Fixed Bug: DataTables warning: table id=post-ipcheck-list - Cannot reinitialise DataTable [https://github.com/aamplugin/advanced-access-manager/issues/149](https://github.com/aamplugin/advanced-access-manager/issues/149)
102
  * Changed: User Level Filter Service: Performance Request by @dannysummerlinjstartorg [https://github.com/aamplugin/advanced-access-manager/issues/142](https://github.com/aamplugin/advanced-access-manager/issues/142)