I have a problem with that ACL API.
I have created a very simple module (named 'aclif') as a simple interface to ACL. It uses the ACL API (including the form interface) to manipulate access lists. Here is what happens:
I first create a new node (7). When I view this node in its initial state, Devel reports:
node prio status realm gid view update delete explained
7 - default all 0 1 0 0 All users may view this node.
I then use the ACL form (and the acl_save_form function) to grant user 'john' view access to this node.
Devel reports:
node prio status realm gid view update delete explained
7 0 ok acl 68 1 0 0 aclif/view_7: john
7 0 empty acl 69 0 0 0 aclif/update_7: no users!
7 0 empty acl 70 0 0 0 aclif/delete_7: no users!
Access to the node is now managed by ACL, and everything works as expected.
The problem arise when I want to clear the ACL for this node, to bring it back to its initial state. From my understanding of the ACL API, I should be able to do this by calling:
acl_node_clear_acls($node->nid, 'aclif');
node_access_acquire_grants($node);
However, doing this results in the following error message when I try to view the node:
"You have errors in your {node_access} table! You may be able to fix these for now by running Rebuild permissions, but this is likely to destroy the evidence and make it impossible to identify the underlying issues. If you don't fix those, the errors will probably come back again. DON'T do this just yet if you intend to ask for help with this situation."
Devel now reports:
node prio status realm gid view update delete explained
7 ? alien all 0 1 0 0 All users may view this node.
7 0 missing acl 68 1 0 0 aclif/view_7: john
7 0 empty acl 69 0 0 0 aclif/update_7: no users!
7 0 empty acl 70 0 0 0 aclif/delete_7: no users!
Obviously, acl_node_clear_acls(7, 'aclif'); did not do what I expected it to do.
I'm unable to figure out this one for myself, so I ask for help with this situation.
PS: Rebuilding permissions results is the following access table:
node prio status realm gid view update delete explained
7 0 ok acl 68 1 0 0 aclif/view_7: john
7 0 empty acl 69 0 0 0 aclif/update_7: no users!
7 0 empty acl 70 0 0 0 aclif/delete_7: no users!
Comments
Comment #1
salvisThank you for the very clear exposition!
I agree with you, this should work as you expect.
After granting user 'john' view access to node 7, you should have a record like (68, 7, 1, 0, 0, 0) in the {acl_node} table. After calling acl_node_clear_acls(7, 'aclif') this as well as all other records with a nid==7 should be gone from the {acl_node} table. Please check that.
The fact that core has created the 7/all/0/1/0/0 record proves that at the time when you called node_access_acquire_grants($node) ACL did not return any 'view' grant.
I believe there is some flaw in your code that causes the (68, 7, 1, 0, 0, 0) record to be recreated at some later point in time by calling either acl_add_nodes() or acl_node_add_acl_record(). Temporarily put a ddebug_backtrace() call into these two functions to check this.
Comment #2
gisleI think I've found a workaround. (Edit: I wrote this before I saw your reply above. I'll check the things you suggest and report back.)
I get the error if I call acl_node_clear_acls when the acl_user table still has any acl_ids associated with this node. So by clearing that before calling acl_node_clear_acls, we avoid gettings this error.
I don't know whether this is the right solution, but it seems to work.
Below is my callback function for a node reset button (i.e. a button to clear any ACLs associated with the node that is managed by aclif). If anyone has a better solution for this, I would love to hear about it.
Comment #3
salvis{acl_user} does not have a nid column. It cannot have "any acl_ids associated with this node" because it does not know about nodes.
If you remove all users from the ACL, you should probably call acl_delete_acl() instead, because the ACL becomes useless. If you have only one node per ACL, then acl_delete_acl() is the function to use -- if you have multiple nodes sharing the same ACL, then you do not want to remove the users from the ACL.
Directly modifying tables of third-party modules is never the right solution. If you find that something is missing from the API, then we have to look into adding it, but I think your "work-around" is not doing what you intend to do.
Comment #4
gisleThank you, salvis!
You were right of course, I had a misplaced call that re-created the ACL right after deleting it.
After I got the logic right, I no longer need to remove users from the ACL, and acl_node_clear_acls() now does what I expect it to do.
Comment #5
salvisGreat, glad you got it working.