added Delete comments permission to manage comments deletion
This commit is contained in:
parent
6ee480a229
commit
920392d124
@ -25,12 +25,12 @@ Changelog
|
|||||||
|
|
||||||
- Fix ownership of comments. [toutpt]
|
- Fix ownership of comments. [toutpt]
|
||||||
|
|
||||||
- Provide 'delete own comments' as a configurable option
|
|
||||||
[gyst]
|
|
||||||
|
|
||||||
- Make comments editable.
|
- Make comments editable.
|
||||||
[pjstevns, gyst]
|
[pjstevns, gyst]
|
||||||
|
|
||||||
|
- Provide 'Delete comments' permission to handle comments deletion
|
||||||
|
[cekk]
|
||||||
|
|
||||||
2.2.10 (2013-09-24)
|
2.2.10 (2013-09-24)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
@ -312,18 +312,9 @@ class CommentsViewlet(ViewletBase):
|
|||||||
"""By default requires 'Review comments'.
|
"""By default requires 'Review comments'.
|
||||||
If 'delete own comments' is enabled, requires 'Edit comments'.
|
If 'delete own comments' is enabled, requires 'Edit comments'.
|
||||||
"""
|
"""
|
||||||
if self.is_delete_own_comment_allowed():
|
return getSecurityManager().checkPermission('Delete comments',
|
||||||
permission = 'Edit comments'
|
|
||||||
else:
|
|
||||||
permission = 'Review comments'
|
|
||||||
return getSecurityManager().checkPermission(permission,
|
|
||||||
aq_inner(reply))
|
aq_inner(reply))
|
||||||
|
|
||||||
def is_delete_own_comment_allowed(self):
|
|
||||||
registry = queryUtility(IRegistry)
|
|
||||||
settings = registry.forInterface(IDiscussionSettings, check=False)
|
|
||||||
return settings.delete_own_comment_enabled
|
|
||||||
|
|
||||||
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()
|
||||||
|
@ -88,7 +88,7 @@
|
|||||||
name="moderate-delete-comment"
|
name="moderate-delete-comment"
|
||||||
layer="..interfaces.IDiscussionLayer"
|
layer="..interfaces.IDiscussionLayer"
|
||||||
class=".moderation.DeleteComment"
|
class=".moderation.DeleteComment"
|
||||||
permission="zope2.DeleteObjects"
|
permission="plone.app.discussion.DeleteComments"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Publish comment view -->
|
<!-- Publish comment view -->
|
||||||
|
@ -54,8 +54,6 @@ class DiscussionSettingsEditForm(controlpanel.RegistryEditForm):
|
|||||||
SingleCheckBoxFieldWidget
|
SingleCheckBoxFieldWidget
|
||||||
self.fields['edit_comment_enabled'].widgetFactory = \
|
self.fields['edit_comment_enabled'].widgetFactory = \
|
||||||
SingleCheckBoxFieldWidget
|
SingleCheckBoxFieldWidget
|
||||||
self.fields['delete_own_comment_enabled'].widgetFactory = \
|
|
||||||
SingleCheckBoxFieldWidget
|
|
||||||
self.fields['anonymous_comments'].widgetFactory = \
|
self.fields['anonymous_comments'].widgetFactory = \
|
||||||
SingleCheckBoxFieldWidget
|
SingleCheckBoxFieldWidget
|
||||||
self.fields['show_commenter_image'].widgetFactory = \
|
self.fields['show_commenter_image'].widgetFactory = \
|
||||||
|
@ -117,18 +117,9 @@ class DeleteComment(BrowserView):
|
|||||||
"""By default requires 'Review comments'.
|
"""By default requires 'Review comments'.
|
||||||
If 'delete own comments' is enabled, requires 'Edit comments'.
|
If 'delete own comments' is enabled, requires 'Edit comments'.
|
||||||
"""
|
"""
|
||||||
if self.is_delete_own_comment_allowed():
|
return getSecurityManager().checkPermission('Delete comments',
|
||||||
permission = 'Edit comments'
|
|
||||||
else:
|
|
||||||
permission = 'Review comments'
|
|
||||||
return getSecurityManager().checkPermission(permission,
|
|
||||||
aq_inner(reply))
|
aq_inner(reply))
|
||||||
|
|
||||||
def is_delete_own_comment_allowed(self):
|
|
||||||
registry = queryUtility(IRegistry)
|
|
||||||
settings = registry.forInterface(IDiscussionSettings, check=False)
|
|
||||||
return settings.delete_own_comment_enabled
|
|
||||||
|
|
||||||
|
|
||||||
class PublishComment(BrowserView):
|
class PublishComment(BrowserView):
|
||||||
"""Publish a comment.
|
"""Publish a comment.
|
||||||
|
@ -253,17 +253,6 @@ class IDiscussionSettings(Interface):
|
|||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
delete_own_comment_enabled = schema.Bool(
|
|
||||||
title=_(u"label_delete_own_comment_enabled",
|
|
||||||
default="Allow users to delete their own comment threads"),
|
|
||||||
description=_(u"help_edit_comment_enabled",
|
|
||||||
default=u"If selected, users may delete their own "
|
|
||||||
"comments -> AND the whole reply thread below that "
|
|
||||||
"comment!"),
|
|
||||||
required=False,
|
|
||||||
default=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
text_transform = schema.Choice(
|
text_transform = schema.Choice(
|
||||||
title=_(u"label_text_transform",
|
title=_(u"label_text_transform",
|
||||||
default="Comment text transform"),
|
default="Comment text transform"),
|
||||||
|
@ -14,5 +14,9 @@
|
|||||||
title="Edit comments"
|
title="Edit comments"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<permission
|
||||||
|
id="plone.app.discussion.DeleteComments"
|
||||||
|
title="Delete comments"
|
||||||
|
/>
|
||||||
|
|
||||||
</configure>
|
</configure>
|
||||||
|
@ -12,6 +12,11 @@
|
|||||||
<role name="Reviewer"/>
|
<role name="Reviewer"/>
|
||||||
<role name="Owner"/>
|
<role name="Owner"/>
|
||||||
</permission>
|
</permission>
|
||||||
|
<permission name="Delete comments" acquire="True">
|
||||||
|
<role name="Manager"/>
|
||||||
|
<role name="Site Administrator"/>
|
||||||
|
<role name="Reviewer"/>
|
||||||
|
</permission>
|
||||||
<permission name="Reply to item" acquire="False">
|
<permission name="Reply to item" acquire="False">
|
||||||
<role name="Authenticated"/>
|
<role name="Authenticated"/>
|
||||||
</permission>
|
</permission>
|
||||||
|
@ -28,6 +28,8 @@ class PloneAppDiscussion(PloneSandboxLayer):
|
|||||||
USER_WITH_FULLNAME_PASSWORD = 'secret'
|
USER_WITH_FULLNAME_PASSWORD = 'secret'
|
||||||
MANAGER_USER_NAME = 'manager'
|
MANAGER_USER_NAME = 'manager'
|
||||||
MANAGER_USER_PASSWORD = 'secret'
|
MANAGER_USER_PASSWORD = 'secret'
|
||||||
|
REVIEWER_NAME = 'reviewer'
|
||||||
|
REVIEWER_PASSWORD = 'secret'
|
||||||
|
|
||||||
def setUpZope(self, app, configurationContext):
|
def setUpZope(self, app, configurationContext):
|
||||||
# Load ZCML
|
# Load ZCML
|
||||||
@ -60,7 +62,15 @@ class PloneAppDiscussion(PloneSandboxLayer):
|
|||||||
['Member'],
|
['Member'],
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
|
acl_users.userFolderAddUser(
|
||||||
|
self.REVIEWER_NAME,
|
||||||
|
self.REVIEWER_PASSWORD,
|
||||||
|
['Member'],
|
||||||
|
[],
|
||||||
|
)
|
||||||
mtool = getToolByName(portal, 'portal_membership', None)
|
mtool = getToolByName(portal, 'portal_membership', None)
|
||||||
|
gtool = getToolByName(portal, 'portal_groups', None)
|
||||||
|
gtool.addPrincipalToGroup(self.REVIEWER_NAME, 'Reviewers')
|
||||||
mtool.addMember('jim', 'Jim', ['Member'], [])
|
mtool.addMember('jim', 'Jim', ['Member'], [])
|
||||||
mtool.getMemberById('jim').setMemberProperties(
|
mtool.getMemberById('jim').setMemberProperties(
|
||||||
{"fullname": 'Jim Fult\xc3\xb8rn'})
|
{"fullname": 'Jim Fult\xc3\xb8rn'})
|
||||||
|
@ -32,6 +32,7 @@ you're not logged in::
|
|||||||
>>> unprivileged_browser = Browser(app)
|
>>> unprivileged_browser = Browser(app)
|
||||||
>>> browser_member = Browser(app)
|
>>> browser_member = Browser(app)
|
||||||
>>> browser_user = Browser(app)
|
>>> browser_user = Browser(app)
|
||||||
|
>>> browser_reviewer = Browser(app)
|
||||||
|
|
||||||
Make sure we have a test user from the layer and it uses fancy characters:
|
Make sure we have a test user from the layer and it uses fancy characters:
|
||||||
|
|
||||||
@ -143,7 +144,6 @@ Post a comment as member
|
|||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
Login as user 'jim'.
|
Login as user 'jim'.
|
||||||
|
|
||||||
>>> browser_member.open(portal_url + '/login_form')
|
>>> browser_member.open(portal_url + '/login_form')
|
||||||
>>> browser_member.getControl(name='__ac_name').value = 'jim'
|
>>> browser_member.getControl(name='__ac_name').value = 'jim'
|
||||||
>>> browser_member.getControl(name='__ac_password').value = 'secret'
|
>>> browser_member.getControl(name='__ac_password').value = 'secret'
|
||||||
@ -320,8 +320,8 @@ But Anon can see the edited comment.
|
|||||||
True
|
True
|
||||||
|
|
||||||
|
|
||||||
Deleting existing comments | 'delete own comments' disabled
|
Deleting existing comments | 'Delete comments' permission
|
||||||
-----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
|
|
||||||
Anonymous cannot delete comments
|
Anonymous cannot delete comments
|
||||||
|
|
||||||
@ -329,7 +329,7 @@ Anonymous cannot delete comments
|
|||||||
>>> 'form.button.Delete' in unprivileged_browser.contents
|
>>> 'form.button.Delete' in unprivileged_browser.contents
|
||||||
False
|
False
|
||||||
|
|
||||||
A member cannot delete his own comments, unless this is explicitly enabled (see later)
|
A member cannot delete his own comments if he can't review or he isn't a Site Administrator
|
||||||
|
|
||||||
>>> browser_member.open(urldoc1)
|
>>> browser_member.open(urldoc1)
|
||||||
>>> 'form.button.Delete' in browser_member.contents
|
>>> 'form.button.Delete' in browser_member.contents
|
||||||
@ -360,7 +360,6 @@ The comment is still there
|
|||||||
>>> comment_id in unprivileged_browser.contents
|
>>> comment_id in unprivileged_browser.contents
|
||||||
True
|
True
|
||||||
|
|
||||||
|
|
||||||
A Member cannot delete even his own comment by hitting the delete url directly.
|
A Member cannot delete even his own comment by hitting the delete url directly.
|
||||||
|
|
||||||
Extract the member comment id from the admin browser
|
Extract the member comment id from the admin browser
|
||||||
@ -387,10 +386,17 @@ The comment is still there
|
|||||||
>>> 'Comment from Jim' in browser_member.contents
|
>>> 'Comment from Jim' in browser_member.contents
|
||||||
True
|
True
|
||||||
|
|
||||||
Admin, who hase 'review comments' permission, can delete comments
|
Now login as user 'reviewer'
|
||||||
|
|
||||||
>>> browser.open(urldoc1)
|
>>> browser_reviewer.open(portal_url + '/login_form')
|
||||||
>>> form = browser.getForm(name='delete', index=0)
|
>>> browser_reviewer.getControl(name='__ac_name').value = 'reviewer'
|
||||||
|
>>> browser_reviewer.getControl(name='__ac_password').value = 'secret'
|
||||||
|
>>> browser_reviewer.getControl(name='submit').click()
|
||||||
|
|
||||||
|
Admin and who have 'Delete comments' permission (reviewers for example), can delete comments
|
||||||
|
|
||||||
|
>>> browser_reviewer.open(urldoc1)
|
||||||
|
>>> form = browser_reviewer.getForm(name='delete', index=0)
|
||||||
>>> '@@moderate-delete-comment' in form.action
|
>>> '@@moderate-delete-comment' in form.action
|
||||||
True
|
True
|
||||||
|
|
||||||
@ -406,58 +412,8 @@ We'll just catch that and check the result later.
|
|||||||
|
|
||||||
Returning to the document we find the deleted comment is indeed gone
|
Returning to the document we find the deleted comment is indeed gone
|
||||||
|
|
||||||
>>> browser.open(urldoc1)
|
>>> browser_reviewer.open(urldoc1)
|
||||||
>>> comment_id in browser.contents
|
>>> comment_id in browser_reviewer.contents
|
||||||
False
|
|
||||||
|
|
||||||
|
|
||||||
Deleting existing comments | 'delete own comments' ENABLED
|
|
||||||
----------------------------------------------------------
|
|
||||||
|
|
||||||
Enable deletion of own comments
|
|
||||||
|
|
||||||
>>> from zope.component import queryUtility
|
|
||||||
>>> from plone.registry.interfaces import IRegistry
|
|
||||||
>>> from plone.app.discussion.interfaces import IDiscussionSettings
|
|
||||||
>>> registry = queryUtility(IRegistry)
|
|
||||||
>>> settings = registry.forInterface(IDiscussionSettings)
|
|
||||||
>>> settings.delete_own_comment_enabled = True
|
|
||||||
|
|
||||||
>>> import transaction
|
|
||||||
>>> transaction.commit()
|
|
||||||
|
|
||||||
Anonymous still cannot delete comments
|
|
||||||
|
|
||||||
>>> unprivileged_browser.open(urldoc1)
|
|
||||||
>>> 'form.button.Delete' in unprivileged_browser.contents
|
|
||||||
False
|
|
||||||
|
|
||||||
A member can now delete his own comments
|
|
||||||
|
|
||||||
>>> browser_member.open(urldoc1)
|
|
||||||
>>> 'form.button.Delete' in browser_member.contents
|
|
||||||
True
|
|
||||||
|
|
||||||
>>> form = browser_member.getForm(name='delete', index=0)
|
|
||||||
>>> '@@moderate-delete-comment' in form.action
|
|
||||||
True
|
|
||||||
|
|
||||||
>>> comment_id = form.action.split('/')[-2]
|
|
||||||
|
|
||||||
Submitting the form runs into a testbrowser notFoundException.
|
|
||||||
We'll just catch that and check the result later.
|
|
||||||
|
|
||||||
>>> try:
|
|
||||||
... form.submit()
|
|
||||||
... except:
|
|
||||||
... pass
|
|
||||||
|
|
||||||
Returning to the document we find the deleted comment is indeed gone
|
|
||||||
|
|
||||||
>>> browser_member.open(urldoc1)
|
|
||||||
>>> comment_id in browser_member.contents
|
|
||||||
False
|
|
||||||
>>> 'Comment from Jim' in browser_member.contents
|
|
||||||
False
|
False
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user