I have a situation where I am dynamically creating roles.

The $user object contains the roles that the user needs to create content for the $type in the example below. Theoretically, module_invoke below should not return false, but it is:

  global $user;
  // Got this from node.module (node_access)
  // No matter the type, this should return us the create permission.
    $module = node_get_types('module', $type);

    if ($module == 'node') {
      $module = 'node_content'; // Avoid function name collisions.
    }

     $access = module_invoke($module, 'access', 'create', $type, $user);
     ...
 

Access is denied. What happens in module_invoke where it would override the roles in the $user object?

This same exact code worked in 5.x, so I have to believe there is something that has changed in 6.x with module_invoke / $user.

Comments

somebodysysop’s picture

In the user_access() function, the static variable $perm is set to hold the permissions for the roles of a user.

Issuing this command: user_access('', NULL, TRUE); (http://api.drupal.org/api/function/user_access/6) will unset the $perm variable and allow it to reset with the permissions from the most current roles. My debug code indicates that it contains the correct permissions and the correct roles from the $user object.

However, when I issue:

module_invoke($module, 'access', 'create', $type, $user);

which, in the case of $module = 'node_content' will itself call user_access($permission, $user),
the $perm value is now set (as it should be from my reset command), but no longer contains the permissions from all roles from the $user object (what was originally set); it now only contains the ones from roles you would find for the user in the role table. Furthermore, I put debug code into user_access() to show me each time it is ran. I do not see it accessed between the time $perm is unset (by my reset command) and it is called by module_invoke().

The way this worked in 5.x:

hook_init() or hook_user('load') would issue user_access('', NULL, TRUE) which would unset the $perm variable so that the next time user_access() ran, it would rebuild $perm. In 6.x appears this no longer works in the same way.

So, it looks like either:

a. Another module (other than the user.module) is manipulating the $perm variable, or;
b. Drupal core is assuring, when module_invoke() is used, that the set $perm variable only contains permissions for roles that the user has in the roles table.

My question is this: Can the $perm variable be manipulated outside of the user.module? If not, then how is b. above accomplished?

Thanks for any assistance whatsoever!

somebodysysop’s picture

I've written a bunch of debug code in the user, node and ogur modules and now have more details. I am printing the output of user_access every time it is called.

When I issue:

user_access('ClearCache', NULL, TRUE)

Static $perm variable is cleared and re-filled with permissions from current $user object. This is correct.

When module_invoke is immediately executed next:

module_invoke('node_content', 'access', 'create', 'story', $user)

This will now execute another call to user_access:

user_access('create story content', $user)

The $user object still contains the same roles. The $perm variable now contains values. But the values in $perm are NOT the same as those inserted during the ClearCache call above! They have changed, and NOT from the user_access function (which I am monitoring)! So the question is: Why has this $perm value changed?

So far, I've found this behaviour occurs with OGUR when one of the following is installed:

taxonomy_access
tac_lite
menu_breadcrumb
admin_menu

I so far am unable to discover what it is about these modules which is causing this problem.

This did not occur in 5.x and earlier 6.x versions of Drupal.

Please, please, please help!

somebodysysop’s picture

Bug in user_access function: http://drupal.org/node/329646

This bug prevents the reset mechanism from working properly. Resolved in 6.x with this patch: http://drupal.org/files/issues/329646-user-module-reset-d6.patch