Users and roles
Everyone who logs in to a WordPress site is a user with a role. The role decides what they can do. WordPress has five roles on a normal site:
| Role | Can do |
|---|---|
| Administrator | everything: settings, themes, plugins, users, all content |
| Editor | publish and manage all posts and pages, including other people's; moderate comments |
| Author | write, publish and delete their own posts; upload files |
| Contributor | write and edit their own posts, but cannot publish or upload files; posts go to review |
| Subscriber | read content and manage their own profile |
On a multisite network there is also a Super Admin who manages all the sites.
Roles are bundles of capabilities
Behind each role is a list of capabilities: specific permissions such as edit_posts, publish_posts, upload_files or manage_options. Let's count them and test a few:
<?php
$caps = [ 'read', 'edit_posts', 'publish_posts', 'upload_files', 'edit_others_posts', 'manage_options' ];
printf( "%-14s %5s %s\n", 'role', 'caps', implode( ' ', array_map( fn( $c ) => str_pad( $c, 6 ), array_keys( $caps ) ) ) );
foreach ( wp_roles()->roles as $slug => $role ) {
$row = array_map( fn( $c ) => str_pad( empty( $role['capabilities'][ $c ] ) ? '-' : 'yes', 6 ), $caps );
printf( "%-14s %5d %s\n", $slug, count( array_filter( $role['capabilities'] ) ), implode( ' ', $row ) );
}
echo "\ncolumns: ", implode( ', ', array_map( fn( $i, $c ) => "$i=$c", array_keys( $caps ), $caps ) ), "\n";role caps 0 1 2 3 4 5
administrator 61 yes yes yes yes yes yes
editor 34 yes yes yes yes yes -
author 10 yes yes yes yes - -
contributor 5 yes yes - - - -
subscriber 2 yes - - - - -
columns: 0=read, 1=edit_posts, 2=publish_posts, 3=upload_files, 4=edit_others_posts, 5=manage_optionsReading across: only Contributors and up can edit_posts, only Authors and up can publish_posts and upload_files, only Editors and up can edit other people's posts, and only Administrators can manage_options (change settings).
Managing users
Users → Add New User creates an account; Users → All Users lists them, where you can change a role or delete a user. When you delete a user who wrote content, WordPress asks whether to delete their content or attribute it to another user; almost always choose the second.
With WP-CLI:
wp user create priya priya@example.com --role=editor --display_name="Priya Shah" --user_pass=a-long-unique-password
wp user create sam sam@example.com --role=contributor --user_pass=another-long-password
wp user list --fields=ID,user_login,display_name,rolesSuccess: Created user 2.
Success: Created user 3.
+----+------------+--------------+---------------+
| ID | user_login | display_name | roles |
+----+------------+--------------+---------------+
| 1 | admin | admin | administrator |
| 2 | priya | Priya Shah | editor |
| 3 | sam | sam | contributor |
+----+------------+--------------+---------------+Checking capabilities in code
When you write themes and plugins, check capabilities, never role names. A site may have customised roles, or a plugin may grant a capability to a role that normally lacks it:
<?php
foreach ( [ 'admin', 'priya', 'sam' ] as $login ) {
$user = get_user_by( 'login', $login );
wp_set_current_user( $user->ID );
printf( "%-6s publish: %-3s settings: %-3s edit post 1: %s\n",
$login,
current_user_can( 'publish_posts' ) ? 'yes' : 'no',
current_user_can( 'manage_options' ) ? 'yes' : 'no',
current_user_can( 'edit_post', 1 ) ? 'yes' : 'no'
);
}admin publish: yes settings: yes edit post 1: yes
priya publish: yes settings: no edit post 1: yes
sam publish: no settings: no edit post 1: nocurrent_user_can( 'edit_post', 1 ) is a meta capability: WordPress works out the answer for that specific post, considering who wrote it and its status. The editor can edit post 1 (written by admin); the contributor cannot.
A custom role
Sites sometimes need a role between the defaults, for example a Shop manager or a Reviewer who can read private content and moderate comments but not publish. Add one in a plugin's activation code, starting from an existing role's capabilities:
<?php
$contributor = get_role( 'contributor' );
add_role( 'reviewer', 'Reviewer', array_merge( $contributor->capabilities, [
'moderate_comments' => true,
'read_private_posts' => true,
] ) );
$reviewer = get_role( 'reviewer' );
echo "reviewer can moderate comments: ", $reviewer->has_cap( 'moderate_comments' ) ? 'yes' : 'no', "\n";
echo "reviewer can publish: ", $reviewer->has_cap( 'publish_posts' ) ? 'yes' : 'no', "\n";reviewer can moderate comments: yes
reviewer can publish: noRoles are saved in the database (the wp_user_roles option), so add_role() only needs to run once, typically when a plugin is activated, and remove_role() when it is uninstalled. Plugins such as Members or User Role Editor let you manage roles without code.
Least privilege
The safest rule: give each person the lowest role that lets them do their job.
- Writers who should be reviewed: Contributor.
- Trusted writers: Author.
- The person who runs the content: Editor.
- Only the people who manage plugins, themes and settings: Administrator, ideally one or two.
- Remove accounts that are no longer needed, such as a developer's after a project ends.
Every administrator account can install code on your site, so each one is a target for password guessing. Use strong unique passwords and two-factor authentication (a plugin adds it) for anyone with high access.
Common mistakes
- Making everyone an administrator because it is easier.
- Checking roles in code, such as
in_array( 'administrator', $user->roles ), instead of capabilities. - Deleting a user and their content by accident instead of reassigning it.
- Forgotten accounts of former staff or agencies.
Exercise
Your site has a marketing manager who writes and publishes everyone's blog posts and moderates comments, and two interns who should only submit drafts. Which roles do they get? Write the WP-CLI commands to create one of the interns.
Show one possible answer
The marketing manager is an Editor: they need to edit and publish other people's posts and moderate comments. The interns are Contributors, so their posts wait for review. For one intern: wp user create anil anil@example.com --role=contributor --display_name="Anil Kumar" --send-email (with --send-email, WordPress emails them a link to set their own password).
Key points
- Every user has a role: Administrator, Editor, Author, Contributor or Subscriber (plus Super Admin on multisite).
- Roles are bundles of capabilities such as edit_posts, publish_posts, edit_others_posts and manage_options.
- Give each person the lowest role that lets them do their job; keep administrators to a minimum.
- Code should check capabilities with current_user_can(), never role names.