summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorTres Seaver <tseaver@palladion.com>2012-12-23 20:54:05 +0000
committerTres Seaver <tseaver@palladion.com>2012-12-23 20:54:05 +0000
commit0902621724687fca77a11f15fd3ff55659a1c2c0 (patch)
tree319278d0c0e3ef047ae17378aa15c021a785e206 /docs
parent4132f26a44ece597d0c5b5abe20cdac627338bf6 (diff)
downloadzope-security-0902621724687fca77a11f15fd3ff55659a1c2c0.tar.gz
Convert doctests in 'zope.security.decorator' into Sphinx doctest snppets.
They are still tested under 'tox -e docs'.
Diffstat (limited to 'docs')
-rw-r--r--docs/api/decorator.rst205
-rw-r--r--docs/index.rst1
2 files changed, 206 insertions, 0 deletions
diff --git a/docs/api/decorator.rst b/docs/api/decorator.rst
new file mode 100644
index 0000000..c4741b9
--- /dev/null
+++ b/docs/api/decorator.rst
@@ -0,0 +1,205 @@
+:mod:`zope.security.decorator`
+===============================
+
+.. testsetup::
+
+ from zope.component.testing import setUp
+ setUp()
+
+.. autoclass:: zope.security.decorator.DecoratedSecurityCheckerDescriptor
+ :members:
+ :member-order: bysource
+
+To illustrate, we'll create a class that will be proxied:
+
+.. doctest::
+
+ >>> class Foo(object):
+ ... a = 'a'
+
+and a class to proxy it that uses a decorated security checker:
+
+.. doctest::
+
+ >>> from zope.security.decorator import DecoratedSecurityCheckerDescriptor
+ >>> from zope.proxy import ProxyBase
+ >>> class Wrapper(ProxyBase):
+ ... b = 'b'
+ ... __Security_checker__ = DecoratedSecurityCheckerDescriptor()
+
+Next we'll create and register a checker for `Foo`:
+
+.. doctest::
+
+ >>> from zope.security.checker import NamesChecker, defineChecker
+ >>> fooChecker = NamesChecker(['a'])
+ >>> defineChecker(Foo, fooChecker)
+
+along with a checker for `Wrapper`:
+
+.. doctest::
+
+ >>> wrapperChecker = NamesChecker(['b'])
+ >>> defineChecker(Wrapper, wrapperChecker)
+
+Using `selectChecker()`, we can confirm that a `Foo` object uses
+ `fooChecker`:
+
+.. doctest::
+
+ >>> from zope.security.checker import selectChecker
+ >>> foo = Foo()
+ >>> selectChecker(foo) is fooChecker
+ True
+ >>> fooChecker.check(foo, 'a')
+ >>> fooChecker.check(foo, 'b') # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ForbiddenAttribute: ('b', <zope.security.decorator.Foo object ...>)
+
+and that a `Wrapper` object uses `wrappeChecker`:
+
+.. doctest::
+
+ >>> wrapper = Wrapper(foo)
+ >>> selectChecker(wrapper) is wrapperChecker
+ True
+ >>> wrapperChecker.check(wrapper, 'b')
+ >>> wrapperChecker.check(wrapper, 'a') # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ForbiddenAttribute: ('a', <zope.security.decorator.Foo object ...>)
+
+(Note that the object description says `Foo` because the object is a
+proxy and generally looks and acts like the object it's proxying.)
+
+When we access wrapper's ``__Security_checker__`` attribute, we invoke
+the decorated security checker descriptor. The decorator's job is to make
+sure checkers from both objects are used when available. In this case,
+because both objects have checkers, we get a combined checker:
+
+.. doctest::
+
+ >>> from zope.security.checker import CombinedChecker
+ >>> checker = wrapper.__Security_checker__
+ >>> type(checker)
+ <class 'zope.security.checker.CombinedChecker'>
+ >>> checker.check(wrapper, 'a')
+ >>> checker.check(wrapper, 'b')
+
+The decorator checker will work even with security proxied objects. To
+illustrate, we'll proxify `foo`:
+
+.. doctest::
+
+ >>> from zope.security.proxy import ProxyFactory
+ >>> secure_foo = ProxyFactory(foo)
+ >>> secure_foo.a
+ 'a'
+ >>> secure_foo.b # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ForbiddenAttribute: ('b', <zope.security.decorator.Foo object ...>)
+
+when we wrap the secured `foo`:
+
+.. doctest::
+
+ >>> wrapper = Wrapper(secure_foo)
+
+we still get a combined checker:
+
+.. doctest::
+
+ >>> checker = wrapper.__Security_checker__
+ >>> type(checker)
+ <class 'zope.security.checker.CombinedChecker'>
+ >>> checker.check(wrapper, 'a')
+ >>> checker.check(wrapper, 'b')
+
+The decorator checker has three other scenarios:
+
+ - the wrapper has a checker but the proxied object doesn't
+ - the proxied object has a checker but the wrapper doesn't
+ - neither the wrapper nor the proxied object have checkers
+
+When the wrapper has a checker but the proxied object doesn't:
+
+.. doctest::
+
+ >>> from zope.security.checker import NoProxy, _checkers
+ >>> del _checkers[Foo]
+ >>> defineChecker(Foo, NoProxy)
+ >>> selectChecker(foo) is None
+ True
+ >>> selectChecker(wrapper) is wrapperChecker
+ True
+
+the decorator uses only the wrapper checker:
+
+.. doctest::
+
+ >>> wrapper = Wrapper(foo)
+ >>> wrapper.__Security_checker__ is wrapperChecker
+ True
+
+When the proxied object has a checker but the wrapper doesn't:
+
+.. doctest::
+
+ >>> del _checkers[Wrapper]
+ >>> defineChecker(Wrapper, NoProxy)
+ >>> selectChecker(wrapper) is None
+ True
+ >>> del _checkers[Foo]
+ >>> defineChecker(Foo, fooChecker)
+ >>> selectChecker(foo) is fooChecker
+ True
+
+the decorator uses only the proxied object checker:
+
+.. doctest::
+
+ >>> wrapper.__Security_checker__ is fooChecker
+ True
+
+Finally, if neither the wrapper not the proxied have checkers:
+
+.. doctest::
+
+ >>> del _checkers[Foo]
+ >>> defineChecker(Foo, NoProxy)
+ >>> selectChecker(foo) is None
+ True
+ >>> selectChecker(wrapper) is None
+ True
+
+the decorator doesn't have a checker:
+
+.. doctest::
+
+ >>> wrapper.__Security_checker__
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'Foo' has no attribute '__Security_checker__'
+
+ __Security_checker__ cannot be None, otherwise Checker.proxy blows
+ up:
+
+ >>> checker.proxy(wrapper) is wrapper
+ True
+
+
+.. autoclass:: zope.security.decorator.SecurityCheckerDecoratorBase
+ :members:
+ :member-order: bysource
+
+
+.. autoclass:: zope.security.decorator.DecoratorBase
+ :members:
+ :member-order: bysource
+
+
+
+
+.. testcleanup::
+
+ from zope.component.testing import tearDown
+ tearDown()
diff --git a/docs/index.rst b/docs/index.rst
index 4446466..2d3196b 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -10,6 +10,7 @@ API Reference
api/interfaces
api/adapter
api/checker
+ api/decorator
api/permission