propagation of role permission settings from workspaces basically working
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3623 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
fdd7f8637b
commit
87f46f0d28
14 changed files with 406 additions and 176 deletions
10
concept.py
10
concept.py
|
@ -165,16 +165,6 @@ 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):
|
||||||
|
|
|
@ -25,7 +25,7 @@ $Id$
|
||||||
from zope.interface import Interface, Attribute
|
from zope.interface import Interface, Attribute
|
||||||
from zope import interface, component, schema
|
from zope import interface, component, schema
|
||||||
|
|
||||||
from loops.interfaces import IConceptSchema
|
from loops.interfaces import IConceptSchema, ILoopsAdapter
|
||||||
from loops.util import _
|
from loops.util import _
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ class IExternalSourceInfo(Interface):
|
||||||
|
|
||||||
# external collections
|
# external collections
|
||||||
|
|
||||||
class IExternalCollection(IConceptSchema):
|
class IExternalCollection(IConceptSchema, ILoopsAdapter):
|
||||||
""" A concept representing a collection of resources that may be
|
""" A concept representing a collection of resources that may be
|
||||||
actively retrieved from an external system using the parameters
|
actively retrieved from an external system using the parameters
|
||||||
given.
|
given.
|
||||||
|
|
|
@ -104,12 +104,8 @@ 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 '
|
workspaceInformation = Attribute('An object with additional '
|
||||||
'workspace-related information, e.g. children grants.')
|
'workspace-related information.')
|
||||||
|
|
||||||
def getType():
|
def getType():
|
||||||
""" Return a concept that provides the object's type.
|
""" Return a concept that provides the object's type.
|
||||||
|
|
|
@ -34,6 +34,7 @@ from cybertools.organize.interfaces import IPerson as IBasePerson
|
||||||
from cybertools.organize.interfaces import ITask
|
from cybertools.organize.interfaces import ITask
|
||||||
from loops.interfaces import IConceptSchema
|
from loops.interfaces import IConceptSchema
|
||||||
from loops.organize.util import getPrincipalFolder
|
from loops.organize.util import getPrincipalFolder
|
||||||
|
from loops.interfaces import ILoopsAdapter
|
||||||
from loops import util
|
from loops import util
|
||||||
from loops.util import _
|
from loops.util import _
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@ class LoginName(schema.TextLine):
|
||||||
mapping=dict(userId=userId)))
|
mapping=dict(userId=userId)))
|
||||||
|
|
||||||
|
|
||||||
class IPerson(IConceptSchema, IBasePerson):
|
class IPerson(IConceptSchema, IBasePerson, ILoopsAdapter):
|
||||||
""" Resembles a human being with a name (first and last name),
|
""" Resembles a human being with a name (first and last name),
|
||||||
a birth date, and a set of addresses. This interface only
|
a birth date, and a set of addresses. This interface only
|
||||||
lists fields used in addition to those provided by the
|
lists fields used in addition to those provided by the
|
||||||
|
@ -101,7 +102,7 @@ class IPerson(IConceptSchema, IBasePerson):
|
||||||
required=False,)
|
required=False,)
|
||||||
|
|
||||||
|
|
||||||
class IAddress(IConceptSchema, IBaseAddress):
|
class IAddress(IConceptSchema, IBaseAddress, ILoopsAdapter):
|
||||||
""" See cybertools.organize.
|
""" See cybertools.organize.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -158,7 +159,7 @@ class IMemberRegistrationManager(Interface):
|
||||||
|
|
||||||
# task
|
# task
|
||||||
|
|
||||||
class ITask(IConceptSchema, ITask):
|
class ITask(IConceptSchema, ITask, ILoopsAdapter):
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -23,18 +23,150 @@ $Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope.app.pagetemplate import ViewPageTemplateFile
|
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||||
|
from zope.app.security.interfaces import IPermission
|
||||||
|
from zope.app.securitypolicy.browser 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 import component
|
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.security.proxy import removeSecurityProxy
|
from zope.security.proxy import removeSecurityProxy
|
||||||
|
from zope.traversing.api import getParent, getParents
|
||||||
|
|
||||||
|
from loops.common import adapted
|
||||||
from loops.security.common import WorkspaceInformation
|
from loops.security.common import WorkspaceInformation
|
||||||
from loops.security.perm import PermissionView
|
from loops.security.interfaces import ISecuritySetter
|
||||||
|
|
||||||
|
|
||||||
permission_template = ViewPageTemplateFile('manage_permissionform.pt')
|
permission_template = ViewPageTemplateFile('manage_permissionform.pt')
|
||||||
|
|
||||||
|
|
||||||
|
class Granting(granting.Granting):
|
||||||
|
|
||||||
|
def status(self):
|
||||||
|
value = super(Granting, self).status()
|
||||||
|
if value:
|
||||||
|
setter = ISecuritySetter(adapted(self.context), None)
|
||||||
|
if setter is not None:
|
||||||
|
setter.propagatePrincipalRoles()
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class PermissionView(object):
|
||||||
|
""" View for permission editing.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, context, request):
|
||||||
|
self.context = context
|
||||||
|
# make sure the real view (delegate) updates our context when
|
||||||
|
# talking about the context's parent:
|
||||||
|
self.__parent__ = context
|
||||||
|
self.request = request
|
||||||
|
self.delegate = RolePermissionView()
|
||||||
|
self.delegate.context = self
|
||||||
|
self.delegate.request = request
|
||||||
|
self.permissionId = request.get('permission_to_manage') or 'zope.View'
|
||||||
|
|
||||||
|
def pagetip(self):
|
||||||
|
return self.delegate.pagetip()
|
||||||
|
|
||||||
|
def roles(self):
|
||||||
|
return self.delegate.roles()
|
||||||
|
|
||||||
|
def permissions(self):
|
||||||
|
return self.delegate.permissions()
|
||||||
|
|
||||||
|
def availableSettings(self, noacquire=False):
|
||||||
|
return self.delegate.availableSettings(noacquire)
|
||||||
|
|
||||||
|
def permissionRoles(self):
|
||||||
|
return self.delegate.permissionRoles()
|
||||||
|
|
||||||
|
def permissionForID(self, pid):
|
||||||
|
return self.delegate.permissionForID(pid)
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def permission(self):
|
||||||
|
return self.permissionForID(self.permissionId)
|
||||||
|
|
||||||
|
def roleForID(self, rid):
|
||||||
|
return self.delegate.roleForID(rid)
|
||||||
|
|
||||||
|
def update(self, testing=None):
|
||||||
|
value = self.delegate.update(testing)
|
||||||
|
if value:
|
||||||
|
setter = ISecuritySetter(self.adapted, None)
|
||||||
|
if setter is not None:
|
||||||
|
setter.propagateRolePermissions()
|
||||||
|
return value
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def adapted(self):
|
||||||
|
return adapted(self.context)
|
||||||
|
|
||||||
|
def getAcquiredPermissionSetting(self, role, perm):
|
||||||
|
for obj in getParents(self.context):
|
||||||
|
rpm = IRolePermissionMap(obj, None)
|
||||||
|
if rpm is not None:
|
||||||
|
setting = rpm.getSetting(perm, role)
|
||||||
|
setting = SettingAsBoolean[setting]
|
||||||
|
if setting is not None:
|
||||||
|
return setting and '+' or '-'
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def listUsersForRole(self, rid):
|
||||||
|
result = ''
|
||||||
|
direct = IPrincipalRoleManager(self.context).getPrincipalsForRole(rid)
|
||||||
|
if direct:
|
||||||
|
result = '<strong>' + self.renderEntry(direct) + '</strong>'
|
||||||
|
acquired = []
|
||||||
|
for obj in getParents(self.context):
|
||||||
|
prm = IPrincipalRoleManager(obj, None)
|
||||||
|
if prm is not None:
|
||||||
|
entry = prm.getPrincipalsForRole(rid)
|
||||||
|
if entry:
|
||||||
|
acquired.append(self.renderEntry(entry))
|
||||||
|
if acquired:
|
||||||
|
if result:
|
||||||
|
result += '<br />'
|
||||||
|
result += '<br />'.join(acquired)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def renderEntry(self, entry):
|
||||||
|
result = []
|
||||||
|
for e in entry:
|
||||||
|
value = SettingAsBoolean[e[1]]
|
||||||
|
value = (value is False and '-') or (value and '+') or ''
|
||||||
|
result.append(value + e[0])
|
||||||
|
return ', '.join(result)
|
||||||
|
|
||||||
|
def getPrincipalPermissions(self):
|
||||||
|
result = ''
|
||||||
|
ppm = IPrincipalPermissionMap(self.context)
|
||||||
|
direct = ppm.getPrincipalsForPermission(self.permissionId)
|
||||||
|
if direct:
|
||||||
|
result = '<strong>' + self.renderEntry(direct) + '</strong>'
|
||||||
|
acquired = []
|
||||||
|
for obj in getParents(self.context):
|
||||||
|
ppm = IPrincipalPermissionMap(obj, None)
|
||||||
|
if ppm is not None:
|
||||||
|
entry = ppm.getPrincipalsForPermission(self.permissionId)
|
||||||
|
if entry:
|
||||||
|
acquired.append(self.renderEntry(entry))
|
||||||
|
if acquired:
|
||||||
|
if result:
|
||||||
|
result += '<br />'
|
||||||
|
result += '<br />'.join(acquired)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def getPermissions(self):
|
||||||
|
return sorted(name for name, perm in component.getUtilitiesFor(IPermission))
|
||||||
|
|
||||||
|
|
||||||
class ManageWorkspaceView(PermissionView):
|
class ManageWorkspaceView(PermissionView):
|
||||||
""" View for managing workspace information.
|
""" View for managing workspace information.
|
||||||
"""
|
"""
|
||||||
|
@ -49,3 +181,9 @@ class ManageWorkspaceView(PermissionView):
|
||||||
@Lazy
|
@Lazy
|
||||||
def permission_macros(self):
|
def permission_macros(self):
|
||||||
return permission_template.macros
|
return permission_template.macros
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def adapted(self):
|
||||||
|
return adapted(getParent(self.context))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,11 @@ $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
|
||||||
|
from zope.app.security.settings import Allow, Deny, Unset
|
||||||
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
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
|
@ -39,7 +41,7 @@ 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
|
||||||
from loops.interfaces import IAssignmentEvent, IDeassignmentEvent
|
from loops.interfaces import IAssignmentEvent, IDeassignmentEvent
|
||||||
from loops.security.interfaces import ISecuritySetter
|
from loops.security.interfaces import ISecuritySetter, IWorkspaceInformation
|
||||||
|
|
||||||
|
|
||||||
allRolesExceptOwner = (
|
allRolesExceptOwner = (
|
||||||
|
@ -81,7 +83,20 @@ def getCurrentPrincipal():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
# functions for setting security properties
|
# functions for checking and setting security properties
|
||||||
|
|
||||||
|
def overrides(s1, s2):
|
||||||
|
settings = [Allow, Deny, Unset]
|
||||||
|
return settings.index(s1) < settings.index(s2)
|
||||||
|
|
||||||
|
def setRolePermission(rpm, p, r, setting):
|
||||||
|
if setting == Allow:
|
||||||
|
rpm.grantPermissionToRole(p, r)
|
||||||
|
elif setting == Deny:
|
||||||
|
rpm.denyPermissionToRole(p, r)
|
||||||
|
else:
|
||||||
|
rpm.unsetPermissionFromRole(p, r)
|
||||||
|
|
||||||
|
|
||||||
def assignOwner(obj, principalId):
|
def assignOwner(obj, principalId):
|
||||||
prm = IPrincipalRoleManager(obj)
|
prm = IPrincipalRoleManager(obj)
|
||||||
|
@ -149,12 +164,16 @@ class WorkspaceInformation(Persistent):
|
||||||
children and resources of the context (=parent) object.
|
children and resources of the context (=parent) object.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
implements(IPhysicallyLocatable)
|
implements(IPhysicallyLocatable, IWorkspaceInformation)
|
||||||
|
|
||||||
__name__ = u'workspace_information'
|
__name__ = u'workspace_information'
|
||||||
|
|
||||||
|
propagatePrincipalRoles = False
|
||||||
|
propagateRolePermissions = 'workspace'
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
self.__parent__ = parent
|
self.__parent__ = parent
|
||||||
|
self.workspaceGroups = PersistentList()
|
||||||
|
|
||||||
def getName(self):
|
def getName(self):
|
||||||
return self.__name__
|
return self.__name__
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
|
|
||||||
<zope:class class="loops.security.common.WorkspaceInformation">
|
<zope:class class="loops.security.common.WorkspaceInformation">
|
||||||
<implements interface="zope.annotation.interfaces.IAttributeAnnotatable" />
|
<implements interface="zope.annotation.interfaces.IAttributeAnnotatable" />
|
||||||
|
<allow interface="loops.security.interfaces.IWorkspaceInformation" />
|
||||||
|
<require set_schema="loops.security.interfaces.IWorkspaceInformation"
|
||||||
|
permission="zope.Security"/>
|
||||||
</zope:class>
|
</zope:class>
|
||||||
|
|
||||||
<zope:adapter
|
<zope:adapter
|
||||||
|
@ -24,6 +27,9 @@
|
||||||
factory="zope.app.securitypolicy.rolepermission.AnnotationRolePermissionManager"
|
factory="zope.app.securitypolicy.rolepermission.AnnotationRolePermissionManager"
|
||||||
trusted="true" />
|
trusted="true" />
|
||||||
|
|
||||||
|
<zope:adapter factory="loops.security.setter.ConceptSecuritySetter" />
|
||||||
|
<zope:adapter factory="loops.security.setter.ResourceSecuritySetter" />
|
||||||
|
|
||||||
<zope:subscriber handler="loops.security.common.setDefaultSecurity" />
|
<zope:subscriber handler="loops.security.common.setDefaultSecurity" />
|
||||||
<zope:subscriber handler="loops.security.common.grantAcquiredSecurity" />
|
<zope:subscriber handler="loops.security.common.grantAcquiredSecurity" />
|
||||||
<zope:subscriber handler="loops.security.common.revokeAcquiredSecurity" />
|
<zope:subscriber handler="loops.security.common.revokeAcquiredSecurity" />
|
||||||
|
@ -33,9 +39,17 @@
|
||||||
name="permissions.html"
|
name="permissions.html"
|
||||||
permission="zope.Security"
|
permission="zope.Security"
|
||||||
template="manage_permissionform.pt"
|
template="manage_permissionform.pt"
|
||||||
class="loops.security.perm.PermissionView"
|
class="loops.security.browser.PermissionView"
|
||||||
menu="zmi_actions" title="Edit Permissions" />
|
menu="zmi_actions" title="Edit Permissions" />
|
||||||
|
|
||||||
|
<browser:page
|
||||||
|
for="loops.interfaces.IConcept"
|
||||||
|
name="grant.html"
|
||||||
|
permission="zope.Security"
|
||||||
|
template="granting.pt"
|
||||||
|
class="loops.security.browser.Granting"
|
||||||
|
menu="zmi_actions" title="Grant" />
|
||||||
|
|
||||||
<browser:page
|
<browser:page
|
||||||
for="loops.interfaces.IConcept"
|
for="loops.interfaces.IConcept"
|
||||||
name="manage_workspace.html"
|
name="manage_workspace.html"
|
||||||
|
|
85
security/granting.pt
Normal file
85
security/granting.pt
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
<html metal:use-macro="context/@@standard_macros/view"
|
||||||
|
i18n:domain="zope">
|
||||||
|
<body>
|
||||||
|
<div metal:fill-slot="body" i18n:domain="zope">
|
||||||
|
<h2 i18n:translate="">Granting Roles and Permissions to Principals</h2>
|
||||||
|
<p tal:define="status view/status"
|
||||||
|
tal:condition="status"
|
||||||
|
tal:content="status" i18n:translate=""/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<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>
|
||||||
|
<td valign="top">
|
||||||
|
<table class="matrix">
|
||||||
|
<tr>
|
||||||
|
<td i18n:translate=""><strong>Permissions</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/permissions">
|
||||||
|
<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">
|
||||||
|
permission 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,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
|
||||||
|
@ -40,15 +40,46 @@ class ISecuritySetter(Interface):
|
||||||
(e.g. the user that created the object).
|
(e.g. the user that created the object).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def setAcquiredRolePermissions(relation, revert=False):
|
def acquireRolePermissions():
|
||||||
|
""" Check (immediate) parents's settings and set role permission
|
||||||
|
assignments on the context object accordingly.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setAcquiredRolePermissions(relation, revert=False, updated=None):
|
||||||
""" Grant role permissions on children/resources for the relation given.
|
""" Grant role permissions on children/resources for the relation given.
|
||||||
|
|
||||||
If the ``revert`` argument is true unset the corresponding settings.
|
If the ``revert`` argument is true unset the corresponding settings.
|
||||||
|
Do not update objects in the ``updated`` collection if present.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def setAcquiredPrincipalRoles(relation, revert=False):
|
def setAcquiredPrincipalRoles(relation, revert=False, updated=None):
|
||||||
""" Assign roles on children/resources for the relation given.
|
""" Assign roles on children/resources for the relation given.
|
||||||
|
|
||||||
If the ``revert`` argument is true unset the corresponding settings.
|
If the ``revert`` argument is true unset the corresponding settings.
|
||||||
|
Do not update objects in the ``updated`` collection if present.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def propagateRolePermissions(updated=None):
|
||||||
|
""" Update role permissions on all sub-objects according to the
|
||||||
|
current setting of the context object.
|
||||||
|
|
||||||
|
Ignore objects in the ``updated`` collection if present.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def propagatePrincipalRoles(updated=None):
|
||||||
|
""" Update roles on all sub-objects according to the
|
||||||
|
current setting of the context object.
|
||||||
|
|
||||||
|
Ignore objects in the ``updated`` collection if present.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class IWorkspaceInformation(Interface):
|
||||||
|
""" Additional information belonging to a concept that controls
|
||||||
|
security-related stuff for sub-objects.
|
||||||
|
"""
|
||||||
|
|
||||||
|
propagatePrincipalRoles = Attribute('Should acquired principal roles be '
|
||||||
|
'propagated to children?')
|
||||||
|
propagateRolePermissions = Attribute('Which role permissions should be '
|
||||||
|
'propagated to children?')
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div metal:fill-slot="body">
|
<div metal:fill-slot="body">
|
||||||
|
<h2 i18n:translate="">Assign Permissions to Roles</h2>
|
||||||
<p tal:define="status view/update"
|
<p tal:define="status view/update"
|
||||||
tal:condition="status"
|
tal:content="status" i18n:translate="" />
|
||||||
tal:content="status"
|
|
||||||
i18n:translate="" />
|
|
||||||
|
|
||||||
<div metal:define-macro="permission_form"
|
<div metal:define-macro="permission_form"
|
||||||
tal:define="permId view/permissionId;
|
tal:define="permId view/permissionId;
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
<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>
|
<h2 i18n:translate="">Assign Permissions to Roles for Children of this Object</h2>
|
||||||
<p tal:define="status view/update"
|
<p tal:define="status view/update"
|
||||||
tal:condition="status"
|
tal:content="status" i18n:translate=""/>
|
||||||
tal:content="status" i18n:translate=""/><br />
|
|
||||||
|
|
||||||
<metal:permissions use-macro="view/permission_macros/permission_form" />
|
<metal:permissions use-macro="view/permission_macros/permission_form" />
|
||||||
|
|
||||||
|
|
139
security/perm.py
139
security/perm.py
|
@ -1,139 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2008 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
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
|
|
||||||
"""
|
|
||||||
Authentication view.
|
|
||||||
|
|
||||||
$Id$
|
|
||||||
"""
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
class PermissionView(object):
|
|
||||||
""" View for permission editing.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, context, request):
|
|
||||||
self.context = context
|
|
||||||
# make sure the real view (delegate) updates our context when
|
|
||||||
# talking about the context's parent:
|
|
||||||
self.__parent__ = context
|
|
||||||
self.request = request
|
|
||||||
self.delegate = RolePermissionView()
|
|
||||||
self.delegate.context = self
|
|
||||||
self.delegate.request = request
|
|
||||||
self.permissionId = request.get('permission_to_manage') or 'zope.View'
|
|
||||||
|
|
||||||
def pagetip(self):
|
|
||||||
return self.delegate.pagetip()
|
|
||||||
|
|
||||||
def roles(self):
|
|
||||||
return self.delegate.roles()
|
|
||||||
|
|
||||||
def permissions(self):
|
|
||||||
return self.delegate.permissions()
|
|
||||||
|
|
||||||
def availableSettings(self, noacquire=False):
|
|
||||||
return self.delegate.availableSettings(noacquire)
|
|
||||||
|
|
||||||
def permissionRoles(self):
|
|
||||||
return self.delegate.permissionRoles()
|
|
||||||
|
|
||||||
def permissionForID(self, pid):
|
|
||||||
return self.delegate.permissionForID(pid)
|
|
||||||
|
|
||||||
@Lazy
|
|
||||||
def permission(self):
|
|
||||||
return self.permissionForID(self.permissionId)
|
|
||||||
|
|
||||||
def roleForID(self, rid):
|
|
||||||
return self.delegate.roleForID(rid)
|
|
||||||
|
|
||||||
def update(self, testing=None):
|
|
||||||
return self.delegate.update(testing)
|
|
||||||
|
|
||||||
def getAcquiredPermissionSetting(self, role, perm):
|
|
||||||
for obj in getParents(self.context):
|
|
||||||
rpm = IRolePermissionMap(obj, None)
|
|
||||||
if rpm is not None:
|
|
||||||
setting = rpm.getSetting(perm, role)
|
|
||||||
setting = SettingAsBoolean[setting]
|
|
||||||
if setting is not None:
|
|
||||||
return setting and '+' or '-'
|
|
||||||
return ''
|
|
||||||
|
|
||||||
def listUsersForRole(self, rid):
|
|
||||||
result = ''
|
|
||||||
direct = IPrincipalRoleManager(self.context).getPrincipalsForRole(rid)
|
|
||||||
if direct:
|
|
||||||
result = '<strong>' + self.renderEntry(direct) + '</strong>'
|
|
||||||
acquired = []
|
|
||||||
for obj in getParents(self.context):
|
|
||||||
prm = IPrincipalRoleManager(obj, None)
|
|
||||||
if prm is not None:
|
|
||||||
entry = prm.getPrincipalsForRole(rid)
|
|
||||||
if entry:
|
|
||||||
acquired.append(self.renderEntry(entry))
|
|
||||||
if acquired:
|
|
||||||
if result:
|
|
||||||
result += '<br />'
|
|
||||||
result += '<br />'.join(acquired)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def renderEntry(self, entry):
|
|
||||||
result = []
|
|
||||||
for e in entry:
|
|
||||||
value = SettingAsBoolean[e[1]]
|
|
||||||
value = (value is False and '-') or (value and '+') or ''
|
|
||||||
result.append(value + e[0])
|
|
||||||
return ', '.join(result)
|
|
||||||
|
|
||||||
def getPrincipalPermissions(self):
|
|
||||||
result = ''
|
|
||||||
ppm = IPrincipalPermissionMap(self.context)
|
|
||||||
direct = ppm.getPrincipalsForPermission(self.permissionId)
|
|
||||||
if direct:
|
|
||||||
result = '<strong>' + self.renderEntry(direct) + '</strong>'
|
|
||||||
acquired = []
|
|
||||||
for obj in getParents(self.context):
|
|
||||||
ppm = IPrincipalPermissionMap(obj, None)
|
|
||||||
if ppm is not None:
|
|
||||||
entry = ppm.getPrincipalsForPermission(self.permissionId)
|
|
||||||
if entry:
|
|
||||||
acquired.append(self.renderEntry(entry))
|
|
||||||
if acquired:
|
|
||||||
if result:
|
|
||||||
result += '<br />'
|
|
||||||
result += '<br />'.join(acquired)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def getPermissions(self):
|
|
||||||
return sorted(name for name, perm in component.getUtilitiesFor(IPermission))
|
|
||||||
|
|
|
@ -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
|
||||||
|
@ -23,11 +23,18 @@ methods for setting role permissions and other security-related stuff.
|
||||||
$Id$
|
$Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from zope.app.security.settings import Allow, Deny, Unset
|
||||||
|
from zope.app.securitypolicy.interfaces import IRolePermissionMap
|
||||||
|
from zope.app.securitypolicy.interfaces import IRolePermissionManager
|
||||||
from zope import component
|
from zope import component
|
||||||
from zope.component import adapts
|
from zope.component import adapts
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
from zope.interface import implements, Interface
|
from zope.interface import implements, Interface
|
||||||
|
from zope.security.proxy import isinstance
|
||||||
|
|
||||||
|
from loops.common import adapted, AdapterBase
|
||||||
|
from loops.security.common import overrides, setRolePermission
|
||||||
|
from loops.interfaces import IConceptSchema, IBaseResourceSchema, ILoopsAdapter
|
||||||
from loops.security.interfaces import ISecuritySetter
|
from loops.security.interfaces import ISecuritySetter
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,8 +52,95 @@ class BaseSecuritySetter(object):
|
||||||
def setDefaultPrincipalRoles(self):
|
def setDefaultPrincipalRoles(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def setAcquiredRolePermissions(self, relation, revert=False):
|
def acquireRolePermissions(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def setAcquiredPrincipalRoles(self, relation, revert=False):
|
def setAcquiredRolePermissions(self, relation, revert=False, updated=None):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def setAcquiredPrincipalRoles(self, relation, revert=False, updated=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def propagateRolePermissions(self, updated=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def propagatePrincipalRoles(self, updated=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class LoopsObjectSecuritySetter(BaseSecuritySetter):
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def baseObject(self):
|
||||||
|
obj = self.context
|
||||||
|
if isinstance(obj, AdapterBase):
|
||||||
|
obj = obj.context
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def acquireRolePermissions(self):
|
||||||
|
obj = self.baseObject
|
||||||
|
if isinstance(obj, AdapterBase):
|
||||||
|
obj = obj.context
|
||||||
|
settings = {}
|
||||||
|
for p in self.parents:
|
||||||
|
if p == obj:
|
||||||
|
continue
|
||||||
|
secProvider = p
|
||||||
|
wi = p.workspaceInformation
|
||||||
|
if wi:
|
||||||
|
if wi.propagateRolePermissions == 'none':
|
||||||
|
continue
|
||||||
|
if wi.propagateRolePermissions == 'workspace':
|
||||||
|
secProvider = wi
|
||||||
|
rpm = IRolePermissionMap(secProvider)
|
||||||
|
for p, r, s in rpm.getRolesAndPermissions():
|
||||||
|
current = settings.get((p, r))
|
||||||
|
if current is None or overrides(s, current):
|
||||||
|
settings[(p, r)] = s
|
||||||
|
rpm = IRolePermissionManager(obj)
|
||||||
|
for p, r, s in rpm.getRolesAndPermissions():
|
||||||
|
# clear previous settings
|
||||||
|
setRolePermission(rpm, p, r, Unset)
|
||||||
|
for (p, r), s in settings.items():
|
||||||
|
setRolePermission(rpm, p, r, s)
|
||||||
|
|
||||||
|
|
||||||
|
class ConceptSecuritySetter(LoopsObjectSecuritySetter):
|
||||||
|
|
||||||
|
adapts(IConceptSchema)
|
||||||
|
|
||||||
|
def setAcquiredRolePermissions(self, relation, revert=False, updated=None):
|
||||||
|
if updated and relation.second in updated:
|
||||||
|
return
|
||||||
|
setter = ISecuritySetter(adapted(relation.second), None)
|
||||||
|
if setter is not None:
|
||||||
|
setter.acquireRolePermissions()
|
||||||
|
setter.propagateRolePermissions(updated)
|
||||||
|
|
||||||
|
def setAcquiredPrincipalRoles(self, relation, revert=False, updated=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def propagateRolePermissions(self, updated=None):
|
||||||
|
if updated is None:
|
||||||
|
updated = set()
|
||||||
|
obj = self.baseObject
|
||||||
|
updated.add(obj)
|
||||||
|
for r in obj.getChildRelations():
|
||||||
|
self.setAcquiredRolePermissions(r, updated=updated)
|
||||||
|
|
||||||
|
def propagatePrincipalRoles(self, updated=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def parents(self):
|
||||||
|
return self.baseObject.getParents()
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceSecuritySetter(LoopsObjectSecuritySetter):
|
||||||
|
|
||||||
|
adapts(IBaseResourceSchema)
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def parents(self):
|
||||||
|
return self.baseObject.getConcepts()
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ from zope.dublincore.interfaces import IZopeDublinCore
|
||||||
from zope.interface import Interface, implements
|
from zope.interface import Interface, implements
|
||||||
from zope.publisher.interfaces.browser import IBrowserRequest, IBrowserView
|
from zope.publisher.interfaces.browser import IBrowserRequest, IBrowserView
|
||||||
from zope.security.checker import Checker, defineChecker
|
from zope.security.checker import Checker, defineChecker
|
||||||
|
from zope.security.management import setSecurityPolicy
|
||||||
|
|
||||||
from cybertools.browser.controller import Controller
|
from cybertools.browser.controller import Controller
|
||||||
from cybertools.catalog.keyword import KeywordIndex
|
from cybertools.catalog.keyword import KeywordIndex
|
||||||
|
@ -71,9 +72,9 @@ from loops.schema.factory import ResourceSchemaFactory, FileSchemaFactory, \
|
||||||
NoteSchemaFactory
|
NoteSchemaFactory
|
||||||
from loops.schema.field import RelationSetFieldInstance
|
from loops.schema.field import RelationSetFieldInstance
|
||||||
from loops.security.common import grantAcquiredSecurity, revokeAcquiredSecurity
|
from loops.security.common import grantAcquiredSecurity, revokeAcquiredSecurity
|
||||||
from zope.security.management import setSecurityPolicy
|
|
||||||
from loops.security.policy import LoopsSecurityPolicy
|
from loops.security.policy import LoopsSecurityPolicy
|
||||||
from loops.security.setter import BaseSecuritySetter
|
from loops.security.setter import BaseSecuritySetter
|
||||||
|
from loops.security.setter import ConceptSecuritySetter, ResourceSecuritySetter
|
||||||
from loops.setup import SetupManager, addObject
|
from loops.setup import SetupManager, addObject
|
||||||
from loops.type import LoopsType, ConceptType, ResourceType, TypeConcept
|
from loops.type import LoopsType, ConceptType, ResourceType, TypeConcept
|
||||||
from loops.view import Node, NodeAdapter
|
from loops.view import Node, NodeAdapter
|
||||||
|
@ -135,6 +136,8 @@ class TestSite(object):
|
||||||
component.provideHandler(grantAcquiredSecurity)
|
component.provideHandler(grantAcquiredSecurity)
|
||||||
component.provideHandler(revokeAcquiredSecurity)
|
component.provideHandler(revokeAcquiredSecurity)
|
||||||
component.provideAdapter(BaseSecuritySetter)
|
component.provideAdapter(BaseSecuritySetter)
|
||||||
|
component.provideAdapter(ConceptSecuritySetter)
|
||||||
|
component.provideAdapter(ResourceSecuritySetter)
|
||||||
component.provideAdapter(LoopsOptions)
|
component.provideAdapter(LoopsOptions)
|
||||||
component.provideAdapter(QueryOptions)
|
component.provideAdapter(QueryOptions)
|
||||||
component.provideAdapter(TypeOptions)
|
component.provideAdapter(TypeOptions)
|
||||||
|
|
Loading…
Add table
Reference in a new issue