Himanshu SharmaSoftware engineer
Let’s talk

WordPress · Lesson 11 of 45

Users, roles and capabilities

Manage WordPress users safely, understand the five default roles and their capabilities, give people the least access they need, and add a custom role.

12 minContentUpdated 23 October 2026

By the end of this lessonChoose the right role for each person, explain how capabilities control access, and manage users from the dashboard and WP-CLI.

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
<?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";
result
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_options

Reading 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:

bash
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,roles
result
Success: 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
<?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'
	);
}
result
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: no

current_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
<?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";
result
reviewer can moderate comments: yes
reviewer can publish: no

Roles 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.

Check yourself

1. Which role can write and publish their own posts but not edit other people's?
2. A freelance writer should submit drafts for your review. Which role fits?
3. How should code check whether the current user may change settings?
4. Why limit the number of administrators?