summaryrefslogtreecommitdiff
path: root/docs/tutorials
diff options
context:
space:
mode:
Diffstat (limited to 'docs/tutorials')
-rw-r--r--docs/tutorials/bfgwiki2/authorization.rst86
-rw-r--r--docs/tutorials/bfgwiki2/background.rst2
-rw-r--r--docs/tutorials/bfgwiki2/definingmodels.rst2
-rw-r--r--docs/tutorials/bfgwiki2/definingviews.rst48
4 files changed, 77 insertions, 61 deletions
diff --git a/docs/tutorials/bfgwiki2/authorization.rst b/docs/tutorials/bfgwiki2/authorization.rst
index 9988602d5..4ee4e6ac4 100644
--- a/docs/tutorials/bfgwiki2/authorization.rst
+++ b/docs/tutorials/bfgwiki2/authorization.rst
@@ -16,10 +16,14 @@ to our application.
Adding A Root Factory
---------------------
-We're going to start to use a custom *root factory* within our
-``run.py`` file in order to be able to attach security declarations to
-a :term:`context` object. When we do this, we can begin to make use
-of the declarative security features of :mod:`repoze.bfg`.
+We're going to start to use a custom :term:`root factory` within our
+``run.py`` file. The objects generated by the root factory will be
+used as the :term:`context` of each of request to our application. In
+order for BFG declarative security to work properly, the context
+object generated during a request must be decorated with security
+declarations; when we begin to use a custom root factory to generate
+our contexts, we can begin to make use of the declarative security
+features of :mod:`repoze.bfg`.
Let's modify our ``run.py``, passing in a :term:`root factory` as the
first argument to ``repoze.bfg.router.make_app``. We'll point it at a
@@ -32,25 +36,25 @@ statements to your ``models.py`` file:
from repoze.bfg.security import Everyone
class RootFactory(object):
- __acl__ = [ (Allow, Everyone, 'view'), (Allow, 'editor', 'edit') ]
- def __init__(self, environ):
- self.__dict__.update(environ['bfg.routes.matchdict'])
-
-Defining a root factory allows us to use declarative security features
-of :mod:`repoze.bfg`. The ``RootFactory`` class we added will be used
-to construct each of the ``context`` objects. The context is attached
-to our request as the ``context`` attribute. All of our ``context``
-objects will possess an ``__acl__`` attribute that allows "Everyone"
-(a special principal) to view all pages, while allowing only a user
-named ``editor`` to edit and add pages. The ``__acl__`` attribute
-attached to a context is interpreted specially by :mod:`repoze.bfg` as
-an access control list during view execution. See
-:ref:`assigning_acls` for more information about what an :term:`ACL`
-represents.
+ __acl__ = [ (Allow, Everyone, 'view'), (Allow, 'editor', 'edit') ]
+ def __init__(self, environ):
+ self.__dict__.update(environ['bfg.routes.matchdict'])
+
+The ``RootFactory`` class we've just added will be used by BFG to
+construct a ``context`` object. The context is attached to our
+request as the ``context`` attribute.
+
+All of our context objects will possess an ``__acl__`` attribute that
+allows "Everyone" (a special principal) to view all pages, while
+allowing only a user named ``editor`` to edit and add pages. The
+``__acl__`` attribute attached to a context is interpreted specially
+by :mod:`repoze.bfg` as an access control list during view execution.
+See :ref:`assigning_acls` for more information about what an
+:term:`ACL` represents.
.. note: Although we don't use the functionality here, the ``factory``
- used to create route contexts may differ per-route instead of
- globally via a ZCML directive. See the ``factory`` attribute in
+ used to create route contexts may differ per-route as opposed to
+ globally. See the ``factory`` attribute in
:ref:`route_zcml_directive` for more info.
Configuring a ``repoze.bfg`` Authentication Policy
@@ -71,22 +75,25 @@ the policy, and pass it as the ``authentication_policy`` argument to
the ``make_app`` function. The first positional argument of an
``AuthTktAuthenticationPolicy`` is a secret used to encrypt cookie
data. Its second argument ("callback") should be a callable that
-accepts a userid. If the userid exists in the system, the callback
-should return a sequence of group identifiers (or an empty sequence if
-the user isn't a member of any groups). If the userid *does not*
-exist in the system, the callback should return ``None``. We'll use
-"dummy" data to represent user and groups sources.
-
-We'll also use the opportunity to pass our ``RootFactory`` in as the
-first argument to ``make_app``. When we're done, your application's
-``run.py`` will look like this.
+accepts a userid (usually a string). If the userid exists in the
+system, the callback should return a sequence of group identifiers (or
+an empty sequence if the user isn't a member of any groups). If the
+userid *does not* exist in the system, the callback should return
+``None``. We'll use "dummy" data to represent user and groups sources
+within ``run.py``. In a "real" application this information would
+almost certainly come from some database.
+
+We'll also use the opportunity to pass the ``RootFactory`` we created
+in the step above in as the first argument to ``make_app``. When
+we're done, your application's ``run.py`` will look like this.
.. literalinclude:: src/authorization/tutorial/run.py
:linenos:
:language: python
-BFG's ``make_app`` callable also can accept an authorization policy
-parameter. We don't need to specify one, we'll use the default.
+BFG's ``make_app`` callable also can accept an "authorization_policy"
+parameter. We don't need to specify one, because we'll be using the
+default; it is the policy that scans the context for ACLs.
Adding Login and Logout Views
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -160,13 +167,14 @@ Changing ``configure.zcml``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Change your application's ``configure.zcml`` to add a ``forbidden``
-stanza which points at our login view. This configures our login view
-to show up when BFG detects that a view invocation can not be
-authorized. Also, add ``permission`` attributes with the value
-``edit`` to the ``edit_page`` and ``add_page`` routes. This indicates
-that the views which these routes reference cannot be invoked without
-the authenticated user possessing the ``edit`` permission. When
-you're done, your ``configure.zcml`` will look like so:
+stanza which points at our login view. This configures our newly
+created login view to show up when BFG detects that a view invocation
+can not be authorized. Also, add ``permission`` attributes with the
+value ``edit`` to the ``edit_page`` and ``add_page`` routes. This
+indicates that the views which these routes reference cannot be
+invoked without the authenticated user possessing the ``edit``
+permission with respect to the current context. When you're done,
+your ``configure.zcml`` will look like so:
.. literalinclude:: src/authorization/tutorial/configure.zcml
:linenos:
diff --git a/docs/tutorials/bfgwiki2/background.rst b/docs/tutorials/bfgwiki2/background.rst
index 097298d1b..934fbcd42 100644
--- a/docs/tutorials/bfgwiki2/background.rst
+++ b/docs/tutorials/bfgwiki2/background.rst
@@ -13,6 +13,6 @@ To code along with this tutorial, the developer will need a UNIX
machine with development tools (Mac OS X with XCode, any Linux or BSD
variant, etc) *or* he will need a Windows system of any kind.
-This tutorial is known to work under :mod:`repoze.bfg` version 0.9.
+This tutorial is known to work under :mod:`repoze.bfg` version 1.0.
Have fun!
diff --git a/docs/tutorials/bfgwiki2/definingmodels.rst b/docs/tutorials/bfgwiki2/definingmodels.rst
index 0ba2b6f5d..5e9078ce8 100644
--- a/docs/tutorials/bfgwiki2/definingmodels.rst
+++ b/docs/tutorials/bfgwiki2/definingmodels.rst
@@ -4,7 +4,7 @@ Defining Models
The first change we'll make to our bone-stock paster-generated
application will be to define a :term:`model` constructor representing
-a wiki page. We'll do this inside our ``models.py`` file.
+a wiki page. We'll do this inside our ``models.py`` file.
Making Edits to ``models.py``
-----------------------------
diff --git a/docs/tutorials/bfgwiki2/definingviews.rst b/docs/tutorials/bfgwiki2/definingviews.rst
index df19a21c2..515090e91 100644
--- a/docs/tutorials/bfgwiki2/definingviews.rst
+++ b/docs/tutorials/bfgwiki2/definingviews.rst
@@ -4,9 +4,18 @@ Defining Views
Views in a :term:`url dispatch` -based BFG application are typically
simple Python functions that accept a single parameter:
-::term:`request`. A view is assumed to return a :term:`response`
+:term:`request`. A view is assumed to return a :term:`response`
object.
+.. note:: A BFG view can also be defined as callable which accepts
+ *two* arguments: a :term:`context` and ` :term:`request`. You'll
+ see that two-argument pattern used in other BFG tutorials and
+ applications. Either calling convention will work in any
+ application. In :term:`url dispatch` based applications, however,
+ the context object is rarely used in the view body itself, so
+ within this tutorial we define views as callables that accept only
+ a request to avoid the noise.
+
The request passed to every view that is called as the result of a
route match has an attribute named ``matchdict`` that contains the
elements placed into the URL by the ``path`` of a ``route`` statement.
@@ -19,13 +28,12 @@ request passed to the view would have a ``one`` key withe the value
Declaring Dependencies in Our ``setup.py`` File
===============================================
-Our application will depend on packages which are not dependencies of
-the original "tutorial" application as it was generated by the
-``paster create`` command. We'll add these dependencies to our
-``tutorial`` package's ``setup.py`` file by assigning these
-dependencies to both the ``install_requires`` and the
-``tests_require`` parameters to the ``setup`` function. In
-particular, we require the ``docutils`` package.
+The view code in our application will depend a package which is not a
+dependency of the original "tutorial" application as it was generated
+by the ``paster create`` command. We need to add a dependency on the
+``docutils`` package to our ``tutorial`` package's ``setup.py`` file
+by assigning this dependency to the ``install_requires`` parameter in
+the ``setup`` function.
Our resulting ``setup.py`` should look like so:
@@ -36,15 +44,16 @@ Our resulting ``setup.py`` should look like so:
Adding View Functions
=====================
-We'll get rid of our ``my_view`` view in our ``views.py`` file. It's
-only an example and isn't relevant to our application.
+We'll get rid of our ``my_view`` view function in our ``views.py``
+file. It's only an example and isn't relevant to our application.
Then we're going to add four :term:`view` functions to our
``views.py`` module. One view (named ``view_wiki``) will display the
wiki itself (it will answer on the root URL), another named
``view_page`` will display an individual page, another named
``add_page`` will allow a page to be added, and a final view named
-``edit_page`` will allow a page to be edited.
+``edit_page`` will allow a page to be edited. We'll describe each one
+briefly and show the resulting ``views.py`` file afterwards.
.. note::
@@ -67,7 +76,6 @@ API to construct a URL to the ``FrontPage`` page
(e.g. ``http://localhost:6543/FrontPage``), and will use it as the
"location" of the HTTPFound response, forming an HTTP redirect.
-
The ``view_page`` view function
-------------------------------
@@ -236,8 +244,8 @@ Mapping Views to URLs in ``configure.zcml``
===========================================
The ``configure.zcml`` file contains ``route`` declarations (and a
-lone ``view`` declaration) which serve to map URLs (via :term:`url
-dispatch`) to view functions. First, we’ll get rid of the existing
+lone ``view`` declaration) which serve to map URLs via :term:`url
+dispatch` to view functions. First, we’ll get rid of the existing
``route`` created by the template using the name ``home``. It’s only
an example and isn’t relevant to our application. We'll leave the
static ``view`` declaration as it is, since we are going to use it to
@@ -292,12 +300,12 @@ commits and aborts of our database connection in view code.
Adding an Element to the Pipeline
---------------------------------
-Let's add a piece of middleware to the WSGI pipeline.
-"egg:Paste#evalerror" middleware which displays debuggable errors in
-the browser while you're developing (not recommeded for deployment).
-Let's insert evalerror into the pipeline right above
-"egg:repoze.tm2#tm", making our resulting ``tutorial.ini`` file look
-like so:
+Let's add a piece of middleware to the WSGI pipeline. We'll add
+``egg:Paste#evalerror`` middleware which displays debuggable errors in
+the browser while you're developing (this is *not* recommeded for
+deployment as it is a security risk). Let's insert evalerror into the
+pipeline right above "egg:repoze.tm2#tm", making our resulting
+``tutorial.ini`` file look like so:
.. literalinclude:: src/views/tutorial.ini
:linenos: