Hi.
I need a little bit support.

How can I select all roles and users who can view newly created node? In my module I implement hook_nodeapi, which have to send email notification to all users who can view that node. And I only need these to which permissions are set.

Now I've implemented it with "Term Permissions" module:

SELECT tpr . * , users.*
              FROM {term_permissions_role} AS tpr
              LEFT JOIN {users_roles} ur ON ur.rid = tpr.rid
              LEFT JOIN {users} users ON ur.uid = users.uid
              WHERE tpr.tid IN ('. implode(",", $terms) .')'

But I don't need this module at all and now its too much configuration for users.

Thanks.

Comments

caschbre’s picture

Version: 6.x-1.3 » 6.x-1.6

This is an old unanswered issue but I have the same question so bumping it.

Ideally there would be a way to simply get a list of users who have access to a particular node but the only thing I know of is to loop through all of the users and run node_access against any given node. Not sure the looping would be ideal though.

If it's possible to get a list of roles that can view the node then I can write a custom module (or rule action) to email all users of a given role.

Even if there was a tac_lite function that could take termIDs and return me associated role IDs then I can work with that. I tried looking through the tac_lite code but didn't notice anything.

Dave Cohen’s picture

tac_lite does not store this in a way that's efficient to get. It's efficient to check the current user's access, but not others.

Theres devel_node_access (part of devel module) which can help, but can't do what your asking for sites with lots of users.

caschbre’s picture

Yeah, I figured that part would be difficult.

Is there a way to use tac_lite to figure out what roles have access to a particular piece of content? I was thinking that if a piece of content is tagged with XYZ term, that tac_lite would know what roles have access based off of that term.

Dave Cohen’s picture

Unfortunately it's not that simple. Access to a node might come from a custom access hook, a permission, or a grant from tac_lite or some other node access granting module. So for Drupal in general you have to test each user individually.

Even if your particular site is less complicated than Drupal in general, its still complicated. Tac_lite stores grants in the node_access table, and links the grant IDs (term ids) to roles via variables and to users via the users.data column. The variables store serialized data so Its not easy to build the query.

If I needed to do it, I'd probably build a test user, one for each role. Then write a little module or block or something that loads each of those users and passes it to node_access() to see which users can do what.

caschbre’s picture

Yeah, I realize that there's quite a lot that can go into whether someone can actually see a node. In my circumstance I think it's more straight forward. I use tac_lite to determine who can view a node. And in my specific situation, I want to email all users (by role) based on what the tac_lite settings are.

Here's what I've done...

I created a custom module with a rule action. When a node is saved the rule triggers.

The rule looks through each scheme that has the 'grant_view' permission. It's the only perm I care about in this case. The node is also loaded to access the terms for that node. An intersection is done to determine what terms line up with the terms from the tac_lite scheme(s). If there is an intersection then those role(s) are used to generate an email.

Once I have my list of roles, I use the rules module email role action and pass those roles to it.

So far everything is working as planned. I realize it's a narrow use-case, but it meets my needs. :)

Dave Cohen’s picture

Why not just call node_access() rather than devise the intersection you describe?

caschbre’s picture

Won't node_access just tell me if an account has access to the node?

I'm trying to email users that do have access to the node that the node has been created... sort of like an email blast.

I was thinking that if tac_lite is tying role access to terms, then I should be able to take the terms from the node and determine what roles have access.

Dave Cohen’s picture

I guess I misread your comment. I thought you had both an account and a node.

As I said before, I'd create a user for each role and use them to test which roles can view a node. I know it sounds like a headache, but tac_lite is optimized to calculate grants for just the current user. That's part of what makes it "lite".

If you come up with a better way, please share it here.

caschbre’s picture

Yeah, I realize I'm trying to use tac_lite slightly different. My goal is that when a node is created / saved, a rule will kick off and email all users a message. Those users are determined by the roles setup through tac_lite.

I created a sandbox project of my custom module that includes custom rules actions at: http://drupal.org/sandbox/caschbre/1487274

Here's the meat of it. I looked through the tac_lite module to see how it assembled the variables.

/**
 * Action: 'rules_email_by_role_action_email_roles_by_tac_lite_view'
 */
function rules_email_by_role_action_email_roles_by_tac_lite_view($node, $settings) {
  $recipient_roles = array();

  // Add the authenticated role as a possibility if chosen on rule setup.
  // This role will be removed when intersected with tac_lite roles assuming
  // the node is tagged with a term monitored by tac_lite.
  if ($settings['email_authenticated']) {
    $recipient_roles['2'] = 2;
  }
  
  // Loop through the node terms and remove any term that is not a part of the tac_lite monitored vocabs.
  $node_terms = $node->taxonomy;
  foreach ($node_terms as $tid => $node_term) {
    if (!array_key_exists($node_term->vid, variable_get('tac_lite_categories', NULL))) {
      unset($node_terms[$tid]);
    }
  }

  // Loop through each scheme / roles / vocab and check if a term matches a term from the node.
  foreach($settings['tac_lite_schemes'] as $k => $v) {
    $scheme_roles = variable_get('tac_lite_grants_scheme_' . $v, FALSE);
    
    foreach($scheme_roles as $roleID => $vocabs) {
      foreach($vocabs as $vocabID => $terms) {
        if (array_intersect_key($terms, $node_terms)) {
          $recipient_roles[$roleID] = $roleID;
        }
      }
    }
  }
  
  // Only perform the emails if a role is set.
  if ($recipient_roles) {
    $settings['recipients'] = $recipient_roles;
    rules_action_mail_to_users_of_role($settings);
  }
}
damienmckenna’s picture

Version: 6.x-1.6 » 2.0.x-dev
Component: Code » Documentation
Category: Support request » Task
Issue summary: View changes

It might be useful to have this information (or code) available on the current version.