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
	
	 helmutm
						helmutm