1

In my module:

function mymodule_menu() {
    $items['reports'] = array(
    'page callback' => 'reports',
    'type' => MENU_CALLBACK,
    'access arguments' => array('access content', 'hr functionality')
    );
    return $items;
}

function mymodule_permission() {
  return array(
    'hr functionality' => array(
      'title' => t('HR functionality'),
      'description' => t('Do things only HR are allowed to do.'),
    )
  );
}

I set HR to have "HR functionality" permissions. I logged in as a user with HR role, and I get access denied to my reports page. I tried clearing cache, etc. If I remove the "hr functionality" access argument it lets me in.

Even if I log in as admin, I get access denied.

What am I doing wrong here?

EDIT: The method I ended up writing per accepted answer:

function multiple_permission_callback() {
    global $user;
    $permissions = func_get_args();

    if (empty($permissions))
        return false;

    foreach ($permissions as $permission) {
      if (!user_access($permission, $user)) {
        return false;
      }
    }
    return true;
}
  • Nice solution :) One thing that might be worth mentioning...if the function is called with no arguments it will always return TRUE. That might not be the best security practice. It's an easy fix though, if (empty($permissions)) { return FALSE; } before the loop – Clive May 17 '12 at 21:19
  • Good suggestion. Added. – Joren May 17 '12 at 21:46
4

The default function for the access callback is user_access(), which has the following signature:

function user_access($string, $account = NULL)

This is the function that will receive your access arguments.

It only takes one permission string at a time, so the second string you're passing in is being used as the $account object. This will cause problems in the user_access() function and is probably why it's returning FALSE all the time.

If you want to test two permissions you could provide your own access callback:

function mymodule_menu() {
  $items['reports'] = array(
    'title' => 'Reports',
    'page callback' => 'reports',
    'type' => MENU_CALLBACK,
    'access callback' => 'mymodule_reports_access'
  );
  return $items;
}

// Potentially accept an account object to make the function more re-usable
function mymodule_reports_access($account = NULL) {
  if (!$account) {
    global $user;
    $account = $user;
  }

  return user_access('access content', $account) && user_access('hr functionality', $account);
}
  • This not only answered my current question, but one I had last week. Thanks! – Joren May 17 '12 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.