After the values are inserted into the user_roles table by the _invite_escalate_role function, they are wiped out by the user_save function called by another hook. Printing the backtrace at that point seems to only show the hooks called from the form.inc user_register_submit function, although it definitely occurs after _invite_escalate_role. The users_roles insert does insert its data, confirmed by stopping the code there. It just gets wiped out by a later user_save where the edit[roles] value does not contain the assigned role. This leads me to believe that there is not enough use of the variable references in your insert case--it is not enough to insert directly into the database at that point. I played with this quite a while adding references and such but could not manage to get a suggestion as to how to change your code.
Notes: email confirmation is required for user registration. Am using autoassignrole to allow the user to select a role at registration. I believe the problem also happened when this was turned off, however.
I inserted this case into my own user hook and it solved the problem, as an ugly workaround, but it suggests a possible cause of the problem, namely the fact that the account and edit variables are being changed, and there is no need to insert role assignments into the database:
$invite = invite_load_from_session();
if (!$invite) {
// Try to look up an invitation in case a user has been invited to join
// the site, but did go straight to the site and signed up without
// using the invite link.
$code = db_result(db_query("SELECT reg_code FROM {invite} WHERE email = '%s'", $account->mail));
if ($code) {
$invite = invite_load($code);
}
}
$roles = array('default');
// Add roles of inviter.
$inviter_uid = db_result(db_query("SELECT uid FROM {invite} WHERE invitee = %d", $account->uid));
if ($inviter_uid && $inviter = user_load(array('uid' => $inviter_uid))) {
$roles = array_merge($roles, array_intersect($inviter->roles, user_roles(0, 'send invitations')));
}
// Map to configured target roles.
$targets = array();
foreach ($roles as $role) {
$role_no_space = str_replace(' ', '_', $role);
$target = variable_get('invite_target_role_'. $role_no_space, DRUPAL_AUTHENTICATED_RID);
if ($target != DRUPAL_AUTHENTICATED_RID) {
$targets[$target] = $target;
}
}
$edit['roles'] += $targets;
| Comment | File | Size | Author |
|---|---|---|---|
| #20 | invite-role-fix.patch | 5.49 KB | bpirkle |
| #14 | 330233-escalation.patch | 4.66 KB | smk-ka |
| #7 | 330233.patch | 2.69 KB | Bevan |
| #4 | 00 To be sorted and contributed.patch | 4.69 KB | Bevan |
| #1 | Invite_implementation_hook_user.zip | 998 bytes | Anonymous (not verified) |
Comments
Comment #1
Anonymous (not verified) commentedThank you for your solution, works like a charm.
Two remarks
1) In my opninion your suggestion is not an 'ugly workaround' but a better approach because the invited user and correct roles are created in one step. Also the necesary invokes are done by the ouser_module, not the invite module which is more simple.
2) Your solution must be placed a few code lines lower in the hook_user to let if function also for the invites that are accepted directly by a-mail. I have attached the code of the complete new hook user that shows how.
Maybe time for a new version of Invite?
Comment #2
shunshifu commentedI tried this but my users are not getting the invite role assigned to them. Bummer
Comment #3
hefox commentedI needed a quick solution to this that didn't span to many lines while wait for this module to be updated with whatever solution works so I inserted this into the invite_user rigfht before 'insert' is finished (line 456ish):
$account = user_load($account->uid);
$edit['roles'] = $account->roles;
By the way shunshifu, it probably didn't work due to none of the helper functions called from invite_user are getting the $edit or $account objects as references (&$edit, $account). S/he didn't copy that part of the code into his/her comment.
Comment #4
Bevan commented#314347: Role escalation bug was marked duplicate.
I implemented a similar solution that changes less code in the the attached patch. This patch includes fixes for some other bugs too, so you may need to filter those out. I'll submit a clean patch later.
The solution I've implemented deprecates the need for
in
_invite_escalate_role()and removes it. This has the side effect of optimizing performance. However some other modules may depend on the change done this way. They will need to be updated to usehook_user('update')as well or instead ofhook_user('insert').Comment #5
Bevan commentedComment #6
Bevan commentedComment #7
Bevan commentedA clean version of this patch is attached. Needs some testing and some input on the removal of the call to
user_module_invoke()Comment #8
hexag commentedworks like a bloody charm, no end of hours of stupid stress have been caused by this issue, YAY for the invitee role!! thank you ever so much
Comment #9
liliplanet commentedHi Bevan,
Also having problems as invitee does not receive assigned role.
Would you be so kind just to upload your invite.module as unfortunately I cannot perform patches.
Look forward to hearing from you, and thank you.
Lilian
Comment #10
Bevan commentedLili, I don't think it's a good idea to use a patched module if you don't know how to apply patches or keep up with the development of the patch/fix. That's when patching becomes forking. Patch files are actually relatively human readable. I suggest you take a look at it and have a go at applying it manually, by editing the source code of invite.module. This one isn't the simplest of patches, but it's also not too large for manual application. Once you have done it manually a couple of times you'll want a tool to automate it for you. See http://drupal.org/patch/apply. If that is all too complicated then you should contract a developer, or wait till this is fixed in a release of invite.module.
Comment #11
andypostLooks like duplicate of #322748: Only administrator can send invitations on multilingual installation.
Escalation depends on settings which could be wrong on multilingual sites
Comment #12
Bevan commentedAndypost; This issue occurs on mono-lingual sites which is where I came across it and created this patch.
Comment #13
icarus75 commentedThis patch in #7 applies cleanly to a 6.x-2.0-alpha1 invite module. Successfully tested the proper setting of invitee's target role with this patch.
Nice,
Bart.
Comment #14
smk-ka commented#137495: Other Modules not notifed of role change was the issue that required the addition of user_module_invoke(). Basically, other modules (User Badges in this case) want to get notified if a role change takes place, therefore we cannot remove it.
However, I've taken the patch from #7 to simplify the workflow a lot, the code responsible for processing an invitation has been consolidated into one function (former _invite_accept, now renamed to invite_process), while hook_user() takes care of the role escalation.
This *should* still work, but needs testing with both User Badges and Auto Assign Role modules.
Comment #15
smk-ka commentedComment #16
WiseMike commentedI tested this patch in #14 with Auto Assign Role, LoginToboggan and Registration Role Keys modules - successfully. Thanks!
Comment #17
smk-ka commentedCommitted, thanks all!
Comment #19
osopolarI don't believe that calling user_module_invoke('update', ...) in the hook invite_user with $op=insert is a good idea. This will start the update-procedures of the user hooks before all insert procedures have been finished.
Example: Let's say, module y has a higher weight in the system table than the invite module, so y_user() gets executed after invite_user(). The hook invite_user calls in the insert case the hook_user to perform the 'update' functionality. In this step drupal will call the hook y_user with $op='update'. After finishing the hook_user update-case (returning back to invite_user; still in the insert case) the until now not executed user_hooks like y_user will be called (with op='insert'; after their 'update' case). If the update case trusts on data set by the insert case it will probably have/cause some trouble.
Suggestion (not verified): why not use the 'submit' case to set (add) the account roles? In my eyes this means that there has never existed a account with other rules than the given ones (set by invite and maybe some other modules). So you don't have to change the rules and it's up to the other modules to recognize that the created account has some more roles.
Comment #20
bpirkle commentedI found that the overall settings for assigning roles to the newly invited member worked fine with patch #14 (thanks!). But assigning a specific role if the invitation was issued by a user with a specific role failed.
The problem appeared to be in function "invite_target_roles". It seemed necessary within the loop in that function to use the "$role" value (with spaces replaced by underscores) rather than the $rid value.
Patch with this change attached.
Comment #21
YK85 commentedHi bpirkle,
This sound really interesting and I want to help with testing (even though it seems no patches are being committed to invite module recently).
To confirm what this patch does:
1) choose the role added to invited users
2) choose the role added to invited user when invitee has role X
Therefore these scenarios should be possible?
1) if user1 with role A invites user2, then user2 receives role A
2) if user3 with role B invites user4, then user4 receives role B
3) if user5 with role C invites user6, then user6 receives role C and role D
Thank you!
Comment #22
smk-ka commented@bpirkle
Your patch is against outdated module versions and contains changes that have long since been committed to the development version.
@yaz085
There is currently nothing that can be tested here. The only issue remaining is #19, finding a way to avoid calling hook_user('update') from within hook_user('insert'), which is indeed problematic but should be discussed in a separate issue.
Comment #23
smk-ka commentedCreated a new issue: #870668: Calling hook_user() from within hook_user is error prone.
Comment #24
YK85 commentedThanks smk-ka! I will follow 870668. Awesome module!!
Comment #25
PACraddock commentedEdit: double-post.
Comment #26
PACraddock commentedWhich version of this module works out of the box with this? I can't seem to get any version to work - no user roles are ever assigned to the invited user.
Comment #27
mlalu commentedHas this problem been fixed in beta 3? The latest version of the module only applies the default role when they register and not the additional one base on the role of the person who sent the invite.