--- a/src/pyams_security/interfaces/__init__.py Wed Jun 17 09:59:26 2015 +0200
+++ b/src/pyams_security/interfaces/__init__.py Tue Jun 30 15:02:07 2015 +0200
@@ -714,14 +714,26 @@
required=True,
default=True)
- everyone_permissions = PermissionsSetField(title=_("Public permissions"),
- description=_("These permissions will be granted to all users"),
+ everyone_denied = PermissionsSetField(title=_("Public denied permissions"),
+ description=_("These permissions will be denied to all users. "
+ "Denied permissions take precedence over granted "
+ "ones."),
+ required=False)
+
+ everyone_granted = PermissionsSetField(title=_("Public granted permissions"),
+ description=_("These permissions will be granted to all users"),
+ required=False)
+
+ authenticated_denied = PermissionsSetField(title=_("Authenticated denied permissions"),
+ description=_("These permissions will be denied to "
+ "authenticated users. Denied permissions "
+ "take precedence over granted ones."),
required=False)
- authenticated_permissions = PermissionsSetField(title=_("Authenticated permissions"),
- description=_("These permissions will be granted to authenticated "
- "users"),
- required=False)
+ authenticated_granted = PermissionsSetField(title=_("Authenticated granted permissions"),
+ description=_("These permissions will be granted to authenticated "
+ "users"),
+ required=False)
inherit_parent_roles = Bool(title=_("Inherit parent roles?"),
description=_("Get roles granted on parent levels"),
@@ -749,6 +761,21 @@
def get_permissions(self, principal_id):
"""Get ID of permissions granted to given principal"""
+ def get_everyone_denied(self):
+ """Get denied permissions for everyone, including inherited ones"""
+
+ def get_everyone_granted(self):
+ """Get granted permissions for everyone, including inherited ones"""
+
+ def get_authenticated_denied(self):
+ """Get denied permissions for authenticated, including inherited ones"""
+
+ def get_authenticated_granted(self):
+ """Get granted permissions for authenticated, including inherited ones"""
+
+ def get_granted_roles(self):
+ """Get all roles, including inherited ones"""
+
class IRoleProtectedObject(IProtectedObject):
"""Roles protected object interface"""
--- a/src/pyams_security/security.py Wed Jun 17 09:59:26 2015 +0200
+++ b/src/pyams_security/security.py Tue Jun 30 15:02:07 2015 +0200
@@ -28,7 +28,7 @@
from pyams_utils.property import request_property
from pyams_utils.registry import query_utility
from pyramid.location import lineage
-from pyramid.security import DENY_ALL, Everyone, Allow, ALL_PERMISSIONS, Authenticated
+from pyramid.security import DENY_ALL, Everyone, Allow, Deny, ALL_PERMISSIONS, Authenticated
from pyramid.threadlocal import get_current_registry
from zope.container.contained import Contained
from zope.interface import implementer
@@ -42,49 +42,59 @@
"""Base class for object protected by roles"""
inherit_parent_security = FieldProperty(IRoleProtectedObject['inherit_parent_security'])
- _everyone_permissions = FieldProperty(IRoleProtectedObject['everyone_permissions'])
- _authenticated_permissions = FieldProperty(IRoleProtectedObject['authenticated_permissions'])
+ everyone_denied = FieldProperty(IRoleProtectedObject['everyone_denied'])
+ everyone_granted = FieldProperty(IRoleProtectedObject['everyone_granted'])
+ authenticated_denied = FieldProperty(IRoleProtectedObject['authenticated_denied'])
+ authenticated_granted = FieldProperty(IRoleProtectedObject['authenticated_granted'])
inherit_parent_roles = FieldProperty(IRoleProtectedObject['inherit_parent_roles'])
def __init__(self):
self._principals_by_role = PersistentDict()
self._roles_by_principal = PersistentDict()
- @property
- def everyone_permissions(self):
- permissions = self._everyone_permissions
- if (not permissions) and self.inherit_parent_security:
+ def get_everyone_denied(self):
+ permissions = self.everyone_denied or set()
+ if self.inherit_parent_security:
+ for parent in lineage(self):
+ if parent in (self, self.__parent__):
+ continue
+ protection = IProtectedObject(parent, None)
+ if protection is not None:
+ permissions = permissions | (protection.everyone_denied or set())
+ return permissions
+
+ def get_everyone_granted(self):
+ permissions = self.everyone_granted or set()
+ if self.inherit_parent_security:
for parent in lineage(self):
if parent in (self, self.__parent__):
continue
protection = IProtectedObject(parent, None)
if protection is not None:
- permissions = protection.everyone_permissions
- if permissions:
- break
+ permissions = permissions | (protection.everyone_granted or set())
return permissions
- @everyone_permissions.setter
- def everyone_permissions(self, value):
- self._everyone_permissions = value
-
- @property
- def authenticated_permissions(self):
- permissions = self._authenticated_permissions
- if (not permissions) and self.inherit_parent_security:
+ def get_authenticated_denied(self):
+ permissions = self.authenticated_denied or set()
+ if self.inherit_parent_security:
for parent in lineage(self):
if parent in (self, self.__parent__):
continue
protection = IProtectedObject(parent, None)
if protection is not None:
- permissions = protection.authenticated_permissions
- if permissions:
- break
+ permissions = permissions | (protection.authenticated_denied or set())
return permissions
- @authenticated_permissions.setter
- def authenticated_permissions(self, value):
- self._authenticated_permissions = value
+ def get_authenticated_granted(self):
+ permissions = self.authenticated_granted or set()
+ if self.inherit_parent_security:
+ for parent in lineage(self):
+ if parent in (self, self.__parent__):
+ continue
+ protection = IProtectedObject(parent, None)
+ if protection is not None:
+ permissions = permissions | (protection.authenticated_granted or set())
+ return permissions
def grant_role(self, role_id, principal_ids):
registry = get_current_registry()
@@ -146,24 +156,43 @@
result |= role.permissions or set()
return result
+ def get_granted_roles(self):
+ roles = set(self._principals_by_role.keys())
+ if self.inherit_parent_roles:
+ for parent in lineage(self):
+ if parent in (self, self.__parent__):
+ continue
+ protection = IProtectedObject(parent, None)
+ if protection is not None:
+ roles = roles | protection.get_granted_roles()
+ return roles
+
@request_property(key=None)
def __acl__(self):
# always grant all permissions to system manager
result = [(Allow, 'system:admin', ALL_PERMISSIONS)]
- # grant permission to everyone and authenticated
- if self.everyone_permissions:
- result.append((Allow, Everyone, self.everyone_permissions))
- if self.authenticated_permissions:
- result.append((Allow, Authenticated, self.authenticated_permissions))
# grant access to all roles permissions
- for role_id in self._principals_by_role.keys():
+ for role_id in self.get_granted_roles():
role = query_utility(IRole, role_id)
if role is not None:
result.append((Allow, 'role:{0}'.format(role_id), role.permissions))
+ # grant permission to everyone and authenticated
+ permissions = self.get_everyone_denied()
+ if permissions:
+ result.append((Deny, Everyone, permissions))
+ permissions = self.get_authenticated_denied()
+ if permissions:
+ result.append((Deny, Authenticated, permissions))
+ permissions = self.get_authenticated_granted()
+ if permissions:
+ result.append((Allow, Authenticated, permissions))
+ permissions = self.get_everyone_granted()
+ if permissions:
+ result.append((Allow, Everyone, permissions))
# stop inheritance if required
if not self.inherit_parent_security:
result.append(DENY_ALL)
- logger.debug('ACL = {0}'.format(str(result)))
+ logger.debug('ACL({0!r}) = {1}'.format(self.__parent__, str(result)))
return result
--- a/src/pyams_security/zmi/security.py Wed Jun 17 09:59:26 2015 +0200
+++ b/src/pyams_security/zmi/security.py Tue Jun 30 15:02:07 2015 +0200
@@ -83,12 +83,6 @@
edit_permission = 'security.manage'
weight = 1
- def updateWidgets(self, prefix=None):
- super(ProtectedObjectSecuritySubform, self).updateWidgets()
- translate = self.request.localizer.translate
- self.widgets['everyone_permissions'].noValueMessage = translate(_("(inherit from parent)"))
- self.widgets['authenticated_permissions'].noValueMessage = translate(_("(inherit from parent)"))
-
@adapter_config(name='roles.subform',
context=(IDefaultProtectionPolicy, IPyAMSLayer, ProtectedObjectRolesEditForm),
--- a/src/pyams_security/zmi/utility.py Wed Jun 17 09:59:26 2015 +0200
+++ b/src/pyams_security/zmi/utility.py Tue Jun 30 15:02:07 2015 +0200
@@ -151,9 +151,6 @@
table_class = SecurityManagerPluginsTable
- def __init__(self, context, request):
- super(SecurityManagerView, self).__init__(context, request)
-
@adapter_config(context=(ISite, IAdminLayer, SecurityManagerView), provides=IPageHeader)
class SecurityManagerHeaderAdapter(DefaultPageHeaderAdapter):
@@ -202,7 +199,7 @@
def update(self):
super(SecurityManagerEditForm, self).update()
- self.add_group(NamedWidgetsGroup('social_group', self.widgets,
+ self.add_group(NamedWidgetsGroup(self, 'social_group', self.widgets,
('enable_social_login', 'social_users_folder',
'authomatic_secret', 'social_login_use_popup'),
legend=_("Enable social login?"),
@@ -210,14 +207,14 @@
switch=True,
checkbox_switch=True,
checkbox_field=ISecurityManager['enable_social_login']))
- self.add_group(NamedWidgetsGroup('registry_group', self.widgets,
+ self.add_group(NamedWidgetsGroup(self, 'registry_group', self.widgets,
('open_registration', 'users_folder'),
legend=_("Enable free registration?"),
css_class='inner',
switch=True,
checkbox_switch=True,
checkbox_field=ISecurityManager['open_registration']))
- plugins_group = NamedWidgetsGroup('plugins_group', self.widgets,
+ plugins_group = NamedWidgetsGroup(self, 'plugins_group', self.widgets,
('credentials_plugins_names', 'authentication_plugins_names',
'directory_plugins_names'),
legend=_("Plug-ins"),