Members - Version 2.0.2

Version Description

If upgrading from a version prior to 2.0.0, please note that the plugin now requires PHP 5.3.0 or later.

Download this release

Release Info

Developer greenshady
Plugin Icon 128x128 Members
Version 2.0.2
Comparing to
See all releases

Code changes from version 2.0.1 to 2.0.2

admin/class-role-edit.php CHANGED
@@ -120,12 +120,12 @@ final class Role_Edit {
120
  check_admin_referer( 'edit_role', 'members_edit_role_nonce' );
121
 
122
  // Get the granted and denied caps.
123
- $grant_caps = ! empty( $_POST['grant-caps'] ) ? array_unique( $_POST['grant-caps'] ) : array();
124
- $deny_caps = ! empty( $_POST['deny-caps'] ) ? array_unique( $_POST['deny-caps'] ) : array();
125
 
126
  // Get the new (custom) granted and denied caps.
127
- $grant_new_caps = ! empty( $_POST['grant-new-caps'] ) ? array_unique( $_POST['grant-new-caps'] ) : array();
128
- $deny_new_caps = ! empty( $_POST['deny-new-caps'] ) ? array_unique( $_POST['deny-new-caps'] ) : array();
129
 
130
  // Get the all and custom cap group objects.
131
  $all_group = members_get_cap_group( 'all' );
@@ -208,7 +208,7 @@ final class Role_Edit {
208
  members_register_role(
209
  $this->role->name,
210
  array(
211
- 'label' => $this->members_role->label,
212
  'caps' => $this->role->capabilities
213
  )
214
  );
@@ -223,19 +223,19 @@ final class Role_Edit {
223
 
224
  // If successful update.
225
  if ( $this->role_updated )
226
- add_settings_error( 'members_edit_role', 'role_updated', sprintf( esc_html__( '%s role updated.', 'members' ), members_get_role( $this->role->name )->label ), 'updated' );
227
 
228
  // If the role is not editable.
229
  if ( ! $this->is_editable )
230
- add_settings_error( 'members_edit_role', 'role_uneditable', sprintf( esc_html__( 'The %s role is not editable. This means that it is most likely added via another plugin for a special use or that you do not have permission to edit it.', 'members' ), members_get_role( $this->role->name )->label ) );
231
 
232
  // If editing the core administrator role.
233
  if ( 'administrator' === $this->role->name )
234
- add_settings_error( 'members_edit_role', 'role_is_admin', sprintf( esc_html__( 'The %s role is typically the most important role on the site. Please take extreme caution that you do not inadvertently remove necessary capabilities.', 'members' ), members_get_role( $this->role->name )->label ) );
235
 
236
  // If a new role was added (redirect from new role screen).
237
  if ( isset( $_GET['message'] ) && 'role_added' === $_GET['message'] )
238
- add_settings_error( 'members_edit_role', 'role_added', sprintf( esc_html__( 'The %s role has been created.', 'members' ), members_get_role( $this->role->name )->label ), 'updated' );
239
 
240
  // Load page hook.
241
  do_action( 'members_load_role_edit' );
@@ -318,7 +318,7 @@ final class Role_Edit {
318
 
319
  <div id="titlewrap">
320
  <span class="screen-reader-text"><?php esc_html_e( 'Role Name', 'members' ); ?></span>
321
- <input type="text" disabled="disabled" readonly="readonly" value="<?php echo esc_attr( members_get_role( $this->role->name )->label ); ?>" />
322
  </div><!-- #titlewrap -->
323
 
324
  <div class="inside">
120
  check_admin_referer( 'edit_role', 'members_edit_role_nonce' );
121
 
122
  // Get the granted and denied caps.
123
+ $grant_caps = ! empty( $_POST['grant-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['grant-caps'] ) ) : array();
124
+ $deny_caps = ! empty( $_POST['deny-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['deny-caps'] ) ) : array();
125
 
126
  // Get the new (custom) granted and denied caps.
127
+ $grant_new_caps = ! empty( $_POST['grant-new-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['grant-new-caps'] ) ) : array();
128
+ $deny_new_caps = ! empty( $_POST['deny-new-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['deny-new-caps'] ) ) : array();
129
 
130
  // Get the all and custom cap group objects.
131
  $all_group = members_get_cap_group( 'all' );
208
  members_register_role(
209
  $this->role->name,
210
  array(
211
+ 'label' => $this->members_role->get( 'label' ),
212
  'caps' => $this->role->capabilities
213
  )
214
  );
223
 
224
  // If successful update.
225
  if ( $this->role_updated )
226
+ add_settings_error( 'members_edit_role', 'role_updated', sprintf( esc_html__( '%s role updated.', 'members' ), members_get_role( $this->role->name )->get( 'label' ) ), 'updated' );
227
 
228
  // If the role is not editable.
229
  if ( ! $this->is_editable )
230
+ add_settings_error( 'members_edit_role', 'role_uneditable', sprintf( esc_html__( 'The %s role is not editable. This means that it is most likely added via another plugin for a special use or that you do not have permission to edit it.', 'members' ), members_get_role( $this->role->name )->get( 'label' ) ) );
231
 
232
  // If editing the core administrator role.
233
  if ( 'administrator' === $this->role->name )
234
+ add_settings_error( 'members_edit_role', 'role_is_admin', sprintf( esc_html__( 'The %s role is typically the most important role on the site. Please take extreme caution that you do not inadvertently remove necessary capabilities.', 'members' ), members_get_role( $this->role->name )->get( 'label' ) ) );
235
 
236
  // If a new role was added (redirect from new role screen).
237
  if ( isset( $_GET['message'] ) && 'role_added' === $_GET['message'] )
238
+ add_settings_error( 'members_edit_role', 'role_added', sprintf( esc_html__( 'The %s role has been created.', 'members' ), members_get_role( $this->role->name )->get( 'label' ) ), 'updated' );
239
 
240
  // Load page hook.
241
  do_action( 'members_load_role_edit' );
318
 
319
  <div id="titlewrap">
320
  <span class="screen-reader-text"><?php esc_html_e( 'Role Name', 'members' ); ?></span>
321
+ <input type="text" disabled="disabled" readonly="readonly" value="<?php echo esc_attr( members_get_role( $this->role->name )->get( 'label' ) ); ?>" />
322
  </div><!-- #titlewrap -->
323
 
324
  <div class="inside">
admin/class-role-list-table.php CHANGED
@@ -248,7 +248,11 @@ class Role_List_Table extends \WP_List_Table {
248
  }
249
 
250
  // Add the title and role states.
251
- $title = sprintf( '<strong><a class="row-title" href="%s">%s</a>%s</strong>', esc_url( members_get_edit_role_url( $role ) ), esc_html( members_get_role( $role )->label ), $role_states );
 
 
 
 
252
 
253
  return apply_filters( 'members_manage_roles_column_role_name', $title, $role );
254
  }
@@ -341,7 +345,7 @@ class Role_List_Table extends \WP_List_Table {
341
  $actions['delete'] = sprintf( '<a class="members-delete-role-link" href="%s">%s</a>', esc_url( members_get_delete_role_url( $role ) ), esc_html__( 'Delete', 'members' ) );
342
 
343
  // If the role cannot be edited.
344
- } else {
345
 
346
  // Add the view role link.
347
  $actions['view'] = sprintf( '<a href="%s">%s</a>', esc_url( members_get_edit_role_url( $role ) ), esc_html__( 'View', 'members' ) );
248
  }
249
 
250
  // Add the title and role states.
251
+ if ( current_user_can( 'edit_roles' ) )
252
+ $title = sprintf( '<strong><a class="row-title" href="%s">%s</a>%s</strong>', esc_url( members_get_edit_role_url( $role ) ), esc_html( members_get_role( $role )->get( 'label' ) ), $role_states );
253
+
254
+ else
255
+ $title = sprintf( '<strong><span class="row-title">%s</span>%s</strong>', esc_html( members_get_role( $role )->get( 'label' ) ), $role_states );
256
 
257
  return apply_filters( 'members_manage_roles_column_role_name', $title, $role );
258
  }
345
  $actions['delete'] = sprintf( '<a class="members-delete-role-link" href="%s">%s</a>', esc_url( members_get_delete_role_url( $role ) ), esc_html__( 'Delete', 'members' ) );
346
 
347
  // If the role cannot be edited.
348
+ } elseif ( current_user_can( 'edit_roles' ) ) {
349
 
350
  // Add the view role link.
351
  $actions['view'] = sprintf( '<a href="%s">%s</a>', esc_url( members_get_edit_role_url( $role ) ), esc_html__( 'View', 'members' ) );
admin/class-role-new.php CHANGED
@@ -161,8 +161,8 @@ final class Role_New {
161
  // Check if any capabilities were selected.
162
  if ( isset( $_POST['grant-caps'] ) || isset( $_POST['deny-caps'] ) ) {
163
 
164
- $grant_caps = ! empty( $_POST['grant-caps'] ) ? array_unique( $_POST['grant-caps'] ) : array();
165
- $deny_caps = ! empty( $_POST['deny-caps'] ) ? array_unique( $_POST['deny-caps'] ) : array();
166
 
167
  foreach ( $_m_caps as $cap ) {
168
 
@@ -174,14 +174,14 @@ final class Role_New {
174
  }
175
  }
176
 
177
- $grant_new_caps = ! empty( $_POST['grant-new-caps'] ) ? array_unique( $_POST['grant-new-caps'] ) : array();
178
- $deny_new_caps = ! empty( $_POST['deny-new-caps'] ) ? array_unique( $_POST['deny-new-caps'] ) : array();
179
 
180
  foreach ( $grant_new_caps as $grant_new_cap ) {
181
 
182
  $_cap = members_sanitize_cap( $grant_new_cap );
183
 
184
- if ( 'do_not_allow' !== $_cap && ! in_array( $_cap, $_m_caps ) )
185
  $new_caps[ $_cap ] = true;
186
  }
187
 
@@ -189,7 +189,7 @@ final class Role_New {
189
 
190
  $_cap = members_sanitize_cap( $deny_new_cap );
191
 
192
- if ( 'do_not_allow' !== $_cap && ! in_array( $_cap, $_m_caps ) )
193
  $new_caps[ $_cap ] = false;
194
  }
195
 
@@ -325,7 +325,7 @@ final class Role_New {
325
 
326
  <div id="titlewrap">
327
  <span class="screen-reader-text"><?php esc_html_e( 'Role Name', 'members' ); ?></span>
328
- <input type="text" name="role_name" value="<?php echo ! $this->role && $this->clone_role ? esc_attr( sprintf( __( '%s Clone', 'members' ), members_get_role( $this->clone_role )->label ) ) : esc_attr( $this->role_name ); ?>" placeholder="<?php esc_attr_e( 'Enter role name', 'members' ); ?>" />
329
  </div><!-- #titlewrap -->
330
 
331
  <div class="inside">
161
  // Check if any capabilities were selected.
162
  if ( isset( $_POST['grant-caps'] ) || isset( $_POST['deny-caps'] ) ) {
163
 
164
+ $grant_caps = ! empty( $_POST['grant-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['grant-caps'] ) ) : array();
165
+ $deny_caps = ! empty( $_POST['deny-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['deny-caps'] ) ) : array();
166
 
167
  foreach ( $_m_caps as $cap ) {
168
 
174
  }
175
  }
176
 
177
+ $grant_new_caps = ! empty( $_POST['grant-new-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['grant-new-caps'] ) ) : array();
178
+ $deny_new_caps = ! empty( $_POST['deny-new-caps'] ) ? members_remove_hidden_caps( array_unique( $_POST['deny-new-caps'] ) ) : array();
179
 
180
  foreach ( $grant_new_caps as $grant_new_cap ) {
181
 
182
  $_cap = members_sanitize_cap( $grant_new_cap );
183
 
184
+ if ( ! in_array( $_cap, $_m_caps ) )
185
  $new_caps[ $_cap ] = true;
186
  }
187
 
189
 
190
  $_cap = members_sanitize_cap( $deny_new_cap );
191
 
192
+ if ( ! in_array( $_cap, $_m_caps ) )
193
  $new_caps[ $_cap ] = false;
194
  }
195
 
325
 
326
  <div id="titlewrap">
327
  <span class="screen-reader-text"><?php esc_html_e( 'Role Name', 'members' ); ?></span>
328
+ <input type="text" name="role_name" value="<?php echo ! $this->role && $this->clone_role ? esc_attr( sprintf( __( '%s Clone', 'members' ), members_get_role( $this->clone_role )->get( 'label' ) ) ) : esc_attr( $this->role_name ); ?>" placeholder="<?php esc_attr_e( 'Enter role name', 'members' ); ?>" />
329
  </div><!-- #titlewrap -->
330
 
331
  <div class="inside">
admin/class-roles.php CHANGED
@@ -128,7 +128,7 @@ final class Roles {
128
  if ( members_role_exists( $role ) ) {
129
 
130
  // Add role deleted message.
131
- add_settings_error( 'members_roles', 'role_deleted', sprintf( esc_html__( '%s role deleted.', 'members' ), members_get_role( $role )->label ), 'updated' );
132
 
133
  // Delete the role.
134
  members_delete_role( $role );
128
  if ( members_role_exists( $role ) ) {
129
 
130
  // Add role deleted message.
131
+ add_settings_error( 'members_roles', 'role_deleted', sprintf( esc_html__( '%s role deleted.', 'members' ), members_get_role( $role )->get( 'label' ) ), 'updated' );
132
 
133
  // Delete the role.
134
  members_delete_role( $role );
admin/class-user-edit.php CHANGED
@@ -105,7 +105,7 @@ final class User_Edit {
105
  <li>
106
  <label>
107
  <input type="checkbox" name="members_user_roles[]" value="<?php echo esc_attr( $role->name ); ?>" <?php checked( in_array( $role->name, $user_roles ) ); ?> />
108
- <?php echo esc_html( $role->label ); ?>
109
  </label>
110
  </li>
111
  <?php endif; ?>
105
  <li>
106
  <label>
107
  <input type="checkbox" name="members_user_roles[]" value="<?php echo esc_attr( $role->name ); ?>" <?php checked( in_array( $role->name, $user_roles ) ); ?> />
108
+ <?php echo esc_html( $role->get( 'label' ) ); ?>
109
  </label>
110
  </li>
111
  <?php endif; ?>
admin/class-user-new.php CHANGED
@@ -117,7 +117,7 @@ final class User_New {
117
  <li>
118
  <label>
119
  <input type="checkbox" name="members_user_roles[]" value="<?php echo esc_attr( $role->name ); ?>" <?php checked( in_array( $role->name, $new_user_roles ) ); ?> />
120
- <?php echo esc_html( $role->label ); ?>
121
  </label>
122
  </li>
123
  <?php endif; ?>
117
  <li>
118
  <label>
119
  <input type="checkbox" name="members_user_roles[]" value="<?php echo esc_attr( $role->name ); ?>" <?php checked( in_array( $role->name, $new_user_roles ) ); ?> />
120
+ <?php echo esc_html( $role->get( 'label' ) ); ?>
121
  </label>
122
  </li>
123
  <?php endif; ?>
admin/functions-admin.php CHANGED
@@ -47,7 +47,8 @@ function members_admin_register_scripts() {
47
  'button_role_ok' => esc_html__( 'OK', 'members' ),
48
  'label_grant_cap' => esc_html__( 'Grant %s capability', 'members' ),
49
  'label_deny_cap' => esc_html__( 'Deny %s capability', 'members' ),
50
- 'ays_delete_role' => esc_html__( 'Are you sure you want to delete this role? This is a permanent action and cannot be undone.', 'members' )
 
51
  );
52
 
53
  wp_localize_script( 'members-edit-role', 'members_i18n', $i18n );
47
  'button_role_ok' => esc_html__( 'OK', 'members' ),
48
  'label_grant_cap' => esc_html__( 'Grant %s capability', 'members' ),
49
  'label_deny_cap' => esc_html__( 'Deny %s capability', 'members' ),
50
+ 'ays_delete_role' => esc_html__( 'Are you sure you want to delete this role? This is a permanent action and cannot be undone.', 'members' ),
51
+ 'hidden_caps' => members_get_hidden_caps()
52
  );
53
 
54
  wp_localize_script( 'members-edit-role', 'members_i18n', $i18n );
changelog.md CHANGED
@@ -1,5 +1,15 @@
1
  # Change Log
2
 
 
 
 
 
 
 
 
 
 
 
3
  ## [2.0.1] - 2017-09-28
4
 
5
  ### Changed
1
  # Change Log
2
 
3
+ ## [2.0.2] - 2017-11-06
4
+
5
+ ### Fixed
6
+
7
+ * Role labels should now be handled correctly where the plugin outputs them. This was not corrected in 2.0.1 as previously thought.
8
+
9
+ ### Security
10
+
11
+ * Corrected a capability escalation issue on multisite where administrators could assign themselves network caps. Administrators are no longer given the `create_role`, `edit_role`, and `delete_role` caps on multisite. A Super Admin must manually set these caps if they want to grant them to a site administrator. Additionally, network caps are always blocked from being assigned.
12
+
13
  ## [2.0.1] - 2017-09-28
14
 
15
  ### Changed
inc/class-role.php CHANGED
@@ -158,4 +158,21 @@ class Role {
158
  $this->has_caps = 0 < $this->granted_cap_count;
159
  }
160
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  }
158
  $this->has_caps = 0 < $this->granted_cap_count;
159
  }
160
  }
161
+
162
+ /**
163
+ * Magic method for getting media object properties. Let's keep from failing if a theme
164
+ * author attempts to access a property that doesn't exist.
165
+ *
166
+ * @since 2.0.2
167
+ * @access public
168
+ * @param string $property
169
+ * @return mixed
170
+ */
171
+ public function get( $property ) {
172
+
173
+ if ( 'label' === $property )
174
+ return members_translate_role( $this->name );
175
+
176
+ return isset( $this->$property ) ? $this->$property : false;
177
+ }
178
  }
inc/class-widget-users.php CHANGED
@@ -229,7 +229,7 @@ class Widget_Users extends \WP_Widget {
229
  <select class="widefat" id="<?php echo $this->get_field_id( 'role' ); ?>" name="<?php echo $this->get_field_name( 'role' ); ?>">
230
  <option value="" <?php selected( $instance['role'], '' ); ?>></option>
231
  <?php foreach ( $roles as $name => $role ) : ?>
232
- <option value="<?php echo esc_attr( $name ); ?>" <?php selected( $instance['role'], $name ); ?>><?php echo esc_html( $role->label ); ?></option>
233
  <?php endforeach; ?>
234
  </select>
235
  </p>
229
  <select class="widefat" id="<?php echo $this->get_field_id( 'role' ); ?>" name="<?php echo $this->get_field_name( 'role' ); ?>">
230
  <option value="" <?php selected( $instance['role'], '' ); ?>></option>
231
  <?php foreach ( $roles as $name => $role ) : ?>
232
+ <option value="<?php echo esc_attr( $name ); ?>" <?php selected( $instance['role'], $name ); ?>><?php echo esc_html( $role->get( 'label' ) ); ?></option>
233
  <?php endforeach; ?>
234
  </select>
235
  </p>
inc/functions-capabilities.php CHANGED
@@ -372,6 +372,23 @@ function members_get_hidden_caps() {
372
  // This is always a hidden cap and should never be added to the caps list.
373
  $caps[] = 'do_not_allow';
374
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
  // Unfiltered uploads.
376
  if ( is_multisite() || ! defined( 'ALLOW_UNFILTERED_UPLOADS' ) || ! ALLOW_UNFILTERED_UPLOADS )
377
  $caps[] = 'unfiltered_upload';
372
  // This is always a hidden cap and should never be added to the caps list.
373
  $caps[] = 'do_not_allow';
374
 
375
+ // Network-level caps.
376
+ // These shouldn't show on single-site installs anyway.
377
+ // On multisite installs, they should be handled by a network-specific role manager.
378
+ $caps[] = 'create_sites';
379
+ $caps[] = 'delete_sites';
380
+ $caps[] = 'manage_network';
381
+ $caps[] = 'manage_sites';
382
+ $caps[] = 'manage_network_users';
383
+ $caps[] = 'manage_network_plugins';
384
+ $caps[] = 'manage_network_themes';
385
+ $caps[] = 'manage_network_options';
386
+ $caps[] = 'upgrade_network';
387
+
388
+ // This cap is needed on single site to set up a multisite network.
389
+ if ( is_multisite() )
390
+ $caps[] = 'setup_network';
391
+
392
  // Unfiltered uploads.
393
  if ( is_multisite() || ! defined( 'ALLOW_UNFILTERED_UPLOADS' ) || ! ALLOW_UNFILTERED_UPLOADS )
394
  $caps[] = 'unfiltered_upload';
inc/functions-deprecated.php CHANGED
@@ -41,7 +41,7 @@ function members_get_active_role_names() {
41
  $has_users = array();
42
 
43
  foreach ( members_get_active_roles() as $role )
44
- $has_users[ $role ] = members_get_role( $role )->label;
45
 
46
  return $has_users;
47
  }
41
  $has_users = array();
42
 
43
  foreach ( members_get_active_roles() as $role )
44
+ $has_users[ $role ] = members_get_role( $role )->get( 'label' );
45
 
46
  return $has_users;
47
  }
inc/functions-roles.php CHANGED
@@ -40,7 +40,7 @@ function members_register_default_roles( $wp_roles ) {
40
  foreach ( $wp_roles->roles as $name => $object ) {
41
 
42
  $args = array(
43
- 'label' => members_translate_role_hook( $object['name'], $name ),
44
  'caps' => $object['capabilities']
45
  );
46
 
40
  foreach ( $wp_roles->roles as $name => $object ) {
41
 
42
  $args = array(
43
+ 'label' => $object['name'],
44
  'caps' => $object['capabilities']
45
  );
46
 
inc/functions-users.php CHANGED
@@ -153,7 +153,7 @@ function members_get_user_role_names( $user_id ) {
153
  $names = array();
154
 
155
  foreach ( $user->roles as $role )
156
- $names[ $role ] = members_get_role( $role )->label;
157
 
158
  return $names;
159
  }
153
  $names = array();
154
 
155
  foreach ( $user->roles as $role )
156
+ $names[ $role ] = members_get_role( $role )->get( 'label' );
157
 
158
  return $names;
159
  }
js/edit-role.js CHANGED
@@ -325,7 +325,8 @@ jQuery( document ).ready( function() {
325
  function() {
326
 
327
  // If there's a value in the input, enable the add new button.
328
- if ( 'do_not_allow' !== jQuery( this ).val() ) {
 
329
 
330
  jQuery( '#members-add-new-cap' ).prop( 'disabled', false );
331
 
@@ -364,7 +365,8 @@ jQuery( document ).ready( function() {
364
  if ( new_cap ) {
365
 
366
  // Don't allow the 'do_not_allow' cap.
367
- if ( 'do_not_allow' === new_cap ) {
 
368
  return;
369
  }
370
 
325
  function() {
326
 
327
  // If there's a value in the input, enable the add new button.
328
+ //if ( 'do_not_allow' !== jQuery( this ).val() ) {
329
+ if ( -1 === jQuery.inArray( jQuery( this ).val(), members_i18n.hidden_caps ) ) {
330
 
331
  jQuery( '#members-add-new-cap' ).prop( 'disabled', false );
332
 
365
  if ( new_cap ) {
366
 
367
  // Don't allow the 'do_not_allow' cap.
368
+ //if ( 'do_not_allow' === new_cap ) {
369
+ if ( -1 !== jQuery.inArray( jQuery( this ).val(), members_i18n.hidden_caps ) ) {
370
  return;
371
  }
372
 
js/edit-role.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(){function e(e){e=e.toLowerCase().trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,""),jQuery(".role-slug").text(e)}function r(){var e=jQuery("#members-tab-all input[data-grant-cap]:checked").length,r=jQuery("#members-tab-all input[data-deny-cap]:checked").length,t=jQuery('#members-tab-custom input[name="grant-new-caps[]"]:checked').length,a=jQuery('#members-tab-custom input[name="deny-new-caps[]"]:checked').length;jQuery("#submitdiv .granted-count").text(e+t),jQuery("#submitdiv .denied-count").text(r+a)}function t(e){var r="grant",t="deny";jQuery(e).attr("data-deny-cap")&&(r="deny",t="grant");var a=jQuery(e).attr("data-"+r+"-cap");jQuery(e).prop("checked")?(jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!0),jQuery("input[data-"+t+'-cap="'+a+'"]').prop("checked",!1)):jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!1)}jQuery(".members-delete-role-link").click(function(){return window.confirm(members_i18n.ays_delete_role)}),jQuery('input[name="role_name"]').keyup(function(){jQuery('input[name="role"]').val()||e(this.value)}),jQuery('input[name="role"], .role-ok-button').hide(),jQuery(document).on("click",".role-edit-button.closed",function(){jQuery(this).removeClass("closed").addClass("open").text(members_i18n.button_role_ok),jQuery('input[name="role"]').show(),jQuery('input[name="role"]').trigger("focus"),jQuery('input[name="role"]').attr("value",jQuery(".role-slug").text())}),jQuery(document).on("click",".role-edit-button.open",function(){jQuery(this).removeClass("open").addClass("closed").text(members_i18n.button_role_edit),jQuery('input[name="role"]').hide();var r=jQuery('input[name="role"]').val();e(r?r:jQuery('input[name="role_name"]').val())}),jQuery('input[name="role"]').keypress(function(e){if(13===e.keyCode)return jQuery(".role-edit-button").click().trigger("focus"),e.preventDefault(),!1}),jQuery('.users_page_role-new input[name="role_name"]').val()||jQuery(".users_page_role-new #publish").prop("disabled",!0),jQuery('.users_page_role-new input[name="role_name"]').on("input",function(){jQuery(this).val()?jQuery(".users_page_role-new #publish").prop("disabled",!1):jQuery(".users_page_role-new #publish").prop("disabled",!0)});var a=wp.template("members-cap-section"),n=wp.template("members-cap-control");"undefined"!=typeof members_sections&&"undefined"!=typeof members_controls&&(_.each(members_sections,function(e){jQuery(".members-tab-wrap").append(a(e))}),_.each(members_controls,function(e){jQuery("#members-tab-"+e.section+" tbody").append(n(e))})),jQuery(".members-cap-tabs .members-tab-content").hide(),jQuery(".members-cap-tabs .members-tab-content:first-child").show(),jQuery(".members-tab-nav :first-child").attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(".members-tab-nav :first-child a").text()),jQuery(".members-tab-nav li a").click(function(e){e.preventDefault();var r=jQuery(this).attr("href");jQuery(this).parents(".members-cap-tabs").find(".members-tab-content").hide(),jQuery(this).parents(".members-cap-tabs").find(r).show(),jQuery(this).parents(".members-cap-tabs").find(".members-tab-title").attr("aria-selected","false"),jQuery(this).parent().attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(this).text())}),r(),jQuery(document).on("change",".members-cap-checklist input[data-grant-cap], .members-cap-checklist input[data-deny-cap]",function(){t(this),r()}),jQuery(document).on("click",".editable-role .members-cap-checklist button",function(){var e=jQuery(this).closest(".members-cap-checklist"),r=jQuery(e).find("input[data-grant-cap]"),t=jQuery(e).find("input[data-deny-cap]");jQuery(r).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!0).change()):jQuery(t).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!1).change()):jQuery(r).prop("checked",!0).change()}),jQuery(document).on("hover",".editable-role .members-cap-checklist button",function(){jQuery(".members-cap-checklist button:focus").not(this).blur()}),postboxes.add_postbox_toggles(pagenow),jQuery("#newcapdiv button.handlediv").attr("type","button"),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery("#members-new-cap-field").on("input",function(){"do_not_allow"!==jQuery(this).val()?jQuery("#members-add-new-cap").prop("disabled",!1):jQuery("#members-add-new-cap").prop("disabled",!0)}),jQuery("#members-new-cap-field").keypress(function(e){if(13===e.keyCode)return jQuery("#members-add-new-cap").click(),e.preventDefault(),!1}),jQuery("#members-add-new-cap").click(function(){var e=jQuery("#members-new-cap-field").val();if(e=e.trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,"")){if("do_not_allow"===e)return;jQuery('a[href="#members-tab-custom"]').trigger("click"),members_i18n.label_grant_cap=members_i18n.label_grant_cap.replace(/%s/g,"<code>"+e+"</code>"),members_i18n.label_deny_cap=members_i18n.label_deny_cap.replace(/%s/g,"<code>"+e+"</code>");var r={cap:e,readonly:"",name:{grant:"grant-new-caps[]",deny:"deny-new-caps[]"},is_granted_cap:!0,is_denied_cap:!1,label:{cap:e,grant:members_i18n.label_grant_cap,deny:members_i18n.label_deny_cap}};jQuery("#members-tab-custom tbody").prepend(n(r));var t=jQuery('[data-grant-cap="'+e+'"]').parents(".members-cap-checklist");jQuery(t).addClass("members-highlight"),setTimeout(function(){jQuery(t).removeClass("members-highlight")},500),jQuery("#members-new-cap-field").val(""),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery('.members-cap-checklist input[data-grant-cap="'+e+'"]').trigger("change")}})});
1
+ jQuery(document).ready(function(){function e(e){e=e.toLowerCase().trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,""),jQuery(".role-slug").text(e)}function r(){var e=jQuery("#members-tab-all input[data-grant-cap]:checked").length,r=jQuery("#members-tab-all input[data-deny-cap]:checked").length,t=jQuery('#members-tab-custom input[name="grant-new-caps[]"]:checked').length,a=jQuery('#members-tab-custom input[name="deny-new-caps[]"]:checked').length;jQuery("#submitdiv .granted-count").text(e+t),jQuery("#submitdiv .denied-count").text(r+a)}function t(e){var r="grant",t="deny";jQuery(e).attr("data-deny-cap")&&(r="deny",t="grant");var a=jQuery(e).attr("data-"+r+"-cap");jQuery(e).prop("checked")?(jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!0),jQuery("input[data-"+t+'-cap="'+a+'"]').prop("checked",!1)):jQuery("input[data-"+r+'-cap="'+a+'"]').not(e).prop("checked",!1)}jQuery(".members-delete-role-link").click(function(){return window.confirm(members_i18n.ays_delete_role)}),jQuery('input[name="role_name"]').keyup(function(){jQuery('input[name="role"]').val()||e(this.value)}),jQuery('input[name="role"], .role-ok-button').hide(),jQuery(document).on("click",".role-edit-button.closed",function(){jQuery(this).removeClass("closed").addClass("open").text(members_i18n.button_role_ok),jQuery('input[name="role"]').show(),jQuery('input[name="role"]').trigger("focus"),jQuery('input[name="role"]').attr("value",jQuery(".role-slug").text())}),jQuery(document).on("click",".role-edit-button.open",function(){jQuery(this).removeClass("open").addClass("closed").text(members_i18n.button_role_edit),jQuery('input[name="role"]').hide();var r=jQuery('input[name="role"]').val();e(r?r:jQuery('input[name="role_name"]').val())}),jQuery('input[name="role"]').keypress(function(e){if(13===e.keyCode)return jQuery(".role-edit-button").click().trigger("focus"),e.preventDefault(),!1}),jQuery('.users_page_role-new input[name="role_name"]').val()||jQuery(".users_page_role-new #publish").prop("disabled",!0),jQuery('.users_page_role-new input[name="role_name"]').on("input",function(){jQuery(this).val()?jQuery(".users_page_role-new #publish").prop("disabled",!1):jQuery(".users_page_role-new #publish").prop("disabled",!0)});var a=wp.template("members-cap-section"),n=wp.template("members-cap-control");"undefined"!=typeof members_sections&&"undefined"!=typeof members_controls&&(_.each(members_sections,function(e){jQuery(".members-tab-wrap").append(a(e))}),_.each(members_controls,function(e){jQuery("#members-tab-"+e.section+" tbody").append(n(e))})),jQuery(".members-cap-tabs .members-tab-content").hide(),jQuery(".members-cap-tabs .members-tab-content:first-child").show(),jQuery(".members-tab-nav :first-child").attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(".members-tab-nav :first-child a").text()),jQuery(".members-tab-nav li a").click(function(e){e.preventDefault();var r=jQuery(this).attr("href");jQuery(this).parents(".members-cap-tabs").find(".members-tab-content").hide(),jQuery(this).parents(".members-cap-tabs").find(r).show(),jQuery(this).parents(".members-cap-tabs").find(".members-tab-title").attr("aria-selected","false"),jQuery(this).parent().attr("aria-selected","true"),jQuery(".members-which-tab").text(jQuery(this).text())}),r(),jQuery(document).on("change",".members-cap-checklist input[data-grant-cap], .members-cap-checklist input[data-deny-cap]",function(){t(this),r()}),jQuery(document).on("click",".editable-role .members-cap-checklist button",function(){var e=jQuery(this).closest(".members-cap-checklist"),r=jQuery(e).find("input[data-grant-cap]"),t=jQuery(e).find("input[data-deny-cap]");jQuery(r).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!0).change()):jQuery(t).prop("checked")?(jQuery(r).prop("checked",!1),jQuery(t).prop("checked",!1).change()):jQuery(r).prop("checked",!0).change()}),jQuery(document).on("hover",".editable-role .members-cap-checklist button",function(){jQuery(".members-cap-checklist button:focus").not(this).blur()}),postboxes.add_postbox_toggles(pagenow),jQuery("#newcapdiv button.handlediv").attr("type","button"),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery("#members-new-cap-field").on("input",function(){-1===jQuery.inArray(jQuery(this).val(),members_i18n.hidden_caps)?jQuery("#members-add-new-cap").prop("disabled",!1):jQuery("#members-add-new-cap").prop("disabled",!0)}),jQuery("#members-new-cap-field").keypress(function(e){if(13===e.keyCode)return jQuery("#members-add-new-cap").click(),e.preventDefault(),!1}),jQuery("#members-add-new-cap").click(function(){var e=jQuery("#members-new-cap-field").val();if(e=e.trim().replace(/<.*?>/g,"").replace(/\s/g,"_").replace(/[^a-zA-Z0-9_]/g,"")){if(-1!==jQuery.inArray(jQuery(this).val(),members_i18n.hidden_caps))return;jQuery('a[href="#members-tab-custom"]').trigger("click"),members_i18n.label_grant_cap=members_i18n.label_grant_cap.replace(/%s/g,"<code>"+e+"</code>"),members_i18n.label_deny_cap=members_i18n.label_deny_cap.replace(/%s/g,"<code>"+e+"</code>");var r={cap:e,readonly:"",name:{grant:"grant-new-caps[]",deny:"deny-new-caps[]"},is_granted_cap:!0,is_denied_cap:!1,label:{cap:e,grant:members_i18n.label_grant_cap,deny:members_i18n.label_deny_cap}};jQuery("#members-tab-custom tbody").prepend(n(r));var t=jQuery('[data-grant-cap="'+e+'"]').parents(".members-cap-checklist");jQuery(t).addClass("members-highlight"),setTimeout(function(){jQuery(t).removeClass("members-highlight")},500),jQuery("#members-new-cap-field").val(""),jQuery("#members-add-new-cap").prop("disabled",!0),jQuery('.members-cap-checklist input[data-grant-cap="'+e+'"]').trigger("change")}})});
members.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Members
4
  * Plugin URI: https://themehybrid.com/plugins/members
5
  * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private.
6
- * Version: 2.0.1
7
  * Author: Justin Tadlock
8
  * Author URI: https://themehybrid.com
9
  * Text Domain: members
@@ -25,7 +25,7 @@
25
  * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26
  *
27
  * @package Members
28
- * @version 2.0.1
29
  * @author Justin Tadlock <justintadlock@gmail.com>
30
  * @copyright Copyright (c) 2009 - 2017, Justin Tadlock
31
  * @link https://themehybrid.com/plugins/members
@@ -297,11 +297,16 @@ final class Members_Plugin {
297
  // If the administrator role exists, add required capabilities for the plugin.
298
  if ( ! empty( $role ) ) {
299
 
300
- $role->add_cap( 'list_roles' ); // View roles in backend.
301
- $role->add_cap( 'create_roles' ); // Create new roles.
302
- $role->add_cap( 'delete_roles' ); // Delete existing roles.
303
- $role->add_cap( 'edit_roles' ); // Edit existing roles/caps.
304
  $role->add_cap( 'restrict_content' ); // Edit per-post content permissions.
 
 
 
 
 
 
 
 
 
305
  }
306
  }
307
 
3
  * Plugin Name: Members
4
  * Plugin URI: https://themehybrid.com/plugins/members
5
  * Description: A user and role management plugin that puts you in full control of your site's permissions. This plugin allows you to edit your roles and their capabilities, clone existing roles, assign multiple roles per user, block post content, or even make your site completely private.
6
+ * Version: 2.0.2
7
  * Author: Justin Tadlock
8
  * Author URI: https://themehybrid.com
9
  * Text Domain: members
25
  * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26
  *
27
  * @package Members
28
+ * @version 2.0.2
29
  * @author Justin Tadlock <justintadlock@gmail.com>
30
  * @copyright Copyright (c) 2009 - 2017, Justin Tadlock
31
  * @link https://themehybrid.com/plugins/members
297
  // If the administrator role exists, add required capabilities for the plugin.
298
  if ( ! empty( $role ) ) {
299
 
 
 
 
 
300
  $role->add_cap( 'restrict_content' ); // Edit per-post content permissions.
301
+ $role->add_cap( 'list_roles' ); // View roles in backend.
302
+
303
+ // Do not allow administrators to edit, create, or delete roles
304
+ // in a multisite setup. Super admins should assign these manually.
305
+ if ( ! is_multisite() ) {
306
+ $role->add_cap( 'create_roles' ); // Create new roles.
307
+ $role->add_cap( 'delete_roles' ); // Delete existing roles.
308
+ $role->add_cap( 'edit_roles' ); // Edit existing roles/caps.
309
+ }
310
  }
311
  }
312
 
readme.txt CHANGED
@@ -4,9 +4,9 @@ Contributors: greenshady
4
  Donate link: https://themehybrid.com/donate
5
  Tags: capabilities, roles, members, users
6
  Requires at least: 4.7
7
- Tested up to: 4.8.2
8
  Requires PHP: 5.3
9
- Stable tag: 2.0.1
10
  License: GPLv2 or later
11
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
12
 
@@ -80,6 +80,12 @@ When the plugin is first activated, it runs a script that sets specific capabili
80
 
81
  If, for some reason, you do have the administrator role and the role manager is still inaccessible to you, deactivate the plugin. Then, reactivate it.
82
 
 
 
 
 
 
 
83
  ### Help! I've locked myself out of my site!
84
 
85
  Please read the documentation for the plugin before actually using it, especially a plugin that controls permissions for your site. I cannot stress this enough. This is a powerful plugin that allows you to make direct changes to roles and capabilities in the database.
4
  Donate link: https://themehybrid.com/donate
5
  Tags: capabilities, roles, members, users
6
  Requires at least: 4.7
7
+ Tested up to: 4.8.3
8
  Requires PHP: 5.3
9
+ Stable tag: 2.0.2
10
  License: GPLv2 or later
11
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
12
 
80
 
81
  If, for some reason, you do have the administrator role and the role manager is still inaccessible to you, deactivate the plugin. Then, reactivate it.
82
 
83
+ ### On multisite, why can't administrators cannot manage roles?
84
+
85
+ If you have a multisite installation, only Super Admins can create, edit, and delete roles by default. This is a security measure to make sure that you absolutely trust sub-site admins to make these types of changes to roles. If you're certain you want to allow this, add the Create Roles (`create_roles`), Edit Roles (`edit_roles`), and/or Delete Roles (`delete_roles`) capabilities to the role on each sub-site where you want to allow this.
86
+
87
+ _Note: This change was made in version 2.0.2 and has no effect on existing installs of Members on existing sub-sites._
88
+
89
  ### Help! I've locked myself out of my site!
90
 
91
  Please read the documentation for the plugin before actually using it, especially a plugin that controls permissions for your site. I cannot stress this enough. This is a powerful plugin that allows you to make direct changes to roles and capabilities in the database.