.. _api_narrative:
|
|
Using the :mod:`repoze.who` Application Programming Interface (API)
|
===================================================================
|
|
.. _without_middleware:
|
|
Using :mod:`repoze.who` without Middleware
|
------------------------------------------
|
|
An application which does not use the :mod:`repoze.who` middleware needs
|
to perform two separate tasks to use :mod:`repoze.who` machinery:
|
|
- At application startup, it must create an :class:`repoze.who.api:APIFactory`
|
instance, populating it with a request classifier, a challenge decider,
|
and a set of plugins. It can do this process imperatively
|
(see :ref:`imperative_configuration`), or using a declarative
|
configuration file (see :ref:`declarative_configuration`). For the latter
|
case, there is a convenience function,
|
:func:`repoze.who.config.make_api_factory_with_config`:
|
|
.. code-block:: python
|
|
# myapp/run.py
|
from repoze.who.config import make_api_factory_with_config
|
who_api_factory = None
|
def startup(global_conf):
|
global who_api_factory
|
who_api_factory = make_api_factory_with_config(global_conf,
|
'/path/to/who.config')
|
|
- When it needs to use the API, it must call the ``APIFactory``, passing
|
the WSGI environment to it. The ``APIFactory`` returns an object
|
implementing the :class:`repoze.who.interfaces:IRepozeWhoAPI` interface.
|
|
.. code-block:: python
|
|
# myapp/views.py
|
from myapp.run import who_api_factory
|
def my_view(context, request):
|
who_api = who_api_factory(request.environ)
|
|
- Calling the ``APIFactory`` multiple times within the same request is
|
allowed, and should be very cheap (the API object is cached in the
|
request environment).
|
|
|
.. _middleware_api_hybrid:
|
|
Mixed Use of :mod:`repoze.who` Middleware and API
|
-------------------------------------------------
|
|
An application which uses the :mod:`repoze.who` middleware may still need
|
to interact directly with the ``IRepozeWhoAPI`` object for some purposes.
|
In such cases, it should call :func:`repoze.who.api:get_api`, passing
|
the WSGI environment.
|
|
.. code-block:: python
|
|
from repoze.who.api import get_api
|
def my_view(context, request):
|
who_api = get_api(request.environ)
|
|
Alternately, the application might configure the ``APIFactory`` at startup,
|
as above, and then use it to find the API object, or create it if it was
|
not already created for the current request (e.g. perhaps by the middleware):
|
|
.. code-block:: python
|
|
def my_view(context, request):
|
who_api = context.who_api_factory(request.environ)
|
|
|
.. _writing_custom_login_view:
|
|
Writing a Custom Login View
|
---------------------------
|
|
:class:`repoze.who.api.API` provides a helper method to assist developers
|
who want to control the details of the login view. The following
|
BFG example illustrates how this API might be used:
|
|
.. code-block:: python
|
:linenos:
|
|
def login_view(context, request):
|
message = ''
|
|
who_api = get_api(request.environ)
|
if 'form.login' in request.POST:
|
creds = {}
|
creds['login'] = request.POST['login']
|
creds['password'] = request.POST['password']
|
authenticated, headers = who_api.login(creds)
|
if authenticated:
|
return HTTPFound(location='/', headers=headers)
|
|
message = 'Invalid login.'
|
else:
|
# Forcefully forget any existing credentials.
|
_, headers = who_api.login({})
|
|
request.response_headerlist = headers
|
if 'REMOTE_USER' in request.environ:
|
del request.environ['REMOTE_USER']
|
|
return {'message': message}
|
|
This application is written as a "hybrid": the :mod:`repoze.who` middleware
|
injects the API object into the WSGI enviornment on each request.
|
|
- In line 4, this application extracts the API object from the environ
|
using :func:`repoze.who.api:get_api`.
|
|
- Lines 6 - 8 fabricate a set of credentials, based on the values the
|
user entered in the form.
|
|
- In line 9, the application asks the API to authenticate those credentials,
|
returning an identity and a set of respones headers.
|
|
- Lines 10 and 11 handle the case of successful authentication: in this
|
case, the application redirects to the site root, setting the headers
|
returned by the API object, which will "remember" the user across requests.
|
|
- Line 13 is reached on failed login. In this case, the headers returned
|
in line 9 will be "forget" headers, clearing any existing cookies or other
|
tokens.
|
|
- Lines 14 - 16 perform a "fake" login, in order to get the "forget" headers.
|
|
- Line 18 sets the "forget" headers to clear any authenticated user for
|
subsequent requests.
|
|
- Lines 19 - 20 clear any authenticated user for the current request.
|
|
- Line 22 returns any message about a failed login to the rendering template.
|
|
|
.. _interfaces:
|
|
Interfaces
|
----------
|
|
.. automodule:: repoze.who.interfaces
|
|
.. autointerface:: IAPIFactory
|
:members:
|
|
.. autointerface:: IAPI
|
:members:
|
|
.. autointerface:: IPlugin
|
:members:
|
|
.. autointerface:: IRequestClassifier
|
:members:
|
|
.. autointerface:: IChallengeDecider
|
:members:
|
|
.. autointerface:: IIdentifier
|
:members:
|
|
.. autointerface:: IAuthenticator
|
:members:
|
|
.. autointerface:: IChallenger
|
:members:
|
|
.. autointerface:: IMetadataProvider
|
:members:
|