[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