work in progress: workspace (parent-) -governed 'children' grants (principal-to-role mappings)
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3616 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
8ad7a0c573
commit
bcd76509e7
9 changed files with 180 additions and 17 deletions
13
concept.py
13
concept.py
|
@ -39,6 +39,7 @@ from zope.security.proxy import removeSecurityProxy, isinstance
|
||||||
from zope.traversing.api import getName, getParent
|
from zope.traversing.api import getName, getParent
|
||||||
from persistent import Persistent
|
from persistent import Persistent
|
||||||
|
|
||||||
|
from cybertools.meta.interfaces import IOptions
|
||||||
from cybertools.relation import DyadicRelation
|
from cybertools.relation import DyadicRelation
|
||||||
from cybertools.relation.registry import getRelations
|
from cybertools.relation.registry import getRelations
|
||||||
from cybertools.relation.interfaces import IRelationRegistry, IRelatable
|
from cybertools.relation.interfaces import IRelationRegistry, IRelatable
|
||||||
|
@ -104,6 +105,8 @@ class Concept(Contained, Persistent):
|
||||||
|
|
||||||
proxyInterface = IConceptView
|
proxyInterface = IConceptView
|
||||||
|
|
||||||
|
workspaceInformation = None
|
||||||
|
|
||||||
def __init__(self, title=u''):
|
def __init__(self, title=u''):
|
||||||
self.title = title
|
self.title = title
|
||||||
|
|
||||||
|
@ -162,6 +165,16 @@ class Concept(Contained, Persistent):
|
||||||
pi.relations.append(rel)
|
pi.relations.append(rel)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@property
|
||||||
|
def isWorkspace(self):
|
||||||
|
ct = self.conceptType
|
||||||
|
if ct != self.getConceptManager().getTypeConcept():
|
||||||
|
from loops.config.base import DummyOptions
|
||||||
|
options = component.queryAdapter(adapted(self), IOptions) or DummyOptions()
|
||||||
|
if options('security.isWorkspace'):
|
||||||
|
return True
|
||||||
|
return IOptions(adapted(ct))('security.isWorkspace')
|
||||||
|
|
||||||
# concept relations
|
# concept relations
|
||||||
|
|
||||||
def getClients(self, relationships=None):
|
def getClients(self, relationships=None):
|
||||||
|
|
|
@ -104,6 +104,13 @@ class IConcept(IConceptSchema, ILoopsObject, IPotentialTarget):
|
||||||
source="loops.conceptTypeSource",
|
source="loops.conceptTypeSource",
|
||||||
required=True)
|
required=True)
|
||||||
|
|
||||||
|
isWorkspace = Attribute('Marks a concept as responsible for providing '
|
||||||
|
'special permission settings (children grants) '
|
||||||
|
'for its sub-objects (children or resources).')
|
||||||
|
|
||||||
|
workspaceInformation = Attribute('An object with additional '
|
||||||
|
'workspace-related information, e.g. children grants.')
|
||||||
|
|
||||||
def getType():
|
def getType():
|
||||||
""" Return a concept that provides the object's type.
|
""" Return a concept that provides the object's type.
|
||||||
"""
|
"""
|
||||||
|
@ -677,6 +684,13 @@ class IPredicate(IConceptSchema):
|
||||||
source='loops.PredicateInterfaceSource',
|
source='loops.PredicateInterfaceSource',
|
||||||
required=False)
|
required=False)
|
||||||
|
|
||||||
|
options = schema.List(
|
||||||
|
title=_(u'Options'),
|
||||||
|
description=_(u'Additional settings.'),
|
||||||
|
value_type=schema.TextLine(),
|
||||||
|
default=[],
|
||||||
|
required=False)
|
||||||
|
|
||||||
|
|
||||||
# probably not useful
|
# probably not useful
|
||||||
class xxIMappingAttributeRelation(IConceptSchema):
|
class xxIMappingAttributeRelation(IConceptSchema):
|
||||||
|
|
|
@ -48,6 +48,12 @@ class Predicate(AdapterBase):
|
||||||
|
|
||||||
_contextAttributes = list(IPredicate) # + list(IConcept)
|
_contextAttributes = list(IPredicate) # + list(IConcept)
|
||||||
|
|
||||||
|
def getOptions(self):
|
||||||
|
return getattr(self.context, '_options', [])
|
||||||
|
def setOptions(self, value):
|
||||||
|
self.context._options = value
|
||||||
|
options = property(getOptions, setOptions)
|
||||||
|
|
||||||
|
|
||||||
class PredicateInterfaceSourceList(TypeInterfaceSourceList):
|
class PredicateInterfaceSourceList(TypeInterfaceSourceList):
|
||||||
""" Collects type interfaces for predicates, i.e. interfaces that
|
""" Collects type interfaces for predicates, i.e. interfaces that
|
||||||
|
|
|
@ -57,6 +57,10 @@
|
||||||
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" />
|
||||||
|
|
||||||
|
<role id="loops.Member"
|
||||||
|
title="[loops-member-role] loops: Member" />
|
||||||
|
<grant role="loops.Member" permission="zope.View" />
|
||||||
|
|
||||||
<role id="loops.xmlrpc.ConceptManager"
|
<role id="loops.xmlrpc.ConceptManager"
|
||||||
title="[xmlrpc-manage-concepts-role] loops: Concept Manager (XML-RPC)" />
|
title="[xmlrpc-manage-concepts-role] loops: Concept Manager (XML-RPC)" />
|
||||||
<grant role="loops.xmlrpc.ConceptManager" permission="loops.xmlrpc.ManageConcepts" />
|
<grant role="loops.xmlrpc.ConceptManager" permission="loops.xmlrpc.ManageConcepts" />
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2009 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,7 +22,9 @@ Common functions and other stuff for working with permissions and roles.
|
||||||
$Id$
|
$Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from persistent import Persistent
|
||||||
from zope import component
|
from zope import component
|
||||||
|
from zope.annotation.interfaces import IAttributeAnnotatable
|
||||||
from zope.app.container.interfaces import IObjectAddedEvent
|
from zope.app.container.interfaces import IObjectAddedEvent
|
||||||
from zope.app.securitypolicy.interfaces import IPrincipalRoleManager
|
from zope.app.securitypolicy.interfaces import IPrincipalRoleManager
|
||||||
from zope.app.securitypolicy.interfaces import IRolePermissionManager
|
from zope.app.securitypolicy.interfaces import IRolePermissionManager
|
||||||
|
@ -32,6 +34,7 @@ from zope.lifecycleevent import IObjectCreatedEvent, IObjectModifiedEvent
|
||||||
from zope.security import canAccess, canWrite
|
from zope.security import canAccess, canWrite
|
||||||
from zope.security import checkPermission as baseCheckPermission
|
from zope.security import checkPermission as baseCheckPermission
|
||||||
from zope.security.management import getInteraction
|
from zope.security.management import getInteraction
|
||||||
|
from zope.traversing.interfaces import IPhysicallyLocatable
|
||||||
|
|
||||||
from loops.common import adapted
|
from loops.common import adapted
|
||||||
from loops.interfaces import ILoopsObject, IConcept
|
from loops.interfaces import ILoopsObject, IConcept
|
||||||
|
@ -44,7 +47,7 @@ allRolesExceptOwner = (
|
||||||
'zope.Anonymous', 'zope.Member', 'zope.ContentManager', 'loops.Staff',
|
'zope.Anonymous', 'zope.Member', 'zope.ContentManager', 'loops.Staff',
|
||||||
'loops.xmlrpc.ConceptManager', # relevant for local security?
|
'loops.xmlrpc.ConceptManager', # relevant for local security?
|
||||||
#'loops.SiteManager',
|
#'loops.SiteManager',
|
||||||
'loops.Master',)
|
'loops.Member', 'loops.Master',)
|
||||||
allRolesExceptOwnerAndMaster = tuple(allRolesExceptOwner[:-1])
|
allRolesExceptOwnerAndMaster = tuple(allRolesExceptOwner[:-1])
|
||||||
minorPrivilegedRoles = ('zope.Anonymous', 'zope.Member',)
|
minorPrivilegedRoles = ('zope.Anonymous', 'zope.Member',)
|
||||||
|
|
||||||
|
@ -137,3 +140,21 @@ def revokeAcquiredSecurity(obj, event):
|
||||||
setter = ISecuritySetter(aObj)
|
setter = ISecuritySetter(aObj)
|
||||||
setter.setAcquiredRolePermissions(event.relation, revert=True)
|
setter.setAcquiredRolePermissions(event.relation, revert=True)
|
||||||
setter.setAcquiredPrincipalRoles(event.relation, revert=True)
|
setter.setAcquiredPrincipalRoles(event.relation, revert=True)
|
||||||
|
|
||||||
|
|
||||||
|
# helper stuff
|
||||||
|
|
||||||
|
class WorkspaceInformation(Persistent):
|
||||||
|
""" For storing security-related stuff pertaining to
|
||||||
|
children and resources of the context (=parent) object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
implements(IPhysicallyLocatable)
|
||||||
|
|
||||||
|
__name__ = u'workspace_information'
|
||||||
|
|
||||||
|
def __init__(self, parent):
|
||||||
|
self.__parent__ = parent
|
||||||
|
|
||||||
|
def getName(self):
|
||||||
|
return self.__name__
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
|
|
||||||
<zope:adapter factory="loops.security.setter.BaseSecuritySetter" />
|
<zope:adapter factory="loops.security.setter.BaseSecuritySetter" />
|
||||||
|
|
||||||
|
<zope:class class="loops.security.common.WorkspaceInformation">
|
||||||
|
<implements interface="zope.annotation.interfaces.IAttributeAnnotatable" />
|
||||||
|
</zope:class>
|
||||||
|
|
||||||
<zope:adapter
|
<zope:adapter
|
||||||
for="loops.interfaces.IConcept"
|
for="loops.interfaces.IConcept"
|
||||||
factory="zope.app.securitypolicy.rolepermission.AnnotationRolePermissionManager"
|
factory="zope.app.securitypolicy.rolepermission.AnnotationRolePermissionManager"
|
||||||
|
@ -32,4 +36,18 @@
|
||||||
class=".perm.PermissionView"
|
class=".perm.PermissionView"
|
||||||
menu="zmi_actions" title="Edit Permissions" />
|
menu="zmi_actions" title="Edit Permissions" />
|
||||||
|
|
||||||
|
<browser:page
|
||||||
|
for="loops.interfaces.IConcept"
|
||||||
|
name="grantchildren.html"
|
||||||
|
permission="zope.Security"
|
||||||
|
template="manage_grantchildrenform.pt"
|
||||||
|
class=".perm.GrantChildrenView" />
|
||||||
|
|
||||||
|
<browser:menuItem
|
||||||
|
for="loops.interfaces.IConcept"
|
||||||
|
action="@@grantchildren.html"
|
||||||
|
permission="zope.Security"
|
||||||
|
menu="zmi_actions" title="Grant Children"
|
||||||
|
filter="python: context.isWorkspace" />
|
||||||
|
|
||||||
</configure>
|
</configure>
|
||||||
|
|
84
security/manage_grantchildrenform.pt
Normal file
84
security/manage_grantchildrenform.pt
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
<html metal:use-macro="context/@@standard_macros/page"
|
||||||
|
i18n:domain="zope">
|
||||||
|
<body>
|
||||||
|
<div metal:fill-slot="body" i18n:domain="zope">
|
||||||
|
<h2 i18n:translate="">Grant Roles for Children of this Object to Principals</h2>
|
||||||
|
<p tal:define="status view/status"
|
||||||
|
tal:condition="status"
|
||||||
|
tal:content="status" i18n:translate=""/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-element"
|
||||||
|
tal:define="perm view/permission"
|
||||||
|
tal:condition="not: view/principal">
|
||||||
|
<table width="100%" cellspacing="0" cellpadding="2" border="0"
|
||||||
|
nowrap="nowrap">
|
||||||
|
<tr class="list-header">
|
||||||
|
<td><strong i18n:translate="">Role</strong></td>
|
||||||
|
<td><strong i18n:translate="">Users/Groups</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="row-normal"
|
||||||
|
tal:repeat="setting perm/roleSettings"
|
||||||
|
tal:attributes="class python:
|
||||||
|
path('repeat/setting/even') and 'row-normal' or 'row-hilite'">
|
||||||
|
<tal:role define="ir repeat/setting/index;
|
||||||
|
roleId python:path('view/roles')[ir].id">
|
||||||
|
<td align="left" valign="top"
|
||||||
|
tal:content="roleId">Manager</td>
|
||||||
|
<td>
|
||||||
|
<span tal:define="users python: view.listUsersForRole(roleId)"
|
||||||
|
tal:replace="structure users">User xy</span></td>
|
||||||
|
</tal:role>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form action="" method="POST">
|
||||||
|
|
||||||
|
<div tal:content="structure view/principal_widget">...</div>
|
||||||
|
|
||||||
|
<div tal:condition="view/principal">
|
||||||
|
|
||||||
|
<h2 i18n:translate="">Grants for the selected principal</h2>
|
||||||
|
<input type="submit" name="GRANT_SUBMIT" value="Change"
|
||||||
|
i18n:attributes="value grant-submit" />
|
||||||
|
|
||||||
|
<table width="100%" border="0">
|
||||||
|
<tr>
|
||||||
|
<td valign="top">
|
||||||
|
<table class="matrix">
|
||||||
|
<tr>
|
||||||
|
<td i18n:translate=""><strong>Roles</strong> </td>
|
||||||
|
<td i18n:translate=""><strong>Allow</strong> </td>
|
||||||
|
<td i18n:translate=""><strong>Unset</strong> </td>
|
||||||
|
<td i18n:translate=""><strong>Deny</strong> </td>
|
||||||
|
</tr>
|
||||||
|
<tr tal:repeat="widget view/roles">
|
||||||
|
<td valign="top" nowrap>
|
||||||
|
<div class="label">
|
||||||
|
<label for="field.name" title="The widget's hint"
|
||||||
|
tal:attributes="for widget/name; title widget/hint"
|
||||||
|
tal:content="widget/label"
|
||||||
|
i18n:translate="">The Label</label>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<tal:block tal:content="structure widget">
|
||||||
|
roles widget
|
||||||
|
</tal:block>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><a href="#top" i18n:translate="">^ top</a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<input type="submit" name="GRANT_SUBMIT" value="Change"
|
||||||
|
i18n:attributes="value grant-submit" />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,19 +1,5 @@
|
||||||
<html metal:use-macro="context/@@standard_macros/view"
|
<html metal:use-macro="context/@@standard_macros/view"
|
||||||
i18n:domain="zope">
|
i18n:domain="zope">
|
||||||
<head>
|
|
||||||
<style metal:fill-slot="headers" type="text/css">
|
|
||||||
<!--
|
|
||||||
.row-normal {
|
|
||||||
background-color: #ffffff;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
.row-hilite {
|
|
||||||
background-color: #efefef;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
-->
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div metal:fill-slot="body">
|
<div metal:fill-slot="body">
|
||||||
|
|
|
@ -26,13 +26,17 @@ from zope import component
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
from zope.app.security.interfaces import IPermission
|
from zope.app.security.interfaces import IPermission
|
||||||
|
from zope.app.securitypolicy.browser.granting 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, IRolePermissionMap
|
from zope.app.securitypolicy.interfaces import IPrincipalRoleManager, IRolePermissionMap
|
||||||
from zope.app.securitypolicy.interfaces import IPrincipalPermissionManager, \
|
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.security.proxy import removeSecurityProxy
|
||||||
from zope.traversing.api import getParents
|
from zope.traversing.api import getParents
|
||||||
|
|
||||||
|
from loops.security.common import WorkspaceInformation
|
||||||
|
|
||||||
|
|
||||||
class PermissionView(object):
|
class PermissionView(object):
|
||||||
""" View for permission editing.
|
""" View for permission editing.
|
||||||
|
@ -135,3 +139,16 @@ class PermissionView(object):
|
||||||
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))
|
||||||
|
|
||||||
|
|
||||||
|
class GrantChildrenView(Granting, PermissionView):
|
||||||
|
""" View for editing grants for children of workspace objects.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, context, request):
|
||||||
|
context = removeSecurityProxy(context)
|
||||||
|
wi = context.workspaceInformation
|
||||||
|
if wi is None:
|
||||||
|
wi = context.workspaceInformation = WorkspaceInformation(context)
|
||||||
|
#self.context = wi
|
||||||
|
#self.request = request
|
||||||
|
PermissionView.__init__(self, wi, request)
|
||||||
|
|
Loading…
Add table
Reference in a new issue