Roles and Capabilities for WordPress Users
How user capabilities work
- Role - it's set of capabilities
- The user's capabilities are checked, not the role name
- Role capabilities are not copied into the database for each user
How this is stored:
- Roles are stored globally in the
wp_user_rolesoption - A user typically has only roles stored in
wp_capabilities - Individual capabilities may also be stored there if they were added directly via WP_User::add_cap()
Example wp_capabilities:
[ 'editor' => true, 'administrator' => true, 'custom_cap' => true, ]
How WordPress determines capabilities:
-
- takes the capabilities of all roles
- adds individual capabilities
- collects the final set into
$this->allcaps
-
- if it's a meta capability (not primitive), first maps it to primitive ones
- runs
$this->allcapsthrough the user_has_cap filter - checks for the presence of the specified capability in
$this->allcaps
Important:
- The full calculated set of capabilities for a user is not stored in the database
- It is assembled dynamically from roles and user caps
- If a capability was granted directly to a user, it is already stored on the user
The relation is:
- role = a template of rights
- user = roles + possibly separate rights
- final rights = the union of all of that
List of Roles
There are 6 roles in WordPress by default:
| Super Admin | Super Administrator. Has rights to manage the network sites. This role appears only in multisite installation. |
| administrator | The administrator of the site (a separate site in the network multisite). |
| editor | Editor. Has access to all posts, pages, comments, categories, tags, and links. |
| author | Author. Can create, upload photos, edit and publish his posts. |
| contributor | Contributor. Can create posts, which are then published by an editor or administrator. |
| subscriber | Subscriber. Can't do anything except edit profile. |
Which role the new user gets is specified in Settings > General. The data is saved in an options: users_can_register and default_role:
List of Capabilities by Roles
A list of primitive (fundamental) user caps. These are capabilities that the specified roles (users) have by default. This list of caps is set once, when you install WordPress - it is stored in the database wp_options table in the wp_user_roles option.
| Capability | Super-admin | Admin | Editor | Author | Contributor | Subscriber |
|---|---|---|---|---|---|---|
| read | yes | yes | yes | yes | yes | yes |
| delete_posts | yes | yes | yes | yes | yes | |
| edit_posts | yes | yes | yes | yes | yes | |
| delete_published_posts | yes | yes | yes | yes | ||
| edit_published_posts | yes | yes | yes | yes | ||
| publish_posts | yes | yes | yes | yes | ||
| upload_files | yes | yes | yes | yes | ||
| delete_others_pages | yes | yes | yes | |||
| delete_others_posts | yes | yes | yes | |||
| delete_pages | yes | yes | yes | |||
| delete_private_pages | yes | yes | yes | |||
| delete_private_posts | yes | yes | yes | |||
| delete_published_pages | yes | yes | yes | |||
| edit_others_pages | yes | yes | yes | |||
| edit_others_posts | yes | yes | yes | |||
| edit_pages | yes | yes | yes | |||
| edit_private_pages | yes | yes | yes | |||
| edit_private_posts | yes | yes | yes | |||
| edit_published_pages | yes | yes | yes | |||
| manage_categories | yes | yes | yes | |||
| manage_links | yes | yes | yes | |||
| moderate_comments | yes | yes | yes | |||
| publish_pages | yes | yes | yes | |||
| read_private_pages | yes | yes | yes | |||
| read_private_posts | yes | yes | yes | |||
| unfiltered_html | yes | yes ¹ | yes ¹ | |||
| activate_plugins | yes | yes ² | ||||
| create_users | yes | yes ¹ | ||||
| deactivate_plugins | yes | yes | ||||
| delete_plugins | yes | yes ¹ | ||||
| delete_themes | yes | yes ¹ | ||||
| delete_users | yes | yes ¹ | ||||
| edit_dashboard | yes | yes | ||||
| edit_files | yes | yes ¹ | ||||
| edit_plugins | yes | yes ¹ | ||||
| edit_theme_options | yes | yes | ||||
| edit_themes | yes | yes ¹ | ||||
| edit_users | yes | yes ¹ | ||||
| export | yes | yes | ||||
| import | yes | yes | ||||
| install_languages | yes | yes ¹ | ||||
| install_plugins | yes | yes ¹ | ||||
| install_themes | yes | yes ¹ | ||||
| list_users | yes | yes | ||||
| manage_options | yes | yes | ||||
| promote_users | yes | yes | ||||
| remove_users | yes | yes | ||||
| switch_themes | yes | yes | ||||
| update_core | yes | yes ¹ | ||||
| update_languages | yes | yes ¹ | ||||
| update_plugins | yes | yes ¹ | ||||
| update_themes | yes | yes ¹ | ||||
| unfiltered_upload | yes ³ | yes ³ | ||||
| manage_network_options | yes | |||||
| manage_network_plugins | yes | |||||
| manage_network_themes | yes | |||||
| manage_network_users | yes | |||||
| manage_network | yes | |||||
| manage_sites | yes | |||||
| setup_network | yes | |||||
| upgrade_network | yes |
¹— when one site (not a multisite).²— when one site (not a multisite). Or enabled in the network settings.³— this right must be included separately, more below.
Meta Capabilities
Above is a list of primitive (fundamental) rights. But there are also so-called meta-rights. They are not saved anywhere, but are computed "on the fly" and eventually turn into a primitive right.
List of meta-rights:
activate_plugin activate_plugins add_comment_meta add_post_meta add_term_meta add_user_meta add_users assign_categories assign_post_tags assign_term create_app_password create_sites create_users customize deactivate_plugin deactivate_plugins delete_app_password delete_app_passwords delete_categories delete_comment_meta delete_page delete_page delete_plugins delete_post delete_post delete_post_meta delete_post_tags delete_site delete_sites delete_term delete_term_meta delete_themes delete_user delete_user delete_user_meta delete_users edit_app_password edit_categories edit_comment edit_comment edit_comment_meta edit_css edit_files edit_page edit_page edit_plugins edit_post edit_post edit_post_meta edit_post_tags edit_term edit_term_meta edit_themes edit_user edit_user edit_user_meta edit_users erase_others_personal_data export_others_personal_data install_languages install_plugins install_themes list_app_passwords manage_links manage_network manage_network_options manage_network_plugins manage_network_themes manage_network_users manage_post_tags manage_privacy_options manage_sites promote_user promote_user publish_post read_app_password read_page read_page read_post read_post remove_user remove_user resume_plugin resume_theme setup_network unfiltered_html unfiltered_upload update_core update_https update_languages update_php update_plugins update_themes upgrade_network upload_plugins upload_themes edit_term — WP 4.7 — It does not check who created the term - it only checks if the specified term and taxonomy exist. delete_term — WP 4.7 — assign_term — WP 4.7 — activate_plugin — WP 4.9 — current_user_can( 'activate_plugin', 'my-plugin/my-plugin.php' ) deactivate_plugin — WP 4.9 — current_user_can( 'deactivate_plugin', 'my-plugin/my-plugin.php' ) export_others_personal_data — WP 4.9.6 — is_multisite() ? 'manage_network' : 'manage_options' erase_others_personal_data — WP 4.9.6 — is_multisite() ? 'manage_network' : 'manage_options' manage_privacy_options — WP 4.9.6 — is_multisite() ? 'manage_network' : 'manage_options' update_php — WP 5.0 — is_multisite() ? is_super_admin() : update_core update_https — WP 5.7 — is_multisite() ? is_super_admin() : manage_options | update_core create_app_password — WP 5.7 — map_meta_cap( 'edit_user', $user_id ) list_app_passwords — WP 5.7 — map_meta_cap( 'edit_user', $user_id ) read_app_password — WP 5.7 — map_meta_cap( 'edit_user', $user_id ) edit_app_password — WP 5.7 — map_meta_cap( 'edit_user', $user_id ) delete_app_passwords — WP 5.7 — map_meta_cap( 'edit_user', $user_id ) delete_app_password — WP 5.7 — map_meta_cap( 'edit_user', $user_id )
To check such rights, you need to pass additional parameters, such as the ID of the post for which you want to check whether the user can edit it. For example:
if( current_user_can( 'edit_post', 123 ) ){
echo 'The current user can edit post 123';
}
In this case, WP checks on the fly whether the user is the author of that post, or has the primitive right to edit all posts. As a result, if the check is passed, this meta right turns into a similar primitive right edit_posts that allows the action to be performed.
Read more about meta rights in map_meta_cap().
Dynamic Capabilities
These are caps that are not stored in the database but are calculated on the fly based on certain conditions. This calculation is done on the hook user_has_cap.
install_languages — WP 4.9 — update_core || install_plugins || install_themes resume_plugins — WP 5.2 — activate_plugins resume_themes — WP 5.2 — switch_themes view_site_health_checks — WP 5.2 — install_plugins && is_super_admin (multisite)
See wp_maybe_grant_install_languages_cap()
See wp_maybe_grant_resume_extensions_caps()
See wp_maybe_grant_site_health_caps()
unfiltered_upload
By default, the unfiltered_upload capability is available to the administrator. However, this right is locked by default, i.e. roles will not pass the if( current_user_can('unfiltered_upload') ) despite having this right.
To make the unfiltered_upload capability start working as expected, you need to add following constant in wp-config.php:
define( 'ALLOW_UNFILTERED_UPLOADS', true );
With the definition of this constant, roles with unfiltered_upload permission will be able to upload files with any extension (without checking the file type).
For multisite, only the Super Administrator has the unfiltered_upload right. If another role has the unfiltered_upload right, it will simply be ignored. See checking the meta-right in map_meta_cap() for details:
case 'unfiltered_upload':
if ( defined( 'ALLOW_UNFILTERED_UPLOADS' ) && ALLOW_UNFILTERED_UPLOADS && ( ! is_multisite() || is_super_admin( $user_id ) ) ) {
$caps[] = $cap;
} else {
$caps[] = 'do_not_allow';
}
break;—
Note embeded into: