[Checkins] SVN: grok/branches/timte-json/src/grok/ After the JSON view got added, I noticed a lot of code redundant

Martijn Faassen faassen at infrae.com
Mon Apr 16 14:10:43 EDT 2007


Log message for revision 74191:
  After the JSON view got added, I noticed a lot of code redundant 
  with both View and XMLRPC. I've refactored this a bit so more
  code is reused.
  
  In addition, some checks for the existence of a permission were
  not taking place with XMLRPC and JSON views. Tests have been
  added and we now make sure we do the same check there too.
  

Changed:
  U   grok/branches/timte-json/src/grok/meta.py
  U   grok/branches/timte-json/src/grok/tests/security/missing_permission.py
  A   grok/branches/timte-json/src/grok/tests/security/missing_permission_json.py
  A   grok/branches/timte-json/src/grok/tests/security/missing_permission_json2.py
  A   grok/branches/timte-json/src/grok/tests/security/missing_permission_xmlrpc.py
  A   grok/branches/timte-json/src/grok/tests/security/missing_permission_xmlrpc2.py
  A   grok/branches/timte-json/src/grok/tests/security/missing_permission_xmlrpc3.py
  U   grok/branches/timte-json/src/grok/tests/security/multiple_require.py
  U   grok/branches/timte-json/src/grok/tests/security/multiple_require_json.py
  U   grok/branches/timte-json/src/grok/tests/security/multiple_require_xmlrpc.py
  U   grok/branches/timte-json/src/grok/util.py

-=-
Modified: grok/branches/timte-json/src/grok/meta.py
===================================================================
--- grok/branches/timte-json/src/grok/meta.py	2007-04-16 18:09:08 UTC (rev 74190)
+++ grok/branches/timte-json/src/grok/meta.py	2007-04-16 18:10:42 UTC (rev 74191)
@@ -6,7 +6,6 @@
                                                IBrowserRequest,
                                                IBrowserPublisher)
 from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest
-from zope.security.checker import NamesChecker, defineChecker
 from zope.security.permission import Permission
 from zope.security.interfaces import IPermission
 from zope.annotation.interfaces import IAnnotations
@@ -83,18 +82,8 @@
         # the outside -- need to discuss how to restrict such things.
         methods = util.methods_from_class(factory)
 
-        # Determine the default permission for the XMLRPC methods.
-        # There can only be 0 or 1 of those.
-        permissions = util.class_annotation(factory, 'grok.require', [])
-        if not permissions:
-            default_permission = None
-        elif len(permissions) == 1:
-            default_permission = permissions[0]
-        else:
-            raise GrokError('grok.require was called multiple times in '
-                            '%r. It may only be called once on class level.'
-                            % factory, factory)
-
+        default_permission = util.get_default_permission(factory)
+        
         for method in methods:
             # Make sure that the class inherits MethodPublisher, so that the
             # views have a location
@@ -110,14 +99,10 @@
             # Protect method_view with either the permission that was
             # set on the method, the default permission from the class
             # level or zope.Public.
-            permission = getattr(method, '__grok_require__', default_permission)
-            if permission is None or permission == 'zope.Public':
-                checker = NamesChecker(['__call__'])
-            else:
-                checker = NamesChecker(['__call__'], permission)
-            defineChecker(method_view, checker)
-
-
+            permission = getattr(method, '__grok_require__',
+                                 default_permission)
+            util.make_checker(factory, method_view, permission)
+    
 class ViewGrokker(grok.ClassGrokker):
     component_class = grok.View
 
@@ -181,25 +166,9 @@
                                  name=view_name)
 
         # protect view, public by default
-        permissions = util.class_annotation(factory, 'grok.require', [])
-        if not permissions:
-            checker = NamesChecker(['__call__'])
-        elif len(permissions) > 1:
-            raise GrokError('grok.require was called multiple times in view '
-                            '%r. It may only be called once.' % factory,
-                            factory)
-        elif permissions[0] == 'zope.Public':
-            checker = NamesChecker(['__call__'])
-        else:
-            perm = permissions[0]
-            if component.queryUtility(IPermission, name=perm) is None:
-                raise GrokError('Undefined permission %r in view %r. Use '
-                                'grok.define_permission first.'
-                                % (perm, factory), factory)
-            checker = NamesChecker(['__call__'], permissions[0])
-
-        defineChecker(factory, checker)
-
+        default_permission = util.get_default_permission(factory)
+        util.make_checker(factory, factory, default_permission)
+    
         # safety belt: make sure that the programmer didn't use
         # @grok.require on any of the view's methods.
         methods = util.methods_from_class(factory)
@@ -218,18 +187,8 @@
         view_context = util.determine_class_context(factory, context)
         methods = util.methods_from_class(factory)
 
-        # Determine the default permission for the JSON methods.
-        # There can only be 0 or 1 of those.
-        permissions = util.class_annotation(factory, 'grok.require', [])
-        if not permissions:
-            default_permission = None
-        elif len(permissions) == 1:
-            default_permission = permissions[0]
-        else:
-            raise GrokError('grok.require was called multiple times in '
-                            '%r. It may only be called once on class level.'
-                            % factory, factory)
-
+        default_permission = util.get_default_permission(factory)
+        
         for method in methods:
             # Create a new class with a __view_name__ attribute so the
             # JSON class knows what method to call.
@@ -245,13 +204,10 @@
             # Protect method_view with either the permission that was
             # set on the method, the default permission from the class
             # level or zope.Public.
-            permission = getattr(method, '__grok_require__', default_permission)
-            if permission is None or permission == 'zope.Public':
-                checker = NamesChecker(['__call__'])
-            else:
-                checker = NamesChecker(['__call__'], permission)
-            defineChecker(method_view, checker)
 
+            permission = getattr(method, '__grok_require__',
+                                 default_permission)
+            util.make_checker(factory, method_view, permission)
 
 class TraverserGrokker(grok.ClassGrokker):
     component_class = grok.Traverser

Modified: grok/branches/timte-json/src/grok/tests/security/missing_permission.py
===================================================================
--- grok/branches/timte-json/src/grok/tests/security/missing_permission.py	2007-04-16 18:09:08 UTC (rev 74190)
+++ grok/branches/timte-json/src/grok/tests/security/missing_permission.py	2007-04-16 18:10:42 UTC (rev 74191)
@@ -4,7 +4,7 @@
 
   >>> grok.grok(__name__)
   Traceback (most recent call last):
-  GrokError: Undefined permission 'doesnt.exist' in view <class 'grok.tests.security.missing_permission.MissingPermission'>. Use grok.define_permission first.
+  GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission.MissingPermission'>. Use grok.define_permission first.
 
 """
 
@@ -17,3 +17,4 @@
 
     def render(self):
         pass
+

Added: grok/branches/timte-json/src/grok/tests/security/missing_permission_json.py
===================================================================
--- grok/branches/timte-json/src/grok/tests/security/missing_permission_json.py	2007-04-16 18:09:08 UTC (rev 74190)
+++ grok/branches/timte-json/src/grok/tests/security/missing_permission_json.py	2007-04-16 18:10:42 UTC (rev 74191)
@@ -0,0 +1,20 @@
+"""
+A permission has to be defined first (using grok.define_permission for
+example) before it can be used in grok.require() in an JSON class.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_json.MissingPermission'>. Use grok.define_permission first.
+
+"""
+
+import grok
+import zope.interface
+
+class MissingPermission(grok.JSON):
+    grok.context(zope.interface.Interface)
+    grok.require('doesnt.exist')
+
+    def foo(self):
+        pass
+

Added: grok/branches/timte-json/src/grok/tests/security/missing_permission_json2.py
===================================================================
--- grok/branches/timte-json/src/grok/tests/security/missing_permission_json2.py	2007-04-16 18:09:08 UTC (rev 74190)
+++ grok/branches/timte-json/src/grok/tests/security/missing_permission_json2.py	2007-04-16 18:10:42 UTC (rev 74191)
@@ -0,0 +1,20 @@
+"""
+A permission has to be defined first (using grok.define_permission for
+example) before it can be used in @grok.require().
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_json2.MissingPermission'>. Use grok.define_permission first.
+
+"""
+
+import grok
+import zope.interface
+
+class MissingPermission(grok.JSON):
+    grok.context(zope.interface.Interface)
+
+    @grok.require('doesnt.exist')
+    def foo(self):
+        pass
+

Added: grok/branches/timte-json/src/grok/tests/security/missing_permission_xmlrpc.py
===================================================================
--- grok/branches/timte-json/src/grok/tests/security/missing_permission_xmlrpc.py	2007-04-16 18:09:08 UTC (rev 74190)
+++ grok/branches/timte-json/src/grok/tests/security/missing_permission_xmlrpc.py	2007-04-16 18:10:42 UTC (rev 74191)
@@ -0,0 +1,20 @@
+"""
+A permission has to be defined first (using grok.define_permission for
+example) before it can be used in grok.require() in an XMLRPC class.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_xmlrpc.MissingPermission'>. Use grok.define_permission first.
+
+"""
+
+import grok
+import zope.interface
+
+class MissingPermission(grok.XMLRPC):
+    grok.context(zope.interface.Interface)
+    grok.require('doesnt.exist')
+
+    def foo(self):
+        pass
+

Added: grok/branches/timte-json/src/grok/tests/security/missing_permission_xmlrpc2.py
===================================================================
--- grok/branches/timte-json/src/grok/tests/security/missing_permission_xmlrpc2.py	2007-04-16 18:09:08 UTC (rev 74190)
+++ grok/branches/timte-json/src/grok/tests/security/missing_permission_xmlrpc2.py	2007-04-16 18:10:42 UTC (rev 74191)
@@ -0,0 +1,20 @@
+"""
+A permission has to be defined first (using grok.define_permission for
+example) before it can be used in @grok.require().
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_xmlrpc2.MissingPermission'>. Use grok.define_permission first.
+
+"""
+
+import grok
+import zope.interface
+
+class MissingPermission(grok.XMLRPC):
+    grok.context(zope.interface.Interface)
+
+    @grok.require('doesnt.exist')
+    def foo(self):
+        pass
+

Added: grok/branches/timte-json/src/grok/tests/security/missing_permission_xmlrpc3.py
===================================================================
--- grok/branches/timte-json/src/grok/tests/security/missing_permission_xmlrpc3.py	2007-04-16 18:09:08 UTC (rev 74190)
+++ grok/branches/timte-json/src/grok/tests/security/missing_permission_xmlrpc3.py	2007-04-16 18:10:42 UTC (rev 74191)
@@ -0,0 +1,24 @@
+"""
+A permission has to be defined first (using grok.define_permission for
+example) before it can be used in grok.require() in an XMLRPC class. This
+is even the case for a default permission that is never used.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+   ...
+  GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_xmlrpc3.MissingPermission'>. Use grok.define_permission first.
+
+"""
+
+import grok
+import zope.interface
+
+grok.define_permission('foo')
+
+class MissingPermission(grok.XMLRPC):
+    grok.context(zope.interface.Interface)
+    grok.require('doesnt.exist')
+
+    @grok.require('foo')
+    def foo(self):
+        pass

Modified: grok/branches/timte-json/src/grok/tests/security/multiple_require.py
===================================================================
--- grok/branches/timte-json/src/grok/tests/security/multiple_require.py	2007-04-16 18:09:08 UTC (rev 74190)
+++ grok/branches/timte-json/src/grok/tests/security/multiple_require.py	2007-04-16 18:10:42 UTC (rev 74191)
@@ -3,7 +3,8 @@
 
   >>> grok.grok(__name__)
   Traceback (most recent call last):
-  GrokError: grok.require was called multiple times in view <class 'grok.tests.security.multiple_require.MultipleView'>. It may only be called once.
+    ...
+  GrokError: grok.require was called multiple times in <class 'grok.tests.security.multiple_require.MultipleView'>. It may only be set once for a class.
 
 """
 import grok

Modified: grok/branches/timte-json/src/grok/tests/security/multiple_require_json.py
===================================================================
--- grok/branches/timte-json/src/grok/tests/security/multiple_require_json.py	2007-04-16 18:09:08 UTC (rev 74190)
+++ grok/branches/timte-json/src/grok/tests/security/multiple_require_json.py	2007-04-16 18:10:42 UTC (rev 74191)
@@ -3,8 +3,9 @@
 
   >>> grok.grok(__name__)
   Traceback (most recent call last):
-  GrokError: grok.require was called multiple times in <class 'grok.tests.security.multiple_require_json.MultipleJSON'>. It may only be called once on class level.
-
+    ...
+  GrokError: grok.require was called multiple times in <class 'grok.tests.security.multiple_require_json.MultipleJSON'>. It may only be set once for a class.
+  
 """
 import grok
 import zope.interface

Modified: grok/branches/timte-json/src/grok/tests/security/multiple_require_xmlrpc.py
===================================================================
--- grok/branches/timte-json/src/grok/tests/security/multiple_require_xmlrpc.py	2007-04-16 18:09:08 UTC (rev 74190)
+++ grok/branches/timte-json/src/grok/tests/security/multiple_require_xmlrpc.py	2007-04-16 18:10:42 UTC (rev 74191)
@@ -3,8 +3,8 @@
 
   >>> grok.grok(__name__)
   Traceback (most recent call last):
-  GrokError: grok.require was called multiple times in <class 'grok.tests.security.multiple_require_xmlrpc.MultipleXMLRPC'>. It may only be called once on class level.
-
+     ...
+  GrokError: grok.require was called multiple times in <class 'grok.tests.security.multiple_require_xmlrpc.MultipleXMLRPC'>. It may only be set once for a class.
 """
 import grok
 import zope.interface

Modified: grok/branches/timte-json/src/grok/util.py
===================================================================
--- grok/branches/timte-json/src/grok/util.py	2007-04-16 18:09:08 UTC (rev 74190)
+++ grok/branches/timte-json/src/grok/util.py	2007-04-16 18:10:42 UTC (rev 74191)
@@ -22,6 +22,9 @@
 from zope import component
 from zope import interface
 
+from zope.security.checker import NamesChecker, defineChecker
+from zope.security.interfaces import IPermission
+
 from grok.error import GrokError, GrokImportError
 
 def not_unicode_or_ascii(value):
@@ -144,3 +147,47 @@
                   if name != '__provides__' ]
     methods = [c for c in candidates if inspect.ismethod(c)]
     return methods
+
+def make_checker(factory, view_factory, permission):
+    """Make a checker for a view_factory associated with factory.
+
+    These could be one and the same for normal views, or different
+    in case we make method-based views such as for JSON and XMLRPC.
+    """
+    if permission is not None:
+        check_permission(factory, permission)
+    if permission is None or permission == 'zope.Public':
+        checker = NamesChecker(['__call__'])
+    else:
+        checker = NamesChecker(['__call__'], permission)
+    defineChecker(view_factory, checker)
+
+def check_permission(factory, permission):
+    """Check whether a permission is defined.
+
+    If not, raise error for factory.
+    """
+    if component.queryUtility(IPermission,
+                              name=permission) is None:
+       raise GrokError('Undefined permission %r in %r. Use '
+                       'grok.define_permission first.'
+                       % (permission, factory), factory)
+
+def get_default_permission(factory):
+    """Determine the default permission for a view.
+    
+    There can be only 0 or 1 default permission.
+    """
+    permissions = class_annotation(factory, 'grok.require', [])
+    if not permissions:
+        return None
+    if len(permissions) > 1:
+        raise GrokError('grok.require was called multiple times in '
+                        '%r. It may only be set once for a class.'
+                        % factory, factory)
+
+    result = permissions[0]
+    check_permission(factory, result)
+    return result
+
+



More information about the Checkins mailing list