the developers thread has a really interesting discussion on how to assign users to roles programmatically.

http://lists.drupal.org/pipermail/development/2006-January/013356.html

Comments

kae’s picture

I'm looking for some way to assign a user to a role programatically.
> You'd think this would be easy to do, but it isn't: I tried just about
> every drupal hook you can think of to hook add this to the "user add"
> and "user edit" screens, and nothing worked. The problem was that
> node_save really really really wanted to get in there last, and I never
> found a way to get around this. I even tried to stamp the fields into
> the database. No use. node_save just went in at the end of the request
> and changed it back for me :-(
>
> Does anyone know how to coerce Drupal 4.6 into doing this? Or sweet
> talk it into this? It would be nice if there was an API for this, but
> AFAIK there isn't. What hook should I use, and which 2x4 do I need to
> apply?

Here are two functions that I used for a customer project that do just that:

function mymodule_role_join($uid, $rid) {
db_query("INSERT INTO {users_roles} (rid, uid) VALUES ('%d',
'%d')", $rid, $uid);
}

function mymodule_role_leave($uid, $rid) {
db_query("DELETE FROM {users_roles} WHERE rid = %d AND uid = %d", $rid, $uid);
}

> That is the caveat: I did not do it at user signup time, but rather
> as to assign the user to a role when certain conditions are met.
>
> I vaguely remember two modules: one to assign the user a role
> automatically at signup, and another to assign them to a pre-defined
> "in limbo" role (something between authenticated user and anonymous
> user). The idea is to keep them in this role before they are given
> full privilege so as to weed out the trolls.
>
> Can't remember the names though, and my PC is too slow for me
> to check it.
>

I think logintoboggan is one.

kae’s picture

When do you call these functions? As part of which hook? I had
> tried to add it to the "user add" admin page using hook_user, but
> as Yoda once said, "Work it did not".

The problem with doing it as part of the user hook is that it saves
at the very end of the hook. and one of the things the user hook does
is delete all the roles and then
add only the new ones.

You can still modify the $edit variable and change what was 'actually
submitted'.

function module_user($op, &$edit, &$user) {
switch ($op) {
case 'insert' :
$edit['roles'][_user_get_rid('administrator')] = '';
$edit['roles'] = array_flip(array_keys($edit['roles'])); //
I am not sure it's strictly necessary, but it maintains the format
that the modules are expecting, so it can't hurt
break;
}
}

function _user_get_rid($name) {
return db_result(db_query("SELECT rid FROM {role} WHERE name ='%s'
limit 1", $name));
}

--
Adrian Rossouw
Drupal developer and Bryght Guy
http://drupal.org | http://bryght.com

* Previous message:

kae’s picture

It sounds like this would be a valuable asset to core (post 4.7 please :))

> function module_user($op, &$edit, &$user) {
> switch ($op) {
> case 'insert' :
> $edit['roles'][_user_get_rid('administrator')] = '';
> $edit['roles'] = array_flip(array_keys($edit['roles'])); //
> I am not sure it's strictly necessary, but it maintains the format
> that the modules are expecting, so it can't hurt
> break;
> }
> }

Bèr

[ Bèr Kessels | Drupal services www.webschuur.com ]

kae’s picture

On 27 Jan 2006, at 4:14 AM, Rob Thorne wrote:
> Does anyone know how to coerce Drupal 4.6 into doing this? Or
> sweet talk it into this? It would be nice if there was an API for
> this, but AFAIK there isn't. What hook should I use, and which 2x4
> do I need to apply?
Just did this recently :

----- snip ---
$user = user_load(array('uid' => $uid));
$edit['roles'][] = _user_get_rid('administrator');

user_save($user, $edit);
---- snip ---

function _user_get_rid($name) {
return db_result(db_query("SELECT rid FROM {role} WHERE name ='%s'
limit 1", $name));
}

I needed to use the user api since I have more specific rules that I
check for.
IE: you can be one of the following 3 roles, in a certain order of
preference, but never
more than one.

--
Adrian Rossouw
Drupal developer and Bryght Guy
http://drupal.org | http://bryght.com

kae’s picture

Much thanks to Adrian and Khalid for their help on this.

It turns out that both of you are right, but for different code paths in
hook_user. Here's what seems to work in 4.6:

* On $op == 'update', Adrian is correct: the right way to do this
is to stuff the rid into the $edit structure ($edit['roles'][] =
$my_rid;)
* On $op == 'insert', Adrian approach doesn't work, because
user_save has already done everything it will ever do with the
user_roles table. So in that case, you need to do what Khalid
suggests: INSERT a row into the user_roles table.

Now that I'm doing both of these things, I'm getting correct behavior on
both registration of new users and update of existing users.

kae’s picture

Rob Thorne wrote:

> * On $op == 'insert', Adrian approach doesn't work, because
> user_save has already done everything it will ever do with the
> user_roles table. So in that case, you need to do what Khalid
> suggests: INSERT a row into the user_roles table.
Yup. you're correct.

I tracked through the code and found out that userapi $op='insert' is
called after
the user_save function. Same with node.

Reason being user_save and node_save is where they get the $uid /
$nid, which
is needed for saving the rest of the data.

Love these fun inconsistencies =)

--
Adrian Rossouw
Drupal developer and Bryght Guy
http://drupal.org | http://bryght.com

kae’s picture

These functions should be in core. It would make addressing

http://drupal.org/node/40546

trivial. As a general thought, I think roles should be given "first class
status" next to users and nodes. Providing a "role API" would allow the
graceful improvement of the role system, behind the scenes.

In the current scenario roles are usually just treated as attributes of
users, not separate and worthy equals.

coupet’s picture

As a general thought, I think roles should be given "first class
status" next to users and nodes.

Agree!