Download & Extend

anonymous disappears from node_access table, gets access denied for all nodes

Project:Drupal core
Version:6.x-dev
Component:node system
Category:bug report
Priority:normal
Assigned:Unassigned
Status:needs review

Issue Summary

Hello -- I upgraded to 6.2 (from 4.7!!) a month or two back. Since the upgrade, I've had this problem twice:

- Anonymous users do not see any nodes (they get the "how to set up drupal" message on the home page and "access denied" on a specific node).
- It turns out that anonymous has disappeared from the node_access table
- If I run the sql command: INSERT INTO node_access (nid, gid, realm, grant_view, grant_update, grant_delete) VALUES (0, 0, 'all', 1, 0, 0); it adds anon back in and the problem is fixed (as recommended here: http://drupal.org/node/134505 )

It's nice to have a quick fix but this happens seemingly at random. The second time it happened I am sure that I have made absolutely no changes to the site permissions nor installed any modules or anything like that. It just happened literally overnight.

I see that this bug has been reported for version 5: http://drupal.org/node/124137

But I am on version 6 so I thought I should post a separate report. The previously linked forum thread, where I found the fix, shows that others are having this happen to them as well on version 6.

I am running on linux/apache with php5 and mysql 4.1. This never happened until the upgrade to 6.2. If I can provide more info please let me know...

Thanks,
Rich

Comments

#1

Version:6.2» 6.4

I've also experienced this problem with drupal 6.4

#2

Version:6.4» 6.10

When posting a story (or comment?) Drupal issues INSERT INTO node_revisions ... query. If it fails due to duplicate key Drupal catches the error, but handles it in a peculiar way: at first it logs it (INSERT INTO watchdog ...), and then does DELETE FROM node_access WHERE nid = 0. This command renders the site inaccessible to anyone but root user. For root user it shows the normal site and for others it displays a page shown when Drupal is just installed and has no contents: "Welcome to your new Drupal site bla-bla-bla."

Well, it is true that INSERT INTO node_revisions ... should never fail. However it may do so in MySQL: http://bugs.mysql.com/bug.php?id=41984. And surely, DELETE FROM node_access WHERE nid = 0 does not seem a right thing to do regardless. It seems that Drupal site cannot exist without this row.

Attached excerpt from the mysql query log showing the problem.

AttachmentSizeStatusTest resultOperations
duplicate_key_bug.txt4.7 KBIgnoredNoneNone

#3

Has anyone found a fix for this? I've just done the same upgrade and am having the same problem with anonymous access. It's driving me nuts!

#4

Rebuilding user permissions on Post Settings sorted this for me

#5

I think the option to rebuild the permissions table is only available on the "post settings" page if the content access module is installed.

#6

I have also ran across this problem, and after looking at the code and a bit of testing, I highly doubt that rebuilding permissions is a permanent solution. My problem arises in this manner: I have two content types, one uses workflow and workflow_access to restrict edits, the second does not use a workflow at all. Here's the first piece of the puzzle from node.module

<?php
function node_access_acquire_grants($node) {
 
$grants = module_invoke_all('node_access_records', $node);
  if (empty(
$grants)) {
   
$grants[] = array('realm' => 'all', 'gid' => 0, 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0);
  }
  else {
   
// retain grants by highest priority
   
$grant_by_priority = array();
    foreach (
$grants as $g) {
     
$grant_by_priority[intval($g['priority'])][] = $g;
    }
   
krsort($grant_by_priority);
   
$grants = array_shift($grant_by_priority);
  }

 
node_access_write_grants($node, $grants);
}
?>

It appears that the default view permission is only granted if no other modules are granting permissions. Since workflow_access is giving grants sometimes the default view grant is not given. A look at node_access_write_grants() shows the death blow for the default view grant
<?php
function node_access_write_grants($node, $grants, $realm = NULL, $delete = TRUE) {
  if (
$delete) {
   
$query = 'DELETE FROM {node_access} WHERE nid = %d';
    if (
$realm) {
     
$query .= " AND realm in ('%s', 'all')";
    }
   
db_query($query, $node->nid, $realm);
  }
...
?>

So it looks like delete is always gonna be true in this invocation and regardless of whether realm is set or not, the all grant gets deleted. What I haven't traced down yet is why rebuilding permissions restores the grant to it's proper state. I do know, however, that subsequent edits will break the permission again. I'm not really sure the correct approach to solving this problem, that's why I haven't supplied a patch. I think the default behavior of Drupal is confusing and leaves a lot of corner cases for access control modules to cover. I'm going to look over the rebuild permissions code and see if I can find any insight there, then I'll check back with some possible solutions.

#7

Version:6.10» 6.x-dev

#8

After further investigation, I found that I had a misbehaving access control module. The behavior of Drupal core is correct and matches the documentation. My opinion is that some module developers do not understand how the node_access system works and are creating modules with incorrect assumptions about it.

#9

Version:6.x-dev» 6.12

I can replicate the issue when node saving fails for issues like unsupported characters. I am reading from csv file and creating nodes for each line.

Code:

$importNode = new StdClass();
$importNode->uid = $user->uid;
$importNode->name = (isset($user->name) ? $user->name : '');
$importNode->type = 'employee';
...
node_save($importNode);

if node_save fails, that is $importNode->nid =0, in db log I see a call "delete from node_access where nid=0".
When node_save is successfull, in db log I see a call "delete from node_access where nid=165" (or what ever the node id is)

So I guess, there should be a check that nid>0 when deleting from node_access table, as 0 is a default value for integer and unfortunatelly a special value for node_access table.

#10

I was led here by plj in #124137-32: Access denied to anonymous users (was: Node access settings). Some of the posters there may be experiencing this issue here.

I'm not sure what exactly can fail in node_save() that will lead to $node->nid remaining 0, but it's certainly true that the node_access_acquire_grants($node); call near the end of node_save() will cause problems if $node->nid==0.

node_save() could well be made more robust, but I'm not sure there's a consensus that that's the way to go. We could also argue that whoever causes node_save() to fail needs to clean up their act...

#11

Version:6.12» 6.19
Status:active» needs review

Here's a simple patch based on salvis' investigation. I agree that in the ideal case we would figure out why this is happening. On the site where I encounter it the most likely cause is nodes being imported by feeds module. The problem comes up irregularly which makes it really hard to debug, of course, and based on the discussions here that seems fairly common.

So I propose that we just make node_save more robust. The comment is trickier here than the code.

AttachmentSizeStatusTest resultOperations
282555_make_sure_we_have_a_node.patch919 bytesIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 282555_make_sure_we_have_a_node.patch.View details | Re-test

#12

Status:needs review» needs work

The last submitted patch, 282555_make_sure_we_have_a_node.patch, failed testing.

#13

Thanks for picking this up, greggles!

Do your comment lines go beyond col 80?

Can a node that won't load be displayed at all? If we don't node_access_acquire_grants(), the node becomes inaccessible to everyone except user 1 and users with the 'administer nodes' permission. This should probably be mentioned in the comment.

Should we write a watchdog entry? I imagine that these nodes can cause all sorts of trouble (for search, for example), and the admin should be made aware of them. This might also lead to further investigation and create some pressure on the modules that cause this problem in the first place.

#14

If we don't have a nid how can we watchdog anything useful?

#15

True, especially because we can't add new strings. Also, it might make more sense to display a message immediately, so that it appears in the proper context.

There's "The post could not be saved." — can we do something with that?

Since we know that something is wrong, it would be good to provide some kind of indication of that fact and give the site maintainer a fighting chance. But I don't have any good ideas...

#16

Version:6.19» 6.x-dev
Status:needs work» needs review

I'm falling into the problem described here...
Attached the greggles patch revisited in the git way, I hope it will pass the testing.
I also hope it will be inserted into the 6.21 version.

AttachmentSizeStatusTest resultOperations
282555_make_sure_we_have_a_node_revisited.patch732 bytesIdlePASSED: [[SimpleTest]]: [MySQL] 190 pass(es).View details | Re-test