Delete own comments
Add permission to allow comment authors to delete their own comments if there are no replies yet.
This commit is contained in:
parent
3eab51e1c4
commit
a7b3c818f2
@ -3,9 +3,17 @@ Changelog
|
|||||||
|
|
||||||
2.1.6 (unreleased)
|
2.1.6 (unreleased)
|
||||||
------------------
|
------------------
|
||||||
|
- Add permission to allow comment authors to delete their own comments if
|
||||||
|
there are no replies yet.
|
||||||
|
[gaudenz]
|
||||||
|
|
||||||
- Add Site Administrator role to Review comments permission.
|
- Add Site Administrator role to Review comments permission.
|
||||||
[gaudenz]
|
[gaudenz]
|
||||||
|
|
||||||
|
- Add permission to allow comment authors to delete their own comments if
|
||||||
|
there are no replies yet.
|
||||||
|
[gaudenz]
|
||||||
|
|
||||||
- Fix excessive JS comment deletion.
|
- Fix excessive JS comment deletion.
|
||||||
[gaudenz]
|
[gaudenz]
|
||||||
|
|
||||||
|
@ -83,6 +83,19 @@
|
|||||||
<span tal:replace="structure reply/getText" />
|
<span tal:replace="structure reply/getText" />
|
||||||
|
|
||||||
<div class="commentActions">
|
<div class="commentActions">
|
||||||
|
<form name="delete"
|
||||||
|
action=""
|
||||||
|
method="post"
|
||||||
|
tal:condition="python: not view.can_review() and view.could_delete_own(reply)"
|
||||||
|
tal:attributes="action string:${reply/absolute_url}/@@delete-own-comment;
|
||||||
|
style python:view.can_delete_own(reply) and 'display: inline' or 'display: none'">
|
||||||
|
<input name="form.button.DeleteComment"
|
||||||
|
class="destructive"
|
||||||
|
type="submit"
|
||||||
|
value="Delete"
|
||||||
|
i18n:attributes="value label_delete;"
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
<form name="delete"
|
<form name="delete"
|
||||||
action=""
|
action=""
|
||||||
method="post"
|
method="post"
|
||||||
|
@ -190,6 +190,7 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
|
|||||||
# Member
|
# Member
|
||||||
member = portal_membership.getAuthenticatedMember()
|
member = portal_membership.getAuthenticatedMember()
|
||||||
username = member.getUserName()
|
username = member.getUserName()
|
||||||
|
userid = member.getUserId()
|
||||||
email = member.getProperty('email')
|
email = member.getProperty('email')
|
||||||
fullname = member.getProperty('fullname')
|
fullname = member.getProperty('fullname')
|
||||||
if not fullname or fullname == '':
|
if not fullname or fullname == '':
|
||||||
@ -206,6 +207,10 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
|
|||||||
comment.user_notification = user_notification
|
comment.user_notification = user_notification
|
||||||
comment.creation_date = datetime.utcnow()
|
comment.creation_date = datetime.utcnow()
|
||||||
comment.modification_date = datetime.utcnow()
|
comment.modification_date = datetime.utcnow()
|
||||||
|
|
||||||
|
# add local "Owner" role for current user
|
||||||
|
comment.manage_setLocalRoles(userid, ['Owner'])
|
||||||
|
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
raise Unauthorized("Anonymous user tries to post a comment, but "
|
raise Unauthorized("Anonymous user tries to post a comment, but "
|
||||||
"anonymous commenting is disabled. Or user does not have the "
|
"anonymous commenting is disabled. Or user does not have the "
|
||||||
@ -283,6 +288,24 @@ class CommentsViewlet(ViewletBase):
|
|||||||
return getSecurityManager().checkPermission('Review comments',
|
return getSecurityManager().checkPermission('Review comments',
|
||||||
aq_inner(self.context))
|
aq_inner(self.context))
|
||||||
|
|
||||||
|
def can_delete_own(self, comment):
|
||||||
|
"""Returns true if the current user can delete the comment. Only
|
||||||
|
comments without replies can be deleted.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return comment.restrictedTraverse('@@delete-own-comment').can_delete()
|
||||||
|
except Unauthorized:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def could_delete_own(self, comment):
|
||||||
|
"""Returns true if the current user could delete the comment if it had no
|
||||||
|
replies. This is used to prepare hidden form buttons for JS.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return comment.restrictedTraverse('@@delete-own-comment').could_delete()
|
||||||
|
except Unauthorized:
|
||||||
|
return False
|
||||||
|
|
||||||
def is_discussion_allowed(self):
|
def is_discussion_allowed(self):
|
||||||
context = aq_inner(self.context)
|
context = aq_inner(self.context)
|
||||||
return context.restrictedTraverse('@@conversation_view').enabled()
|
return context.restrictedTraverse('@@conversation_view').enabled()
|
||||||
@ -346,7 +369,6 @@ class CommentsViewlet(ViewletBase):
|
|||||||
conversation = IConversation(context)
|
conversation = IConversation(context)
|
||||||
|
|
||||||
wf = getToolByName(context, 'portal_workflow')
|
wf = getToolByName(context, 'portal_workflow')
|
||||||
|
|
||||||
# workflow_actions is only true when user
|
# workflow_actions is only true when user
|
||||||
# has 'Manage portal' permission
|
# has 'Manage portal' permission
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
permission="zope2.View"
|
permission="zope2.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Delete comment view -->
|
<!-- Delete comment views -->
|
||||||
<browser:page
|
<browser:page
|
||||||
for="plone.app.discussion.interfaces.IComment"
|
for="plone.app.discussion.interfaces.IComment"
|
||||||
name="moderate-delete-comment"
|
name="moderate-delete-comment"
|
||||||
@ -80,6 +80,14 @@
|
|||||||
permission="plone.app.discussion.ReviewComments"
|
permission="plone.app.discussion.ReviewComments"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<browser:page
|
||||||
|
for="plone.app.discussion.interfaces.IComment"
|
||||||
|
name="delete-own-comment"
|
||||||
|
layer="..interfaces.IDiscussionLayer"
|
||||||
|
class=".moderation.DeleteOwnComment"
|
||||||
|
permission="plone.app.discussion.DeleteOwnComments"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- Publish comment view -->
|
<!-- Publish comment view -->
|
||||||
<browser:page
|
<browser:page
|
||||||
for="plone.app.discussion.interfaces.IComment"
|
for="plone.app.discussion.interfaces.IComment"
|
||||||
|
@ -193,6 +193,9 @@
|
|||||||
$(this).remove();
|
$(this).remove();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// Add delete button to the parent
|
||||||
|
var parent = comment.prev('[class*="replyTreeLevel' + (treelevel - 1) + '"]');
|
||||||
|
parent.find('form[name="delete"]').css('display', 'inline');
|
||||||
// remove comment
|
// remove comment
|
||||||
$(this).fadeOut('fast', function () {
|
$(this).fadeOut('fast', function () {
|
||||||
$(this).remove();
|
$(this).remove();
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from Acquisition import aq_inner, aq_parent
|
from Acquisition import aq_inner, aq_parent
|
||||||
|
|
||||||
|
from AccessControl import Unauthorized, getSecurityManager
|
||||||
|
|
||||||
from Products.Five.browser import BrowserView
|
from Products.Five.browser import BrowserView
|
||||||
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
|
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
|
||||||
|
|
||||||
@ -10,6 +12,7 @@ from Products.statusmessages.interfaces import IStatusMessage
|
|||||||
|
|
||||||
from plone.app.discussion.interfaces import _
|
from plone.app.discussion.interfaces import _
|
||||||
from plone.app.discussion.interfaces import IComment
|
from plone.app.discussion.interfaces import IComment
|
||||||
|
from plone.app.discussion.interfaces import IReplies
|
||||||
|
|
||||||
|
|
||||||
class View(BrowserView):
|
class View(BrowserView):
|
||||||
@ -104,6 +107,34 @@ class DeleteComment(BrowserView):
|
|||||||
return self.context.REQUEST.RESPONSE.redirect(came_from)
|
return self.context.REQUEST.RESPONSE.redirect(came_from)
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteOwnComment(DeleteComment):
|
||||||
|
"""Delete an own comment if it has no replies. Following conditions have to be true
|
||||||
|
for a user to be able to delete his comments:
|
||||||
|
* "Delete own comments" permission
|
||||||
|
* no replies to the comment
|
||||||
|
* Owner role directly assigned on the comment object
|
||||||
|
"""
|
||||||
|
|
||||||
|
def could_delete(self):
|
||||||
|
"""returns true if the comment could be deleted if it had no replies."""
|
||||||
|
sm = getSecurityManager()
|
||||||
|
context = aq_inner(self.context)
|
||||||
|
userid = sm.getUser().getId()
|
||||||
|
return (sm.checkPermission('Delete own comments',
|
||||||
|
context)
|
||||||
|
and 'Owner' in context.get_local_roles_for_userid(userid))
|
||||||
|
|
||||||
|
def can_delete(self):
|
||||||
|
return (len(IReplies(aq_inner(self.context))) == 0
|
||||||
|
and self.could_delete())
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
if self.can_delete():
|
||||||
|
super(DeleteOwnComment, self).__call__()
|
||||||
|
else:
|
||||||
|
raise Unauthorized("Your not allowed to delete this comment.")
|
||||||
|
|
||||||
|
|
||||||
class PublishComment(BrowserView):
|
class PublishComment(BrowserView):
|
||||||
"""Publish a comment.
|
"""Publish a comment.
|
||||||
|
|
||||||
|
@ -9,4 +9,9 @@
|
|||||||
title="Review comments"
|
title="Review comments"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<permission
|
||||||
|
id="plone.app.discussion.DeleteOwnComments"
|
||||||
|
title="Delete own comments"
|
||||||
|
/>
|
||||||
|
|
||||||
</configure>
|
</configure>
|
||||||
|
@ -9,5 +9,11 @@
|
|||||||
<permission name="Reply to item" acquire="False">
|
<permission name="Reply to item" acquire="False">
|
||||||
<role name="Authenticated"/>
|
<role name="Authenticated"/>
|
||||||
</permission>
|
</permission>
|
||||||
|
<permission name="Delete own comments" acquire="False">
|
||||||
|
<role name="Manager"/>
|
||||||
|
<role name="Site Administrator"/>
|
||||||
|
<role name="Reviewer"/>
|
||||||
|
<role name="Owner"/>
|
||||||
|
</permission>
|
||||||
</permissions>
|
</permissions>
|
||||||
</rolemap>
|
</rolemap>
|
||||||
|
Loading…
Reference in New Issue
Block a user