David Tulloh
2016-04-19 b70ba392164791f87deb20260188425ba868c864
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: