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 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):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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>
|
||||
|
|
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"
|
||||
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">
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue