Projet

Général

Profil

0001-remember-5-last-selected-ous-on-login-form-35209.patch

Benjamin Dauvergne, 02 août 2019 15:53

Télécharger (8,4 ko)

Voir les différences:

Subject: [PATCH] remember 5 last selected ous on login form (#35209)

 src/authentic2/authenticators.py       | 20 ++++++++++++++---
 src/authentic2/forms/authentication.py | 11 ++++++++++
 src/authentic2/utils.py                | 27 +++++++++++++++++++++++
 tests/test_login.py                    | 12 +++++++++++
 tests/test_utils.py                    | 30 ++++++++++++++++++++++++++
 5 files changed, 97 insertions(+), 3 deletions(-)
src/authentic2/authenticators.py
17 17
from django.shortcuts import render
18 18
from django.utils.translation import ugettext as _, ugettext_lazy
19 19

  
20
from authentic2.a2_rbac.models import OrganizationalUnit as OU
20 21
from . import views, app_settings, utils, constants
21 22
from .forms import authentication as authentication_forms
22 23

  
......
37 38
        context = kwargs.get('context', {})
38 39
        is_post = request.method == 'POST' and self.submit_name in request.POST
39 40
        data = request.POST if is_post else None
40
        form = authentication_forms.AuthenticationForm(request=request, data=data)
41
        preferred_ous = utils.get_remember_cookie(request, 'preferred-ous')
42
        if preferred_ous:
43
            preferred_ous = OU.objects.filter(pk__in=preferred_ous)
44
        initial = {}
45
        if preferred_ous:
46
            initial['ou'] = preferred_ous[0]
47
        form = authentication_forms.AuthenticationForm(
48
            request=request,
49
            data=data,
50
            initial=initial,
51
            preferred_ous=preferred_ous)
41 52
        if app_settings.A2_ACCEPT_EMAIL_AUTHENTICATION:
42 53
            form.fields['username'].label = _('Username or email')
43 54
        if app_settings.A2_USERNAME_LABEL:
......
54 65
                if form.cleaned_data.get('remember_me'):
55 66
                    request.session['remember_me'] = True
56 67
                    request.session.set_expiry(app_settings.A2_USER_REMEMBER_ME)
57
                return utils.login(request, form.get_user(), how,
58
                                   service_slug=request.GET.get(constants.SERVICE_FIELD_NAME))
68
                response = utils.login(request, form.get_user(), how,
69
                                       service_slug=request.GET.get(constants.SERVICE_FIELD_NAME))
70
                if 'ou' in form.fields:
71
                    utils.prepend_remember_cookie(request, response, 'preferred-ous', form.cleaned_data['ou'].pk)
72
                return response
59 73
        context['form'] = form
60 74
        return render(request, 'authentic2/login_password_form.html', context)
61 75

  
src/authentic2/forms/authentication.py
41 41
        queryset=OU.objects.all())
42 42

  
43 43
    def __init__(self, *args, **kwargs):
44
        preferred_ous = kwargs.pop('preferred_ous', [])
45

  
44 46
        super(AuthenticationForm, self).__init__(*args, **kwargs)
47

  
45 48
        self.exponential_backoff = ExponentialRetryTimeout(
46 49
            key_prefix='login-exp-backoff-',
47 50
            duration=app_settings.A2_LOGIN_EXPONENTIAL_RETRY_TIMEOUT_DURATION,
......
57 60
            self.remote_addr = self.request.META['REMOTE_ADDR']
58 61
        else:
59 62
            self.remote_addr = '0.0.0.0'
63
        if preferred_ous and 'ou' in self.fields:
64
            choices = self.fields['ou'].choices
65
            new_choices = [
66
                (_('Preferred organizational units'), [
67
                    (ou.pk, ou.name) for ou in preferred_ous]),
68
                (_('All organizational units'), list(choices)),
69
            ]
70
            self.fields['ou'].choices = new_choices
60 71

  
61 72
    def exp_backoff_keys(self):
62 73
        return self.cleaned_data['username'], self.remote_addr
src/authentic2/utils.py
1152 1152
def authenticate(request=None, **kwargs):
1153 1153
    # Compatibility layer with Django 1.8
1154 1154
    return dj_authenticate(request=request, **kwargs)
1155

  
1156

  
1157
def get_remember_cookie(request, name, count=5):
1158
    value = request.COOKIES.get(name)
1159
    if not value:
1160
        return []
1161
    try:
1162
        parsed = value.split()
1163
    except Exception:
1164
        return []
1165

  
1166
    values = []
1167
    for i, v in zip(range(count), parsed):
1168
        try:
1169
            values.append(int(v))
1170
        except ValueError:
1171
            return []
1172
    return values
1173

  
1174

  
1175
def prepend_remember_cookie(request, response, name, value, count=5):
1176
    values = get_remember_cookie(request, name, count=count)
1177
    values = [value] + values[:count - 1]
1178
    response.set_cookie(name, ' '.join(map(str, values)),
1179
                        max_age=86400 * 52,
1180
                        path=request.path,
1181
                        httponly=True)
tests/test_login.py
141 141
    # Check selector is here and there are no errors
142 142
    assert not response.pyquery('.errorlist')
143 143
    assert response.pyquery.find('select#id_ou')
144
    assert len(response.pyquery.find('select#id_ou optgroup')) == 0
144 145
    assert (set([elt.text for elt in response.pyquery.find('select#id_ou option')])
145 146
            == set([u'Default organizational unit', u'OU1', u'---------']))
146 147
    # Check selector is required
......
160 161
    response.form.set('ou', str(simple_user.ou.pk))
161 162
    response = response.form.submit(name='login-password-submit').follow()
162 163
    assert '_auth_user_id' in app.session
164
    response = response.click('Logout').maybe_follow()
165
    assert '_auth_user_id' not in app.session
166
    assert app.cookies['preferred-ous'] == '1'
167

  
168
    # Check last ou is preselected and shown first
169
    response = app.get('/login/')
170
    assert response.pyquery.find('select#id_ou')
171
    assert len(response.pyquery.find('select#id_ou optgroup')) == 2
172
    assert (set([elt.text for elt in response.pyquery.find('select#id_ou option')])
173
            == set([u'Default organizational unit', u'OU1', u'---------']))
174
    assert response.pyquery.find('select#id_ou option[selected]')[0].text == u'Default organizational unit'
tests/test_utils.py
86 86
    assert 'password' not in [ev['how'] for ev in get_authentication_events(request)]
87 87
    login(request, user, 'password')
88 88
    assert 'password' in [ev['how'] for ev in get_authentication_events(request)]
89

  
90

  
91
def test_remember_cookie(rf):
92
    from authentic2.utils import get_remember_cookie, prepend_remember_cookie
93
    from django.http import HttpResponse
94

  
95
    request = rf.get('/')
96
    request.COOKIES['preferrence'] = '1 2'
97
    assert get_remember_cookie(request, 'preferrence') == [1, 2]
98
    request.COOKIES['preferrence'] = '1 2 3 4 5 6'
99
    assert get_remember_cookie(request, 'preferrence') == [1, 2, 3, 4, 5]
100
    request.COOKIES['preferrence'] = '1 2 3 4 x'
101
    assert get_remember_cookie(request, 'preferrence') == []
102
    request.COOKIES['preferrence'] = 'aaa'
103
    assert get_remember_cookie(request, 'preferrence') == []
104

  
105
    response = HttpResponse()
106
    request.COOKIES['preferrence'] = '1 2'
107
    prepend_remember_cookie(request, response, 'preferrence', 4)
108
    assert response.cookies['preferrence'].value == '4 1 2'
109

  
110
    response = HttpResponse()
111
    request.COOKIES['preferrence'] = '1 2 a'
112
    prepend_remember_cookie(request, response, 'preferrence', 4)
113
    assert response.cookies['preferrence'].value == '4'
114

  
115
    response = HttpResponse()
116
    request.COOKIES['preferrence'] = '1 2 3 4 5'
117
    prepend_remember_cookie(request, response, 'preferrence', 7)
118
    assert response.cookies['preferrence'].value == '7 1 2 3 4'
89
-