From 211bf8a89fa774cb3b7758fbfc40bde3396545a3 Mon Sep 17 00:00:00 2001 From: Arnaud Fontaine <arnaud.fontaine@nexedi.com> Date: Mon, 1 Jul 2013 16:02:10 +0900 Subject: [PATCH] ZODB Components: Ensure that Permissions on Developer can be updated later (through Filesystem). In aed4f30, Permissions were set in ComponentTool __init__ and it could not be modified later on because it is set directly in the ZODB. Moreover, Permissions could be modified after execution by modifying attributes. --- product/ERP5Type/Tool/ComponentTool.py | 50 +++++++++++++------------- product/ERP5Type/dynamic/lazy_class.py | 8 +++++ 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/product/ERP5Type/Tool/ComponentTool.py b/product/ERP5Type/Tool/ComponentTool.py index 1bc701cf3a..e9ee4e027a 100644 --- a/product/ERP5Type/Tool/ComponentTool.py +++ b/product/ERP5Type/Tool/ComponentTool.py @@ -62,32 +62,34 @@ class ComponentTool(BaseTool): security = ClassSecurityInfo() security.declareObjectProtected(Permissions.AccessContentsInformation) - def __init__(self, *args, **kwargs): + @classmethod + def _applyAllStaticSecurity(cls): """ - Except 'Access *', 'View*' and 'WebDAV' permissions (Acquired) and 'Reset - dynamic classes' (Manager, required to reset Components), everything - requires Developer Role. - - Another solution would be to load it from XML as it was previously done, - but from a security point of view, it's better to forbid everything and - allows only some. - - XXX-arnau: Really all 'Access *' and 'View*'? nothing else? + Apply static security on portal_components to ensure that nobody can + change Permissions, only 'ghost' Developer Role has Permissions to + add/modify/delete Components. Also, make these permissions read-only + thanks to 'property'. + + cls is erp5.portal_type.Component Tool and not this class as this function + is called on Portal Type class when loading Componet Tool Portal Type + class """ - obj = BaseTool.__init__(self, *args, **kwargs) - for permission_tuple in self.ac_inherited_permissions(1): - name = permission_tuple[0] - value = permission_tuple[1] - if name == 'Reset dynamic classes': - p = Permission(name, value, self) - p.setRoles(('Manager',)) - elif not (name.startswith('Access ') or - name.startswith('View') or - name.startswith('WebDAV')): - p = Permission(name, value, self) - p.setRoles(('Developer',)) - - return obj + # XXX-Cosmetic: From Zope >= 2.13, getPermissions() can be used instead of + # protected _registeredPermissions module attribute + from AccessControl.Permission import _registeredPermissions, pname + for permission_name in _registeredPermissions: + if permission_name == 'Reset dynamic classes': + permission_function = lambda self: ('Manager',) + elif permission_name in ('Change permissions', 'Define permissions'): + permission_function = lambda self: () + elif not (permission_name.startswith('Access ') or + permission_name.startswith('View') or + permission_name.startswith('WebDAV')): + permission_function = lambda self: ('Developer',) + else: + continue + + setattr(cls, pname(permission_name), property(permission_function)) def _isBootstrapRequired(self): """ diff --git a/product/ERP5Type/dynamic/lazy_class.py b/product/ERP5Type/dynamic/lazy_class.py index 0613552844..b7c3a268d6 100644 --- a/product/ERP5Type/dynamic/lazy_class.py +++ b/product/ERP5Type/dynamic/lazy_class.py @@ -193,9 +193,17 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder): pmc_init_of(subclass) def setupSecurity(cls): + apply_security_function = getattr(cls, '_applyAllStaticSecurity', None) + if apply_security_function: + apply_security_function() + # note that after this call the 'security' attribute will be gone. InitializeClass(cls) for subclass in PortalTypeMetaClass.getSubclassList(cls): + apply_security_function = getattr(cls, '_applyAllStaticSecurity', None) + if apply_security_function: + apply_security_function() + InitializeClass(subclass) def restoreGhostState(cls): -- 2.30.9