Project

General

Profile

0001-Enhance-get-backends-helper-function-and-registratio.patch

Mikaël Ates, 15 Jun 2016 09:34 AM

Download (10.9 KB)

View differences:

Subject: [PATCH 1/1] Enhance get backends helper function and registration
 frontend management.

 src/authentic2/registration_backend/views.py       | 10 ++--
 .../templates/registration/registration_form.html  | 11 +++-
 src/authentic2/utils.py                            | 50 ++++++++++++++---
 src/authentic2/views.py                            | 65 +++++++---------------
 4 files changed, 77 insertions(+), 59 deletions(-)
src/authentic2/registration_backend/views.py
68 68
        request_context.push(ctx)
69 69
        if django.VERSION >= (1, 8, 0):
70 70
            request_context['add_to_blocks'] = collections.defaultdict(lambda: [])
71
        registration_frontends = utils.accumulate_from_backends(self.request,
72
                                                                'registration_frontend',
73
                                                                context_instance=request_context)
74
        request_context['registration_frontends'] = registration_frontends
71
        parameters = {'request': self.request,
72
                      'context_instance': request_context}
73
        blocks = [utils.get_backend_method(backend, 'registration', parameters)
74
                  for backend in utils.get_backends('AUTH_FRONTENDS')]
75
        request_context['frontends'] = collections.OrderedDict((block['id'], block)
76
                                                               for block in blocks if block)
75 77
        return request_context
76 78

  
77 79

  
src/authentic2/templates/registration/registration_form.html
18 18
<form method="post">
19 19
  {% csrf_token %}
20 20
  {{ form.as_p }}
21

  
22 21
  <input type="submit" value="{% trans 'Submit' %}" />
23 22
</form>
24 23

  
25
{% for registration_frontend in registration_frontends %}
26
    {{ registration_frontend|safe }}
24
{% for id, block in frontends.items %}
25
  <div class="registration_frontend">
26
    <h2>{{ block.name }}</h2>
27
    <p>
28
      {{ block.content|safe }}
29
    </p>
30
  </div>
27 31
{% endfor %}
32

  
28 33
{% endblock %}
src/authentic2/utils.py
12 12

  
13 13
import django
14 14
from django.conf import settings
15
from django.http import HttpResponseRedirect
15
from django.http import HttpResponseRedirect, HttpResponse
16 16
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
17 17
from django.http.request import QueryDict
18 18
from django.contrib.auth import (REDIRECT_FIELD_NAME, login as auth_login, SESSION_KEY,
......
150 150

  
151 151

  
152 152
def get_backends(setting_name='IDP_BACKENDS'):
153
    '''Return the list of IdP backends'''
153
    '''Return the list of enabled cleaned backends.'''
154 154
    backends = []
155 155
    for backend_path in getattr(app_settings, setting_name):
156 156
        kwargs = {}
157 157
        if not isinstance(backend_path, six.string_types):
158 158
            backend_path, kwargs = backend_path
159 159
        backend = load_backend(backend_path)
160
        # If no enabled method is defined on the backend, backend enabled by default.
161
        if hasattr(backend, 'enabled') and not backend.enabled():
162
            continue
160 163
        kwargs_settings = getattr(app_settings, setting_name + '_KWARGS', {})
161 164
        if backend_path in kwargs_settings:
162 165
            kwargs.update(kwargs_settings[backend_path])
166
        # Clean id and name for legacy support
163 167
        if hasattr(backend, 'id'):
164
            if hasattr(backend.id, '__call__'):
165
                bid = backend.id()
166
            else:
167
                bid = backend.id
168
            if bid in kwargs_settings:
169
                kwargs.update(kwargs_settings[bid])
168
            if callable(backend.id):
169
                backend.id = backend.id()
170
        else:
171
            backend.id = None
172
        if hasattr(backend, 'name'):
173
            if callable(backend.name):
174
                backend.name = backend.name()
175
        else:
176
            backend.name = None
177
        if not hasattr(backend, 'priority'):
178
            backend.priority = 0
179
        if backend.id and backend.id in kwargs_settings:
180
            kwargs.update(kwargs_settings[backend.id])
170 181
        backend.__dict__.update(kwargs)
171 182
        backends.append(backend)
183
    # Order backends list with backend priority
184
    backends.sort(key=lambda backend: backend.priority)
172 185
    return backends
173 186

  
174 187

  
188
def get_backend_method(backend, method, parameters):
189
    if not hasattr(backend, method):
190
        return None
191
    content = response = getattr(backend, method)(**parameters)
192
    if not response:
193
        return None
194
    status_code = 200
195
    # Some backend methods return an HttpResponse, others return a string
196
    if isinstance(response, HttpResponse):
197
        content = response.content
198
        status_code = response.status_code
199
    return {
200
            'id': backend.id,
201
            'name': backend.name,
202
            'content': content,
203
            'response': response,
204
            'status_code': status_code,
205
            'backend': backend,
206
    }
207

  
208

  
175 209
def add_arg(url, key, value=None):
176 210
    '''Add a parameter to an URL'''
177 211
    key = urllib.quote(key)
src/authentic2/views.py
228 228

  
229 229
    frontends = utils.get_backends('AUTH_FRONTENDS')
230 230

  
231
    # set default priority and name
232
    for frontend in frontends:
233
        if hasattr(frontend.name, '__call__'):
234
            frontend.name = frontend.name()
235
        if not hasattr(frontend, 'priority'):
236
            frontend.priority = 0
237

  
238 231
    blocks = []
239 232

  
240 233
    context_instance = RequestContext(request, {
......
252 245

  
253 246
    # Create blocks
254 247
    for frontend in frontends:
255
        if not frontend.enabled():
256
            continue
257 248
        # Legacy API
258 249
        if not hasattr(frontend, 'login'):
259
            fid = frontend.id()
250
            fid = frontend.id
260 251
            name = frontend.name
261 252
            form_class = frontend.form()
262 253
            submit_name = 'submit-%s' % fid
......
276 267
                block['form'] = form_class()
277 268
            blocks.append(block)
278 269
        else: # New frontends API
279
            response = frontend.login(request,
280
                                      context_instance=context_instance)
281
            if not response:
282
                continue
283
            if response.status_code != 200:
284
                return response
285
            blocks.append({
286
                    'id': frontend.id(),
287
                    'name': frontend.name,
288
                    'content': response.content,
289
                    'frontend': frontend,
290
            })
270
            parameters = {'request': request,
271
                          'context_instance': context_instance}
272
            block = utils.get_backend_method(frontend, 'login', parameters)
273
            # If a login frontend method returns an HttpResponse with a status code != 200
274
            # this response is returned.
275
            if block:
276
                if block['status_code'] != 200:
277
                    return block['response']
278
                blocks.append(block)
291 279
        if hasattr(frontend, 'is_hidden'):
292 280
            blocks[-1]['is_hidden'] = frontend.is_hidden(request)
293 281
        else:
......
314 302

  
315 303
    request.session.set_test_cookie()
316 304

  
317
    # order blocks by their frontend priority
318
    blocks.sort(key=lambda block: block['frontend'].priority)
319

  
320 305
    # legacy context variable
321 306
    rendered_forms = [(block['name'], block['content']) for block in blocks]
322 307

  
......
356 341
        ctx = super(ProfileView, self).get_context_data(**kwargs)
357 342
        frontends = utils.get_backends('AUTH_FRONTENDS')
358 343

  
359
        # set default priority and name
360
        for frontend in frontends:
361
            if hasattr(frontend.name, '__call__'):
362
                frontend.name = frontend.name()
363
            if not hasattr(frontend, 'priority'):
364
                frontend.priority = 0
365
        frontends.sort(key=lambda f: f.priority)
366

  
367 344
        request = self.request
368 345

  
369 346
        context_instance = RequestContext(request, ctx)
......
371 348
            context_instance['add_to_blocks'] = collections.defaultdict(lambda: [])
372 349
        if request.method == "POST":
373 350
            for frontend in frontends:
374
                if not frontend.enabled():
375
                    continue
376
                if 'submit-%s' % frontend.id() in request.POST:
351
                if 'submit-%s' % frontend.id in request.POST:
377 352
                    form = frontend.form()(data=request.POST)
378 353
                    if form.is_valid():
379 354
                        if request.session.test_cookie_worked():
......
425 400
                value = map(unicode, value)
426 401
            if value or app_settings.A2_PROFILE_DISPLAY_EMPTY_FIELDS:
427 402
                profile.append((title, value))
403

  
428 404
        # Credentials management
429
        blocks = [ frontend.profile(request, context_instance=context_instance) for frontend in frontends \
430
                if hasattr(frontend, 'profile') and frontend.enabled() ]
431
        blocks_by_id = {}
432
        for frontend in frontends:
433
            if hasattr(frontend, 'profile') and frontend.enabled():
434
                blocks_by_id[frontend.id()] = \
435
                    {'name': frontend.name,
436
                     'content': frontend.profile(request, context_instance=context_instance)}
405
        parameters = {'request': request,
406
                      'context_instance': context_instance}
407
        profiles = [utils.get_backend_method(frontend, 'profile', parameters)
408
                            for frontend in frontends]
409
        # Old frontends data structure for templates
410
        blocks = [block['content'] for block in profiles if block]
411
        # New frontends data structure for templates
412
        blocks_by_id = collections.OrderedDict((block['id'], block) for block in profiles if block)
413

  
437 414
        idp_backends = utils.get_backends()
438 415
        # Get actions for federation management
439 416
        federation_management = []
440
-