Users in WordPress
Basic information you need to know about WordPress users.
Table wp_users
- ID(number)
- User ID. Specified only if you need to update data for an existing user. All required parameters become optional.
- user_login(string) (required)
- Login of the new user. To perform additional validation of the login before creation/update, you can use the filter: pre_user_login.
- user_pass(string) (required)
- Password for the created user. Hashed.
- user_nicename(string)
- User's name. If not specified, it will be the same as the login. Contains a sanitized login for use in the URL - sanitized through sanitize_title(). For example, if the email [email protected] is provided in the login field during registration, it will result in userexample-com. Used in the link to the author's archive page, so the field value must be unique for each user.
- user_email(string)
- Email. Checked for existence in the database.
- user_url(string)
- Website. Filter: pre_user_url.
- user_registered(DATETIME)
- Registration date. Format: Y-m-d H:i:s. If not specified when creating a user, the current date within the GMT range is taken.
- user_activation_key
- Hash key for password recovery, created when requested. See get_password_reset_key().
- user_status(not used)
This field is no longer used by the WordPress core, which was previously used in Multisite when moving a user to spam (this functionality has been removed). See more in the function: update_user_status().
You can use the column for your own purposes, but it's better to leave it alone.
- display_name(string)
- Display name. If empty, it will be the same as the login.
Table wp_usermeta
Important meta-data (meta-fields)
- wp_capabilities(array)
User role and capabilities:
a:1:{s:13:"administrator";b:1;}.IMPORTANT! The prefix of this option
wp_must match the prefix of the database tables$wpdb->prefixor$wpdb->get_blog_prefix()for multisite.For example, if the table prefix is changed on the live site in
wp-config.php, then the prefix in this option also needs to be manually changed, otherwise all users will lose their rights because after changing the prefix, for example, towk_, WordPress will look for rights in the meta-fieldwk_capabilities.- session_tokens
- Active sessions. Created when logging into the account.
Other data stored in the metadata table
- nickname(string)
- Nickname. If empty, it will be the same as the login.
- first_name(string)
- First name.
- last_name(string)
- Last name.
- description(string)
- A little about yourself.
- rich_editing(string/bool)
- Enable (true) or disable (false) the visual editor. See user_can_richedit().
Default - 'true' - syntax_highlighting(string/bool)
- Whether to enable syntax highlighting for the visual editor.
- comment_shortcuts(string/bool)
- Whether to enable comment moderation shortcuts for the user. Whether to enqueue the script
enqueue_comment_hotkeys_js. See enqueue_comment_hotkeys_js().
Default - 'false' - use_ssl(string/bool)
- Whether the user should always log in via https.
Default - 'false' - show_admin_bar_front(string)
- Whether to show the admin bar on the site or not.
Default - 'true' - role(string)
- User role.
Default is taken from the settings: get_option('default_role') - locale(string)
- User's language (locale). For example: ru_RU. Since WP 4.7.
Default - '' - default_password_nag(true/false)
- true - means that the default password is set.
Also, the metadata contains Admin Panel Options — these are settings for admin pages and more. For example: saved choices of metaboxes on different pages.
| meta_key | meta_value |
|---|---|
| admin_color | midnight |
closedpostboxes_dashboard | a:0:{} |
|
| metaboxhidden_dashboard | a:4:{i:0;s:17:"dashboard_primary";i:1;s:24:"tinypng_dashboard_widget";i:2;s:18:"dashboard_activity";i:3;s:21:"dashboard_quick_press";} |
| closedpostboxes_{POST_TYPE} | a:1:{i:0;s:11:"commentsdiv";} |
| metaboxhidden_{POST_TYPE} | a:3:{i:0;s:7:"slugdiv";i:1;s:13:"trackbacksdiv";i:2;s:11:"commentsdiv";} |
| meta-box-order_dashboard | |
| meta-box-order_{POST_TYPE} | |
| meta-box-order | |
| wp_media_library_mode | Can be: list or grid. See upload.php |
| show_welcome_panel | 0 |
| show_admin_bar_front | true |
| wp_user-settings deprecated: wp_usersettings |
editor=tinymce&editor_expand=off&libraryContent=browse&dtmenuRight=1&mfold=o&posts_list_mode=list |
| wp_user-settings-time deprecated: wp_usersettingstime |
1604820217 |
| dismissed_wp_pointers | Various notes that need to be shown to the user in the admin panel. Can store the following keys: theme_editor_notice,wp330_toolbar,wp330_media_uploader,wp330_saving_widgets,wp340_customize_current_theme_link,wp340_choose_image_from_library,wp350_media,wp360_revisions,wp360_locks,wp390_widgets,wp410_dfw,wp496_privacy |
| {PAGE_KEY}_per_page | On WP_List_Table pages, how many items to display in the table. Examples of option names: edit_post_per_page, users_per_page, edit_comments_per_page, upload_per_page |
User Roles and Capabilities
User Role Editor - a plugin for managing roles. WordPress user role editor, the plugin allows easy modification of user roles and capabilities.
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;
PHP Functions
See the full list of functions here. Here are some of the functions:
| current_user_can() | Whether the current user has a specific capability. |
| wp_get_current_user() | Retrieve the current authorized user data (WP_User object). Sets current user, if not set yet. |
| get_current_user_id() | Get the current user's ID. |
| is_user_logged_in() | Checks if the user is authorized (if the user has logged in with their username). Returns true if the user is authorized and false if not. Conditional tag. |
| get_userdata() | Retrieve user data by user ID as WP_User object. |
| get_user_by() | Gets the user by the specified field and the value of this field (by ID, login, mail). |
| get_users() | Gets users according to the passed parameters. |
| update_user_meta() | Updates the meta-field of the specified user. |
| get_user_meta() | Gets an single meta field or all meta fields of the specified user. |
| delete_user_meta() | Deletes the specified meta-data of a certain user. |
| map_meta_cap() | Translates the given meta-capability into a primitive capability so that the user's access can then be checked. |
| wp_insert_user() | Creates a WordPress user in the Database. |
| wp_update_user() | Update a user data in the database. Work with both tables wp_usermeta and wp_users. |
| wp_create_user() | A simpler way of inserting a user into the database. |
| register_new_user() | Registers a new user. Only the login and email are specified. |
| wp_login_url() | Gets the login/authentication page URL: /wp-login.php |
| wp_signon() | Authorizes the user by the specified login/email, password, and remember parameter. |
| wp_set_password() | Updates the user's password with a new encrypted one. Updates the specified password in the database and resets the user's cache. |
| wp_check_password() | Checks the plaintext password against the encrypted Password. |
| WP_User::add_cap() | Adds or removes the right (ability) for the specified user. |
User Authorization (Setting) Process
To set the current user in the core, the following functions are hooked onto the determine_current_user hook. Each of them sets the current user for different types of requests (front, REST request).
add_filter( 'determine_current_user', 'wp_validate_auth_cookie' ); add_filter( 'determine_current_user', 'wp_validate_logged_in_cookie', 20 ); add_filter( 'determine_current_user', 'wp_validate_application_password', 20 );
The hook determine_current_user is triggered upon the first call of the function wp_get_current_user(), which is based on the function _wp_get_current_user().
_wp_get_current_user() sets the current user in the global variable $current_user upon the first call and retrieves data from there on subsequent calls.
The earliest the function wp_get_current_user() can be called is the plugins_loaded event (preferably with a high priority, so it runs at the end), i.e., after all plugins are loaded and their basic initialization is completed.
In general, it is recommended to call it on the init hook, i.e., after the core and all plugins are loaded and their basic code is executed, and the next step is to display data on the screen.