From bcd76509e7d69a5952ee3c83ac62963f232602b4 Mon Sep 17 00:00:00 2001 From: helmutm Date: Sun, 1 Nov 2009 21:30:17 +0000 Subject: [PATCH] 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 --- concept.py | 13 +++++ interfaces.py | 14 +++++ predicate.py | 6 ++ security.zcml | 4 ++ security/common.py | 25 ++++++++- security/configure.zcml | 18 ++++++ security/manage_grantchildrenform.pt | 84 ++++++++++++++++++++++++++++ security/manage_permissionform.pt | 16 +----- security/perm.py | 17 ++++++ 9 files changed, 180 insertions(+), 17 deletions(-) create mode 100644 security/manage_grantchildrenform.pt 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

+

+             +           + +

+ + + + + + + + + + + +
RoleUsers/Groups
Manager + User xy
+
+ +
+ +
...
+ +
+ +

Grants for the selected principal

+ + + + + + +
+ + + + + + + + + + + roles widget + + + + + +
Roles Allow Unset Deny 
+
+ +
+
^ top
+
+ + +
+
+
+ + 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)