Ok, so maybe I'm stupid, or maybe something changed in 4.3.0.
I'm trying to do the following: accept mail from a user with permissions to post a story, but without a password in the commmand. I have security disabled.
expect: that it will post the story
get: an error saying that the (correct) email address may not update items
If I allow anonymous users to post, then it works. If I post a story directly as that user it works. If I use the Retrieve link in the mailhandler UI then it works. It only fails if its triggered by a cron job - which of course is the anonymous user as shown by the messages logs.
It seems to be failing the node_access() check near line 107, because it correctly finds the user and passes the mailhandler_authenticate() check (verified with lots of watchdog() debug statements).
Is it possible that 4.3.0 introduced more stringent user validation that relies on a global $user variable that is only set by an actual user? Or something like this? (Looking at the node.module and user.module code suggests this).
Any further suggestions on how to debug and/or fix this? Thanks!
Comments
Comment #1
jjanssen commentedNo solution, but I believe I am experiencing the same problem. I traced it a bit further, but I think your appraisal is about right... node_access calls the specific node type module access function (story_access in my case), which in turn calls user_access. The user variable is a global there, which says to me that the function is used for "what user is logged in" versus "what user I tell you", if that makes sense. Perhaps using a different node type would fix this. If I find anything more I'll post it here...
Comment #2
moshe weitzman commentedmailhandler used to successfully post these emails by changing $user to a global. then bruno committed a change which avoids the global.
Bruno - should we rollback your commit?
Comment #3
bruno commentedI'm at work with no access to my notes. Let me check that tonight, please ;-)
Bruno
Comment #4
bruno commentedjjanssen, you are right when you say:
The user variable is a global there, which says to me that the function is used for "what user is logged in" versus "what user I tell you"
about user_access(), and that's the problem.
I have made a change to mailhandler, removing the $user globals because it caused the current logged user to be "switched" to the user from which originated the messages, when processing the messages manually (admin>>configuration>>modules>>mailhandler>>retrieve).
It was apparently working OK with cron, because I was still logged in when I ran cron.php. Then user_access() was happy.
Now, if we reintroduce the $user global in mailhandler, we will also reintroduce the "user switching" problem. Maybe we could consider it as a minor defect compaired to this issue.
We could solve both issues easily, if user module would allow checking user access rights without the need of loading user data into $user global.
Any other suggestion?
Comment #5
TDobes commentedMoshe's taxonomy_access patch [1] enhances the user_access function to allow it to check permissions of an account passed as the second (optional) argument. Perhaps this part of the patch could be separated and added to the core to solve this problem. This would avoid the problem of needing to change the $user global for CVS, but not for 4.3, I'm afraid.
[1] http://cvs.drupal.org/viewcvs/contributions/sandbox/moshe/taxonomy_acces...
Comment #6
jjanssen commentedAha, but it isn't as simple as getting whether or not our specific user has access, we also need to post it _as_ that user. Using that taxonomy_access patch as an example, I tried to hack the code to to get user_access to take an optional account variable (but still default to global $user). I got it to work, but it posted as Anonymous and not my user! Rather than hack around doing the same sort of stuff (in several files), I simply added the following three lines:
FILE mailhandler.module:
FIND:
function mailhandler_node_submit($node, $header, $mailbox, $origbody) {
ADD BELOW:
global $user;
FIND:
$fromaddress = mailhandler_get_fromaddress($header, $mailbox);
ADD BELOW:
$user = user_load(array("mail" => $fromaddress));
FIND:
user_mail($fromaddress, t("Email submission to %sn failed - %subj", array ("%sn" => variable_get("site_name", "Drupal"), "%subj" => $node->title)), $errortxt, $headers);
}
}
ADD BELOW:
$user = user_load( array("uid" => 0 ));
And that's it! Three lines. Bruno, I think this addresses the problem of "user switching" by switching back to the Anonymous user just before the function ends. I'll agree that this probably isn't the "right" solution, but it is a lot simpler than patching a ton of modules and functions. I've tested this with one email, I'd like a test where there are multiple emails coming in at the same time so I can see it switch between the users successfully.
Comment #7
moshe weitzman commentedI agree that we have to change the global user as we process each message. After processing all messages, we should switch back to the original user (which is anonymous in the case of cron, but is an admin in the case of manual retrieve).
Comment #8
killes@www.drop.org commentedThere is a fix in cvs.
Comment #9
(not verified) commented