[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/securitypolicy/browser/ Sprinting with Jim:

Stephan Richter srichter at cosmos.phy.tufts.edu
Wed Oct 13 11:00:05 EDT 2004


Log message for revision 28095:
  Sprinting with Jim:
  
  Provide new Granting Permissions and Roles UI for Principals using new 
  search code.
  

Changed:
  U   Zope3/trunk/src/zope/app/securitypolicy/browser/configure.zcml
  A   Zope3/trunk/src/zope/app/securitypolicy/browser/granting.pt
  A   Zope3/trunk/src/zope/app/securitypolicy/browser/granting.py
  A   Zope3/trunk/src/zope/app/securitypolicy/browser/granting.txt
  A   Zope3/trunk/src/zope/app/securitypolicy/browser/tests/test_granting.py

-=-
Modified: Zope3/trunk/src/zope/app/securitypolicy/browser/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/securitypolicy/browser/configure.zcml	2004-10-13 14:59:17 UTC (rev 28094)
+++ Zope3/trunk/src/zope/app/securitypolicy/browser/configure.zcml	2004-10-13 15:00:04 UTC (rev 28095)
@@ -110,4 +110,15 @@
                         getPermissionsForPrincipal" 
       /  -->
 
+<!-- Granting Roles and Permissions to Principals -->
+
+  <page
+    for="zope.app.annotation.interfaces.IAnnotatable"
+    name="granting.html"
+    permission="zope.Security"
+    template="granting.pt" 
+    class=".granting.Granting"
+    menu="zmi_actions" title="Granting" />
+
+
 </zope:configure>

Added: Zope3/trunk/src/zope/app/securitypolicy/browser/granting.pt
===================================================================
--- Zope3/trunk/src/zope/app/securitypolicy/browser/granting.pt	2004-10-13 14:59:17 UTC (rev 28094)
+++ Zope3/trunk/src/zope/app/securitypolicy/browser/granting.pt	2004-10-13 15:00:04 UTC (rev 28095)
@@ -0,0 +1,64 @@
+<html metal:use-macro="context/@@standard_macros/page">
+<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">
+<p>Select a principal:</p>
+<div tal:content="structure view/principal_widget">...</div>
+
+<div tal:condition="view/principal">
+
+  <h2>Grants for the selected principal</h2>
+
+  <input type="submit" name="GRANT_SUBMIT" value="Change" 
+         i18n:attributes="value grant-submit" />
+
+<table width="100%">
+  <tr>
+    <th i18n:translate="">Roles:</th>
+    <th i18n:translate="">Permissions:</th>
+  <tr/>
+  <tr>
+    <td valign="top">
+      <div class="row" tal:repeat="widget view/roles">
+        <div class="label">
+          <label for="field.name" title="The widget's hint"
+            tal:attributes="for widget/name; title widget/hint"
+            tal:content="widget/label">The Label</label>
+        </div>
+        <div class="field" tal:content="structure widget">
+          <input type="text" style="width:100%"/>
+        </div>
+      </div>
+    </td>
+    <td valign="top">
+      <div class="row" tal:repeat="widget view/permissions">
+        <div class="label">
+          <label for="field.name" title="The widget's hint"
+            tal:attributes="for widget/name; title widget/hint"
+            tal:content="widget/label">The Label</label>
+        </div>
+        <div class="field" tal:content="structure widget">
+          <input type="text" style="width:100%"/>
+        </div>
+      </div>
+    </td>
+  <tr/>
+</table>
+
+  <input type="submit" name="GRANT_SUBMIT" value="Change" 
+         i18n:attributes="value grant-submit" />
+
+</div>
+</form>
+
+</div>
+</body>
+</html>

Added: Zope3/trunk/src/zope/app/securitypolicy/browser/granting.py
===================================================================
--- Zope3/trunk/src/zope/app/securitypolicy/browser/granting.py	2004-10-13 14:59:17 UTC (rev 28094)
+++ Zope3/trunk/src/zope/app/securitypolicy/browser/granting.py	2004-10-13 15:00:04 UTC (rev 28095)
@@ -0,0 +1,128 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Granting Roles and Permissions to Principals
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+import zope.schema
+from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
+from zope.app import zapi
+from zope.app.security.vocabulary import PrincipalSource
+from zope.app.form.utility import setUpWidget
+from zope.app.i18n import ZopeMessageIDFactory as _
+
+from zope.app.form.interfaces import IInputWidget
+from zope.app.securitypolicy.interfaces import IPrincipalPermissionManager
+from zope.app.securitypolicy.interfaces import IPrincipalRoleManager
+from zope.app.securitypolicy.interfaces import IRole
+from zope.app.security.interfaces import IPermission
+from zope.app.security import settings
+
+settings_vocabulary = SimpleVocabulary(
+    [SimpleTerm(settings.Allow, token="allow", title=_('Allow')),
+     SimpleTerm(settings.Unset, token="unset", title=_('Unset')),
+     SimpleTerm(settings.Deny,  token='deny',  title=_('Deny')),
+     ])
+
+class Granting(object):
+
+    principal = None
+
+    principal_field = zope.schema.Choice(
+        __name__ = 'principal',
+        source=PrincipalSource(),
+        required=True)
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    def status(self):
+        setUpWidget(self, 'principal', self.principal_field, IInputWidget)
+        if not self.principal_widget.hasInput():
+            return u''
+        
+        principal = self.principal_widget.getInputValue()
+        self.principal = principal
+
+        roles = [role for name, role in zapi.getUtilitiesFor(IRole)]
+        roles.sort(lambda x, y: cmp(x.title, y.title))
+        principal_roles = IPrincipalRoleManager(self.context)
+
+        self.roles = []
+        for role in roles:
+            name = principal + '.role.'+role.id
+            field = zope.schema.Choice(__name__= name,
+                                       title=role.title,
+                                       vocabulary=settings_vocabulary)
+            setUpWidget(self, name, field, IInputWidget,
+                        principal_roles.getSetting(role.id, principal))
+            self.roles.append(getattr(self, name+'_widget'))
+
+        perms = [perm for name, perm in zapi.getUtilitiesFor(IPermission)]
+        perms.sort(lambda x, y: cmp(x.title, y.title))
+        principal_perms = IPrincipalPermissionManager(self.context)
+
+        self.permissions = []
+        for perm in perms:
+            if perm.id == 'zope.Public':
+                continue
+            name = principal + '.permission.'+perm.id
+            field = zope.schema.Choice(__name__=name,
+                                       title=perm.title,
+                                       vocabulary=settings_vocabulary)
+            setUpWidget(self, name, field, IInputWidget,
+                        principal_perms.getSetting(perm.id, principal))
+            self.permissions.append(
+                getattr(self, name+'_widget'))
+
+        if 'GRANT_SUBMIT' not in self.request:
+            return u''
+        
+        for role in roles:
+            name = principal + '.role.'+role.id
+            role_widget = getattr(self, name+'_widget')
+            if role_widget.hasInput():
+                setting = role_widget.getInputValue()
+                # Arrgh!
+                if setting is settings.Allow:
+                    principal_roles.assignRoleToPrincipal(
+                        role.id, principal)
+                elif setting is settings.Deny:
+                    principal_roles.removeRoleFromPrincipal(
+                        role.id, principal)
+                else:
+                    principal_roles.unsetRoleForPrincipal(
+                        role.id, principal)
+        
+        for perm in perms:
+            if perm.id == 'zope.Public':
+                continue
+            name = principal + '.permission.'+perm.id
+            perm_widget = getattr(self, name+'_widget')
+            if perm_widget.hasInput():
+                setting = perm_widget.getInputValue()
+                # Arrgh!
+                if setting is settings.Allow:
+                    principal_perms.grantPermissionToPrincipal(
+                        perm.id, principal)
+                elif setting is settings.Deny:
+                    principal_perms.denyPermissionToPrincipal(
+                        perm.id, principal)
+                else:
+                    principal_perms.unsetPermissionForPrincipal(
+                        perm.id, principal)
+                    
+        return u'Grants updated.'

Added: Zope3/trunk/src/zope/app/securitypolicy/browser/granting.txt
===================================================================
--- Zope3/trunk/src/zope/app/securitypolicy/browser/granting.txt	2004-10-13 14:59:17 UTC (rev 28094)
+++ Zope3/trunk/src/zope/app/securitypolicy/browser/granting.txt	2004-10-13 15:00:04 UTC (rev 28095)
@@ -0,0 +1,202 @@
+Granting View
+=============
+
+The granting view allows the user to grant permissions and roles to
+principals. The view unfortunately depends on a lot of other components:
+
+  - Roles
+
+    >>> from zope.app.tests import ztapi
+    >>> from zope.app.securitypolicy.role import Role
+    >>> from zope.app.securitypolicy.interfaces import IRole
+    >>> ztapi.provideUtility(IRole, Role(u'role1', u'Role 1'), u'role1')
+    >>> ztapi.provideUtility(IRole, Role(u'role2', u'Role 2'), u'role2')
+    >>> ztapi.provideUtility(IRole, Role(u'role3', u'Role 3'), u'role3')
+
+  - Permissions
+
+    >>> from zope.app.tests import ztapi
+    >>> from zope.app.security.permission import Permission
+    >>> from zope.app.security.interfaces import IPermission
+    >>> ztapi.provideUtility(IPermission, Permission(u'permission1', 
+    ...                      u'Permission 1'), u'permission1')
+    >>> ztapi.provideUtility(IPermission, Permission(u'permission2',
+    ...                      u'Permission 2'), u'permission2')
+    >>> ztapi.provideUtility(IPermission, Permission(u'permission3', 
+    ...                      u'Permission 3'), u'permission3')
+
+  - Authentication Service
+
+    >>> class Principal:
+    ...     def __init__(self, id, title): self.id, self.title = id, title
+
+    >>> from zope.app.security.interfaces import IAuthenticationService
+    >>> from zope.interface import implements
+    >>> class AuthService:
+    ...     implements(IAuthenticationService)
+    ...     data = {'jim': Principal('jim', 'Jim Fulton'),
+    ...             'stephan': Principal('stephan', 'Stephan Richter')}
+    ...
+    ...     def getPrincipal(self, id):
+    ...         return self.data.get(id)
+    ...
+    ...     def getPrincipals(self, search):
+    ...         return [principal 
+    ...                 for principal in self.data.values()
+    ...                 if search in principal.title]
+
+    >>> ztapi.provideService('Authentication', AuthService(), 
+    ...                      IAuthenticationService)
+
+  - Security-related Adapters
+
+    >>> from zope.app.annotation.interfaces import IAnnotatable
+    >>> from zope.app.securitypolicy.interfaces import IPrincipalRoleManager
+    >>> from zope.app.securitypolicy.principalrole import \
+    ...     AnnotationPrincipalRoleManager
+ 
+    >>> ztapi.provideAdapter(IAnnotatable, IPrincipalRoleManager,
+    ...                      AnnotationPrincipalRoleManager)
+
+    >>> from zope.app.securitypolicy.interfaces import \
+    ...     IPrincipalPermissionManager
+    >>> from zope.app.securitypolicy.principalpermission import \
+    ...     AnnotationPrincipalPermissionManager
+ 
+    >>> ztapi.provideAdapter(IAnnotatable, IPrincipalPermissionManager,
+    ...                      AnnotationPrincipalPermissionManager)
+
+  - Vocabulary Choice Widgets
+
+    >>> from zope.schema.interfaces import IChoice
+    >>> from zope.app.form.browser import ChoiceInputWidget
+    >>> from zope.app.form.interfaces import IInputWidget
+    >>> ztapi.browserViewProviding(IChoice, ChoiceInputWidget, IInputWidget)
+
+    >>> from zope.schema.interfaces import IVocabularyTokenized
+    >>> from zope.publisher.interfaces.browser import IBrowserRequest
+    >>> from zope.app.form.browser import DropdownWidget
+    >>> ztapi.provideMultiView((IChoice, IVocabularyTokenized), 
+    ...                        IBrowserRequest, IInputWidget, '', 
+    ...                        DropdownWidget)
+
+  - Support Views for the Principal Source Widget
+
+    >>> from zope.app.security.interfaces import IPrincipalSource
+    >>> from zope.app.security.browser.principalterms import PrincipalTerms
+    >>> from zope.app.form.browser.interfaces import ITerms
+    >>> ztapi.browserViewProviding(IPrincipalSource, PrincipalTerms, ITerms)
+
+    >>> from zope.app.security.browser.auth import AuthServiceSearchView
+    >>> from zope.app.form.browser.interfaces import ISourceQueryView
+    >>> ztapi.browserViewProviding(IAuthenticationService, 
+    ...                            AuthServiceSearchView,
+    ...                            ISourceQueryView)
+
+
+    >>> from zope.schema.interfaces import ISource
+    >>> from zope.app.form.browser.source import SourceInputWidget
+    >>> ztapi.provideMultiView((IChoice, ISource), IBrowserRequest, 
+    ...                        IInputWidget, '', SourceInputWidget)
+
+  - Attribute Annotatable Adapter
+
+    >>> from zope.app.annotation.attribute import AttributeAnnotations
+    >>> from zope.app.annotation.interfaces import IAnnotations
+    >>> from zope.app.annotation.interfaces import IAttributeAnnotatable
+    >>> ztapi.provideAdapter(IAttributeAnnotatable, IAnnotations,
+    ...                      AttributeAnnotations)
+
+  - Content Object 
+
+    >>> class Content:
+    ...     implements(IAttributeAnnotatable)
+    ...     __annotations__ = {}
+
+  (This is Jim's understanding of a "easy" setup!)
+
+Now that we have all the components we need, let's create *the* view. 
+
+  >>> ob = Content()
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+ 
+  >>> from zope.app.securitypolicy.browser.granting import Granting
+  >>> view = Granting(ob, request)
+
+If we call status, we get nothing and the view's principal attribute is `None`:
+
+  >>> view.status()
+  u''
+  >>> view.principal
+
+Since we have not selected a principal, we have no role or permission widgets:
+
+  >>> getattr(view, 'roles', None)
+  >>> getattr(view, 'permissions', None)
+
+Now that we have a selected principal, then
+
+
+  >>> view.request.form['field.principal.displayed'] = 'y'
+  >>> view.request.form['field.principal'] = 'amlt'
+
+(Yes, 'amlt' is the base 64 code for 'jim'.)   
+
+  >>> view.status()
+  u''
+
+and now the `view.principal` is set:
+
+  >>> view.principal
+  'jim'
+
+Now we should have a list of role and permission widgets, and all of them
+should be unset, because do not have any settings for 'jim'.
+
+  >>> [role.context.title for role in view.roles]
+  [u'Role 1', u'Role 2', u'Role 3']
+  >>> [perm.context.title for perm in view.permissions]
+  [u'Permission 1', u'Permission 2', u'Permission 3']
+
+Now we change some settings and submit the form:
+
+  >>> from zope.app.security import settings
+
+  >>> view.request.form['field.jim.role.role1'] = 'unset'
+  >>> view.request.form['field.jim.role.role1-empty-makrer'] = 1
+  >>> view.request.form['field.jim.role.role2'] = 'allow'
+  >>> view.request.form['field.jim.role.role2-empty-makrer'] = 1
+  >>> view.request.form['field.jim.role.role3'] = 'deny'
+  >>> view.request.form['field.jim.role.role3-empty-makrer'] = 1
+
+  >>> view.request.form['field.jim.permission.permission1'] = 'unset'
+  >>> view.request.form['field.jim.permission.permission1-empty-makrer'] = 1
+  >>> view.request.form['field.jim.permission.permission2'] = 'allow'
+  >>> view.request.form['field.jim.permission.permission2-empty-makrer'] = 1
+  >>> view.request.form['field.jim.permission.permission3'] = 'deny'
+  >>> view.request.form['field.jim.permission.permission3-empty-makrer'] = 1
+
+  >>> view.request.form['GRANT_SUBMIT'] = 'Submit'
+
+If we get the status now, the data should be written and a status message
+should be returned:
+
+  >>> view.status()
+  u'Grants updated.'
+
+  >>> roles = IPrincipalRoleManager(ob)
+  >>> roles.getSetting('role1', 'jim') is settings.Unset
+  True
+  >>> roles.getSetting('role2', 'jim') is settings.Allow
+  True
+  >>> roles.getSetting('role3', 'jim') is settings.Deny
+  True
+
+  >>> roles = IPrincipalPermissionManager(ob)
+  >>> roles.getSetting('permission1', 'jim') is settings.Unset
+  True
+  >>> roles.getSetting('permission2', 'jim') is settings.Allow
+  True
+  >>> roles.getSetting('permission3', 'jim') is settings.Deny
+  True
\ No newline at end of file

Added: Zope3/trunk/src/zope/app/securitypolicy/browser/tests/test_granting.py
===================================================================
--- Zope3/trunk/src/zope/app/securitypolicy/browser/tests/test_granting.py	2004-10-13 14:59:17 UTC (rev 28094)
+++ Zope3/trunk/src/zope/app/securitypolicy/browser/tests/test_granting.py	2004-10-13 15:00:04 UTC (rev 28095)
@@ -0,0 +1,32 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Security Policy Granting Views Tests
+
+$Id: tests.py 27985 2004-10-12 08:00:42Z srichter $
+"""
+__docformat__ = "reStructuredText"
+import unittest
+from zope.testing import doctest
+from zope.app.tests import placelesssetup
+
+def test_suite():
+    return unittest.TestSuite((
+        doctest.DocFileSuite('../granting.txt',
+                             setUp=placelesssetup.setUp,
+                             tearDown=placelesssetup.tearDown),
+        ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
+



More information about the Zope3-Checkins mailing list