summaryrefslogtreecommitdiff
path: root/docs/tutorials
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-05-30 06:54:31 +0000
committerChris McDonough <chrism@agendaless.com>2009-05-30 06:54:31 +0000
commitb0a3958409901788da67ad5bf9f8ff4e664c6516 (patch)
tree4534d2d96b9444a4663c41b03f0f108cf0ed5335 /docs/tutorials
parentc92023b5bd630a91f2ae1dc8812349d920105343 (diff)
downloadpyramid-b0a3958409901788da67ad5bf9f8ff4e664c6516.tar.gz
pyramid-b0a3958409901788da67ad5bf9f8ff4e664c6516.tar.bz2
pyramid-b0a3958409901788da67ad5bf9f8ff4e664c6516.zip
Modify tutorial for a6.
Diffstat (limited to 'docs/tutorials')
-rw-r--r--docs/tutorials/bfgwiki/authorization.rst235
-rw-r--r--docs/tutorials/bfgwiki/src/authorization/setup.py1
-rw-r--r--docs/tutorials/bfgwiki/src/authorization/tutorial.ini5
-rw-r--r--docs/tutorials/bfgwiki/src/authorization/tutorial/configure.zcml3
-rw-r--r--docs/tutorials/bfgwiki/src/authorization/tutorial/login.py43
-rw-r--r--docs/tutorials/bfgwiki/src/authorization/tutorial/run.py13
-rw-r--r--docs/tutorials/bfgwiki/src/authorization/tutorial/templates/login.pt32
-rw-r--r--docs/tutorials/bfgwiki/src/authorization/tutorial/templates/view.pt2
-rw-r--r--docs/tutorials/bfgwiki/src/authorization/tutorial/views.py18
-rw-r--r--docs/tutorials/bfgwiki/src/authorization/who.ini40
-rw-r--r--docs/tutorials/bfgwiki/src/authorization/wiki.passwd1
11 files changed, 179 insertions, 214 deletions
diff --git a/docs/tutorials/bfgwiki/authorization.rst b/docs/tutorials/bfgwiki/authorization.rst
index 3b5c2e3de..f52312c14 100644
--- a/docs/tutorials/bfgwiki/authorization.rst
+++ b/docs/tutorials/bfgwiki/authorization.rst
@@ -7,133 +7,121 @@ view, edit, and add pages to our wiki. For purposes of demonstration
we'll change our application to allow people whom possess a specific
username (`editor`) to add and edit wiki pages but we'll continue
allowing anyone with access to the server to view pages.
+:mod:`repoze.bfg` provides facilities for *authorization* and
+*authentication*. We'll make use of both features to provide security
+to our application.
-:mod:`repoze.bfg` provides a facility for *authorization*, but it
-relies on "upstream" software to provide *authentication* information.
-We're going to use a package named ``repoze.who`` to our setup, and
-we'll rely on it to give us authentication information.
-
-Adding a Dependency on ``repoze.who`` to Our ``setup.py`` File
---------------------------------------------------------------
-
-We need to change our ``setup.py`` file, adding a dependency on the
-``repoze.who`` package. The ``repoze.who`` package provides a
-mechanism for providing *authentication* data via :term:`WSGI`
-middleware. We'll add the ``repoze.who`` package to our ``requires``
-list.
+Configuring a ``repoze.bfg`` Authentication Policy
+--------------------------------------------------
-The resulting setup.py file:
+For any :mod:`repoze.bfg` application to perform authorization, we
+need to change our ``run.py`` module to add an :term:`authentication
+policy`. Adding an authentication policy actually causes the system
+to begin to use :term:`authorization`.
+
+Changing ``run.py``
+~~~~~~~~~~~~~~~~~~~
+
+Change your ``run.py`` module to import the
+``AuthTktAuthenticationPolicy`` from ``repoze.bfg.authentication``.
+Within the body of the ``make_app`` function, construct an instance of
+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. When we're done,
+your application's ``run.py`` will look like this.
-.. literalinclude:: src/authorization/setup.py
+.. literalinclude:: src/authorization/tutorial/run.py
:linenos:
:language: python
-Changing our ``tutorial.ini`` file to Include the ``repoze.who`` Middleware
----------------------------------------------------------------------------
-
-In order to make use of the ``repoze.who`` middleware which provides
-authentication services, we need to wire it into our ``tutorial.ini``
-file. We'll add a ``[filter:who]`` section to our ``tutorial.ini``
-file and wire it into our pipeline. Our resulting ``tutorial.ini``
-file will look like so:
+BFG's ``make_app`` callable also can accept an authorization policy
+parameter. We don't need to specify one, we'll use the default.
-.. literalinclude:: src/authorization/tutorial.ini
- :linenos:
- :language: ini
+Adding Login and Logout Views
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Note that we added a ``who`` line to our pipeline. This refers to the
-``[filter:who]`` section above it. The ``[filter:who]`` section has a
-``use`` line that points at an egg entry point for configuring the
-repoze.who middleware via a config file. The ``config_file`` line
-points at an .ini config file named ``who.ini``. This file is assumed
-to live in the same directory as the ``tutorial.ini`` file. We'll
-need to create this file in order to get authentication working.
+We'll add a ``login`` view which renders a login form and processes
+the post from the login form, checking credentials.
-Adding a ``who.ini`` File
--------------------------
+We'll also add a ``logout`` view to our application and provide a link
+to it. This view will clear the credentials of the logged in user and
+redirect back to the front page.
-We'll create a file in our package directory named ``who.ini``. It
-will have the following contents.
+We'll add a different file (for presentation convenience) to add login
+and logout views. Add a file to your application in the same
+directory as ``login.py`` with the following content:
-.. literalinclude:: src/authorization/who.ini
+.. literalinclude:: src/authorization/tutorial/login.py
:linenos:
- :language: ini
+ :language: python
-The ``[general]``, ``[identifiers]``, ``[authenticators]``, and
-``[challengers]`` section of this file are the meat of the
-configuration in this file.
+Changing Existing Views
+~~~~~~~~~~~~~~~~~~~~~~~
-The ``[general]`` Section
-~~~~~~~~~~~~~~~~~~~~~~~~~
+Then we need to change each opf our ``view_page``, ``edit_page`` and
+``add_page`` views to pass a "logged in" parameter into its template.
+We'll add something like this to each view body:
-The ``[general]`` section configures the default "request classifier"
-and "challenge decider". For the purposes of this tutorial, it is not
-important that you understand these settings.
+.. code-block:: python
+ :linenos:
-The ``[identifiers]`` Section
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ logged_in = authenticated_user(context, request)
-The ``[identifiers]`` section configures the identifier plugins that
-will be used for this application. In our case, our identifiers are
-both the ``form`` plugin (configured above the ``[identifiers]``
-section within ``[plugin:form]``) and the ``auth_tkt`` plugin
-(configured above the ``[identifiers]`` section within
-``[plugin:auth_tkt]``. The ``form`` identifier will only be used when
-the request is a "browser request" (for example, it *won't* be used
-when the request is an XML-RPC request).
+We'll then change the return value of ``render_template_to_response``
+to pass the `resulting `logged_in`` value to the template, e.g.:
-The ``[authenticators]`` Section
+.. code-block:: python
+ :linenos:
+
+ return render_template_to_response('templates/view.pt',
+ request = request,
+ page = context,
+ content = content,
+ logged_in = logged_in,
+ edit_url = edit_url)
+
+Adding the ``login.pt`` Template
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The ``[authenticators]`` section configures the "authenticator"
-plugins that will be used in our setup. An authenticator plugin is
-one which checks a username and password provided by a user against a
-database of valid username/password combinations. We'll use an
-htpasswd file as this database. Since the ``htpasswd`` plugin
-requires a file, we'll need to add a ``wiki.passwd`` file to our
-``tutorial`` package with these contents:
+Add a ``login.pt`` template to your templates directory. It's
+referred to within the login view we just added to ``login.py``.
-.. literalinclude:: src/authorization/wiki.passwd
+.. literalinclude:: src/authorization/tutorial/templates/login.pt
:linenos:
- :language: ini
+ :language: xml
-The ``[challengers]`` Section
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Change ``view.pt`` and ``edit.pt``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The ``[challengers]`` section configures a "challenger" which is a
-``repoze.who`` plugin which displays a login form. We'll use the
-standard ``repoze.who.plugins.form`` plugin for this, configured
-within the ``[plugin:form]`` section of the file.
+We'll also need to change our ``edit.pt`` and ``view.pt`` templates to
+display a "Logout" link if someone is logged in. This link will
+invoke the logout view.
-The ``[plugin:*]`` Sections
----------------------------
+To do so we'll add this to both templates within the ``<div
+class="main_content">`` div:
-The ``[plugin:*]`` sections of the configuration file configure
-individual plugins used by the more general configuration sections
-(``[identifiers]``, ``[authenticators]``, ``[challengers]``). The
-``auth_tkt`` plugin is an identifier plugin which obtains credentials
-from a cookie, the ``form`` plugin is an identifier and challenger
-plugin which obtains credentials from a form post, the ``htpasswd``
-plugin is an authenticator plugin which checks credentials against
-valid usernames and files specified in an htpasswd file.
+.. code-block:: xml
+ :linenos:
-Configuring a ``repoze.bfg`` Authentication Policy
---------------------------------------------------
+ <span tal:condition="logged_in"><a href="${request.application_url}/logout">Logout</a></span>
-For any :mod:`repoze.bfg` application to perform authorization, we
-need to change our ``run.py`` module to add an :term:`authentication
-policy`. Adding an authentication policy causes the system to use
-authorization.
+Changing ``configure.zcml``
+~~~~~~~~~~~~~~~~~~~~~~~~~
-Change your run.py to import the ``RepozeWho1AuthenticationPolicy``
-from ``repoze.who.authentication``, construct an instance of the
-policy, and pass it as the ``authentication_policy`` argument to the
-``make_app`` function. When you're done, your application's
-``run.py`` will look like this.
+Change your application's ``configure.zcml`` to add a slightly
+inscrutable ``utility`` stanza. This configures our login view to
+show up when BFG detects that a view invocation can not be authorized.
+When you're done, your ``configure.zcml`` will look like so:
-.. literalinclude:: src/authorization/tutorial/run.py
+.. literalinclude:: src/authorization/tutorial/configure.zcml
:linenos:
- :language: python
+ :language: xml
Giving Our Root Model Object an ACL
-----------------------------------
@@ -248,61 +236,6 @@ our application in a browser. The views we'll try are as follows:
username ``editor``, password ``editor`` will show the edit page
form being displayed.
-Add A Logout View
--------------------
-
-We'll add a ``logout`` view to our application and provide a link to
-it. This view will clear the credentials of the logged in user and
-redirect back to the front page. The logout view will look someting
-like this:
-
-.. code-block:: python
- :linenos:
-
- @bfg_view(for_=Wiki, name='logout')
- def logout(context, request):
- identity = request.environ.get('repoze.who.identity')
- headers = []
- if identity is not None:
- auth_tkt = request.environ['repoze.who.plugins']['auth_tkt']
- headers = auth_tkt.forget(request.environ, identity)
- return HTTPFound(location = model_url(context, request),
- headers = headers)
-
-
-We'll also change our ``edit.pt`` template to display a "Logout" link
-if someone is logged in. This link will invoke the logout view.
-
-To do so we'll add this to both templates within the ``<div
-class="main_content">`` div:
-
-.. code-block:: xml
- :linenos:
-
- <span tal:condition="logged_in"><a href="${request.application_url}/logout">Logout</a></span>
-
-Then we need to change each opf our ``view_page``, ``edit_page`` and
-``add_page`` views to pass a "logged in" parameter into its template.
-We'll add something like this to each view body:
-
-.. code-block:: python
- :linenos:
-
- logged_in = 'repoze.who.identity' in request.environ
-
-We'll then change the return value of ``render_template_to_response``
-to pass the `resulting `logged_in`` value to the template, e.g.:
-
-.. code-block:: python
- :linenos:
-
- return render_template_to_response('templates/view.pt',
- request = request,
- page = context,
- content = content,
- logged_in = logged_in,
- edit_url = edit_url)
-
Seeing Our Changes To ``views.py`` and our Templates
----------------------------------------------------
diff --git a/docs/tutorials/bfgwiki/src/authorization/setup.py b/docs/tutorials/bfgwiki/src/authorization/setup.py
index 6d300b473..b289ca8b0 100644
--- a/docs/tutorials/bfgwiki/src/authorization/setup.py
+++ b/docs/tutorials/bfgwiki/src/authorization/setup.py
@@ -15,7 +15,6 @@ requires = [
'ZODB3',
'repoze.zodbconn',
'repoze.tm',
- 'repoze.who',
]
setup(name='tutorial',
diff --git a/docs/tutorials/bfgwiki/src/authorization/tutorial.ini b/docs/tutorials/bfgwiki/src/authorization/tutorial.ini
index d30aa2672..181682585 100644
--- a/docs/tutorials/bfgwiki/src/authorization/tutorial.ini
+++ b/docs/tutorials/bfgwiki/src/authorization/tutorial.ini
@@ -8,16 +8,11 @@ debug_authorization = false
debug_notfound = false
zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000
-[filter:who]
-use = egg:repoze.who#config
-config_file = %(here)s/who.ini
-
[pipeline:main]
pipeline =
egg:repoze.zodbconn#closer
egg:Paste#evalerror
egg:repoze.tm#tm
- who
zodb
[server:main]
diff --git a/docs/tutorials/bfgwiki/src/authorization/tutorial/configure.zcml b/docs/tutorials/bfgwiki/src/authorization/tutorial/configure.zcml
index b1501597d..df11c18b1 100644
--- a/docs/tutorials/bfgwiki/src/authorization/tutorial/configure.zcml
+++ b/docs/tutorials/bfgwiki/src/authorization/tutorial/configure.zcml
@@ -5,4 +5,7 @@
<scan package="."/>
+ <utility provides="repoze.bfg.interfaces.IForbiddenResponseFactory"
+ component=".login.login"/>
+
</configure>
diff --git a/docs/tutorials/bfgwiki/src/authorization/tutorial/login.py b/docs/tutorials/bfgwiki/src/authorization/tutorial/login.py
new file mode 100644
index 000000000..c4c595e81
--- /dev/null
+++ b/docs/tutorials/bfgwiki/src/authorization/tutorial/login.py
@@ -0,0 +1,43 @@
+from webob.exc import HTTPFound
+
+from repoze.bfg.chameleon_zpt import render_template_to_response
+from repoze.bfg.security import remember
+from repoze.bfg.security import forget
+from repoze.bfg.view import bfg_view
+from repoze.bfg.url import model_url
+
+from tutorial.models import Wiki
+from tutorial.run import USERS
+
+@bfg_view(for_=Wiki, name='login')
+def login(context, request):
+ referrer = request.environ.get('HTTP_REFERER', '/')
+ came_from = request.params.get('came_from', referrer)
+ message = ''
+ login = ''
+ password = ''
+ if 'form.submitted' in request.params:
+ login = request.params['login']
+ password = request.params['password']
+ if USERS.get(login) == password:
+ headers = remember(context, request, login)
+ return HTTPFound(location = came_from,
+ headers = headers)
+ message = 'Failed login'
+
+ return render_template_to_response(
+ 'templates/login.pt',
+ message = message,
+ url = request.application_url + '/login',
+ came_from = came_from,
+ login = login,
+ password = password,
+ request =request,
+ )
+
+@bfg_view(for_=Wiki, name='logout')
+def logout(context, request):
+ headers = forget(context, request)
+ return HTTPFound(location = model_url(context, request),
+ headers = headers)
+
diff --git a/docs/tutorials/bfgwiki/src/authorization/tutorial/run.py b/docs/tutorials/bfgwiki/src/authorization/tutorial/run.py
index 45920615f..a5d0cf39c 100644
--- a/docs/tutorials/bfgwiki/src/authorization/tutorial/run.py
+++ b/docs/tutorials/bfgwiki/src/authorization/tutorial/run.py
@@ -1,5 +1,5 @@
from repoze.bfg.router import make_app
-from repoze.bfg.authentication import RepozeWho1AuthenticationPolicy
+from repoze.bfg.authentication import AuthTktAuthenticationPolicy
from repoze.zodbconn.finder import PersistentApplicationFinder
@@ -15,8 +15,17 @@ def app(global_config, **kw):
if zodb_uri is None:
raise ValueError("No 'zodb_uri' in application configuration.")
- authpolicy = RepozeWho1AuthenticationPolicy()
+ authpolicy = AuthTktAuthenticationPolicy('seekr!t', callback=groupfinder)
get_root = PersistentApplicationFinder(zodb_uri, appmaker)
return make_app(get_root, tutorial, authentication_policy=authpolicy,
options=kw)
+
+USERS = {'editor':'editor',
+ 'viewer':'viewer'}
+GROUPS = {'editor':['group.editors']}
+
+def groupfinder(userid):
+ if userid in USERS:
+ return GROUPS.get(userid, [])
+
diff --git a/docs/tutorials/bfgwiki/src/authorization/tutorial/templates/login.pt b/docs/tutorials/bfgwiki/src/authorization/tutorial/templates/login.pt
new file mode 100644
index 000000000..a9e086461
--- /dev/null
+++ b/docs/tutorials/bfgwiki/src/authorization/tutorial/templates/login.pt
@@ -0,0 +1,32 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
+
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
+ <title>bfg tutorial wiki (based on TurboGears 20-Minute Wiki)</title>
+ <link rel="stylesheet" type="text/css"
+ href="${request.application_url}/static/style.css" />
+</head>
+
+<body>
+
+<h1>Log In</h1>
+
+<div tal:replace="message"/>
+
+<div class="main_content">
+ <form action="${url}" method="post">
+ <input type="hidden" name="came_from" value="${came_from}"/>
+ <input type="text" name="login" value="${login}"/>
+ <br/>
+ <input type="password" name="password" value="${password}"/>
+ <br/>
+ <input type="submit" name="form.submitted" value="Log In"/>
+ </form>
+</div>
+
+</body>
+</html>
diff --git a/docs/tutorials/bfgwiki/src/authorization/tutorial/templates/view.pt b/docs/tutorials/bfgwiki/src/authorization/tutorial/templates/view.pt
index cae6940c2..3c5cc2a33 100644
--- a/docs/tutorials/bfgwiki/src/authorization/tutorial/templates/view.pt
+++ b/docs/tutorials/bfgwiki/src/authorization/tutorial/templates/view.pt
@@ -17,7 +17,7 @@
<div style="float:right; width: 10em;"> Viewing
<span tal:replace="page.__name__">Page Name Goes Here</span> <br/>
You can return to the <a href="${request.application_url}">FrontPage</a>.
- <span tal:condition="logged_in"><a href="${request.application_url}/logout">Logout</a></span>
+<span tal:condition="logged_in"><a href="${request.application_url}/logout">Logout</a></span>
</div>
<div tal:replace="structure content">Page text goes here.</div>
diff --git a/docs/tutorials/bfgwiki/src/authorization/tutorial/views.py b/docs/tutorials/bfgwiki/src/authorization/tutorial/views.py
index 7beab58b0..1d3e57de3 100644
--- a/docs/tutorials/bfgwiki/src/authorization/tutorial/views.py
+++ b/docs/tutorials/bfgwiki/src/authorization/tutorial/views.py
@@ -4,6 +4,9 @@ import re
from webob.exc import HTTPFound
from repoze.bfg.url import model_url
from repoze.bfg.chameleon_zpt import render_template_to_response
+
+from repoze.bfg.security import authenticated_userid
+
from repoze.bfg.view import static
from repoze.bfg.view import bfg_view
@@ -41,7 +44,7 @@ def view_page(context, request):
content = wikiwords.sub(check, content)
edit_url = model_url(context, request, 'edit_page')
- logged_in = 'repoze.who.identity' in request.environ
+ logged_in = authenticated_userid(context, request)
return render_template_to_response('templates/view.pt',
request = request,
@@ -88,15 +91,4 @@ def edit_page(context, request):
save_url = model_url(context, request,
'edit_page')
)
-
-
-@bfg_view(for_=Wiki, name='logout')
-def logout(context, request):
- identity = request.environ.get('repoze.who.identity')
- headers = []
- if identity is not None:
- auth_tkt = request.environ['repoze.who.plugins']['auth_tkt']
- headers = auth_tkt.forget(request.environ, identity)
- return HTTPFound(location = model_url(context, request),
- headers = headers)
-
+
diff --git a/docs/tutorials/bfgwiki/src/authorization/who.ini b/docs/tutorials/bfgwiki/src/authorization/who.ini
deleted file mode 100644
index 73d820b3d..000000000
--- a/docs/tutorials/bfgwiki/src/authorization/who.ini
+++ /dev/null
@@ -1,40 +0,0 @@
-[plugin:form]
-# identification and challenge
-use = repoze.who.plugins.form:make_plugin
-login_form_qs = __do_login
-rememberer_name = auth_tkt
-
-[plugin:auth_tkt]
-# identification
-use = repoze.who.plugins.auth_tkt:make_plugin
-secret = s33kr1t
-cookie_name = oatmeal
-secure = False
-include_ip = False
-
-[plugin:htpasswd]
-# authentication
-use = repoze.who.plugins.htpasswd:make_plugin
-filename = %(here)s/wiki.passwd
-check_fn = repoze.who.plugins.htpasswd:plain_check
-
-[general]
-request_classifier = repoze.who.classifiers:default_request_classifier
-challenge_decider = repoze.who.classifiers:default_challenge_decider
-
-[identifiers]
-# plugin_name;classifier_name:.. or just plugin_name (good for any)
-plugins =
- form;browser
- auth_tkt
-
-[authenticators]
-# plugin_name;classifier_name.. or just plugin_name (good for any)
-plugins =
- htpasswd
-
-[challengers]
-# plugin_name;classifier_name:.. or just plugin_name (good for any)
-plugins =
- form
-
diff --git a/docs/tutorials/bfgwiki/src/authorization/wiki.passwd b/docs/tutorials/bfgwiki/src/authorization/wiki.passwd
deleted file mode 100644
index c9cd6fe83..000000000
--- a/docs/tutorials/bfgwiki/src/authorization/wiki.passwd
+++ /dev/null
@@ -1 +0,0 @@
-editor:editor