There is only one perm, now : administer comments on ALL nodes, whoever created the node, and whatever is the content-type of that node. I need more granularity in access control for a specific application.
From another forum thread, I gather that some serious comment.module hacking is in order for this... ?
Trouble is how do I know from the comment itself, say $comment passed as argument to a function, who is the author of the node that comment is attached to, in php, insde comment.module ? Not the author of the comment, but the author of the node the comment is attached to ?
So far here's what I did :
In my custom type module, short_story.module, I added a perm : 'administer comments of own short stories'.
And I am checking this for registered users.
In comment.module, I modified the function comment_form_alter to add the comment settings at the bottom of the page in edit mode :
function comment_form_alter($form_id, &$form) {
if (isset($form['type'])) {
if ($form['type']['#value'] .'_node_settings' == $form_id) {
$form['workflow']['comment_'. $form['type']['#value']] = array('#type' => 'radios', '#title' => t('Default comment setting'), '#default_value' => variable_get('comment_'. $form['type']['#value'], COMMENT_NODE_READ_WRITE), '#options' => array(t('Disabled'), t('Read only'), t('Read/Write')), '#description' => t('Users with the <em>administer comments</em> permission will be able to override this setting.'));
}
if ($form['type']['#value'] .'_node_form' == $form_id) {
$node = $form['#node'];
if (user_access('administer comments') || user_access('administer comments of own short stories')) {
$form['comment_settings'] = array(
'#type' => 'fieldset',
'#title' => t('Comment settings'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#weight' => 30,
);
$form['comment_settings']['comment'] = array(
'#type' => 'radios',
'#parents' => array('comment'),
'#default_value' => $node->comment,
'#options' => array(t('Disabled'), t('Read only'), t('Read/Write')),
);
}
else {
$form['comment_settings']['comment'] = array(
'#type' => 'value',
'#value' => $node->comment,
);
}
}
}
}The only line that is modified in the above code snippet is :
if (user_access('administer comments') || user_access('administer comments of own short stories')) {
Now I am faced with the second challenge which is to allow users to edit/delete comments in their own nodes.
The function that I now need to modify is comment_links :
function comment_links($comment, $return = 1) {
global $user;
$links = array();
// If we are viewing just this comment, we link back to the node.
if ($return) {
$links[] = l(t('parent'), comment_node_url(), NULL, NULL, "comment-$comment->cid");
}
if (node_comment_mode($comment->nid) == COMMENT_NODE_READ_WRITE) {
if (user_access('administer comments') && user_access('post comments')) {
$links[] = l(t('delete'), "comment/delete/$comment->cid");
$links[] = l(t('edit'), "comment/edit/$comment->cid");
$links[] = l(t('reply'), "comment/reply/$comment->nid/$comment->cid");
}
else if (user_access('post comments')) {
if (comment_access('edit', $comment)) {
$links[] = l(t('edit'), "comment/edit/$comment->cid");
}
$links[] = l(t('reply'), "comment/reply/$comment->nid/$comment->cid");
}
else {
$links[] = theme('comment_post_forbidden', $comment->nid);
}
}
return $links;
}
I need to add the edit/delete and reply links when :
-> user_access('administer comments of own short stories') and
-> the $user->uid is equal to the uid of the creator of the node to which the comment ($comment) is attached.
I have trouble checking for the second condition. Please help.
Comments
Is that the only route ?
Is the only route here to :
1. Use $comment->nid
2. Look up the database to find the uid associated with that nid.
Thanks
Caroline
hook_menu
It seems I have to modify the comment_menu function as well in order for users to actually be able to access the edit and delete pages of comments.
Can someone help ?
I guess module development expertise is required here.
Caroline
I moved the links stuff
I moved the links stuff from comment_module to my custom type module, which gives me the same good results but is less of a hack :
Now I am still left with removing that "denied access" for the edit and delete pages...
I modified my short_story_menu function :
Trouble is that I don't even understand what I am doing in the hook_menu function...
Can someone take a look at this, please ?
Caroline
Where in the code...?
I want to modify EITHER comment.module or
short_story.module to
by checking to see if the user can edit a node, let him/her edit/delete the comments of the node as well
Caroline
Progress?
Hi Caroline -- did you make any progress with this?
It seems like it would be really useful feature.
--
I dropped that along the way. I did not get any help, so.
Now that I am looking at this again, I think I can figure it out. It would still be a hack, though. I really believe that we need one more perm in Drupal core : administer own nodes comments.
Maybe I can create a patch and a feature request. I will solve the puzzle and come back here to explain the hack.
Creating a module for this is overkill in my opinion (for me anyway), but it can be done, and should.
Caroline
Who am I | Where are we
11 heavens
A wacky idea
Instead of hacking the comment.module, why don't you write a tiny module that grants users the 'administer comments' permission at run time, at
mymodule_init?--
That's a great idea!!!!! If I achieve this I give you credit... there's no way in hell I would have ever thought about going at it this way. It's really creative. I would do this for ony certain content types - maybe a minimalist admin settings page that lists current content types to check... and voilà.
Maybe I should use hook_menu instead ?
Now how do I force a perm on a user at runtime ? (based on another perm).
Thanks Mooffie.
Caroline
Who am I | Where are we
11 heavens
...
Well, what I have in mind is a quite ugly and tricky. I didn't test the idea, but I believe it might work.
Drupal calls
user_access('administer comments')to check if we have the right permission. If you examine the source code you see that we need to use some trick to circumvent its internal cache ("static $parm" is a cahce; it's a common technique in Drupal code).The plan, which may or may not work:
I agree. It's a feature I always wanted.
Trial and error. Some module may call user_access() before we have a chance to do that ourselves. That's why I suggested hook_init(). But maybe if we assign a negative weight to our module we can use hook_menu():
Ugly. More tricks may be needed.
Maybe it would be easier to continue with your original plan. You have one small thing left to do, if I understand correctly; you have to modifiy
comment_access(); you don't need to touchcomment_menu()....
BTW, In Drupal 5.0 you no longer need to modify a core module to fix such things.
In the past, modules had the following pattern:
Drupal 5.0 introduces the '#access' attribute; modules now use the following pattern:
The advantage is that now you can implement
hook_form_alterin your module and set this other module's '#access' to TRUE.That's one less modification to 'comment.module'.
...
comment_menu() delegates to comment_edit(), when one asks to edit a comment. It's this function, and not comment_menu(), the one that checks the permission, and it does this by calling comment_access(). this comment_access() is quite trivial. I hope it's the last piece in your puzzle.
Very simple (and dirty) one-line hack
One way to let a user administer only the comments of his own nodes is to give him 'administer comments' access and filter the list of comments displayed by admin/content/comment.
I hacked comment.module, function comment_admin_overview() to achieve this, line 1180 (Drupal 5.1):
That's all. Only users with 'administer comments' and 'update' access on a given node can delete or moderate the related comments. The good news is that it is compatible with Taxonomy Access module, which i use much.
Another little hack
Another little hack: now we want to prevent users who can administer comments on their own nodes to change the system-wide settings of the comment module. We only want the administrator to access the settings. To do this, we display the tab "settings" only to the administrator. Of course, if a user with 'administer comment' access knows the url, he can still go to the settings page.
function comment_menu(), line 172:
You'll have to wait a while for the cache of the menus to be updated, or manually flush the {cache_menu} table of Drupal.
bad idea
It's only a list. Users would be able to navigate to q=comment/edit/<comment-id> and edit any comment.
No, he won't be able to access that URL (becasue 'access'=>false).
===
Modifying core to let users edit their nodes' comments is easy. We're trying to achieve this without touching core. I've came up with another idea, but have yet to check it out.
You're right. I'll be happy
You're right. I'll be happy to use a good (and bullet-proof ;) module to extend the core Comments module when it's ready.
That's true, and the "edit" and "delete" links are displayed next to all comments for a user who has "administer comments" access. Hacking a little bit more in comment.module, it's possible to prevent this, changing line 835:
to:
It is not still very secure, as nothing prevents a user with "administer comments" access to edit or delete a comment if he knows the url to do it. I further hacked comment.module to fix this. The idea is to limit "administer comments" access to the nodes the user has "update" access to. So it consists on looking for the expression:
and replace it with something like:
or
or
(depending on how the nid of the node is available). This is VERY dirty indeed, but will make the hack more secure.
--
As long as
- a hack involves 2-3 lines of code changed maximum
- I put a comment next to my hacks with my full name (whatever word one can use to find quickly while searching)
- I add a description of each of my hacks to a list of hacks in a notebook (with file name, line number, etc.)
- I keep the number of items in that list to a minimum
- I replace the hacks with clean solutions as my expertise increases
Then I do what I have to do.
Caroline
Who am I | Where are we
11 heavens