4.6.x user.module user_access($string, $account = NULL)
4.7.x user.module user_access($string, $account = NULL)
5.x user.module user_access($string, $account = NULL)
6.x user.module user_access($string, $account = NULL, $reset = FALSE)
7.x user.module user_access($string, $account = NULL)

Determine whether the user has a given privilege.


$string: The permission, such as "administer nodes", being checked for.

$account: (optional) The account to check, if not given use currently logged in user.

Return value

Boolean TRUE if the user has the requested permission.

All permission checks in Drupal should go through this function. This way, we guarantee consistent behavior, and ensure that the superuser can perform all actions.

67 calls to user_access()
authorize_access_allowed in ./authorize.php
Determines if the current user is allowed to run authorize.php.
block_admin_configure in modules/block/block.admin.inc
Form constructor for the block configuration form.
blog_page_user_access in modules/blog/blog.module
Access callback for user blog pages.
book_form_node_form_alter in modules/book/book.module
Implements hook_form_BASE_FORM_ID_alter() for node_form().
comment_access in modules/comment/comment.module
Determines whether the current user has access to a particular comment.

... See full list

10 string references to 'user_access'
field_ui_menu in modules/field_ui/field_ui.module
Implements hook_menu().
menu_menu in modules/menu/menu.module
Implements hook_menu().
statistics_menu in modules/statistics/statistics.module
Implements hook_menu().
UserPermissionsTestCase::testUserPermissionChanges in modules/user/user.test
Change user permissions and check user_access().
user_menu in modules/user/user.module
Implements hook_menu().

... See full list


modules/user/user.module, line 798
Enables the user registration and login system.


function user_access($string, $account = NULL) {
  global $user;
  if (!isset($account)) {
    $account = $user;

  // User #1 has all privileges:
  if ($account->uid == 1) {
    return TRUE;

  // To reduce the number of SQL queries, we cache the user's permissions
  // in a static variable.
  // Use the advanced drupal_static() pattern, since this is called very often.
  static $drupal_static_fast;
  if (!isset($drupal_static_fast)) {
    $drupal_static_fast['perm'] =& drupal_static(__FUNCTION__);
  $perm =& $drupal_static_fast['perm'];
  if (!isset($perm[$account->uid])) {
    $role_permissions = user_role_permissions($account->roles);
    $perms = array();
    foreach ($role_permissions as $one_role) {
      $perms += $one_role;
    $perm[$account->uid] = $perms;
  return isset($perm[$account->uid][$string]);


traviss359’s picture

It should be noted that any permission string entered into this function should be all lowercase. If one were to copy and paste a permission from the admin/people/permissions page that included an uppercase first letter, then the function will return false.

jpvivere’s picture

The actual string to be entered in to the user_access() function is the array index (a string) defined in each module's hook_permission() function. In the case of the user module, these indexes are indeed an exact lowercase copy of the title shown on the permissions admin page, but using the lowercase version of the permissions admin page may be a good guess, but shouldn't be the rule.

Instead, just open the module's .module file and look for the hook_permission() function to be sure.

Snippet of the user_permission() function...

function user_permission() {
  return array(
    'administer permissions' =>  array(
      'title' => t('Administer permissions'),
      'restrict access' => TRUE,
    'administer users' => array(
      'title' => t('Administer users'),
      'restrict access' => TRUE,
brian_c’s picture

Personally I just inspect the checkbox on the Permissions page and see what its value is.

Much easier than digging up the actual code that created it.

thomas_rendleman Go to Django for a better experience.’s picture

I just used user access for the first time.
I installed devel.
admin/config/development/devel turn on Display $page array
admin/people/permissions click on the array box (screen top)
This array box area expands to give you the correct name for the user access permissions. Notice that the names don't always match the rule of lowercase. See block IP addresses.

array >> content > system main > permission

Purplemonkey’s picture

If you want to find a permission you can look in admin/people/permissions but they will not relate directly, for example I wanted the permission "Basic page: Edit own content" but to use as an argument for user_access I'd use "edit own page content". I discovered this by dumping the users roles to my webpage by doing

$roles = array(2=>'2'); // 2 = the role ID, which is passed as the Key.
$check = user_role_permissions($roles)
print ('');

aaronaverill’s picture

SELECT r.name,p.module,p.permission FROM role_permission p
left join role r on p.rid=r.rid
order by name,module, permission

3rd column is what you are looking for.

cdmo’s picture

Thanks for the select statement.

BeachsidePaul’s picture

Easily found my mistake thanks to this simple little chunk of code ... thanks again!

Liviu’s picture

Nice one, thank you for this!

pfrenssen’s picture

You can get full information about available hooks in the terminal by invoking hook_permission(). This is useful because you can grep the output for what you need.

$ drush eval "var_dump(module_invoke_all('permission'))"
mralexho’s picture

Thanks for this. Very helpful ;)

a.ross’s picture

You can also inspect the corresponding checkbox. It's value attribute contains the permission's machine name.

a_thakur’s picture

How to use $account parameter while implementing hook_menu.

For example
/** Implement hook_menu **/
function abc_menu() {
$items['user/%user_uid_optional/content'] = array(
'title' => 'abc',
'access callback' => 'user_access',
'access arguments' => array('administer content', 1),
'type' => MENU_LOCAL_TASK,


Am i on the right track as i want to load the user in case the load is not logged in. So I am not really sure about the second argument. According to online resources "1" in access arguments would be the wildcard in the menu.


technicalknockout’s picture

You only need to pass in a user argument if you intend to not use the current user. The parameters description above maybe is a little unclear since the phrase 'currently logged in user' does not explain what happens when a user is not logged in. In this case, the line <?php global $user; ?> loads a user account with id 0. Sounds like you'd be fine with:

'access arguments' => array('administer content'), 
Brian.Harris’s picture

It's also important to note that in Drupal 7, the argument is 'administer nodes', not 'administer content'

'access arguments' => array('administer nodes'), 
DrupalGideon’s picture

I needed to add a role to the Anonymous user to allow them to access certain content under certain conditions. In order to get this working, I needed to run


after adding the role. Very useful function.

wjaspers’s picture

I'm curious, why doesn't this function have an alter hook available for it?
Then module could override/extend functionality.

function user_access($string, $account = NULL) {
  $has_perm = isset($perm[$account->uid][$string]);
  drupal_alter('user_access', $string, $account, $has_perm);
  return $has_perm;
ppatriotis’s picture

I have a use case where this would help a lot.

I want the user to be able to "lock" the account, and only give rights to certain menu routings and disable all of the rest that are defined with the role. Once they unlock (using their password) they can get rights to everything again. This would be all within one user account, so the standard roles don't help.

westwesterson’s picture

I have submitted a patch for drupal 8.
if you want hook_user_access_alter() in drupal 8, review the patch here!!

pandubabu’s picture

I'm beginner to drupal world. I have created a page by graphical interface ( Add Content) to a menu link. Now i want to add php script to that page.
please let me know how to do it...

jnicola’s picture

Important things to note:

Permission titles for admin and regular users are not the same!

Boy that is annoying and non-sensical. Here's what I used to make it happen.

global $user;

if(user_access('case study: create new content') || user_access('create case_study content')){.......

Same permission, different checks. The first one is the lower case only example that works for admin. The second is the type that works for everyone.

The DPM is the way to see all available permission checks for a role.

codesidekick’s picture

I've written a simple tutorial of how to use user_access in combination with hook_permission on your site at http://interactivejunky.com/blog/user-permissions-drupal

wranvaud’s picture

Chi’s picture

netgenius.co.uk’s picture

A simple solution for testing if the current user has access to at least one of various permissions:

$permissions = array( 'permission1', 'permission2', ... );
$has_access = !empty( array_filter( $permissions, 'user_access' ));

And now, user has access to ALL of various permissions:

$permissions = array( 'permission1', 'permission2', ... );
$has_all = count(array_filter( $permissions, 'user_access' )) == count($permissions);
mr.j’s picture

The static caching used in this method (for both D6 and 7) is not optimal because it uses uid as a cache key, but the permissions only differ by role combinations. So if you have to look up permissions for say 20 users that all have the same roles, you still hit the database 20 times with the same query. If you're seeing that in your profiling its better to patch this function to use a combination of the role ids as the cache key.

Stevel’s picture

You may hit the user_role_permissions function 20 times, but that function has a cache per role, and uses a single query at most, so if your 20 users have the same roles, only 1 database query is executed in total. If 10 users have roles A B and C, and the other 10 have roles A B and D, 2 queries are run in total: one for roles A, B and C, and one for role D. Everything else uses cached results.