diff --git a/concept.py b/concept.py
index b871baf..69bdfad 100644
--- a/concept.py
+++ b/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):
diff --git a/interfaces.py b/interfaces.py
index c58d16d..19c1a71 100644
--- a/interfaces.py
+++ b/interfaces.py
@@ -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):
diff --git a/predicate.py b/predicate.py
index 79cf138..39c3844 100644
--- a/predicate.py
+++ b/predicate.py
@@ -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
diff --git a/security.zcml b/security.zcml
index e47ef31..3593d49 100644
--- a/security.zcml
+++ b/security.zcml
@@ -57,6 +57,10 @@
title="[loops-master-role] loops: Master" />
+
+
+
diff --git a/security/common.py b/security/common.py
index 07b08ca..634878e 100644
--- a/security/common.py
+++ b/security/common.py
@@ -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__
diff --git a/security/configure.zcml b/security/configure.zcml
index 9215998..cc08975 100644
--- a/security/configure.zcml
+++ b/security/configure.zcml
@@ -7,6 +7,10 @@
+
+
+
+
+
+
+
+
diff --git a/security/manage_grantchildrenform.pt b/security/manage_grantchildrenform.pt
new file mode 100644
index 0000000..c1d7f60
--- /dev/null
+++ b/security/manage_grantchildrenform.pt
@@ -0,0 +1,84 @@
+
+
+
+
Grant Roles for Children of this Object to Principals
+
+
+
+
+
+
+
+
+
+
diff --git a/security/manage_permissionform.pt b/security/manage_permissionform.pt
index 7610712..d7bc7c7 100644
--- a/security/manage_permissionform.pt
+++ b/security/manage_permissionform.pt
@@ -1,19 +1,5 @@
-
-
-
+ i18n:domain="zope">
diff --git a/security/perm.py b/security/perm.py
index 3bbb3cf..ac0080b 100644
--- a/security/perm.py
+++ b/security/perm.py
@@ -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)