WordPress Roles and Capabilities Explained (Plus Code-Based Tweaks)

WordPress Roles and Capabilities Explained (Plus Code-Based Tweaks)

You know how you can log in to a WordPress site as an author and then not delete others’ posts or manage core website stuff like themes and plugins?

The amazingly useful system that manages all this is called roles and capabilities and we’re going to explore it in more detail in this Weekend WordPress Project, including some code-based fixes you can make to tailor role and capabilities to meet the needs of your site.

What Are Roles and Capabilities?

This WordPress sub-system is responsible for determining what actions any given user of a website can take. This decreases clutter in the dashboard (authors/contributors won’t see many menu items) and also increases security by simply not allowing some actions for some users.

The system is much more than just a way to hide items. On the UI side of things, all you may notice is that the “move to trash” link is missing. However, if you were to visit the URL of this link you would still not be able to delete a post as your permissions or checked before an action is taken. This prevents intentional wrongdoing and unintentional harm as well.

Capabilities

Capabilities are the building blocks of the system: they determine the actions a user is allowed to take. For example, all administrators have the publish_pages capability. This allows them to publish a page (no real surprise there). Other groups like authors or subscribers do not have this capability, hence they cannot publish posts.

There are 50+ capabilities governing everything from managing plugins, posts, options, multisite networks and so on. We’ll look at using them later in this article.

Roles

Roles are simply capabilities grouped together into a package. When I referred to “other groups like authors” just now, what I really meant was “other roles.”

WordPress has six roles by default:

  • Super Admin
  • Administrator
  • Editor
  • Author
  • Contributor
  • Subscriber

These roles are all groupings of a specific set of capabilities. Subscribers only have the read capability, contributors also have delete_posts and edit_posts, which enables them to create/modify/delete their own posts.

The Benefits Of Roles and Capabilities

There are oh-so-many. This system is the backbone of WordPress’ user management and does a great job at separating user groups. So, on one hand we have the benefit of being able to work with our users efficiently.

The WordPress user management interface
The WordPress user management interface

This in turn allows us to manage a site’s contents better. Making sure that we give as little access as possible but as much as needed is the basis of a well-oiled and secure system. Editors don’t see theme and plugin options because they don’t need to – authors can’t delete others’ posts because they don’t need to. When an admin looks at someone’s role they immediately know what the user in question can and cannot do, making teamwork (and troubleshooting) much easier.

A subscriber's view of the WordPress admin
A subscriber’s view of the WordPress admin

Finally, the capabilities system has an immense security benefit, especially when coupled with the nonce system, which checks for intent as well as permissions. Whenever you perform any action, WordPress will check that you have the corresponding capability. If you do it uses nonces to check intent and if all is well the action is performed, otherwise you get an error message, something like the one below:

This is what happens when you're not allowed to do something but you try it anyway
This is what happens when you’re not allowed to do something, but you try it anyway

Let’s consider why nonces are also necessary. The link for deleting a post could look like this: http://wordpress.local/wp-admin/post.php?post=1&action=delete. If you visit the link as a logged in administrator the post will be deleted. If WordPress doesn’t check where you came from this could be a problem. I could simply post a link to delete the content of your website anywhere – if you click on it you’re in trouble. This is why capabilities are great for making sure you have the permissions to perform the action, but we need nonces to check intent as well. If you’d like to know more, check out our article on nonces.

Using Roles and Capabilities

When creating plugins and themes you may want to limit certain actions to roles. For example, if you create an SEO plugin, you may want to restrict its usage to authors, editors and admins. You would also want to restrict the main options to admins only. To make this happen you would use the current_user_can() function, or specific parameters of existing WordPress functions. Let’s take a look at both:

The example above shows how an additional top-level menu item can be added to the admin menu. The add_menu_page() function has a parameter for defining the capability required for seeing the menu item. In our case, it is manage_options, which means that by default, only admins will be able to see it.

You can test for capabilities yourself using the current_user_can() (or user_can()) functions. Let’s hide a delete link from view using this method:

Note that I used capabilities in both cases, even though it’s pretty obvious that what I’m really trying to do is just give administrators access. There are two reasons you should always use capabilities. One has to do with how the checking function is built. In some cases if you specify a role it will return true only for that role, not roles “above” it. See Trac ticket #22624 for more information.

The second reason has to do with the roles and caps (capabilities) architecture. Roles are completely arbitrary names assigned to a completely arbitrary list of capabilities. In fact, there is no real guarantee that an administrator will actually have the manage_options capability. WordPress does assign it by default but using code or plugins capabilities can be added/removed from roles or even specific users. This makes role-based code unstable so always use capabilities.

Creating Custom Roles

When building a larger scale application you may well need custom roles, perhaps just for grouping users separately. If you run your own ads across your site you may want to create a “company” role. Users belonging to that role may have a special capability that allows them to view a stats page displaying their ads’ performance.

The basic code for getting this done is the following: using the add_role() function we create a role and add the capabilities we would like the role to have to the third parameter. The first parameter is the name of the role, the second is the displayed title.

Since the add_role() function either creates the role or returns null if it exists you can safely use it anywhere in your code. That said, there really is no reason to run this function all the time and putting it in an activation hook is my preferred method of working with it. Take a look at a more advanced example below:

There are two differences. First of all, I’ve wrapped my code in an activation function. This only runs once when the plugin is activated and will create the role if it doesn’t exist.

Additionally, instead of writing down all the capabilities I want, I decided to copy the capability list of the author role and then add my unique one for viewing ad stats. To do this I used the get_role() function to retrieve the author role and I simply copied the capability list into the correct parameter of the add_role() function.

Our New Company Role
Our new company role in the profile section

A Note About User Levels

Before version 2.0 of WordPress (a long time ago) a user level system was used. In 2.0 it was replaced by the much-improved roles and capabilities system. This is where the level_x capability comes from in the code snippets above.

It’s not strictly necessary and I’m sure very few systems use it today. If you want to ensure maximum backward compatibility then do add it, you can find a handy guide in the Codex, or in the screenshot below. If you do not want to add user levels, make sure to indicate that your work is only compatible with version 2.0 and above.

User Levels In WordPress
The old user level system in WordPress

Adding Custom Capabilities

The previous examples have already shown how you can add capabilities to roles. We can simply pass a list to the add_role() function or use the add_cap() method on a role object. You can, however, add a capability to a single user as well.

To get this done we’ll need to use the add_role() method on a user object. Here’s a short example that shows you how.

Custom capabilities are extremely useful for managing user flows on your site, especially if you have a highly user-interactive application. You could run an ad server and have separate roles for ad buyers, ad sellers, account managers and so on. The ability to easily modify who can see/do what is a huge asset as a developer.

Role and Capability Plugins

  • Role Scoper

    Role scoper is for the anal-retentive managers, it gives you granular control over every aspect of your roles and capabilities. Mix-and-match to get any combination and set your permissions up just right. Try not to go overboard, lots of roles and caps mixed up can be a horrible sight!

  • Members

    Members – by Justin Tadlock – is essentially a front-end to the roles and capabilities system. It allows you to create roles and assign capabilities to them and manage all this in a proper user interface.

  • Capability Manager Enhanced

    Another frontend UI for the roles and capabilities module. It isn’t as popular as Members but still have a sizable 30,000+ active install count. It does pretty much everything you’d expect, you’ll be able to add/edit/modify roles and capabilities to your heart’s content.

    Interested in Capability Manager Enhanced?

Overview

The roles and capabilities system in WordPress is largely under-utilised even though it gives you tremendous benefits when it comes to user management. I hope this article gave you the push to get your hands dirty!

Remember not to go overboard. Creating a bunch of roles with dozens of capabilities is possible but you should always pause and think about what is best for the system as a whole. In general a couple of roles with a couple of capabilities should be enough to meet most needs.

Do you have a project that relies heavily on custom roles and capabilities? Do you particularly like or dislike how WordPress handles this? Let us know in the comments below.