summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-01-16 22:00:45 +0000
committerChris McDonough <chrism@agendaless.com>2009-01-16 22:00:45 +0000
commit8325f1a17d17f744582ffb9eef50da117a00e57f (patch)
tree60f26c3df09ebef6c65f6594aa6726f174a7d997
parent1ccc194a225c579ba937fe1578f841db9aeb2720 (diff)
downloadpyramid-8325f1a17d17f744582ffb9eef50da117a00e57f.tar.gz
pyramid-8325f1a17d17f744582ffb9eef50da117a00e57f.tar.bz2
pyramid-8325f1a17d17f744582ffb9eef50da117a00e57f.zip
- Add a section on "Using BFG Security With URL Dispatch" into the
urldispatch chapter of the documentation. Clean up "BFG" vernacular (replace with repoze.bfg).
-rw-r--r--CHANGES.txt6
-rw-r--r--docs/narr/hooks.rst6
-rw-r--r--docs/narr/urldispatch.rst78
-rw-r--r--docs/narr/views.rst13
-rw-r--r--repoze/bfg/urldispatch.py4
5 files changed, 94 insertions, 13 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index e1c6cc691..b23c6cdc7 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -42,6 +42,12 @@ Implementation Changes
``webob.Request.get_response`` to do its work rather than relying on
homegrown WSGI code.
+Documentation Additions
+-----------------------
+
+- Add a section on "Using BFG Security With URL Dispatch" into the
+ urldispatch chapter of the documentation.
+
0.6.2 (2009-01-13)
==================
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index 009943e9e..5d1c9612e 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -13,9 +13,9 @@ Changing the request factory
You may change the class used as the "request factory" from within the
:mod:`repoze.bfg` ``Router`` class (the ``Router`` class turns the
WSGI environment into a "request" object which is used ubiquitously
-throughout BFG). The default "request factory" is the class
-``webob.Request``. You may change it by placing the following ZCML in
-your ``configure.zcml`` file.
+throughout :mod:`repoze.bfg`). The default "request factory" is the
+class ``webob.Request``. You may change it by placing the following
+ZCML in your ``configure.zcml`` file.
.. code-block:: xml
:linenos:
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 7572ddd65..dadc3d9df 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -154,6 +154,9 @@ configure the ``RoutesMapper`` like so:
.. code-block:: python
:linenos:
+ from repoze.bfg.router import make_app
+ from repoze.bfg.urldispatch import RoutesMapper
+
def fallback_get_root(environ):
return {} # the graph traversal root is empty in this example
@@ -166,8 +169,6 @@ configure the ``RoutesMapper`` like so:
context_factory=Article)
import myapp
- from repoze.bfg.router import make_app
-
app = make_app(get_root, myapp)
The effect of this configuration: when this :mod:`repoze.bfg`
@@ -183,10 +184,81 @@ In this case in particular, when a user visits
Article class and it will have an ``article`` attribute with the value
of ``something``.
+Using :mod:`repoze.bfg` Security With URL Dispatch
+--------------------------------------------------
+
+:mod:`repoze.bfg` provides its own security framework which consults a
+:term:`security policy` before allowing any application code to be
+called. This framework operates in terms of ACLs (Access Control
+Lists, see :ref:`security_chapter` for more information about the
+:mod:`repoze.bfg` security subsystem). A common thing to want to do
+is to attach an ``__acl__`` to the context object dynamically for
+declarative security purposes. A Routes 'trick' can allow for this.
+
+Routes makes it possible to pass a ``conditions`` argument to the
+``connect`` method of a mapper. The value of ``conditions`` is a
+dictionary. If you pass a ``conditions`` dictionary to this
+``connect`` method with a `function`` key that has a value which is a
+function, this function can be used to update the ``__acl__`` of the
+model object.
+
+When Routes tries to resolve a particular route via a match, the route
+object itself will pass the environment and the "match_dict" to the
+``conditions`` function. Typically, a ``conditions`` function decides
+whether or not the route match should "succeed". But we'll use it
+differently: we'll use it to update the "match dict". The match dict
+is what is eventually returned by Routes to :mod:`repoze.bfg`. If the
+function that is used as the ``conditions`` function adds an
+``__acl__`` key/value pair to the match dict and subsequently always
+returns ``True`` (indicating that the "condition" passed), the
+resulting ``__acl__`` key and its value will appear in the match
+dictionary. Since all values returned in the match dictionary are
+eventually set on your context object, :mod:`repoze.bfg` will set an
+``__acl__`` attribute on the context object returned to
+:mod:`repoze.bfg` matching the value you've put into the match
+dictionary under ``__acl__``, just in time for the :mod:`repoze.bfg`
+security machinery to find it. :mod:`repoze.bfg` security will allow
+or deny further processing of the request based on the ACL.
+
+Here's an example:
+
+.. code-block:: python
+
+ from repoze.bfg.router import make_app
+ from repoze.bfg.security import Allow
+ from repoze.bfg.urldispatch import RoutesMapper
+
+ class Article(object):
+ def __init__(self, **kw):
+ self.__dict__.update(kw)
+
+ def add_acl(environ, match_dict):
+ if match_dict.get('article') == 'article1':
+ routes_dict['__acl__'] = [ (Allow, 'editor', 'view') ]
+
+ get_root = RoutesMapper(fallback_get_root)
+ get_root.connect('archives/:article', controller='articles',
+ context_factory=Article, conditions={'function':add_acl})
+
+ import myapp
+ app = make_app(get_root, myapp)
+
+Obviously you can do more generic things that inspect the routes match
+dict to see if the ``article`` argument matches a particular string;
+our sample ``add_acl`` function is not very ambitious.
+
+.. note:: See :ref:`security_chapter` for more information about
+ :mod:`repoze.bfg` security and ACLs.
+
+.. note:: See `Conditions
+ <http://routes.groovie.org/manual.html#conditions>`_ in the
+ :term:`Routes` manual for a general overview of what the
+ ``condition`` argument to ``.connect`` does.
+
Further Documentation and Examples
----------------------------------
-URL-dispatch related API documentation is available in the
+URL-dispatch related API documentation is available in
:ref:`urldispatch_module` .
The `repoze.shootout <http://svn.repoze.org/repoze.shootout/trunk/>`_
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index eca6001b5..edbe03d82 100644
--- a/docs/narr/views.rst
+++ b/docs/narr/views.rst
@@ -165,10 +165,11 @@ Mapping Views to URLs Using a Decorator
If you're allergic to reading and writing :term:`ZCML`, or you're just
more comfortable defining your view declarations using Python, you may
use the ``repoze.bfg.view.bfg_view`` decorator to associate your view
-functions with URLs instead of using :term:`ZCML` for the same purpose.
-``repoze.bfg.view.bfg_view`` can be used to associate ``for``,
-``name``, ``permission`` and ``request_type`` information -- as done
-via the equivalent ZCML -- with a function that acts as a BFG view.
+functions with URLs instead of using :term:`ZCML` for the same
+purpose. ``repoze.bfg.view.bfg_view`` can be used to associate
+``for``, ``name``, ``permission`` and ``request_type`` information --
+as done via the equivalent ZCML -- with a function that acts as a
+:mod:`repoze.bfg` view.
To make :mod:`repoze.bfg` process your ``bfg_view`` declarations, you
*must* insert the following boilerplate into your application's
@@ -527,8 +528,8 @@ or interface that represents your root object.
name="static"
/>
-In this case, ``.models.Root`` refers to the class of which your BFG
-application's root object is an instance.
+In this case, ``.models.Root`` refers to the class of which your
+:mod:`repoze.bfg` application's root object is an instance.
.. note:: You can also give a ``for`` of ``*`` if you want the name
``static`` to be accessible as the static view against any model.
diff --git a/repoze/bfg/urldispatch.py b/repoze/bfg/urldispatch.py
index 46812390a..5a8c7664f 100644
--- a/repoze/bfg/urldispatch.py
+++ b/repoze/bfg/urldispatch.py
@@ -77,7 +77,9 @@ class RoutesMapper(object):
default context factory (the ``RoutesContext`` class) will be
used. The interface ``repoze.bfg.interfaces.IRoutesContext``
will always be tacked on to the context instance in addition
- to whatever interfaces the context instance already supplies."""
+ to whatever interfaces the context instance already supplies.
+ """
+
self.mapper.connect(*arg, **kw)
class RoutesModelTraverser(object):