commit | author | age
|
d95e97
|
1 |
.. _api_narrative: |
TS |
2 |
|
|
3 |
Using the :mod:`repoze.who` Application Programming Interface (API) |
|
4 |
=================================================================== |
|
5 |
|
|
6 |
.. _without_middleware: |
|
7 |
|
|
8 |
Using :mod:`repoze.who` without Middleware |
|
9 |
------------------------------------------ |
|
10 |
|
|
11 |
An application which does not use the :mod:`repoze.who` middleware needs |
|
12 |
to perform two separate tasks to use :mod:`repoze.who` machinery: |
|
13 |
|
|
14 |
- At application startup, it must create an :class:`repoze.who.api:APIFactory` |
|
15 |
instance, populating it with a request classifier, a challenge decider, |
|
16 |
and a set of plugins. It can do this process imperatively |
|
17 |
(see :ref:`imperative_configuration`), or using a declarative |
a349a2
|
18 |
configuration file (see :ref:`declarative_configuration`). For the latter |
TS |
19 |
case, there is a convenience function, |
|
20 |
:func:`repoze.who.config.make_api_factory_with_config`: |
d95e97
|
21 |
|
cb7449
|
22 |
.. code-block:: python |
TS |
23 |
|
|
24 |
# myapp/run.py |
a349a2
|
25 |
from repoze.who.config import make_api_factory_with_config |
TS |
26 |
who_api_factory = None |
cb7449
|
27 |
def startup(global_conf): |
6663c7
|
28 |
global who_api_factory |
a349a2
|
29 |
who_api_factory = make_api_factory_with_config(global_conf, |
TS |
30 |
'/path/to/who.config') |
cb7449
|
31 |
|
d95e97
|
32 |
- When it needs to use the API, it must call the ``APIFactory``, passing |
TS |
33 |
the WSGI environment to it. The ``APIFactory`` returns an object |
|
34 |
implementing the :class:`repoze.who.interfaces:IRepozeWhoAPI` interface. |
|
35 |
|
cb7449
|
36 |
.. code-block:: python |
TS |
37 |
|
|
38 |
# myapp/views.py |
|
39 |
from myapp.run import who_api_factory |
|
40 |
def my_view(context, request): |
|
41 |
who_api = who_api_factory(request.environ) |
|
42 |
|
d95e97
|
43 |
- Calling the ``APIFactory`` multiple times within the same request is |
cb7449
|
44 |
allowed, and should be very cheap (the API object is cached in the |
TS |
45 |
request environment). |
d95e97
|
46 |
|
TS |
47 |
|
|
48 |
.. _middleware_api_hybrid: |
|
49 |
|
|
50 |
Mixed Use of :mod:`repoze.who` Middleware and API |
|
51 |
------------------------------------------------- |
|
52 |
|
|
53 |
An application which uses the :mod:`repoze.who` middleware may still need |
|
54 |
to interact directly with the ``IRepozeWhoAPI`` object for some purposes. |
|
55 |
In such cases, it should call :func:`repoze.who.api:get_api`, passing |
|
56 |
the WSGI environment. |
|
57 |
|
cb7449
|
58 |
.. code-block:: python |
TS |
59 |
|
|
60 |
from repoze.who.api import get_api |
|
61 |
def my_view(context, request): |
|
62 |
who_api = get_api(request.environ) |
|
63 |
|
|
64 |
Alternately, the application might configure the ``APIFactory`` at startup, |
6663c7
|
65 |
as above, and then use it to find the API object, or create it if it was |
TS |
66 |
not already created for the current request (e.g. perhaps by the middleware): |
cb7449
|
67 |
|
TS |
68 |
.. code-block:: python |
|
69 |
|
|
70 |
def my_view(context, request): |
|
71 |
who_api = context.who_api_factory(request.environ) |
|
72 |
|
|
73 |
|
9a8e60
|
74 |
.. _writing_custom_login_view: |
TS |
75 |
|
|
76 |
Writing a Custom Login View |
|
77 |
--------------------------- |
|
78 |
|
|
79 |
:class:`repoze.who.api.API` provides a helper method to assist developers |
|
80 |
who want to control the details of the login view. The following |
|
81 |
BFG example illustrates how this API might be used: |
|
82 |
|
|
83 |
.. code-block:: python |
|
84 |
:linenos: |
|
85 |
|
|
86 |
def login_view(context, request): |
|
87 |
message = '' |
|
88 |
|
|
89 |
who_api = get_api(request.environ) |
|
90 |
if 'form.login' in request.POST: |
|
91 |
creds = {} |
|
92 |
creds['login'] = request.POST['login'] |
|
93 |
creds['password'] = request.POST['password'] |
|
94 |
authenticated, headers = who_api.login(creds) |
|
95 |
if authenticated: |
|
96 |
return HTTPFound(location='/', headers=headers) |
|
97 |
|
|
98 |
message = 'Invalid login.' |
|
99 |
else: |
|
100 |
# Forcefully forget any existing credentials. |
|
101 |
_, headers = who_api.login({}) |
|
102 |
|
|
103 |
request.response_headerlist = headers |
|
104 |
if 'REMOTE_USER' in request.environ: |
|
105 |
del request.environ['REMOTE_USER'] |
|
106 |
|
|
107 |
return {'message': message} |
|
108 |
|
|
109 |
This application is written as a "hybrid": the :mod:`repoze.who` middleware |
|
110 |
injects the API object into the WSGI enviornment on each request. |
|
111 |
|
|
112 |
- In line 4, this application extracts the API object from the environ |
|
113 |
using :func:`repoze.who.api:get_api`. |
|
114 |
|
|
115 |
- Lines 6 - 8 fabricate a set of credentials, based on the values the |
|
116 |
user entered in the form. |
|
117 |
|
|
118 |
- In line 9, the application asks the API to authenticate those credentials, |
|
119 |
returning an identity and a set of respones headers. |
|
120 |
|
|
121 |
- Lines 10 and 11 handle the case of successful authentication: in this |
|
122 |
case, the application redirects to the site root, setting the headers |
|
123 |
returned by the API object, which will "remember" the user across requests. |
|
124 |
|
|
125 |
- Line 13 is reached on failed login. In this case, the headers returned |
|
126 |
in line 9 will be "forget" headers, clearing any existing cookies or other |
|
127 |
tokens. |
|
128 |
|
|
129 |
- Lines 14 - 16 perform a "fake" login, in order to get the "forget" headers. |
|
130 |
|
|
131 |
- Line 18 sets the "forget" headers to clear any authenticated user for |
|
132 |
subsequent requests. |
|
133 |
|
|
134 |
- Lines 19 - 20 clear any authenticated user for the current request. |
|
135 |
|
|
136 |
- Line 22 returns any message about a failed login to the rendering template. |
|
137 |
|
|
138 |
|
d95e97
|
139 |
.. _interfaces: |
TS |
140 |
|
|
141 |
Interfaces |
|
142 |
---------- |
|
143 |
|
12dd40
|
144 |
.. automodule:: repoze.who.interfaces |
d95e97
|
145 |
|
12dd40
|
146 |
.. autointerface:: IAPIFactory |
TS |
147 |
:members: |
d95e97
|
148 |
|
12dd40
|
149 |
.. autointerface:: IAPI |
TS |
150 |
:members: |
d95e97
|
151 |
|
12dd40
|
152 |
.. autointerface:: IPlugin |
TS |
153 |
:members: |
d95e97
|
154 |
|
12dd40
|
155 |
.. autointerface:: IRequestClassifier |
TS |
156 |
:members: |
d95e97
|
157 |
|
12dd40
|
158 |
.. autointerface:: IChallengeDecider |
TS |
159 |
:members: |
d95e97
|
160 |
|
12dd40
|
161 |
.. autointerface:: IIdentifier |
TS |
162 |
:members: |
d95e97
|
163 |
|
12dd40
|
164 |
.. autointerface:: IAuthenticator |
TS |
165 |
:members: |
d95e97
|
166 |
|
12dd40
|
167 |
.. autointerface:: IChallenger |
TS |
168 |
:members: |
d95e97
|
169 |
|
12dd40
|
170 |
.. autointerface:: IMetadataProvider |
TS |
171 |
:members: |