[Checkins] SVN: zope.security/trunk/ Added to zope.security the implementation of the simple <module>
Brandon Rhodes
brandon at rhodesmill.org
Wed Jan 28 11:00:23 EST 2009
Log message for revision 95342:
Added to zope.security the implementation of the simple <module>
directive, so that everyone needing it will no longer have to rely,
for just that reason, upon the monstrous zope.app.security.
Changed:
U zope.security/trunk/CHANGES.txt
U zope.security/trunk/src/zope/security/meta.zcml
U zope.security/trunk/src/zope/security/metaconfigure.py
U zope.security/trunk/src/zope/security/metadirectives.py
A zope.security/trunk/src/zope/security/tests/redefineperms.zcml
A zope.security/trunk/src/zope/security/tests/test_module_directives.py
-=-
Modified: zope.security/trunk/CHANGES.txt
===================================================================
--- zope.security/trunk/CHANGES.txt 2009-01-28 15:59:18 UTC (rev 95341)
+++ zope.security/trunk/CHANGES.txt 2009-01-28 16:00:22 UTC (rev 95342)
@@ -10,6 +10,9 @@
- Moved the `protectclass` module from `zope.app.security` to this
package to reduce the number of dependencies on `zope.app.security`.
+- Moved the <module> directive implementation from `zope.app.security`
+ to this package.
+
- Moved the <class> directive implementation from `zope.app.component`
to this package.
Modified: zope.security/trunk/src/zope/security/meta.zcml
===================================================================
--- zope.security/trunk/src/zope/security/meta.zcml 2009-01-28 15:59:18 UTC (rev 95341)
+++ zope.security/trunk/src/zope/security/meta.zcml 2009-01-28 16:00:22 UTC (rev 95342)
@@ -51,4 +51,23 @@
</meta:complexDirective>
</meta:directives>
+
+ <meta:groupingDirective
+ name="module"
+ namespace="http://namespaces.zope.org/zope"
+ schema=".metadirectives.IModule"
+ handler="zope.configuration.config.GroupingContextDecorator" />
+
+ <meta:directive
+ name="allow"
+ namespace="http://namespaces.zope.org/zope"
+ schema=".metadirectives.IAllow"
+ handler=".metaconfigure.allow" />
+
+ <meta:directive
+ name="require"
+ namespace="http://namespaces.zope.org/zope"
+ schema=".metadirectives.IRequire"
+ handler=".metaconfigure.require" />
+
</configure>
Modified: zope.security/trunk/src/zope/security/metaconfigure.py
===================================================================
--- zope.security/trunk/src/zope/security/metaconfigure.py 2009-01-28 15:59:18 UTC (rev 95341)
+++ zope.security/trunk/src/zope/security/metaconfigure.py 2009-01-28 16:00:22 UTC (rev 95342)
@@ -27,6 +27,8 @@
from zope.schema.interfaces import IField
from zope.configuration.exceptions import ConfigurationError
+from zope.security.checker import moduleChecker, Checker, defineChecker
+from zope.security.checker import CheckerPublic
from zope.security.protectclass import protectLikeUnto, protectName
from zope.security.protectclass import protectSetAttribute
@@ -170,3 +172,57 @@
# same namespace, despite the utilities/content division
utility(_context, IFactory, factoryObj,
permission=PublicPermission, name=id)
+
+
+def protectModule(module, name, permission):
+ """Set up a module checker to require a permission to access a name
+
+ If there isn't a checker for the module, create one.
+ """
+
+ checker = moduleChecker(module)
+ if checker is None:
+ checker = Checker({}, {})
+ defineChecker(module, checker)
+
+ if permission == 'zope.Public':
+ # Translate public permission to CheckerPublic
+ permission = CheckerPublic
+
+ # We know a dictionary get method was used because we set it
+ protections = checker.get_permissions
+ protections[name] = permission
+
+
+def _names(attributes, interfaces):
+ seen = {}
+ for name in attributes:
+ if not name in seen:
+ seen[name] = 1
+ yield name
+ for interface in interfaces:
+ for name in interface:
+ if not name in seen:
+ seen[name] = 1
+ yield name
+
+
+def allow(context, attributes=(), interface=()):
+
+ for name in _names(attributes, interface):
+ context.action(
+ discriminator=('http://namespaces.zope.org/zope:module',
+ context.module, name),
+ callable = protectModule,
+ args = (context.module, name, 'zope.Public'),
+ )
+
+
+def require(context, permission, attributes=(), interface=()):
+ for name in _names(attributes, interface):
+ context.action(
+ discriminator=('http://namespaces.zope.org/zope:module',
+ context.module, name),
+ callable = protectModule,
+ args = (context.module, name, permission),
+ )
Modified: zope.security/trunk/src/zope/security/metadirectives.py
===================================================================
--- zope.security/trunk/src/zope/security/metadirectives.py 2009-01-28 15:59:18 UTC (rev 95341)
+++ zope.security/trunk/src/zope/security/metadirectives.py 2009-01-28 16:00:22 UTC (rev 95342)
@@ -18,11 +18,15 @@
__docformat__ = 'restructuredtext'
import zope.configuration.fields
+from zope.configuration.fields import GlobalObject, GlobalInterface
+from zope.configuration.fields import Tokens, PythonIdentifier
import zope.interface
import zope.schema
+from zope.interface import Interface
import zope.security.zcml
from zope.security.i18n import ZopeMessageFactory as _
+from zope.security.zcml import Permission
class IClassDirective(zope.interface.Interface):
"""Make statements about a class"""
@@ -141,3 +145,53 @@
" factory does"),
required=False,
)
+
+class IModule(Interface):
+ """Group security declarations about a module"""
+
+ module = GlobalObject(
+ title=u"Module",
+ description=u"Pointer to the module object.",
+ required=True)
+
+
+class IAllow(Interface):
+ """Allow access to selected module attributes
+
+ Access is unconditionally allowed to any names provided directly
+ in the attributes attribute or to any names defined by
+ interfaces listed in the interface attribute.
+ """
+
+ attributes = Tokens(
+ title=u"Attributes",
+ description=u"The attributes to provide access to.",
+ value_type = PythonIdentifier(),
+ required=False)
+
+ interface = Tokens(
+ title=u"Interface",
+ description=u"Interfaces whos names to provide access to. Access "
+ u"will be provided to all of the names defined by the "
+ u"interface(s). Multiple interfaces can be supplied.",
+ value_type = GlobalInterface(),
+ required=False)
+
+
+class IRequire(Interface):
+ """Require a permission to access selected module attributes
+
+ The given permission is required to access any names provided
+ directly in the attributes attribute or any names defined by
+ interfaces listed in the interface attribute.
+ """
+
+ attributes = Tokens(
+ title=u"Attributes",
+ description=u"The attributes to require permission for.",
+ value_type = PythonIdentifier(),
+ required=False)
+
+ permission = Permission(
+ title=u"Permission ID",
+ description=u"The id of the permission to require.")
Copied: zope.security/trunk/src/zope/security/tests/redefineperms.zcml (from rev 95329, zope.app.security/trunk/src/zope/app/security/tests/redefineperms.zcml)
===================================================================
--- zope.security/trunk/src/zope/security/tests/redefineperms.zcml (rev 0)
+++ zope.security/trunk/src/zope/security/tests/redefineperms.zcml 2009-01-28 16:00:22 UTC (rev 95342)
@@ -0,0 +1,33 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:meta="http://namespaces.zope.org/meta"
+ i18n_domain="zope"
+ >
+
+ <include package="zope.security" file="meta.zcml" />
+
+ <meta:directive
+ name="dummy"
+ namespace="http://namespaces.zope.org/zope"
+ schema=".test_module_directives.IDummy"
+ handler=".test_module_directives.dummy" />
+
+ <permission
+ id="zope.View"
+ title="[view-permission] View"
+ />
+
+ <permission
+ id="zope.Security"
+ title="[change-security-settings-permission] Change security settings"
+ />
+
+ <meta:redefinePermission
+ from="zope.View"
+ to="zope.Security"
+ />
+
+ <dummy
+ perm="zope.View" />
+
+</configure>
Property changes on: zope.security/trunk/src/zope/security/tests/redefineperms.zcml
___________________________________________________________________
Added: cvs2svn:cvs-rev
+ 1.1
Added: svn:mergeinfo
+
Added: svn:eol-style
+ native
Copied: zope.security/trunk/src/zope/security/tests/test_module_directives.py (from rev 95329, zope.app.security/trunk/src/zope/app/security/tests/test_directives.py)
===================================================================
--- zope.security/trunk/src/zope/security/tests/test_module_directives.py (rev 0)
+++ zope.security/trunk/src/zope/security/tests/test_module_directives.py 2009-01-28 16:00:22 UTC (rev 95342)
@@ -0,0 +1,236 @@
+##############################################################################
+#
+# Copyright (c) 2003 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.
+#
+##############################################################################
+"""Directives Tests
+
+$Id$
+"""
+import unittest
+from pprint import PrettyPrinter
+
+import zope.security.zcml
+from zope.interface import Interface, Attribute
+from zope.testing import doctest
+from zope.component.testing import setUp, tearDown, PlacelessSetup
+from zope.configuration import xmlconfig
+
+from zope.security import metaconfigure
+
+def pprint(ob, width=70):
+ PrettyPrinter(width=width).pprint(ob)
+
+class I1(Interface):
+ def x(): pass
+ y = Attribute("Y")
+
+class I2(I1):
+ def a(): pass
+ b = Attribute("B")
+
+test_perm = 'zope.security.metaconfigure.test'
+test_bad_perm = 'zope.security.metaconfigure.bad'
+
+def test_protectModule():
+ """
+ >>> from zope.security.tests import test_directives
+ >>> from zope.security.interfaces import IPermission
+ >>> from zope.security.permission import Permission
+
+ >>> from zope.component import provideUtility
+
+ Initially, there's no checker defined for the module:
+
+ >>> from zope.security.checker import moduleChecker
+ >>> moduleChecker(test_directives)
+
+ >>> perm = Permission(test_perm, '')
+ >>> provideUtility(perm, IPermission, test_perm)
+ >>> metaconfigure.protectModule(test_directives, 'foo', test_perm)
+
+ Now, the checker should exist and have an access dictionary with the
+ name and permission:
+
+ >>> checker = moduleChecker(test_directives)
+ >>> cdict = checker.get_permissions
+ >>> pprint(cdict)
+ {'foo': 'zope.security.metaconfigure.test'}
+
+ If we define additional names, they will be added to the dict:
+
+ >>> metaconfigure.protectModule(test_directives, 'bar', test_perm)
+ >>> metaconfigure.protectModule(test_directives, 'baz', test_perm)
+ >>> pprint(cdict)
+ {'bar': 'zope.security.metaconfigure.test',
+ 'baz': 'zope.security.metaconfigure.test',
+ 'foo': 'zope.security.metaconfigure.test'}
+
+ """
+
+def test_allow():
+ """
+
+ The allow directive creates actions for each named defined
+ directly, or via interface:
+
+ >>> class Context(object):
+ ... def __init__(self):
+ ... self.actions = []
+ ...
+ ... def action(self, discriminator, callable, args):
+ ... self.actions.append(
+ ... {'discriminator': discriminator,
+ ... 'callable': int(callable is metaconfigure.protectModule),
+ ... 'args': args})
+ ...
+ ... module='testmodule'
+
+ >>> context = Context()
+ >>> metaconfigure.allow(context, attributes=['foo', 'bar'],
+ ... interface=[I1, I2])
+
+ >>> context.actions.sort(
+ ... lambda a, b: cmp(a['discriminator'], b['discriminator']))
+ >>> pprint(context.actions)
+ [{'args': ('testmodule', 'a', 'zope.Public'),
+ 'callable': 1,
+ 'discriminator': ('http://namespaces.zope.org/zope:module',
+ 'testmodule',
+ 'a')},
+ {'args': ('testmodule', 'b', 'zope.Public'),
+ 'callable': 1,
+ 'discriminator': ('http://namespaces.zope.org/zope:module',
+ 'testmodule',
+ 'b')},
+ {'args': ('testmodule', 'bar', 'zope.Public'),
+ 'callable': 1,
+ 'discriminator': ('http://namespaces.zope.org/zope:module',
+ 'testmodule',
+ 'bar')},
+ {'args': ('testmodule', 'foo', 'zope.Public'),
+ 'callable': 1,
+ 'discriminator': ('http://namespaces.zope.org/zope:module',
+ 'testmodule',
+ 'foo')},
+ {'args': ('testmodule', 'x', 'zope.Public'),
+ 'callable': 1,
+ 'discriminator': ('http://namespaces.zope.org/zope:module',
+ 'testmodule',
+ 'x')},
+ {'args': ('testmodule', 'y', 'zope.Public'),
+ 'callable': 1,
+ 'discriminator': ('http://namespaces.zope.org/zope:module',
+ 'testmodule',
+ 'y')}]
+
+ """
+
+def test_require():
+ """
+
+ The allow directive creates actions for each named defined
+ directly, or via interface:
+
+ >>> class Context(object):
+ ... def __init__(self):
+ ... self.actions = []
+ ...
+ ... def action(self, discriminator, callable, args):
+ ... self.actions.append(
+ ... {'discriminator': discriminator,
+ ... 'callable': int(callable is metaconfigure.protectModule),
+ ... 'args': args})
+ ...
+ ... module='testmodule'
+
+ >>> context = Context()
+ >>> metaconfigure.require(context, attributes=['foo', 'bar'],
+ ... interface=[I1, I2], permission='p')
+
+ >>> context.actions.sort(
+ ... lambda a, b: cmp(a['discriminator'], b['discriminator']))
+ >>> pprint(context.actions)
+ [{'args': ('testmodule', 'a', 'p'),
+ 'callable': 1,
+ 'discriminator': ('http://namespaces.zope.org/zope:module',
+ 'testmodule',
+ 'a')},
+ {'args': ('testmodule', 'b', 'p'),
+ 'callable': 1,
+ 'discriminator': ('http://namespaces.zope.org/zope:module',
+ 'testmodule',
+ 'b')},
+ {'args': ('testmodule', 'bar', 'p'),
+ 'callable': 1,
+ 'discriminator': ('http://namespaces.zope.org/zope:module',
+ 'testmodule',
+ 'bar')},
+ {'args': ('testmodule', 'foo', 'p'),
+ 'callable': 1,
+ 'discriminator': ('http://namespaces.zope.org/zope:module',
+ 'testmodule',
+ 'foo')},
+ {'args': ('testmodule', 'x', 'p'),
+ 'callable': 1,
+ 'discriminator': ('http://namespaces.zope.org/zope:module',
+ 'testmodule',
+ 'x')},
+ {'args': ('testmodule', 'y', 'p'),
+ 'callable': 1,
+ 'discriminator': ('http://namespaces.zope.org/zope:module',
+ 'testmodule',
+ 'y')}]
+
+ """
+
+class IDummy(Interface):
+
+ perm = zope.security.zcml.Permission(title=u'')
+
+perms = []
+
+def dummy(context_, perm):
+ global perms
+ perms.append(perm)
+
+
+class DirectivesTest(PlacelessSetup, unittest.TestCase):
+
+ def setUp(self):
+ super(DirectivesTest, self).setUp()
+ from zope.security import tests
+ self.context = xmlconfig.file("redefineperms.zcml", tests)
+
+ def tearDown(self):
+ super(DirectivesTest, self).tearDown()
+ perms.remove('zope.Security')
+
+ def testRedefinePermission(self):
+ self.assertEqual(perms, ['zope.Security'])
+
+def setUpAuth(test=None):
+ setUp(test)
+
+def zcml(s):
+ context = xmlconfig.file('meta.zcml', package=zope.security)
+ xmlconfig.string(s, context)
+
+def reset():
+ tearDown()
+ setUpAuth()
+
+def test_suite():
+ return unittest.TestSuite((
+ doctest.DocTestSuite(setUp=setUp, tearDown=tearDown),
+ doctest.DocTestSuite('zope.security.zcml'),
+ unittest.makeSuite(DirectivesTest),
+ ))
Property changes on: zope.security/trunk/src/zope/security/tests/test_module_directives.py
___________________________________________________________________
Added: cvs2svn:cvs-rev
+ 1.2
Added: svn:keywords
+ Id
Added: svn:mergeinfo
+
Added: svn:eol-style
+ native
More information about the Checkins
mailing list