I'm using acl in combination with content_access and have noticed that acl does not distinguish between view. edit and delete. This may be simply because of my particular configuration of modules. I'm using Drupal 5.10 and have modified node.module (for multinode access), but I've tested it using the original node.module and on another site, as well, with the same result: acl does not seem to differentiate between view/edit/delete.
/**
* Implementation of hook_node_grants
*/
function acl_node_grants($account, $op) {
$array = array('acl' => array());
$result = db_query("SELECT acl_id FROM {acl_user} WHERE uid = %d", $account->uid);
while ($row = db_fetch_object($result)) {
$array['acl'][] = $row->acl_id;
}
return !empty($array['acl']) ? $array : NULL;
}
It returns all grants for the user regardless of what they allow. I've found that when node_access_grants_sql processes this, it uses only the last permission found for that user:
foreach ($rule as $gid) {
// Grants ids must be numeric.
if (is_numeric($gid)) {
$grants[$group][$realm] = $gid;
}
}
and so regardless of the individual user settings, the result (in the case of unmodified node.module) is view access only. With the multinode access patch installed this became full access only.
In order to get the behaviour I require I have rewritten the function as follows:
/**
* Implementation of hook_node_grants
*/
function acl_node_grants($account, $op) {
$array = array('acl' => array());
$result = db_query("SELECT acl_id FROM {acl_user} WHERE uid = %d", $account->uid);
while ($row = db_fetch_object($result)) {
$grant_name = db_result(db_query("SELECT name FROM {acl} WHERE acl_id=%d", $row->acl_id));
if(strpos('a'.$grant_name, $op)) $array['acl'][] = $row->acl_id;
}
return !empty($array['acl']) ? $array : NULL;
}
strpos('a'.$grant_name, $op) is like this because I'm danged if I can get strpos to read from the beginning of a string, so I add an 'a'.
Anyway this produces the desired behaviour: when I allow edit permissions, the user can edit, when I allow only view, the user can only view.
Comments
Comment #1
salvisSorry for taking so long to respond.
I see that we're ignoring $op, which may cause problems, and I'd like to create a setup which lets me test this, but I'm not sure how to do this. What is node_access_grants_sql that you're referring to?
Your rewrite (with a query inside a fetch loop) is very wasteful, something we can't have deep down in the infrastructure. This needs to be rewritten as a join in the outer query.
Please adhere to the Drupal coding conventions and submit code changes as patches, so that they can be properly tracked.
Comment #2
NewZeal CreditAttribution: NewZeal commentednode_access_grants_sql() is in node.module. In Drupal 5.10 it is written as follows:
Yes, I agree the patch could be written more efficiently and I could use patch technology. So far I have not been able to implement patches on my PC and get it to work correctly. Do you have any links to tutorials for me to learn this?
Many thanks
Comment #3
salvisI'm looking at node.module from Drupal 5.10: // $Id: node.module,v 1.776.2.30 2008/07/16 19:04:21 drumm Exp $
It has 3097 lines but no such function...
Have you hacked core?
http://drupal.org/patch has extensive coverage of patching.
Comment #4
NewZeal CreditAttribution: NewZeal commentedMy apologies,
My copy of node.module in my main repository has been inadvertently replaced by the multinode access patched version. node_access_grants_sql comes from the patch.
I have reinstalled drupal 5.10 into the repository and checked acl with the unpatched node.module and it is working correctly because the sql is constructed as follows:
in which the realm is included in the grants array.
This bug should be transferred to the multinode access patch: http://groups.drupal.org/node/5392 which needs to be modified in order to cater for acl as it claims.
I apologise for inconveniencing you. It is taking me a while to understand how modules interface with node_access.
Comment #5
salvisOk, no problem.