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:
helmutm 2009-11-01 21:30:17 +00:00
parent 8ad7a0c573
commit bcd76509e7
9 changed files with 180 additions and 17 deletions

View file

@ -39,6 +39,7 @@ from zope.security.proxy import removeSecurityProxy, isinstance
from zope.traversing.api import getName, getParent
from persistent import Persistent
from cybertools.meta.interfaces import IOptions
from cybertools.relation import DyadicRelation
from cybertools.relation.registry import getRelations
from cybertools.relation.interfaces import IRelationRegistry, IRelatable
@ -104,6 +105,8 @@ class Concept(Contained, Persistent):
proxyInterface = IConceptView
workspaceInformation = None
def __init__(self, title=u''):
self.title = title
@ -162,6 +165,16 @@ class Concept(Contained, Persistent):
pi.relations.append(rel)
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
def getClients(self, relationships=None):

View file

@ -104,6 +104,13 @@ class IConcept(IConceptSchema, ILoopsObject, IPotentialTarget):
source="loops.conceptTypeSource",
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():
""" Return a concept that provides the object's type.
"""
@ -677,6 +684,13 @@ class IPredicate(IConceptSchema):
source='loops.PredicateInterfaceSource',
required=False)
options = schema.List(
title=_(u'Options'),
description=_(u'Additional settings.'),
value_type=schema.TextLine(),
default=[],
required=False)
# probably not useful
class xxIMappingAttributeRelation(IConceptSchema):

View file

@ -48,6 +48,12 @@ class Predicate(AdapterBase):
_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):
""" Collects type interfaces for predicates, i.e. interfaces that

View file

@ -57,6 +57,10 @@
title="[loops-master-role] loops: Master" />
<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"
title="[xmlrpc-manage-concepts-role] loops: Concept Manager (XML-RPC)" />
<grant role="loops.xmlrpc.ConceptManager" permission="loops.xmlrpc.ManageConcepts" />

View file

@ -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
# 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$
"""
from persistent import Persistent
from zope import component
from zope.annotation.interfaces import IAttributeAnnotatable
from zope.app.container.interfaces import IObjectAddedEvent
from zope.app.securitypolicy.interfaces import IPrincipalRoleManager
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 checkPermission as baseCheckPermission
from zope.security.management import getInteraction
from zope.traversing.interfaces import IPhysicallyLocatable
from loops.common import adapted
from loops.interfaces import ILoopsObject, IConcept
@ -44,7 +47,7 @@ allRolesExceptOwner = (
'zope.Anonymous', 'zope.Member', 'zope.ContentManager', 'loops.Staff',
'loops.xmlrpc.ConceptManager', # relevant for local security?
#'loops.SiteManager',
'loops.Master',)
'loops.Member', 'loops.Master',)
allRolesExceptOwnerAndMaster = tuple(allRolesExceptOwner[:-1])
minorPrivilegedRoles = ('zope.Anonymous', 'zope.Member',)
@ -137,3 +140,21 @@ def revokeAcquiredSecurity(obj, event):
setter = ISecuritySetter(aObj)
setter.setAcquiredRolePermissions(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__

View file

@ -7,6 +7,10 @@
<zope:adapter factory="loops.security.setter.BaseSecuritySetter" />
<zope:class class="loops.security.common.WorkspaceInformation">
<implements interface="zope.annotation.interfaces.IAttributeAnnotatable" />
</zope:class>
<zope:adapter
for="loops.interfaces.IConcept"
factory="zope.app.securitypolicy.rolepermission.AnnotationRolePermissionManager"
@ -32,4 +36,18 @@
class=".perm.PermissionView"
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>

View 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=""/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<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>&nbsp;</td>
<td i18n:translate=""><strong>Allow</strong>&nbsp;</td>
<td i18n:translate=""><strong>Unset</strong>&nbsp;</td>
<td i18n:translate=""><strong>Deny</strong>&nbsp;</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>

View file

@ -1,19 +1,5 @@
<html metal:use-macro="context/@@standard_macros/view"
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>
i18n:domain="zope">
<body>
<div metal:fill-slot="body">

View file

@ -26,13 +26,17 @@ from zope import component
from zope.interface import implements
from zope.cachedescriptors.property import Lazy
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.interfaces import IPrincipalRoleManager, IRolePermissionMap
from zope.app.securitypolicy.interfaces import IPrincipalPermissionManager, \
IPrincipalPermissionMap
from zope.app.securitypolicy.zopepolicy import SettingAsBoolean
from zope.security.proxy import removeSecurityProxy
from zope.traversing.api import getParents
from loops.security.common import WorkspaceInformation
class PermissionView(object):
""" View for permission editing.
@ -135,3 +139,16 @@ class PermissionView(object):
def getPermissions(self):
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)