implement workspace-based security management
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3891 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
6fbf8a08ae
commit
3d7c87b7b9
18 changed files with 313 additions and 90 deletions
|
@ -120,13 +120,17 @@ class BaseView(GenericView, I18NView):
|
||||||
self.context = removeSecurityProxy(context)
|
self.context = removeSecurityProxy(context)
|
||||||
try:
|
try:
|
||||||
if not self.checkPermissions():
|
if not self.checkPermissions():
|
||||||
raise Unauthorized('%r: title' % (self.context))
|
raise Unauthorized(str(self.contextInfo))
|
||||||
except ForbiddenAttribute: # ignore when testing
|
except ForbiddenAttribute: # ignore when testing
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def checkPermissions(self):
|
def checkPermissions(self):
|
||||||
return canAccessObject(self.context)
|
return canAccessObject(self.context)
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def contextInfo(self):
|
||||||
|
return dict(view=self, context=getName(self.context))
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def conceptMacros(self):
|
def conceptMacros(self):
|
||||||
return concept_macros.macros
|
return concept_macros.macros
|
||||||
|
|
|
@ -554,7 +554,7 @@
|
||||||
name="create_object.html"
|
name="create_object.html"
|
||||||
for="loops.interfaces.INode"
|
for="loops.interfaces.INode"
|
||||||
class="loops.browser.form.CreateObjectForm"
|
class="loops.browser.form.CreateObjectForm"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<page
|
<page
|
||||||
|
@ -568,49 +568,49 @@
|
||||||
name="edit_object.html"
|
name="edit_object.html"
|
||||||
for="loops.interfaces.INode"
|
for="loops.interfaces.INode"
|
||||||
class="loops.browser.form.EditObjectForm"
|
class="loops.browser.form.EditObjectForm"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<page
|
<page
|
||||||
name="create_concept.html"
|
name="create_concept.html"
|
||||||
for="loops.interfaces.INode"
|
for="loops.interfaces.INode"
|
||||||
class="loops.browser.form.CreateConceptForm"
|
class="loops.browser.form.CreateConceptForm"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<page
|
<page
|
||||||
name="edit_concept.html"
|
name="edit_concept.html"
|
||||||
for="loops.interfaces.INode"
|
for="loops.interfaces.INode"
|
||||||
class="loops.browser.form.EditConceptForm"
|
class="loops.browser.form.EditConceptForm"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<page
|
<page
|
||||||
name="edit_concept_page.html"
|
name="edit_concept_page.html"
|
||||||
for="loops.interfaces.INode"
|
for="loops.interfaces.INode"
|
||||||
class="loops.browser.form.EditConceptPage"
|
class="loops.browser.form.EditConceptPage"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<page
|
<page
|
||||||
name="inner_form.html"
|
name="inner_form.html"
|
||||||
for="loops.interfaces.INode"
|
for="loops.interfaces.INode"
|
||||||
class="loops.browser.form.InnerForm"
|
class="loops.browser.form.InnerForm"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<page
|
<page
|
||||||
name="inner_concept_form.html"
|
name="inner_concept_form.html"
|
||||||
for="loops.interfaces.INode"
|
for="loops.interfaces.INode"
|
||||||
class="loops.browser.form.InnerConceptForm"
|
class="loops.browser.form.InnerConceptForm"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<page
|
<page
|
||||||
name="inner_concept_edit_form.html"
|
name="inner_concept_edit_form.html"
|
||||||
for="loops.interfaces.INode"
|
for="loops.interfaces.INode"
|
||||||
class="loops.browser.form.InnerConceptEditForm"
|
class="loops.browser.form.InnerConceptEditForm"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<zope:adapter
|
<zope:adapter
|
||||||
|
@ -618,7 +618,7 @@
|
||||||
for="loops.browser.node.NodeView
|
for="loops.browser.node.NodeView
|
||||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||||
factory="loops.browser.form.CreateObject"
|
factory="loops.browser.form.CreateObject"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<zope:adapter
|
<zope:adapter
|
||||||
|
@ -626,7 +626,7 @@
|
||||||
for="loops.browser.node.NodeView
|
for="loops.browser.node.NodeView
|
||||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||||
factory="loops.browser.form.EditObject"
|
factory="loops.browser.form.EditObject"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<zope:adapter
|
<zope:adapter
|
||||||
|
@ -634,14 +634,14 @@
|
||||||
for="loops.browser.node.NodeView
|
for="loops.browser.node.NodeView
|
||||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||||
factory="loops.browser.form.CreateConcept"
|
factory="loops.browser.form.CreateConcept"
|
||||||
permission="zope.ManageContent" />
|
permission="zope.View" />
|
||||||
|
|
||||||
<zope:adapter
|
<zope:adapter
|
||||||
name="edit_concept"
|
name="edit_concept"
|
||||||
for="loops.browser.node.NodeView
|
for="loops.browser.node.NodeView
|
||||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||||
factory="loops.browser.form.EditConcept"
|
factory="loops.browser.form.EditConcept"
|
||||||
permission="zope.ManageContent" />
|
permission="zope.View" />
|
||||||
|
|
||||||
<!-- inner HTML views -->
|
<!-- inner HTML views -->
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2010 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -35,7 +35,9 @@ from zope.cachedescriptors.property import Lazy
|
||||||
from zope.contenttype import guess_content_type
|
from zope.contenttype import guess_content_type
|
||||||
from zope.publisher.browser import FileUpload
|
from zope.publisher.browser import FileUpload
|
||||||
from zope.publisher.interfaces import BadRequest
|
from zope.publisher.interfaces import BadRequest
|
||||||
|
from zope.security.interfaces import ForbiddenAttribute, Unauthorized
|
||||||
from zope.security.proxy import isinstance, removeSecurityProxy
|
from zope.security.proxy import isinstance, removeSecurityProxy
|
||||||
|
from zope.traversing.api import getName
|
||||||
|
|
||||||
from cybertools.ajax import innerHtml
|
from cybertools.ajax import innerHtml
|
||||||
from cybertools.browser.form import FormController
|
from cybertools.browser.form import FormController
|
||||||
|
@ -58,6 +60,7 @@ from loops.i18n.browser import I18NView
|
||||||
from loops.query import ConceptQuery, IQueryConcept
|
from loops.query import ConceptQuery, IQueryConcept
|
||||||
from loops.resource import Resource
|
from loops.resource import Resource
|
||||||
from loops.schema.field import relation_macros
|
from loops.schema.field import relation_macros
|
||||||
|
from loops.security.common import canAccessObject, canListObject, canWriteObject
|
||||||
from loops.type import ITypeConcept
|
from loops.type import ITypeConcept
|
||||||
from loops import util
|
from loops import util
|
||||||
from loops.util import _
|
from loops.util import _
|
||||||
|
@ -77,12 +80,20 @@ class ObjectForm(NodeView):
|
||||||
isPopup = False
|
isPopup = False
|
||||||
showAssignments = True
|
showAssignments = True
|
||||||
|
|
||||||
def __init__(self, context, request):
|
def checkPermissions(self):
|
||||||
super(ObjectForm, self).__init__(context, request)
|
obj = self.target
|
||||||
# target is the object the view acts upon - this is not necessarily
|
if obj is None:
|
||||||
# the same object as the context (the object the view was created for)
|
obj = self.context
|
||||||
self.target = context
|
return canWriteObject(obj)
|
||||||
#self.registerDojoForm()
|
|
||||||
|
@Lazy
|
||||||
|
def target(self):
|
||||||
|
return self.virtualTargetObject or self.context
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def contextInfo(self):
|
||||||
|
return dict(view=self, context=getName(self.context),
|
||||||
|
target=getName(self.target))
|
||||||
|
|
||||||
def closeAction(self, submit=False):
|
def closeAction(self, submit=False):
|
||||||
if self.isPopup:
|
if self.isPopup:
|
||||||
|
@ -196,18 +207,13 @@ class ObjectForm(NodeView):
|
||||||
|
|
||||||
class EditObjectForm(ObjectForm):
|
class EditObjectForm(ObjectForm):
|
||||||
|
|
||||||
@Lazy
|
|
||||||
def macro(self):
|
|
||||||
return self.template.macros['edit']
|
|
||||||
|
|
||||||
title = _(u'Edit Resource')
|
title = _(u'Edit Resource')
|
||||||
form_action = 'edit_resource'
|
form_action = 'edit_resource'
|
||||||
dialog_name = 'edit'
|
dialog_name = 'edit'
|
||||||
|
|
||||||
def __init__(self, context, request):
|
@Lazy
|
||||||
super(EditObjectForm, self).__init__(context, request)
|
def macro(self):
|
||||||
#self.url = self.url # keep virtual target URL (???)
|
return self.template.macros['edit']
|
||||||
self.target = self.virtualTargetObject
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def assignments(self):
|
def assignments(self):
|
||||||
|
@ -251,13 +257,13 @@ class EditConceptPage(EditConceptForm):
|
||||||
|
|
||||||
class CreateObjectForm(ObjectForm):
|
class CreateObjectForm(ObjectForm):
|
||||||
|
|
||||||
@property
|
|
||||||
def macro(self): return self.template.macros['create']
|
|
||||||
|
|
||||||
defaultTitle = u'Create Resource, Type = '
|
defaultTitle = u'Create Resource, Type = '
|
||||||
form_action = 'create_resource'
|
form_action = 'create_resource'
|
||||||
dialog_name = 'create'
|
dialog_name = 'create'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def macro(self): return self.template.macros['create']
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def fixedType(self):
|
def fixedType(self):
|
||||||
return self.request.form.get('fixed_type')
|
return self.request.form.get('fixed_type')
|
||||||
|
@ -445,6 +451,25 @@ class EditObject(FormController, I18NView):
|
||||||
prefix = 'form.'
|
prefix = 'form.'
|
||||||
conceptPrefix = 'assignments.'
|
conceptPrefix = 'assignments.'
|
||||||
|
|
||||||
|
def __init__(self, context, request):
|
||||||
|
super(EditObject, self).__init__(context, request)
|
||||||
|
try:
|
||||||
|
if not self.checkPermissions():
|
||||||
|
raise Unauthorized(str(self.contextInfo))
|
||||||
|
except ForbiddenAttribute: # ignore when testing
|
||||||
|
pass
|
||||||
|
|
||||||
|
def checkPermissions(self):
|
||||||
|
return canWriteObject(self.target)
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def contextInfo(self):
|
||||||
|
return dict(formcontroller=self, view=self.view, target=getName(self.target))
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def target(self):
|
||||||
|
return self.view.virtualTargetObject or self.context
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def adapted(self):
|
def adapted(self):
|
||||||
return adapted(self.object, self.languageInfoForUpdate)
|
return adapted(self.object, self.languageInfoForUpdate)
|
||||||
|
@ -476,7 +501,7 @@ class EditObject(FormController, I18NView):
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
# create new version if necessary
|
# create new version if necessary
|
||||||
target = self.view.virtualTargetObject
|
target = self.target
|
||||||
obj = self.checkCreateVersion(target)
|
obj = self.checkCreateVersion(target)
|
||||||
if obj != target:
|
if obj != target:
|
||||||
# make sure new version is used by the view
|
# make sure new version is used by the view
|
||||||
|
|
|
@ -176,12 +176,15 @@ standard checker defined in the test setup.
|
||||||
The automatic assignment of the blog post is done in the form controller
|
The automatic assignment of the blog post is done in the form controller
|
||||||
used for creating the blog post.
|
used for creating the blog post.
|
||||||
|
|
||||||
|
>>> home = views['home']
|
||||||
|
>>> home.target = myBlog
|
||||||
|
|
||||||
>>> from loops.compound.blog.browser import CreateBlogPostForm, CreateBlogPost
|
>>> from loops.compound.blog.browser import CreateBlogPostForm, CreateBlogPost
|
||||||
>>> input = {'title': u'John\'s first post', 'text': u'Text of John\'s post',
|
>>> input = {'title': u'John\'s first post', 'text': u'Text of John\'s post',
|
||||||
... 'date': '2008-02-02T15:54:11',
|
... 'date': '2008-02-02T15:54:11',
|
||||||
... 'privateComment': u'John\'s private comment',
|
... 'privateComment': u'John\'s private comment',
|
||||||
... 'form.type': '.loops/concepts/blogpost'}
|
... 'form.type': '.loops/concepts/blogpost'}
|
||||||
>>> cbpForm = CreateBlogPostForm(myBlog, TestRequest(form=input))
|
>>> cbpForm = CreateBlogPostForm(home, TestRequest(form=input))
|
||||||
>>> cbpController = CreateBlogPost(cbpForm, cbpForm.request)
|
>>> cbpController = CreateBlogPost(cbpForm, cbpForm.request)
|
||||||
>>> cbpController.update()
|
>>> cbpController.update()
|
||||||
False
|
False
|
||||||
|
|
|
@ -36,7 +36,7 @@ from loops.browser.form import CreateConceptForm, EditConceptForm
|
||||||
from loops.browser.form import CreateConcept, EditConcept
|
from loops.browser.form import CreateConcept, EditConcept
|
||||||
from loops.common import adapted
|
from loops.common import adapted
|
||||||
from loops.organize.party import getPersonForUser
|
from loops.organize.party import getPersonForUser
|
||||||
from loops.security.common import checkPermission
|
from loops.security.common import checkPermission, canAccessObject
|
||||||
from loops import util
|
from loops import util
|
||||||
from loops.util import _
|
from loops.util import _
|
||||||
|
|
||||||
|
@ -175,20 +175,30 @@ class EditBlogPostForm(EditConceptForm):
|
||||||
title = _(u'Edit Blog Post')
|
title = _(u'Edit Blog Post')
|
||||||
form_action = 'edit_blogpost'
|
form_action = 'edit_blogpost'
|
||||||
|
|
||||||
|
def checkPermissions(self):
|
||||||
|
return canAccessObject(self.target)
|
||||||
|
|
||||||
|
|
||||||
class CreateBlogPostForm(CreateConceptForm):
|
class CreateBlogPostForm(CreateConceptForm):
|
||||||
|
|
||||||
title = _(u'Create Blog Post')
|
title = _(u'Create Blog Post')
|
||||||
form_action = 'create_blogpost'
|
form_action = 'create_blogpost'
|
||||||
|
|
||||||
|
def checkPermissions(self):
|
||||||
|
return canAccessObject(self.target)
|
||||||
|
|
||||||
|
|
||||||
class EditBlogPost(EditConcept):
|
class EditBlogPost(EditConcept):
|
||||||
|
|
||||||
pass
|
def checkPermissions(self):
|
||||||
|
return canAccessObject(self.target)
|
||||||
|
|
||||||
|
|
||||||
class CreateBlogPost(CreateConcept):
|
class CreateBlogPost(CreateConcept):
|
||||||
|
|
||||||
|
def checkPermissions(self):
|
||||||
|
return canAccessObject(self.target)
|
||||||
|
|
||||||
def collectAutoConcepts(self):
|
def collectAutoConcepts(self):
|
||||||
#super(CreateBlogPost, self).collectConcepts(fieldName, value)
|
#super(CreateBlogPost, self).collectConcepts(fieldName, value)
|
||||||
person = getPersonForUser(self.container, self.request)
|
person = getPersonForUser(self.container, self.request)
|
||||||
|
|
|
@ -46,14 +46,14 @@
|
||||||
name="create_blogpost.html"
|
name="create_blogpost.html"
|
||||||
for="loops.interfaces.INode"
|
for="loops.interfaces.INode"
|
||||||
class="loops.compound.blog.browser.CreateBlogPostForm"
|
class="loops.compound.blog.browser.CreateBlogPostForm"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<browser:page
|
<browser:page
|
||||||
name="edit_blogpost.html"
|
name="edit_blogpost.html"
|
||||||
for="loops.interfaces.INode"
|
for="loops.interfaces.INode"
|
||||||
class="loops.compound.blog.browser.EditBlogPostForm"
|
class="loops.compound.blog.browser.EditBlogPostForm"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<zope:adapter
|
<zope:adapter
|
||||||
|
@ -62,7 +62,7 @@
|
||||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||||
provides="zope.interface.Interface"
|
provides="zope.interface.Interface"
|
||||||
factory="loops.compound.blog.browser.CreateBlogPost"
|
factory="loops.compound.blog.browser.CreateBlogPost"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<zope:adapter
|
<zope:adapter
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
for="loops.browser.node.NodeView
|
for="loops.browser.node.NodeView
|
||||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||||
factory="loops.compound.blog.browser.EditBlogPost"
|
factory="loops.compound.blog.browser.EditBlogPost"
|
||||||
permission="zope.ManageContent"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</configure>
|
</configure>
|
||||||
|
|
Binary file not shown.
|
@ -3,7 +3,7 @@ msgstr ""
|
||||||
|
|
||||||
"Project-Id-Version: $Id$\n"
|
"Project-Id-Version: $Id$\n"
|
||||||
"POT-Creation-Date: 2007-05-22 12:00 CET\n"
|
"POT-Creation-Date: 2007-05-22 12:00 CET\n"
|
||||||
"PO-Revision-Date: 2010-05-16 12:00 CET\n"
|
"PO-Revision-Date: 2010-06-11 12:00 CET\n"
|
||||||
"Last-Translator: Helmut Merz <helmutm@cy55.de>\n"
|
"Last-Translator: Helmut Merz <helmutm@cy55.de>\n"
|
||||||
"Language-Team: loops developers <helmutm@cy55.de>\n"
|
"Language-Team: loops developers <helmutm@cy55.de>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
@ -159,16 +159,16 @@ msgid "Create a new event"
|
||||||
msgstr "Einen neuen Termin anlegen"
|
msgstr "Einen neuen Termin anlegen"
|
||||||
|
|
||||||
msgid "Create Task..."
|
msgid "Create Task..."
|
||||||
msgstr "Aufgabe anlegen..."
|
msgstr "Crear tarea..."
|
||||||
|
|
||||||
msgid "Create a new task"
|
msgid "Create a new task"
|
||||||
msgstr "Eine neue Aufgabe anlegen"
|
msgstr "Crear una nueva tarea"
|
||||||
|
|
||||||
msgid "Edit Task..."
|
msgid "Edit Task..."
|
||||||
msgstr "Aufgabe bearbeiten..."
|
msgstr "Editar tarea..."
|
||||||
|
|
||||||
msgid "Modify task"
|
msgid "Modify task"
|
||||||
msgstr "Aufgabe bearbeiten"
|
msgstr "Modificar la tarea"
|
||||||
|
|
||||||
msgid "Create Work Item..."
|
msgid "Create Work Item..."
|
||||||
msgstr "Aktivität anlegen..."
|
msgstr "Aktivität anlegen..."
|
||||||
|
@ -243,7 +243,7 @@ msgid "Topic"
|
||||||
msgstr "Thema"
|
msgstr "Thema"
|
||||||
|
|
||||||
msgid "Task"
|
msgid "Task"
|
||||||
msgstr "Aufgabe"
|
msgstr "Tarea"
|
||||||
|
|
||||||
msgid "Domain"
|
msgid "Domain"
|
||||||
msgstr "Bereich"
|
msgstr "Bereich"
|
||||||
|
|
|
@ -35,6 +35,7 @@ from loops.browser.node import NodeView
|
||||||
from loops.organize.comment.base import Comment
|
from loops.organize.comment.base import Comment
|
||||||
from loops.organize.party import getPersonForUser
|
from loops.organize.party import getPersonForUser
|
||||||
from loops.organize.tracking.report import TrackDetails
|
from loops.organize.tracking.report import TrackDetails
|
||||||
|
from loops.security.common import canAccessObject
|
||||||
from loops.setup import addObject
|
from loops.setup import addObject
|
||||||
from loops import util
|
from loops import util
|
||||||
from loops.util import _
|
from loops.util import _
|
||||||
|
@ -91,6 +92,9 @@ class CreateCommentForm(ObjectForm):
|
||||||
|
|
||||||
template = comment_macros
|
template = comment_macros
|
||||||
|
|
||||||
|
def checkPermissions(self):
|
||||||
|
return canAccessObject(self.target)
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def macro(self):
|
def macro(self):
|
||||||
return self.template.macros['create_comment']
|
return self.template.macros['create_comment']
|
||||||
|
@ -98,6 +102,9 @@ class CreateCommentForm(ObjectForm):
|
||||||
|
|
||||||
class CreateComment(EditObject):
|
class CreateComment(EditObject):
|
||||||
|
|
||||||
|
def checkPermissions(self):
|
||||||
|
return canAccessObject(self.target)
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def personId(self):
|
def personId(self):
|
||||||
p = getPersonForUser(self.context, self.request)
|
p = getPersonForUser(self.context, self.request)
|
||||||
|
|
|
@ -58,8 +58,15 @@ def getPrincipalFolder(context=None, authPluginId=None, ignoreErrors=False):
|
||||||
return plugin
|
return plugin
|
||||||
|
|
||||||
|
|
||||||
def getGroupsFolder(context=None, name='gloops'):
|
def getGroupsFolder(context=None, name='gloops', create=False):
|
||||||
return getPrincipalFolder(authPluginId=name, ignoreErrors=True)
|
gf = getPrincipalFolder(authPluginId=name, ignoreErrors=True)
|
||||||
|
if gf is None and create:
|
||||||
|
pau = component.getUtility(IAuthentication, context=context)
|
||||||
|
gf = pau[name] = PrincipalFolder()
|
||||||
|
gf.prefix = name + '.'
|
||||||
|
pau.authenticatorPlugins = tuple(
|
||||||
|
list(pau.authenticatorPlugins) + ['name'])
|
||||||
|
return gf
|
||||||
|
|
||||||
|
|
||||||
def getGroupId(group):
|
def getGroupId(group):
|
||||||
|
|
|
@ -47,6 +47,7 @@ from loops.organize.stateful.browser import StateAction
|
||||||
from loops.organize.tracking.browser import BaseTrackView
|
from loops.organize.tracking.browser import BaseTrackView
|
||||||
from loops.organize.tracking.report import TrackDetails
|
from loops.organize.tracking.report import TrackDetails
|
||||||
from loops.organize.work.base import WorkItem
|
from loops.organize.work.base import WorkItem
|
||||||
|
from loops.security.common import canAccessObject, canListObject, canWriteObject
|
||||||
from loops import util
|
from loops import util
|
||||||
from loops.util import _
|
from loops.util import _
|
||||||
|
|
||||||
|
@ -277,10 +278,19 @@ class CreateWorkItemForm(ObjectForm, BaseTrackView):
|
||||||
|
|
||||||
template = work_macros
|
template = work_macros
|
||||||
|
|
||||||
|
def checkPermissions(self):
|
||||||
|
return canAccessObject(self.task or self.target)
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def macro(self):
|
def macro(self):
|
||||||
return self.template.macros['create_workitem']
|
return self.template.macros['create_workitem']
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def task(self):
|
||||||
|
uid = self.track.taskId
|
||||||
|
if uid:
|
||||||
|
return util.getObjectForUid(uid)
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def track(self):
|
def track(self):
|
||||||
id = self.request.form.get('id')
|
id = self.request.form.get('id')
|
||||||
|
@ -352,6 +362,17 @@ class CreateWorkItemForm(ObjectForm, BaseTrackView):
|
||||||
|
|
||||||
class CreateWorkItem(EditObject, BaseTrackView):
|
class CreateWorkItem(EditObject, BaseTrackView):
|
||||||
|
|
||||||
|
def checkPermissions(self):
|
||||||
|
return canAccessObject(self.task or self.target)
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def task(self):
|
||||||
|
if self.track is None:
|
||||||
|
return None
|
||||||
|
uid = self.track.taskId
|
||||||
|
if uid:
|
||||||
|
return util.getObjectForUid(uid)
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def track(self):
|
def track(self):
|
||||||
id = self.request.form.get('id')
|
id = self.request.form.get('id')
|
||||||
|
@ -368,7 +389,8 @@ class CreateWorkItem(EditObject, BaseTrackView):
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def object(self):
|
def object(self):
|
||||||
return self.view.virtualTargetObject
|
return self.target
|
||||||
|
#return self.view.virtualTargetObject
|
||||||
|
|
||||||
def processForm(self):
|
def processForm(self):
|
||||||
form = self.request.form
|
form = self.request.form
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
name="create_workitem.html"
|
name="create_workitem.html"
|
||||||
for="loops.interfaces.INode"
|
for="loops.interfaces.INode"
|
||||||
class="loops.organize.work.browser.CreateWorkItemForm"
|
class="loops.organize.work.browser.CreateWorkItemForm"
|
||||||
permission="zope.ManageContent" />
|
permission="zope.View" />
|
||||||
|
|
||||||
<zope:adapter
|
<zope:adapter
|
||||||
name="create_workitem"
|
name="create_workitem"
|
||||||
|
|
|
@ -31,6 +31,10 @@
|
||||||
id="loops.EditRestricted"
|
id="loops.EditRestricted"
|
||||||
title="[loops-edit-restricted-permission] loops: Edit Restricted Information" />
|
title="[loops-edit-restricted-permission] loops: Edit Restricted Information" />
|
||||||
|
|
||||||
|
<permission
|
||||||
|
id="loops.AssignAsParent"
|
||||||
|
title="[loops-assign-as-parent-permission] loops: Assign as Parent" />
|
||||||
|
|
||||||
<permission
|
<permission
|
||||||
id="loops.Execute"
|
id="loops.Execute"
|
||||||
title="[loops-execute-permission] loops: Execute" />
|
title="[loops-execute-permission] loops: Execute" />
|
||||||
|
@ -42,13 +46,19 @@
|
||||||
<grant role="loops.SiteManager" permission="loops.ManageSite" />
|
<grant role="loops.SiteManager" permission="loops.ManageSite" />
|
||||||
<grant role="loops.SiteManager" permission="loops.ManageTypes" />
|
<grant role="loops.SiteManager" permission="loops.ManageTypes" />
|
||||||
<grant role="loops.SiteManager" permission="loops.ManageWorkspaces" />
|
<grant role="loops.SiteManager" permission="loops.ManageWorkspaces" />
|
||||||
|
<grant role="loops.SiteManager" permission="loops.AssignAsParent" />
|
||||||
<grant role="loops.SiteManager" permission="loops.xmlrpc.ManageConcepts" />
|
<grant role="loops.SiteManager" permission="loops.xmlrpc.ManageConcepts" />
|
||||||
<grant role="loops.SiteManager" permission="zope.ManageContent" />
|
<grant role="loops.SiteManager" permission="zope.ManageContent" />
|
||||||
<grant role="loops.SiteManager" permission="zope.View" />
|
<grant role="loops.SiteManager" permission="zope.View" />
|
||||||
|
|
||||||
|
<role id="loops.xmlrpc.ConceptManager"
|
||||||
|
title="[xmlrpc-manage-concepts-role] loops: Concept Manager (XML-RPC)" />
|
||||||
|
<grant role="loops.xmlrpc.ConceptManager" permission="loops.xmlrpc.ManageConcepts" />
|
||||||
|
|
||||||
<role id="loops.Staff"
|
<role id="loops.Staff"
|
||||||
title="[loops-staff-role] loops: Staff" />
|
title="[loops-staff-role] loops: Staff" />
|
||||||
<grant role="loops.Staff" permission="loops.ManageWorkspaces" />
|
<grant role="loops.Staff" permission="loops.ManageWorkspaces" />
|
||||||
|
<grant role="loops.Staff" permission="loops.AssignAsParent" />
|
||||||
<grant role="loops.Staff" permission="loops.EditRestricted" />
|
<grant role="loops.Staff" permission="loops.EditRestricted" />
|
||||||
<grant role="loops.Staff" permission="zope.ManageContent" />
|
<grant role="loops.Staff" permission="zope.ManageContent" />
|
||||||
<grant role="loops.Staff" permission="zope.View" />
|
<grant role="loops.Staff" permission="zope.View" />
|
||||||
|
@ -56,19 +66,19 @@
|
||||||
<role id="loops.Master"
|
<role id="loops.Master"
|
||||||
title="[loops-master-role] loops: Master" />
|
title="[loops-master-role] loops: Master" />
|
||||||
<grant role="loops.Master" permission="zope.ManageContent" />
|
<grant role="loops.Master" permission="zope.ManageContent" />
|
||||||
|
<grant role="loops.Master" permission="loops.AssignAsParent" />
|
||||||
|
|
||||||
<role id="loops.Member"
|
<role id="loops.Member"
|
||||||
title="[loops-member-role] loops: Member" />
|
title="[loops-member-role] loops: Member" />
|
||||||
<grant role="loops.Member" permission="zope.View" />
|
<grant role="loops.Member" permission="zope.View" />
|
||||||
|
|
||||||
<role id="loops.xmlrpc.ConceptManager"
|
|
||||||
title="[xmlrpc-manage-concepts-role] loops: Concept Manager (XML-RPC)" />
|
|
||||||
<grant role="loops.xmlrpc.ConceptManager" permission="loops.xmlrpc.ManageConcepts" />
|
|
||||||
|
|
||||||
<role id="loops.Owner"
|
<role id="loops.Owner"
|
||||||
title="[loops-owner-role] Owner" />
|
title="[loops-owner-role] Owner" />
|
||||||
<grant role="loops.Owner" permission="zope.ManageContent" />
|
<grant role="loops.Owner" permission="zope.ManageContent" />
|
||||||
<grant role="loops.Owner" permission="loops.ViewRestricted" />
|
<grant role="loops.Owner" permission="loops.ViewRestricted" />
|
||||||
<grant role="loops.Owner" permission="zope.View" />
|
<grant role="loops.Owner" permission="zope.View" />
|
||||||
|
|
||||||
|
<!-- moved to etc/securitypolicy.zcml: -->
|
||||||
|
<!--<grant role="zope.ContentManager" permission="loops.AssignAsParent" />-->
|
||||||
|
|
||||||
</configure>
|
</configure>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2010 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -22,8 +22,10 @@ Security-related views.
|
||||||
$Id$
|
$Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from zope.app.authentication.groupfolder import GroupInformation
|
||||||
from zope.app.pagetemplate import ViewPageTemplateFile
|
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||||
from zope.app.security.interfaces import IPermission
|
from zope.app.security.interfaces import IPermission
|
||||||
|
from zope.app.security.settings import Allow, Deny, Unset
|
||||||
from zope.app.securitypolicy.browser import granting
|
from zope.app.securitypolicy.browser import granting
|
||||||
from zope.app.securitypolicy.browser.rolepermissionview import RolePermissionView
|
from zope.app.securitypolicy.browser.rolepermissionview import RolePermissionView
|
||||||
from zope.app.securitypolicy.interfaces import IPrincipalRoleManager, \
|
from zope.app.securitypolicy.interfaces import IPrincipalRoleManager, \
|
||||||
|
@ -32,13 +34,17 @@ from zope.app.securitypolicy.interfaces import IPrincipalPermissionManager, \
|
||||||
IPrincipalPermissionMap
|
IPrincipalPermissionMap
|
||||||
from zope.app.securitypolicy.zopepolicy import SettingAsBoolean
|
from zope.app.securitypolicy.zopepolicy import SettingAsBoolean
|
||||||
from zope import component
|
from zope import component
|
||||||
|
from zope.event import notify
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
|
from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
|
||||||
from zope.security.proxy import removeSecurityProxy
|
from zope.security.proxy import removeSecurityProxy
|
||||||
from zope.traversing.api import getParent, getParents
|
from zope.traversing.api import getName, getParent, getParents
|
||||||
|
|
||||||
from loops.common import adapted
|
from loops.common import adapted
|
||||||
|
from loops.organize.util import getGroupsFolder
|
||||||
from loops.security.common import WorkspaceInformation
|
from loops.security.common import WorkspaceInformation
|
||||||
|
from loops.security.common import localPermissions, localRoles, setPrincipalRole
|
||||||
from loops.security.interfaces import ISecuritySetter
|
from loops.security.interfaces import ISecuritySetter
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,7 +168,11 @@ class PermissionView(object):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def getPermissions(self):
|
def getPermissions(self):
|
||||||
return sorted(name for name, perm in component.getUtilitiesFor(IPermission))
|
return sorted(name for name, perm in component.getUtilitiesFor(IPermission)
|
||||||
|
if name in localPermissions)
|
||||||
|
|
||||||
|
def hideRole(self, role):
|
||||||
|
return role not in localRoles
|
||||||
|
|
||||||
|
|
||||||
class ManageWorkspaceView(PermissionView):
|
class ManageWorkspaceView(PermissionView):
|
||||||
|
@ -176,12 +186,86 @@ class ManageWorkspaceView(PermissionView):
|
||||||
wi = context.workspaceInformation = WorkspaceInformation(context)
|
wi = context.workspaceInformation = WorkspaceInformation(context)
|
||||||
PermissionView.__init__(self, wi, request)
|
PermissionView.__init__(self, wi, request)
|
||||||
|
|
||||||
|
def update(self, testing=None):
|
||||||
|
if 'SUBMIT_PERMS' in self.request.form:
|
||||||
|
super(ManageWorkspaceView, self).update(testing)
|
||||||
|
elif 'save_wsinfo' in self.request.form:
|
||||||
|
self.saveWSInfo()
|
||||||
|
|
||||||
|
def saveWSInfo(self):
|
||||||
|
gn = {}
|
||||||
|
form = self.request.form
|
||||||
|
gfName = self.context.workspaceGroupsFolderName
|
||||||
|
gf = getGroupsFolder(self.context, gfName, create=True)
|
||||||
|
parentRM = IPrincipalRoleManager(self.parent)
|
||||||
|
wsiRM = IPrincipalRoleManager(self.context)
|
||||||
|
for pn in form.get('predicate_name', []):
|
||||||
|
groupName = form.get('group_name_' + pn)
|
||||||
|
gn[pn] = groupName
|
||||||
|
if groupName and groupName not in gf:
|
||||||
|
group = GroupInformation(groupName)
|
||||||
|
notify(ObjectCreatedEvent(group))
|
||||||
|
gf[groupName] = group
|
||||||
|
notify(ObjectModifiedEvent(group))
|
||||||
|
roleParent = bool(form.get('role_parent_' + pn))
|
||||||
|
roleWSI = bool(form.get('role_wsi_' + pn))
|
||||||
|
roleName = 'loops.' + pn.lstrip('is').title()
|
||||||
|
gid = '.'.join((gfName, groupName))
|
||||||
|
setPrincipalRole(parentRM, roleName, gid,
|
||||||
|
roleParent and Allow or None)
|
||||||
|
setPrincipalRole(wsiRM, roleName, gid,
|
||||||
|
roleWSI and Allow or None)
|
||||||
|
self.context.workspaceGroupNames = gn
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def permission_macros(self):
|
def permission_macros(self):
|
||||||
return permission_template.macros
|
return permission_template.macros
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def parent(self):
|
||||||
|
return self.context.getParent()
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def adapted(self):
|
def adapted(self):
|
||||||
return adapted(getParent(self.context))
|
return adapted(self.parent)
|
||||||
|
|
||||||
|
def getGroupsInfo(self):
|
||||||
|
root = self.parent.getLoopsRoot()
|
||||||
|
conceptManager = root.getConceptManager()
|
||||||
|
def getDefaultGroupName(predicateName):
|
||||||
|
rootName = '_'.join([getName(obj) for obj in
|
||||||
|
reversed(getParents(conceptManager)[:-1])])
|
||||||
|
objName = getName(self.parent)
|
||||||
|
return '.'.join((rootName, objName, predicateName.strip('is')))
|
||||||
|
apn = [pn for pn in self.context.allocationPredicateNames
|
||||||
|
if pn in conceptManager]
|
||||||
|
gn = self.context.workspaceGroupNames
|
||||||
|
if not isinstance(gn, dict): # backwards compatibility
|
||||||
|
gn = {}
|
||||||
|
result = [dict(predicateName=pn,
|
||||||
|
predicateTitle=conceptManager[pn].title,
|
||||||
|
groupName='', groupExists=False,
|
||||||
|
roleParent=False, roleWSI=False)
|
||||||
|
for pn in apn]
|
||||||
|
gfName = self.context.workspaceGroupsFolderName
|
||||||
|
gf = getGroupsFolder(self.context, gfName)
|
||||||
|
if gf is None:
|
||||||
|
return result
|
||||||
|
parentRMget = IPrincipalRoleManager(self.parent).getPrincipalsForRole
|
||||||
|
wsiRMget = IPrincipalRoleManager(self.context).getPrincipalsForRole
|
||||||
|
for item in result:
|
||||||
|
pn = item['predicateName']
|
||||||
|
groupName = item['groupName'] = gn.get(pn, getDefaultGroupName(pn))
|
||||||
|
roleName = 'loops.' + pn.lstrip('is').title()
|
||||||
|
if gf is not None and groupName in gf:
|
||||||
|
item['groupExists'] = True
|
||||||
|
gid = '.'.join((gfName, groupName))
|
||||||
|
item['roleParent'] = isSet(parentRMget(roleName), gid)
|
||||||
|
item['roleWSI'] = isSet(wsiRMget(roleName), gid)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def isSet(entry, id):
|
||||||
|
for name, setting in entry:
|
||||||
|
if name == id:
|
||||||
|
return SettingAsBoolean[setting]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2010 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -23,7 +23,6 @@ $Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from persistent import Persistent
|
from persistent import Persistent
|
||||||
from persistent.list import PersistentList
|
|
||||||
from zope import component
|
from zope import component
|
||||||
from zope.annotation.interfaces import IAttributeAnnotatable
|
from zope.annotation.interfaces import IAttributeAnnotatable
|
||||||
from zope.app.container.interfaces import IObjectAddedEvent
|
from zope.app.container.interfaces import IObjectAddedEvent
|
||||||
|
@ -52,6 +51,15 @@ allRolesExceptOwner = (
|
||||||
'loops.Member', 'loops.Master',)
|
'loops.Member', 'loops.Master',)
|
||||||
allRolesExceptOwnerAndMaster = tuple(allRolesExceptOwner[:-1])
|
allRolesExceptOwnerAndMaster = tuple(allRolesExceptOwner[:-1])
|
||||||
minorPrivilegedRoles = ('zope.Anonymous', 'zope.Member',)
|
minorPrivilegedRoles = ('zope.Anonymous', 'zope.Member',)
|
||||||
|
localRoles = ('zope.Anonymous', 'zope.Member', 'zope.ContentManager',
|
||||||
|
'loops.Staff', 'loops.Member', 'loops.Master', 'loops.Owner')
|
||||||
|
|
||||||
|
localPermissions = ('zope.ManageContent', 'zope.View', 'loops.ManageWorkspaces',
|
||||||
|
'loops.ViewRestricted', 'loops.EditRestricted', 'loops.AssignAsParent',)
|
||||||
|
|
||||||
|
allocationPredicateNames = ('ismaster', 'ismember')
|
||||||
|
|
||||||
|
workspaceGroupsFolderName = 'gloops_ws'
|
||||||
|
|
||||||
|
|
||||||
# checking and querying functions
|
# checking and querying functions
|
||||||
|
@ -70,6 +78,9 @@ def canWriteObject(obj):
|
||||||
def canEditRestricted(obj):
|
def canEditRestricted(obj):
|
||||||
return checkPermission('loops.EditRestricted', obj)
|
return checkPermission('loops.EditRestricted', obj)
|
||||||
|
|
||||||
|
def canAssignAsParent(obj):
|
||||||
|
return checkPermission('loops.AssignAsParent', obj)
|
||||||
|
|
||||||
def checkPermission(permission, obj):
|
def checkPermission(permission, obj):
|
||||||
return baseCheckPermission(permission, obj)
|
return baseCheckPermission(permission, obj)
|
||||||
|
|
||||||
|
@ -174,11 +185,15 @@ class WorkspaceInformation(Persistent):
|
||||||
__name__ = u'workspace_information'
|
__name__ = u'workspace_information'
|
||||||
|
|
||||||
propagateRolePermissions = 'workspace'
|
propagateRolePermissions = 'workspace'
|
||||||
|
allocationPredicateNames = allocationPredicateNames
|
||||||
|
workspaceGroupsFolderName = workspaceGroupsFolderName
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
self.__parent__ = parent
|
self.__parent__ = parent
|
||||||
self.workspaceGroupNames = PersistentList()
|
self.workspaceGroupNames = {}
|
||||||
|
|
||||||
def getName(self):
|
def getName(self):
|
||||||
return self.__name__
|
return self.__name__
|
||||||
|
|
||||||
|
def getParent(self):
|
||||||
|
return self.__parent__
|
||||||
|
|
|
@ -70,6 +70,6 @@ class IWorkspaceInformation(Interface):
|
||||||
security-related stuff for sub-objects.
|
security-related stuff for sub-objects.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
propagateRolePermissions = Attribute('Which role permissions should be '
|
propagateRolePermissions = Attribute('Whose role permissions should be '
|
||||||
'propagated to children?')
|
'propagated to children (workspace_informaton or parent)?')
|
||||||
|
|
||||||
|
|
|
@ -37,37 +37,32 @@
|
||||||
tal:attributes="value permId" />
|
tal:attributes="value permId" />
|
||||||
<div class="form-element">
|
<div class="form-element">
|
||||||
|
|
||||||
<table width="100%" cellspacing="0" cellpadding="2" border="0"
|
<table class="listing" cellspacing="0" cellpadding="2" border="0"
|
||||||
nowrap="nowrap">
|
nowrap="nowrap">
|
||||||
|
|
||||||
<tr class="list-header">
|
<tr class="list-header">
|
||||||
<td><strong i18n:translate="">Role</strong></td>
|
<th i18n:translate="">Role</th>
|
||||||
<td><strong i18n:translate="">Users/Groups</strong></td>
|
<th i18n:translate="">Users/Groups</th>
|
||||||
<td><strong i18n:translate="">Acquired Setting</strong></td>
|
<th i18n:translate="">Acquired Setting</th>
|
||||||
<td><strong i18n:translate="">Setting</strong></td>
|
<th i18n:translate="">Setting</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tal:role tal:repeat="setting perm/roleSettings">
|
||||||
<tr class="row-normal"
|
<tr class="row-normal"
|
||||||
tal:repeat="setting perm/roleSettings"
|
tal:define="ir repeat/setting/index;
|
||||||
tal:attributes="class python:
|
roleId python:path('view/roles')[ir].id"
|
||||||
path('repeat/setting/even') and 'row-normal' or 'row-hilite'">
|
tal:attributes="style python:view.hideRole(roleId) and
|
||||||
<tal:role define="ir repeat/setting/index;
|
'visibility: collapse' or ''">
|
||||||
roleId python:path('view/roles')[ir].id">
|
|
||||||
<td align="left" valign="top"
|
<td align="left" valign="top"
|
||||||
tal:content="roleId">
|
tal:content="roleId" />
|
||||||
Manager
|
|
||||||
</td>
|
|
||||||
<td>
|
<td>
|
||||||
<span tal:define="users python: view.listUsersForRole(roleId)"
|
<span tal:define="users python: view.listUsersForRole(roleId)"
|
||||||
tal:replace="structure users">
|
tal:replace="structure users" /></td>
|
||||||
User xy
|
<td class="center">
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span tal:replace="python:
|
<span tal:replace="python:
|
||||||
view.getAcquiredPermissionSetting(roleId, permId)" />
|
view.getAcquiredPermissionSetting(roleId, permId)" />
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td class="center">
|
||||||
<select name="settings:list">
|
<select name="settings:list">
|
||||||
<option value="Unset"
|
<option value="Unset"
|
||||||
tal:repeat="option view/availableSettings"
|
tal:repeat="option view/availableSettings"
|
||||||
|
@ -77,16 +72,16 @@
|
||||||
i18n:translate="">+</option>
|
i18n:translate="">+</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tal:role>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr tal:define="principals view/getPrincipalPermissions"
|
</tal:role>
|
||||||
|
<tr tal:define="principals view/getPrincipalPermissions"
|
||||||
tal:condition="principals">
|
tal:condition="principals">
|
||||||
<td>
|
<td>
|
||||||
<strong i18n:translate="">Direct Settings</strong>
|
<strong i18n:translate="">Direct Settings</strong>
|
||||||
</td>
|
</td>
|
||||||
<td colspan="3" tal:content="structure principals">+xyz</td>
|
<td colspan="3" tal:content="structure principals">+xyz</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,51 @@
|
||||||
i18n:domain="zope">
|
i18n:domain="zope">
|
||||||
<body>
|
<body>
|
||||||
<div metal:fill-slot="body" i18n:domain="zope">
|
<div metal:fill-slot="body" i18n:domain="zope">
|
||||||
<h2 i18n:translate="">Assign Permissions to Roles for Children of this Object</h2>
|
<h1 i18n:translate="">Define Workspace Properties</h1>
|
||||||
<p tal:define="status view/update"
|
<p tal:define="status view/update"
|
||||||
tal:content="status" i18n:translate=""/>
|
tal:content="status" i18n:translate=""/>
|
||||||
|
<form method="post">
|
||||||
|
<table class="listing">
|
||||||
|
<tr>
|
||||||
|
<th colspan="3"></th>
|
||||||
|
<th colspan="2">Assign role in</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Predicate</th>
|
||||||
|
<th>Group name</th>
|
||||||
|
<th>Exists</th>
|
||||||
|
<th>Parent</th>
|
||||||
|
<th>WS Info</th>
|
||||||
|
</tr>
|
||||||
|
<tr tal:repeat="gi view/getGroupsInfo">
|
||||||
|
<td>
|
||||||
|
<input type="hidden" name="predicate_name:list"
|
||||||
|
tal:attributes="value gi/predicateName" />
|
||||||
|
<span tal:content="gi/predicateTitle" />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" size="40"
|
||||||
|
tal:attributes="name string:group_name_${gi/predicateName};
|
||||||
|
value gi/groupName">
|
||||||
|
</td>
|
||||||
|
<td class="center"
|
||||||
|
tal:content="python:gi['groupExists'] and 'yes' or 'no'" />
|
||||||
|
<td class="center">
|
||||||
|
<input type="checkbox" value="true"
|
||||||
|
tal:attributes="name string:role_parent_${gi/predicateName};
|
||||||
|
checked gi/roleParent" /></td>
|
||||||
|
<td class="center">
|
||||||
|
<input type="checkbox" value="true"
|
||||||
|
tal:attributes="name string:role_wsi_${gi/predicateName};
|
||||||
|
checked gi/roleWSI" /></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br />
|
||||||
|
<input type="submit" name="save_wsinfo" value="Save Settings" />
|
||||||
|
</form>
|
||||||
|
<br />
|
||||||
|
<h2 i18n:translate="">Assign Permissions to Roles for Children of this Object</h2>
|
||||||
|
<br />
|
||||||
<metal:permissions use-macro="view/permission_macros/permission_form" />
|
<metal:permissions use-macro="view/permission_macros/permission_form" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue