Hi,

It seems that adding or removing roles of a user by rules doesn't work when reacting on the Organic Group event 'User has become a group member' or 'After saving a new og membership'.

My setup:

User 'test' with roles:
- verified user (role id = 2)
- important (role id = 4)

Rule:

EVENT: 
- User has become a group member

CONDITON: 
- site:current-user has role 'important'

ACTION: 
- PHP action: dpm($user);
- Remove role 'important' from site:current-user
- PHP action: dpm($user);

Now 'test' joins a group --> rule fires

dpm output before removing role:
roles = array(2, 4);

dpm output after removing role:
roles = array(2);

Watchdog barks the rule has been successfully fired.
So it seems the roles *are* being changed in the rule itself, but afterwards when checking them on the user's profile page, nothing has changed...

Note: doing exactly the same for the event 'on node submit' does work!

Any thoughts on this?

Comments

Anonymous’s picture

Project: Rules » Organic groups
Issue summary: View changes

extra info

Anonymous’s picture

Issue summary: View changes

extra info

Anonymous’s picture

Issue summary: View changes

added info 'after saving a new og membership'

Anonymous’s picture

Version: 7.x-2.1 » 7.x-2.0-alpha2
Component: Rules Engine » og.module
amitaibu’s picture

Priority: Critical » Normal
Status: Active » Postponed (maintainer needs more info)

Please try with the -dev version.

Anonymous’s picture

Version: 7.x-2.0-alpha2 » 7.x-1.4

Oops, just realised this issue applies to OG 7.x-1.4. Anyhow, I tested -dev and it's working in there.

Maybe there's just a quick fix for 1.4?

lpedretti’s picture

Not working here for me, even on 1.x-dev, same problem, rules log show roles are added/removed but no change when checking user after that, however it does work after updating content, it just doesn't work after events that imply a user account modification (user has been removed from group, after updating an existing user account, etc.)
I found this problem before, it's related of some place where a hook modifies the user but then it's saved again in the original state at the end of the hook. Unfortunately however i don't remember where it was

lpedretti’s picture

On further testing, i found the following: i had a rule that fired before the event "after updating an existing user account", it reacted to the event "User has been removed from group", and the only action was to cancel subscription of the user to the group (kinda redundant, it was part of my former tests to try to make the normal rules work), when i deactivated that rule it al behaved normal, i'm using 7.x-1.x-dev

Best regards

chiebert’s picture

I'm finding the same behaviour in OG 7.x-1.4 (which is now dated more recent than 1.x-dev). Moreover, I've found that as soon as I add an action that impinges on [account] (i.e., add user role), I can no longer successfully add users to groups via group/node/[nid]/admin/people/add-user. The following implies the addition was successful:

  • Rules debug says everything has fired,
  • I get the 'user has been added to group' message,
  • When I view the user's profile page, the Groups Audience field correctly shows the new group

However:

  • group/node/[nid]/admin/people fails to show the new user as part of the group
  • database table 'og_membership' does not have a row for the new membership (!!)

Not until I 'edit' the user and immediately hit 'save' does the membership take effect. And if I remove the 'add roles' action and replace it with an 'add message to site' with [account:name] in the message body, it all works fine.

I have no other rules firing on any user accounts during all this. Like the OP, if my rule reacts on something non-OG, like:

  • Event: after saving new content
  • Condition: "has roles" "node:author" "[some-role]" "NEGATE"
  • Action: "add role" "node:author" "[some-role"

... works fine.

I realise that 7.x-2.x has just hit beta, but if this is indeed a bug in 1.x, then it would be nice to have it fixed for those of us who this close to finishing our 1.x projects. :)

amitaibu’s picture

@chiebert,
Please provide a patch and it will be fixed for 1.x :)

chiebert’s picture

Believe me I would, but I haven't a clue where to start tracking down the problem. From the symptoms, can anyone detect any patterns that can translate into hints?

lpedretti’s picture

Ok, i have been tracking this issue through all rules, og and drupal's user module.

This is the main situation when using "After saving a new og membership" and "After updating an existing og membership" events and constructing a rule that modifies the user's roles:
- og.module calls entity_save() in line 1678
- This goes through a few calls and ends up calling user_save() from drupal's user module.
- user_save() recieves the account and a $edit form with the original values (this $edit variable has the original roles of the user).
- user_save() in line 467 calls module_invoke_all and passes "entity_presave" as the hook and the account as parameters
this entity_presave branch finally fires up the rule, the rule saves the user with the updated info.
- Now comes the problem: when this branch returns control to user_save() it follows up with the original user information, and later saves the user. In fact, user_save() in line 560 calls user_module_invoke with the "update" hook, and again the original user values in an array and the original account. I still don't know exactly where is the original account info saved again, but the issue lies on this behaviour. It may affect other og events with rules modifying user info.

To trace it, i created the rule, enabled the devel module, and created a function in a custom module "module_user_update(&$edit, $account, $category) { dpm($edit); dpm($account); dpm(debug_backtrace()); }". This should give enough information to trace the place, but from there on i will solve the issue modifying the account in this hook instead of using rules as i have to solve it right now.

Hope it helps, and tell me if there's anything else i can do.

Best regards

jjpost’s picture

Is there any update on this issue? I encounter the same problem, using Rules 7.x.2.2 and OG 7.x-1.5.

rerooting’s picture

Version: 7.x-2.3 » 7.x-1.4

**edit** Umm as follow up... in my case, the actual problem was that the rule was disabled :(( < embarrassed face

Disregard the earlier message about a related issue, as this seems to be a real issue folks are having and I didn't want to leave my message up as a red herring.

Angry Dan’s picture

Maybe I'm dragging up an old conversation, but this is definitely a problem for me using OG 7.x-2.0.

The problem, as far as I can see, is that user_save is sometimes called before an og_membership_save.

My rule is essentially as such: "If you are no longer a member of any groups, remove the user role X"

If, using og_ui, I unsubscribe from a group then I am basically calling og_membership_delete(), my rule triggers which in turn then fires a user_save() to remove the role.

The user_save is important - it will execute against the original user entity, which still has the group membership, because og_membership_delete() isn't done yet. In this case, that's a good thing because the diff of current and new group memberships, so no changes will be seen and no more OG functions get called.

However, if using the user edit page I remove a user from all of their groups, I'm immediately triggering a user_save(). This time the OG membership diff shows that I've left a group and og_memberhsip_delete() get's triggered (or it's derivative). What happens next is that my rule triggers, it gets passed an original copy of the user object (which still has the group membership) because user_save isn't done yet. My rule removes the role... which triggers another user_save()! Because this user_save is on the original user object - which still has the group attached - the user gets re-added to the group.

rachel_norfolk’s picture

Ah!! I think you have given me an idea as to why users are acting really oddly on my site at the moment. I have a couple of rules detecting when users are added and deleted from groups and then doing role changes etc. Been REALLY odd as users were being deleted immediately as they were added and vice versa.

WebSinPat’s picture

Version: 7.x-1.4 » 7.x-2.3

I'm running into the same problems using OG 2.3 and rules 2.3

It sounds like folks have made great progress understanding the issue..anyone close to having a solution?

WebSinPat’s picture

Version: 7.x-1.4 » 7.x-2.3

Some brainstorms and workarounds I was playing around with

  1. create a rule set that first does an entity save on the user object (force save to happen immediately), then proceeds with the rule I actually want. This seemed to have no effect whatsoever. I guess the entity passed to the rule just does not have the new information so saving that object has no effect.
  2. separate the rule execution from the og membership event and instead run the rule via the scheduler/cron when the og_memberships have been saved and are not in flux. so instead loop through all users/groups checking for whatever conditions i want, and then execute the actions. i have not tried this. seems like it might work conceptually, but would be pretty inefficient. I'd approach it by using VBO to pass the entities to the rule, but I'm not savvy enough with views relationships and contextual filters to make it happen.
  3. a variation i just thought of would be to write a rule triggered on the og_membership event that saves the user and group information to be passed to a rule that can be executed later via scheduler/cron, so that instead of having to loop through all users, it would just check the particular user/group that was passed to it. I have no idea if this is possible.
  4. at this point, though, I am giving up and will just manage my roles and memberships by hand for the moment

posting these brainstorms here in case any of them make sense to other folks who would know how to pull them off.

WebSinPat’s picture

Issue summary: View changes

added info 'before saving a new og membership'

othermachines’s picture

I'm having trouble duplicating this. @WebSinPat, can you please describe your problem in detail and also post your exported rule? Thx -

WebSinPat’s picture

EDIT: Note: the "og_user_has_role" condition mentioned in this comment is still under review here: #1327326: add rules action for adding og roles for a user per group

steps to reproduce on my setup (commons 3.3, shipped with OG 2.3, and rules 2.3, with default roles/permissions overridden)
- set up the rule to check for og_role in group nid 327 to check for role "administrator member" (will include the rule export below)
- go to the group (nid 327 in my case), go to "administer group", go to "people", and edit the user you want to promote to group admin.
- in my case this takes me to group/node/327/admin/people/edit-membership/385
- add "administrator member" role for the user and click "update membership"
- at which point i would expect the rule to evaluate TRUE and fire
- here is the rules evaluation log

        0 ms Reacting on event After updating an existing og membership.
    10.164 ms Evaluating conditions of rule og_admin_get_membership_coordinator_role_2. [edit]
    10.97 ms The condition entity_is_of_type evaluated to TRUE [edit]
    11.2 ms The condition entity_is_of_type evaluated to TRUE [edit]
    12.227 ms The condition og_user_has_role evaluated to FALSE [edit]
    12.236 ms AND evaluated to FALSE.
    12.252 ms Finished reacting on event After updating an existing og membership.

- so the condition has not evaluated as expected.
- now go back and edit that user again at group/node/327/admin/people/edit-membership/385
- they are shown to have the admin role, as expected, so the problem is not that the admin role didn't get assigned correctly.
- resave the user/membership without making any changes, leaving them assigned the admin role
- here is the rules eval log:

    0 ms Reacting on event After updating an existing og membership.
    10.186 ms Evaluating conditions of rule og_admin_get_membership_coordinator_role_2. [edit]
    10.993 ms The condition entity_is_of_type evaluated to TRUE [edit]
    11.239 ms The condition entity_is_of_type evaluated to TRUE [edit]
    12.267 ms The condition og_user_has_role evaluated to TRUE [edit]
    12.276 ms AND evaluated to TRUE.
        0 ms Rule og_admin_get_membership_coordinator_role_2 fires.
        0.146 ms Evaluating the action user_add_role. [edit]
        1.151 ms Rule og_admin_get_membership_coordinator_role_2 has fired.
    13.466 ms Saved og_membership:entity of type user.
    215.836 ms Finished reacting on event After updating an existing og membership.

- so now the condition evaluates TRUE as expected
- and now repeatedly saving the user/og_membership with admin role (i.e. without making any changes to the user object), the rule consistently evaluates TRUE as expected
- now remove the admin role from the user and click "update membership"
- i would expect the rule to evaluate FALSE
- but it evaluates TRUE
- then resave the user, leaving the settings the same so not admin role
- now the rule will evaluate FALSE as expected

- so it can correctly evaluate the user's role if the role/user object is not changing, but if the og_membership update includes changing the role, that change to the user object is not being passed correctly to the rule.
- the rule will only evaluate correctly as i expect it to the 2nd time i save the user after making a change, but not in the instance of making the change.

here is my rule export


{ "rules_og_admin_get_membership_coordinator_role_2" : {
    "LABEL" : "og_admin_get_membership_coordinator_role_2",
    "PLUGIN" : "reaction rule",
    "REQUIRES" : [ "rules", "og" ],
    "ON" : [ "og_membership_insert", "og_membership_update" ],
    "IF" : [
      { "entity_is_of_type" : { "entity" : [ "og-membership:group" ], "type" : "node" } },
      { "entity_is_of_type" : { "entity" : [ "og-membership:entity" ], "type" : "user" } },
      { "og_user_has_role" : {
          "account" : [ "og-membership:entity" ],
          "group" : [ "og-membership:group" ],
          "roles" : { "value" : { "21" : "21" } }
        }
      }
    ],
    "DO" : [
      { "user_add_role" : {
          "account" : [ "og-membership:entity" ],
          "roles" : { "value" : { "5" : "5" } }
        }
      }
    ]
  }
}

Let me know if this gets you closer to reproducing it, or if there's any other info i can provide.

othermachines’s picture

Note: the "og_user_has_role" condition mentioned in comment #17 above is still under review here: Issue #1327326: add rules action for adding og roles for a user per group.

othermachines’s picture

Issue summary: View changes

@WebSinPat:

Looks like there may well be some sort of conflict of timing with entities og_membership and user that persists with the current version of OG. However I'm not convinced this is the same problem as OP so I'm going to revert your edit to the original post so that it can be easier for me (and others) to follow the thread.

That being said, if you're looking to simultaneously assign/revoke an OG role and a Drupal role, you will find two new conditions events in 7.x-2.x-dev: OG role granted to user and OG role revoked from user. Might these do the trick?

othermachines’s picture

**Edit #19 - "events" not "conditions".

WebSinPat’s picture

(gah, my comment from a few days ago didn't seem to have made it. Will try to recreate as well as add new observations.)

@othermachines, I'll have to take your word on whether what I'm noticing is due to the same issue as the OP :), I can't wrap my head around the code to say for sure. Should we move this (and some of the subsequent comments relating to similar behavior in 7.x.2.x) to a new issue?

Meantime, I am trying out the grant/revoke_role functionality as provided in #1816800: Integration of OG Grant Roles with Rules

yes, overall the grant/revoke_role events work more smoothly than the membership-based events.

However, there are still a number of issues when trying to manipulate user roles based on og_roles events. Plus a few other quirks I'll note below.

my goal: assign/revoke a site role based on an og_role. (i.e. group admins get a particular coordinator role on the site)
my rules: on event og_grant_role, check if user was granted og_admin role, if so assign them site coordinator role. on og_revoke_role, if user was revoked og_admin role, remove coordinator role.

  1. with default roles overridden (as by commons3.3), i can't use the grant/revoke_role rid argument, because of course the numerical rid varies from group to group. so i have to combine it with the other roles patch #1327326: add rules action for adding og roles for a user per group to check what og_roles the user has.
  2. revoke_role event fires regardless of if the user role is changing, so fires every time a membership is saved. (grant_role only fires if a new role is being added) I didn't notice this to cause any problems, it just threw me off initially for it to fire when i didn't expect.
  3. revoke_role does not work with og_user_has_role in the same rule instance, (i.e. the revoked role still looks like it's there when checking if og_user_has_role). I was able to address this by adding a cache clear. No clue if this is a good or terrible solution.
    <?php
    function og_role_revoke($group_type, $gid, $uid, $rid) {
    //...
        if (module_exists('rules'))  {
    +      drupal_static_reset("og_get_user_roles");
          rules_invoke_event('og_role_revoke', og_get_membership($group_type, $gid, 'user', $uid), entity_metadata_wrapper('user', $uid), $rid);
        }
    ?>
    
  4. adding a user to a group with a role causes grant_role rule to fire, and then to fire my add_user_role action, which then causes the user to not actually get added to the group. As described in some of the comments above, due to saving the user object with old data.
  5. (adding a user to group without any role (other than member) does not fire grant_role event and works as expected with the user becoming a member of the group.)
  6. removing a user from group does not fire revoke_roles, including when the user had an admin role at the time of removing them. If this is the desired behavior and not an oversight bug, a workaround could be to write a separate rule on the event OG user has been removed from group.

So there are still too many undesired and unpredictable behaviors when trying to write rules tying og_roles to user roles at the moment to be able to have any such rules enabled. Well I guess it's only point#4 on my list that is serious enough and without a workaround, that prevents the rule from being enabled.

EDIT: I'm running Commons3.3, Rules2.3, OG2.3 with patches https://drupal.org/files/og-add_og_role_events-1816800-4.patch and https://drupal.org/files/issues/og-rules_og_roles-1327326-7_0.patch
EDIT again fix some typos and add a bit more clarification.

othermachines’s picture

@WebSinPat -

Yes, please move this text to a separate thread and mark it support request. While these reports are appreciated I'm not sure how much time I'll have in the coming weeks. In the meantime you might be better off making do with production code until these features are fully fleshed out.

Also, sorry to be redundant but please post the rules export you are working with. It helps. Thanks -