You are here

Users Creating Users in Drupal

Corey Pennycuff's picture

One of the biggest mistakes that I feel that Drupal has made is that it is difficult for non-administrators to create accounts for other users.  While at first blush this seems appropriate, there are many, many valid reasons that users should be able to create accounts on behalf of other people.  The problem is that, in all versions of Drupal (at least 5-8) there is a call to drupal_goto() inside the form generation function that is executed unless the user has the "administer users" permission.

This is bad!  I actually feel that this is a defect, in that the code should not perform a redirect when generating a form!  Returning nothing would be much preferred!

That being said, I have had 3 sites in as many months that needed the functionality of one individual (not an administrator) creating an account for another user.  The general method presented here is not without difficulty, as you may have to do other altering of the form in order to get it to do everything that you want it to, but the code shown here will provide the basic functionality.

Other Resources

Before we go too far into custom coding, it is worth noting that there are several modules that can do some of this functionality.  I do not want to muddy the waters here, though, so I will point you to a blog post by Lowell Montgomery that does precisely that.  For my implementations, however, none of these solutions were fitting, so I had to use custom code.

Realize what needs to be done

Drupal will only generate a user registration form if:

  1. The user is anonymous and the site's settings allow for anonymous users to register their own account.
  2. The user has the "administer users" permission.

Failing either of these two situations, the form will perform a redirect, and you will not be a happy camper!

Potential Solutions

We have three possible courses of actions:

  1. Write a custom registration form.
  2. Trick Drupal into thinking that we are an anonymous user and render the form.
  3. Trick Drupal into thinking that we have "administer users" permission and render the form.

Of these potential solutions, I did not want to write a custom registration form, due to factors beyond the scope of this post.  In short, it would have been A LOT of work!  I also could not go the route of anonymous user because of site settings (which also could have been worked around by more code, but that is another issue).  That leaves us with only one option: faking an administrator account.

Plan of Attack

For this to work, we must do a few things.  First, we will provide a place for our form to be generated, such as a block or a menu callback.  Second, we must spoof the administrator access temporarily, generate the form, then fix any problems we may have caused.

Menu Callback

For the example code given here, we assume that a module named CUSTOM has been created.

/**
 * Implements hook_menu().
 */
function CUSTOM_menu() {
  $items = array();
  $items['custom_registration'] = array(
    'title' => 'Add User Account',
    'page callback' => 'CUSTOM_user_registration',
    'type' => MENU_LOCAL_TASK,
  );
  return $items;
}

You will probably want to provide your own access method for security.

Form Generation

/**
 * CUSTOM callback to generate a user registration form.
 */
function CUSTOM_user_registration() {
  global $user;
  // Retrieve the user permissions from drupal_static()
  $permissions = &drupal_static('user_access');
 
  // Keep a record of the state of this permission before we mess with it
  if (!isset($permissions[$user->uid]['administer users'])) {
    $cleanup = 'unset';
  }
  else {
    $cleanup = $permissions[$user->uid]['administer users'];
  }
 
  // Add the 'administer users' permission to the logged-in user
  $permissions[$user->uid]['administer users'] = TRUE;
 
  // Generate the form HTML normally
  $form = drupal_get_form('user_register_form');
 
  // Restore the user permissions to their default state
  if ($cleanup === 'unset') {
    unset($permissions[$user->uid]['administer users']);
  }
  else {
    $permissions[$user->uid]['administer users'] = $cleanup;
  }
 
  // Return the rendered HTML
  return $form;
}

The comments in the code describe what is happening quite well. The gist is that we temporarily grant the correct permission to the user, long enough to generate the form, then restore the permission to its original state. Be aware that, when drupal_get_form() is called, all of the hook_form_alter()'s will also be called, all while the user has the elevated permission. If you need additional functionality or alterations to the form, it is proper to add it in a hook_form_alter().

Conclusion

With a little bit of code is it absolutely possible to get custom functionality out of the user registration form. The major caveat, however, is that you are responsible to make sure that only the things that you intend to show are allowed in the form. The reward is ultimate and individual control over the user creation experience on your site, which may very well make or break your project!

Tags: 

5 Comments

Natan Miranda's picture

Great!

Heyyyy, thanks man, I was searching for it for hours!! I need users to create other users without permission "Administer users".

However, I created a small module and insert the Menu Callback and Form Generation and nothing happened. I need to do something else? I like to put a link to create new users in the administrator menu (admin_menu).

Corey Pennycuff's picture

Glad that you found this

Glad that you found this information useful! There could be many different issues causing difficulty. First of all, have you cleared your cache? Beyond that, there are several things that you can check.

Does the page exist when you type in the url directly? If so, then all that you need to do is add a link to the menu of your choice. This is the easiest problem to fix.

If the page does not show up when you type in the url, then you need to do a bit of troubleshooting. Double check that the module is enabled, then clear your cache. If you are still getting a "Page not found" error, then something else may be wrong in the code (probably in the hook_menu() function). If, on the other hand, you get a "Permission denied" error, then you know that the issue is permission-related in some way. Overall, these types of problems are usually solved with some sort of process-of-elimination technique.

Above all, experiment with your code, and I'm sure that you will be able to get this working on your site.

sujomuc's picture

Thanks a lot for the great

Thanks a lot for the great post!
I just tried your lines and everything works fine but if the temporary administer
creates an account, after the submit of the form the username is deleted and I get the error : field user name is requiered.
Do you have any idea? thanks in advance

Corey Pennycuff's picture

This is not a situation that

This is not a situation that I have encountered, but it sounds like a complication from another module. What you can do is to inspect the $form array and see if there is anything being added in the validation step that might be changing the data. Make sure to examine all of the #validate entries, as there can be more than one in different places within the array.

sujomuc's picture

I got the solution. The

I got the solution. The module honey_pot was deleting the user name.
The honey pot element name was name too. After changing that at the honey pot configuration page every thing works fine. Thanks for listening.