 So I've no idea how many of you are in the room because these lights are a bit bright But it sounds like there's quite a few of you and first of all apologies if you did expect to see tar Dunbar up here talking about React and JavaScript and stuff. Unfortunately. He's stuck in the US and he couldn't make it but hopefully There'll be some stuff in my talk that you'll find interesting so Let's take it away. So I Am John Blackburn. I'm one of the WordPress core developers I've been working with WordPress for something like 12 years now. It sounds like quite a long time in web development terms I'm a senior engineer at human made which is one of the WordPress dot-com VIP partner agencies Work over in UK if you want to follow me on Twitter or get hub or wordpress.org Or whatever you can do that at John billion and I'll tweet my slides out and Answer any questions that you've got afterwards So I'm going to start by giving some background on the user roles and capabilities API in WordPress and then a little later on in my talk. I'll go into some good technical detail about what you can do with the API So most of you are probably aware of the default roles in WordPress We've got the administrator role editors authors contributors and Subscribers, but there are actually two kind of pseudo roles as well in WordPress that a user can have and the first is Super admin, so if you're running WordPress multi-site A user can be a super administrator and this means the user can do anything on any site right across the network But the important thing to remember Here is that a super admin is not actually a role It's a flag that gets set in the user meta against the user account So when a user is a super administrator, they actually bypass all of the usual roles and capabilities checks in WordPress because a super admin can do everything and A user can actually have no role in WordPress even though the user account still exists This sounds like something that might not be very useful But it can be useful for example when you need to remove a user from the site without actually deleting their user account so in the admin area here in WordPress When you're editing a user the little drop down to control a user's role has an option at the bottom to select No role for this site Although they may seem it roles in WordPress aren't actually Hierarchical from a technical point of view. So this is the roles and capabilities page from the WordPress codex The default roles in WordPress kind of are hierarchical But purely from a technical point of view, they aren't actually hierarchical and let's find out why that's the case if we think about roles capabilities and Responsibilities for example, what are the responsibilities of each role in WordPress? We can start to see how the API isn't hierarchical So what are the responsibilities of the roles in WordPress? Well, the responsibility of an administrator is to administer the site. They can do pretty much anything on the site An editor or their responsibility is to edit all of the content on the site An author their responsibility is to edit just their own content because an author can't edit other users content Contributor their responsibility is to contribute proposals. They can't publish content live to the website and A subscriber well a subscriber doesn't really have any responsibilities. They just exist Now in WordPress a user can actually have more than one role at the same time It doesn't actually make much sense with the default roles for example If a user had the role of both an editor and an author it wouldn't make any sense because the capabilities of an author are Just a subset of the capabilities of an editor But if we start to think about custom roles that a plug-in might provide We might be able to see how having more than one role at the same time makes sense So these two roles here a comment moderator and an employee manager. They have two very distinct Responsibilities a comment moderators responsibilities Are to moderate comments and an employee manager or maybe their responsibility is just to manage all of the users on the site So you can see how it would make sense for a user to have both of these roles at the same time because they are very distinct responsibilities So let's take a look at this in a real world plug-in BB press is a popular Plug-in for wordpress for providing forums functionality actually provide actually powers the support forums on wordpress.org And BB press provides some custom roles specifically for the forums We've got a key master their responsibility is For managing the forums as a whole kind of like an administrator's responsibility is to manage the website as a whole Moderator will their responsibility is to moderate all of the discussion on the forums Participant this is a role given to users who are participating in discussion on the forums and a spectator Doesn't really have any responsibilities This is just a role that's given to users who follow the topic without actually participating in it So with BB press installed on our site We could see how it would make sense for a user to be both an author and a forum Moderator at the same time because as I've said they're very distinct roles with distinct responsibilities and BB press provides a nice user interface for for this in wordpress When you're editing a user you can select the role of the user on the site as a whole for example here The user has got a role of author and then their forum role is a moderator But this is just a better user interface to the fact that the user has two roles on the site at the same time There's a really nice plug-in by Justin tadlock called members which provides the same functionality It changes that drop-down Into a list of checkboxes so you can check multiple roles for users and here We've got a user who is both an author and an events manager because again those roles those roles provide very distinct responsibilities So if we bear this in mind roles capabilities and responsibilities We can get a really good understanding of how powerful the roles and capabilities API is in wordpress So let's look at capabilities. Well The capabilities determine whether or not a user can perform a given function and most of the time We use it with the current user can function for example current user can edit posts manage options upload files There's a system function to this called user can and it takes a user ID So if you need to check the capabilities of a user who isn't the current logged in user You can do that by passing the user ID to the user can function please Don't do this as I've just talked about respect a distinct Responsibilities for a role make the whole roles and capabilities the API really powerful if you start checking for users roles Instead of their capabilities the whole kind of system Breaks down you should instead check for distinct capabilities The reason or one of the reasons for this is that if you're using WordPress multi-site and a user is a super administrator Super admin can do anything on any site on the network They might not actually have the role of administrator on all of the individual sites on the network So this just falls down So don't do this I think actually in WordPress 4.8 We managed to put in a doing it wrong notice if you now check for a role instead of a capability So if you see that warning coming up in your code from WordPress 4.8, you'll know that's the reason so switch over to doing capability checks instead Back in the day back in up to WordPress 2.0 I think WordPress didn't really have a powerful roles and capabilities API. I just used user levels So a user was you know level one level five level ten whatever If you're still using these levels in your code You're doing it very very wrong and your years and years out of date and you'll see some doing it wrong notices there as well So if you do see these levels it's a very old system But of course because WordPress is so committed to backwards compatibility. This still actually Does work even in WordPress 4.8? So how does the capability system in WordPress work well in this example here edit post It's not actually a capability that any user or any user role in WordPress Will have the singular form of edit post doesn't exist So what is this? Well, this is a meta capability WordPress maps meta capabilities to the primitive capabilities that a user actually has based on the context And in this case the context is the post ID The function that handles this is called map meta cap it handles mapping of meta capabilities such as edit post and the post ID To the primitive capabilities that are actually required of the user in order to be able to perform the action in This case edit others posts if you're trying to edit the post that belongs to another user So let's take a look and see how this works Here we're calling current user can edit post on a particular post ID The first thing that map meta cap does is to check to see whether the post even exists If it doesn't what map meta cap does is it adds do not allow To the array of required capabilities to perform that action now Do not allow is a very special capability that no user in WordPress can have So by adding this to the array of required Capabilities to perform that action it prevents the user from being able to perform the action because it doesn't make sense That if a post doesn't exist that user would be able to edit it or delete it or publish it Little further down map meta cap We'll check to see if the current user is the author of the post And if the post is published then one of the required capabilities to edit that post is edit published posts If the post isn't published then the required capability becomes edit posts for example for draft posts or scheduled posts However, if the user is not the author of the post then The required capabilities are a little bit different. For example, if you're trying to edit someone else's post You need the edit others posts capability now where this surface is itself in WordPress is that editors and Administrators can edit the posts that belong to other users But lower level roles such as authors and contributors can't edit other users posts Even though they can edit their own. So this is where map meta cap maps those capabilities in addition to that then we Require the edit published posts capability if the post is published and if it's private edit private posts so current user can edit post post ID if We are trying to edit another user's published posts and the actual required capabilities become edit published posts and Edit others posts whereas if we're just trying to edit for example our own draft post Then the only capability that's required is edit posts So from that one single meta capability called edit post map meta cap maps all of the required primitive capabilities for that context for that post ID Matt meta cap doesn't handle just posts of course. It handles all of the capability checks So here we're going to do a capability check for delete user and a user ID The only check that's done here is a multi site related check So for example on multi site a regular administrator can't delete a user So here we'll do a check for his multi site And if the user isn't a super admin then we'll block this Ability to delete the user by adding do not allow to the array of required capabilities If we're not using multi site or the user is a super admin Then we just require the delete user's capability and by default in WordPress. That is assigned to just administrators So Matt meta cap is a really powerful function It's kind of a gatekeeper to roles and capabilities in WordPress. It handles the mapping of meta capabilities to primitive capabilities, but Most interesting part of this function is the very last line There's a filter at the end of this function called map meta cap. This opens up a whole world of possibilities Probably actually this filter is probably the most powerful filter in WordPress because it allows you to completely change the way that Users can perform actions in WordPress and We'll take an exam. We'll take a look at some examples in a moment. So this filter Includes the first parameter includes a list of the capabilities that are required to perform the current capability check The meta capability that was passed in such as edit post passes in the current user ID and it passes in Any context that you've provided and in this case, it would be the post ID So let's see what we can do with this. Well here. I've added a call back to the map meta cap filter The required capabilities for this check get passed in as a first parameter and what we're doing here is we're checking to see if Delete term is the current capability check and if it is we can do something for example Like preventing a user from deleting a protected term So if we had a plug-in that added a protected flag to the term meta All we need to do is add do not allow to the list of required capabilities for this action and This prevents the current user from being able to delete the term that we're trying to delete and We need to remember to return the required caps at the end of this function Otherwise will accidentally allow every user to do everything on the whole of the network. So that's an important line So with these few lines of code we don't need to deal with hiding delete links in the admin area We don't need to override form handlers or Ajax handlers or anything like that because Throughout WordPress the current user can checks are used at multiple stages to make sure a user can do the action They're trying to do so this is all we need to do to prevent the user from being able to delete a given term Just five lines of code really powerful filter Let's introduce some lady luck into the admin area here. We've got a Function that rolls a virtual dice if the dice lands on three then the user is allowed to publish a post If it doesn't sorry, you're out of luck. You need to Try and roll that dice again to see if you can publish the post Important thing to know here as well as if the dice does land on three then there's no special handling needed It just falls back to returning the required capabilities and the user can publish it just as normal the Mat meta cap filter though it can be used to grant capabilities as well as taking them away all of the examples I've given so far We've just added the do not allow capability into the list of required capabilities Here what we're doing is allowing Users to upload files so a contributor Role in WordPress a user with a role of contributor Although they can submit posts. They can't actually upload files into that So they can't add images and things to a post but we can enable this quite easily with the mat meta cap filter so we'll Check to see if upload files is the current capability check And if it is what we'll do is we'll override the complete array of required capabilities and we'll just replace it with an array containing edit posts Well, this means is any user who has the edit posts capability is now able to upload files whether that is a Contributor or a custom role doesn't matter and again just three four lines of code in there So that's the map meta cap filter as I said probably the most powerful filter in WordPress You use this filter to alter the required primitive capabilities for a capability check There's also another filter called a user has cap is equally as powerful And what this filter does is this allows you to control the actual capabilities that a user has at runtime It gets passed in the array of capabilities that the user has An array of the capabilities that are required for the current check And any arguments which is the context such as the post ID? So let's see what we can do with this This is some code from a plug-in of mine called user switching It's a plug-in which allows you to immediately switch between different user accounts in WordPress and in this plug-in I have a capability called switch to user It looks like a regular capability in WordPress, but I've got handling in this Current in this user has cap filter here, which maps the switch to user capability to another Capability so for example here We're checking to see if switch to user is the capability that's being checked if it is will grant the switch to user capability Based on whether the user can edit the user they're trying to switch to so in user switching You can only switch to a user if you can edit that user So we'll just map those capabilities with one another In addition as well, you can't switch to your own user account So there's just some logic in here to check for that and then We will return the user caps array at the end of this function so Again, not a lot of code to fundamentally change the way that the capability system in WordPress is used It's important to remember that even if you don't understand this particular example These filters are very powerful and they allow you to do quite a lot with not a lot of code So the mat meta cap filter allows you to alter the required capabilities for a given capability check and Has and user has cap allows you to filter the actual capabilities that a user has in order to perform a given check So as a recap then we've covered roles and responsibilities of the roles We've covered the capabilities and the way that you can alter those capabilities in WordPress I've covered the map meta cap filter and the user has cap filter and I'm gonna wrap up with some trivia about the roles and capabilities API so Non logged in users current user can do something this works for all logged in users if they've got the do capability But we've got any special capability here called exist The difference with exist is that any user can Exist even if they're not logged in now if you go and look inside the current user can function It looks like there's some code in there that prevents a user from being able to exist if they don't log in However, it doesn't actually work and it hasn't worked for the whole 12 years that that code has been in place This introduces some interest in functionality Buddy press the buddy press applied again actually makes use of this In a bit of a roundabout way to determine whether a user is logged in So the only reason I'm mentioning this is is in case you end up building some custom front-end Functionality on your site and your checking current user can exist You also need to ensure that the user is logged in with is user logged in Otherwise you'll get some false positives and if you go digging around in the code you'll understand why it doesn't work There's a bit of a push at the moment in wordpress to introduce more granular Capabilities so for example here. We've got these meta capabilities called edit user. You pass the user ID Delete post where you pass the post ID But you can't currently do this for things such as themes plugins and sites The the capabilities are more generic in that edit themes activate plugins deactivate plugins so hopefully in a Future version of wordpress. We'll have more granular capabilities So you'll be able to control whether or not a user can activate or deactivate Individual plugins based on the plugin name or whether they can archive or delete or restore sites on a network based on the site ID So all of this is is ongoing and we managed to introduce more granular capabilities for Taxonomy terms back in wordpress 4.7 and this is an ongoing push to do that a bit further Also for widgets and sidebars and menus and comments and all of that hopefully we'll get some much more granular control in place if you want to Understand exactly what capabilities every role in wordpress has you can go to the roles and capabilities page on the codex But you really really want to understand it There's actually a class in the wordpress tests we called tests user Capabilities in this for every single capability in wordpress it lists all of the roles that can do that capability It also means that as we make changes to wordpress core itself We can be assured that we don't accidentally Introduce the ability for a role to perform an action that they shouldn't be able to perform So if you're interested in All of the capabilities that a role can perform go and take a look at this class called tests user capabilities And it's all mapped out there for you. I'm a little bit ahead of time. So that's it for me. Are there any questions? Yeah, we've got someone coming here Hi Martin. Hey. Hello, John. I enjoyed your presentation Could you please go back to the slide with? Current user can do and something. Yeah Yeah, my question about that is that if you recommend not relying on the last function Which is there which is just easy user logged in because I use that one In some cases. So should I instead use the current user can? so Ideally if you just need to know that a user is logged in and you don't care about their capabilities, then you can just use Is user logged in? the point really is is If you were to go and look inside the current user can function You'll see this exist right there as one of the kind of first lines of code So you might think oh, I can use that instead of using is a user logged in but it doesn't quite work as you would expect As I mentioned buddy press has got some strange behavior around actually utilizing the exist capability So yeah, if you don't care about the capabilities of user You just need to know that they logged in or not you can just use is use a logged in and just forget about the exist Thing altogether. Yeah. Oh, yeah, that's enough for me. Thank you. Sure. Thanks So hi John hi John I'm slava from Ukraine and I have actually two questions one of them is small and the other one might be not very small so regarding the Capabilities and meta capabilities. Why are they are so complicated which when we have a Real capability and not real capability which is then mapped Further is it done on purpose or is it just a legacy for? From the 10 more than 10 years work of development Yeah, it's just done on purpose to confuse everyone. I think That explains a lot. Let's have a look So, um, so let's Let's take a look at a better example and lost in my slides here. I don't mind. I'll talk anyway. Um, so So imagine a situation where you have You have a post and you're trying to determine whether the user can edit that post or not if we didn't have meta capabilities You would actually have to perform a bunch of checks at that time So you would have to know whether the post is published You'd have to know whether the post is Private you would have to know whether the current user is the author of the post You have to know whether the current user has the ability to edit published posts Whether the user has the ability to edit other users posts whether they have the ability to edit private posts So the idea of the meta capabilities is it abstracts all the way that complexity to you So all you need to do is call current user can edit post and all of the complexity around whether it's published or Whether the user has ability to edit published posts or other users post kind of handled behind the scenes for you so If we didn't have meta capabilities You would you would have to kind of account for that every single time you're trying to determine whether a user could edit a post and it would also mean that Maybe some point down the road where WordPress introduces a whole kind of new concept to posts Maybe a new post status for example We can introduce that and hide away all that complexity in that meta cap And you still only need to use the edit post capability You don't need to kind of concern yourself with all of the underlying capabilities of users. Does that make sense? Yeah, I think so. Thank you And the other one smallish one is regarding the splitting some capabilities into several one because for example for taxonomies We have managed taxonomy managed term capability, but there is no one Create term Edit term they exist edit term, but no create term So for example, it's not very easy to allow editing and deleting but do not allow creating Yeah, so is it possible and when it will be implemented? Yeah, you're exactly right So we've got we've got capabilities for edit term delete term Assign term But we don't have the create term capability currently There is a ticket open on WordPress track to introduce create term capability. That's I who created the ticket, right? So yeah, I'd love to get that in and and that kind of falls under the umbrella of Making all of the terms much more granular So if it's not in the 4.9 milestone, then I'll go and move it in and hopefully we can we can get that in Yep Thank you. Thank you Chat here. Hi, my name is Jeffrey from the Netherlands I was wondering let's say there's a plug-in in your WP admin that gives users access to a certain page That has a hard-coded user can manage options check Is there any? Possibility to grant a user with or without your the filters you just mentioned to grant users access to that page without actually granting them the managed options Yes, but it would potentially have Some sort of unexpected side effects, I guess So we can see here where we're We've got the mat meta cap filter and all of the kind of context is passed in What we're doing here like for example for the delete term capability Up here. We're adding the do not allow capability what you could do is You could do a check and look to see if manage options is the current capability that's being checked and Also add some additional check there For example, are we looking at the current page that the user that you that you're talking about maybe look at the page ID or the slug or whatever and then you could actually grant the manage options capability here by Passing in something such as edit post and what that would mean that that particular call to current user can manage options on That particular page you are actually granting the manage options capability to a user who can edit posts for example So that would that would kind of work, but you also need to bear in mind that for the For that page load the user has got the manage options capability effectively So you might see Some side effects, you know, there might be some edit links or links to setting screens or whatever so ideally That particular plug-in would use a custom capability such as my example They were switched to user and it would map switch to user to manage options And it would allow you to override it much more easily You know, you've got a much more granular kind of capability check there So if that's not one of your plugins like if that's the third party plug-in You could maybe go to the plug-in author and recommend that they use a custom capability there and map it using the map Meta cap filter Thank you very much. Okay Over here. Yes. Hey, hi, my name is Lawrence from Holland. Okay, step forward to Mike a bit this this much Yep, okay. My name is Lawrence from Holland and I'm thanking you for your talk And you showed that it's possible to grant upload files capability by for example doing edit posts There has been a discussion by some developers, I think there's a ticket for it to grant Or to create the edit attachments Capability because it doesn't exist yet. It's attachments are currently considered posts. Yep, not Objects on their own and would you suggest developers that want to Distinguish posts from attachments to check the post type in such filters or is there any time Coming an end to that discussion and will be integrated in core Yeah, so As you pointed out So this is kind of some code pseudo code from the map meta cap function It looks that like if the post Exists but as you said that if you're trying to edit an attachment it There's there's no Distinct capability collect edit attachments or publish attachments or whatever if you need Now if you need to Restrict the ability for users to edit attachments and disconnect that from posts you could use the Map meta cap filters and as you said look at the post type and then do whatever logic you need to do to determine whether Are you just should be able to edit attachments or not? I think maybe a precursor to that a precursor to having that in core is The attachments status API So in a in WordPress core an attachment doesn't have a status You know we haven't got draft and published and things like that and attachment either exists or it doesn't If we introduce a status API to attachments Then we can start to put in some real fine-grained controls for whether a user should be able to create Edit delete publish attachments based on its status, but yeah for now if you need to Restrict the ability for a user to you know mess for attachments You can look at the post type and it will be attachment and then you can do any logic you need to do there and Return do not allow or any other capability that you think is appropriate. Okay. Thank you. Okay Last minute question Sorry John one more question Because you showed several two at least the hard-coded capabilities that Do not allow and exist the question is actually are they Written somewhere in the codex or handbook and if not which are which others capabilities They cha we which are hard-coded exist That does exist. Yeah a good question Off the top my head they are the only two kind of special capabilities Exist So in the map meta cap function when you get right down to the bottom of the function and the filter has already run after that filter That's where the exist capability is handled. So it all users will always be able to exist They do not allow Coincidentally wasn't enforced until Contribute a day on Thursday when I added some code in which does ensure that a user cannot ever have the do not allow Capabilities, so those are the only two off the top of my head that are kind of special case capabilities Whether or not they're documented anywhere Good question They should be on the codex page for roles and capabilities if they're not then Maybe someone can go in and add add them there Okay, thank you. Hopefully this will be done by someone. Yeah, someone not me I Everyone with the wordpress.org account can modify codex pages exactly. Yeah. Yeah Okay, any more questions. I don't see any more questions. That's it. Thank you very much. Give him a big applause