Take the 2-minute tour ×
Drupal Answers is a question and answer site for Drupal developers and administrators. It's 100% free, no registration required.

I have a site (7.18) in which I want to grant teachers access to assignments created by their students. My current solution is to set a teacher for each student, using a User Reference field. I then use a Rule to propagate the teacher setting to a field on each node the student creates, and I use the Node Access User Reference module to give access to the user referenced in the teacher field.

This should work fine, but whenever a student creates a node, I get the error message PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '*X*-*Y*-nodeaccess_userreference' for key 'PRIMARY', where X is the auto-increment ID for the next node that should be created, and Y is the user ID for the teacher (see the paste linked below for the full error message).

The full error references some code in node.module (lines 3427-3440). I got it to provide a dump of the queries it's doing (also in the paste below), and it seems that the function to insert access permissions in node_access is being called twice with (almost) the exact same parameters: First it does one query that inserts rows granting access to the admin account, the author, and the designated teacher, then it attempts to do the same thing over again.

This creates a key conflict in the node_access table. After that it presumably does a rollback, because the permissions (and the node itself) don't appear even once, but the auto_increment value for the node table does increase.

I've verified that this only occurs when the node access user reference effect is invoked. A student who does not have a teacher assigned can create nodes with no problem, and removing the node access for teachers from the relevant content type also eliminates the problem.

Any idea why this is happening, or how I can fix it? The quickest solution that comes to mind is to change node_access inserts to use insert if not exists but I'd rather not hack a core module in such an ignorant and potentially far-reaching way.

The error messages and database queries are quite long; see this paste for the details.

share|improve this question

2 Answers 2

up vote 1 down vote accepted

I was able to fix this by putting in a check to see if access rights had already been granted, before attempting to grant them. Currently it's an ugly hack to node.module (it even uses global variables :P). I'd love to see other responses that can either explain why this happened, or offer a less dangerous solution.

At some point I should try to reimplement it as a proper module, using hook_node_access_records() or something like that. But in case anyone else has an exigent need to deal with this problem, the ugly version of the solution is essentially to declare a global array variable $already_granted in node.module. Inside node_access_write_grants(), do the following while it iterates over $grants:

global $already_granted;
$fixkey = $node->nid . "-" . $grant['gid'] . "-" . $grant['realm'];
if(in_array($fixkey, $already_granted)) {
  // the grant was already inserted
  continue;
}
else {
  $already_granted[] = $fixkey;
}
share|improve this answer

The patch from https://drupal.org/node/1961054 helped me with this problem. I applied it manualy because automatical pathing failed.

share|improve this answer
    
This patch worked for me, with automatic pathing as well. This seems to me to be the best approach. –  Michael Greisman Jan 14 at 20:35
    
It's this core issue committed to 7.25: drupal.org/node/1146244 –  aexl Apr 23 at 15:44

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.