--- a/src/pyams_content/shared/common/zmi/__init__.py Tue Oct 01 08:31:43 2019 +0200
+++ b/src/pyams_content/shared/common/zmi/__init__.py Tue Oct 01 12:04:20 2019 +0200
@@ -10,8 +10,6 @@
# FOR A PARTICULAR PURPOSE.
#
-__docformat__ = 'restructuredtext'
-
from datetime import datetime
from uuid import uuid4
@@ -24,10 +22,10 @@
from zope.location import locate
from pyams_content.features.review.interfaces import IReviewComments
-from pyams_content.interfaces import CREATE_CONTENT_PERMISSION, MANAGE_CONTENT_PERMISSION, MANAGE_SITE_ROOT_PERMISSION, \
- PUBLISH_CONTENT_PERMISSION
-from pyams_content.shared.common.interfaces import IBaseSharedTool, IManagerRestrictions, ISharedContent, \
- IWfSharedContent
+from pyams_content.interfaces import CREATE_CONTENT_PERMISSION, MANAGE_CONTENT_PERMISSION, \
+ MANAGE_SITE_ROOT_PERMISSION, PUBLISH_CONTENT_PERMISSION
+from pyams_content.shared.common.interfaces import IBaseSharedTool, IContributorRestrictions, \
+ IManagerRestrictions, ISharedContent, IWfSharedContent
from pyams_form.form import AJAXAddForm, ajax_config
from pyams_form.interfaces.form import IFormContextPermissionChecker, IWidgetsPrefixViewletsManager
from pyams_form.schema import CloseButton
@@ -44,20 +42,24 @@
from pyams_skin.viewlet.breadcrumb import BreadcrumbAdminLayerItem
from pyams_skin.viewlet.toolbar import ToolbarMenuDivider, ToolbarMenuItem
from pyams_template.template import template_config
-from pyams_utils.adapter import ContextAdapter, ContextRequestAdapter, ContextRequestViewAdapter, adapter_config
+from pyams_utils.adapter import ContextAdapter, ContextRequestAdapter, ContextRequestViewAdapter, \
+ adapter_config
from pyams_utils.interfaces import FORBIDDEN_PERMISSION
from pyams_utils.registry import get_utility
from pyams_utils.request import check_request
from pyams_utils.traversing import get_parent
from pyams_utils.url import absolute_url, generate_url
from pyams_viewlet.viewlet import Viewlet, viewlet_config
-from pyams_workflow.interfaces import IWorkflow, IWorkflowCommentInfo, IWorkflowInfo, IWorkflowPublicationInfo, \
- IWorkflowState, IWorkflowVersions
+from pyams_workflow.interfaces import IWorkflow, IWorkflowCommentInfo, IWorkflowInfo, \
+ IWorkflowPublicationInfo, IWorkflowState, IWorkflowVersions
from pyams_workflow.versions import WorkflowHistoryItem
from pyams_zmi.form import AdminDialogAddForm
from pyams_zmi.interfaces.menu import ISiteManagementMenu
from pyams_zmi.layer import IAdminLayer
+
+__docformat__ = 'restructuredtext'
+
from pyams_content import _
@@ -108,7 +110,8 @@
IWorkflowInfo(wf_content).fire_transition('init', comment=wf_content.notepad)
def nextURL(self):
- return absolute_url(self.context, self.request, '{0}/++versions++/1/admin#properties.html'.format(self.__uuid))
+ return absolute_url(self.context, self.request,
+ '{0}/++versions++/1/admin#properties.html'.format(self.__uuid))
class SharedContentAJAXAddForm(AJAXAddForm):
@@ -121,7 +124,8 @@
}
-@viewlet_config(name='wf-create-message', context=Interface, layer=IPyAMSLayer, view=SharedContentAddForm,
+@viewlet_config(name='wf-create-message', context=Interface, layer=IPyAMSLayer,
+ view=SharedContentAddForm,
manager=IWidgetsPrefixViewletsManager, weight=20)
@template_config(template='templates/wf-create-message.pt')
class SharedContentAddFormMessage(Viewlet):
@@ -153,16 +157,20 @@
def edit_permission(self):
workflow = IWorkflow(self.context)
state = IWorkflowState(self.context).state
- if state in workflow.readonly_states: # access forbidden to all for archived contents
+ if state in workflow.readonly_states:
+ # forbidden access to all for archived contents
return FORBIDDEN_PERMISSION
- elif state in workflow.protected_states: # webmaster can update published contents
+ elif state in workflow.protected_states:
+ # webmaster can update published contents
return MANAGE_SITE_ROOT_PERMISSION
else:
request = check_request()
- if request.has_permission(MANAGE_SITE_ROOT_PERMISSION, self.context): # webmaster access
+ if request.has_permission(MANAGE_SITE_ROOT_PERMISSION, self.context):
+ # webmaster access
return MANAGE_SITE_ROOT_PERMISSION
principal_id = request.principal.id
- if state in workflow.manager_states: # restricted manager access
+ if state in workflow.manager_states:
+ # restricted manager access
if principal_id in self.context.managers:
return PUBLISH_CONTENT_PERMISSION
for parent in lineage(self.context):
@@ -177,8 +185,27 @@
else:
return FORBIDDEN_PERMISSION
else:
- if principal_id in self.context.owner | self.context.contributors | self.context.managers:
+ # access is granted to content's owner and designated contributors or managers
+ if principal_id in self.context.owner | \
+ self.context.contributors | \
+ self.context.managers:
return MANAGE_CONTENT_PERMISSION
+ # check if current principal can manage owner's contents
+ for parent in lineage(self.context):
+ contrib_restrictions = IContributorRestrictions(parent, None)
+ if contrib_restrictions is not None:
+ user_restrictions = contrib_restrictions.get_restrictions(principal_id)
+ if user_restrictions:
+ if user_restrictions.check_access(self.context,
+ permission=MANAGE_CONTENT_PERMISSION,
+ request=request):
+ return MANAGE_CONTENT_PERMISSION
+ restrictions = IContributorRestrictions(self.context).get_restrictions(principal_id)
+ if restrictions and restrictions.check_access(self.context,
+ permission=MANAGE_CONTENT_PERMISSION,
+ request=request):
+ return MANAGE_CONTENT_PERMISSION
+ # check if current principal can manage content's due to manager restrictions
for parent in lineage(self.context):
manager_restrictions = IManagerRestrictions(parent, None)
if manager_restrictions is not None:
@@ -188,8 +215,6 @@
permission=MANAGE_CONTENT_PERMISSION,
request=request):
return MANAGE_CONTENT_PERMISSION
- else:
- return FORBIDDEN_PERMISSION
restrictions = IManagerRestrictions(self.context).get_restrictions(principal_id)
if restrictions and restrictions.check_access(self.context,
permission=MANAGE_CONTENT_PERMISSION,
@@ -249,13 +274,15 @@
#
@viewlet_config(name='duplication.divider', context=IWfSharedContent, layer=IPyAMSLayer,
- view=Interface, manager=IContextActions, permission=CREATE_CONTENT_PERMISSION, weight=49)
+ view=Interface, manager=IContextActions, permission=CREATE_CONTENT_PERMISSION,
+ weight=49)
class WfSharedContentDuplicationMenuDivider(ToolbarMenuDivider):
"""Shared content duplication menu divider"""
@viewlet_config(name='duplication.menu', context=IWfSharedContent, layer=IPyAMSLayer,
- view=Interface, manager=IContextActions, permission=CREATE_CONTENT_PERMISSION, weight=50)
+ view=Interface, manager=IContextActions, permission=CREATE_CONTENT_PERMISSION,
+ weight=50)
class WfSharedContentDuplicateMenu(ToolbarMenuItem):
"""Shared content duplication menu item"""
@@ -326,11 +353,13 @@
state.history.clear()
history = WorkflowHistoryItem(date=datetime.utcnow(),
principal=self.request.principal.id,
- comment=translate(_("Clone created from version {source} of {oid} "
- "(in « {state} » state)")).format(
+ comment=translate(
+ _("Clone created from version {source} of {oid} "
+ "(in « {state} » state)")).format(
source=source_state.version_id,
oid=ISequentialIdInfo(self.context).get_short_oid(),
- state=translate(IWorkflow(self.context).get_state_label(source_state.state)))
+ state=translate(IWorkflow(self.context).get_state_label(
+ source_state.state)))
)
state.history.append(history)
history = WorkflowHistoryItem(date=datetime.utcnow(),
@@ -371,5 +400,5 @@
translate = self.request.localizer.translate
value += '<i class="fa fa-fw fa-circle txt-color-orange hint align-middle padding-left-5" ' \
'title="{0}" data-ams-hint-gravity="w"></i>'.format(
- translate(_("Created or modified in this version")))
+ translate(_("Created or modified in this version")))
return value