remember 5 last selected ous on login form (#35209)

This commit is contained in:
Benjamin Dauvergne 2019-08-02 13:53:46 +02:00
parent ab5ee3179b
commit 0fd98047ee
5 changed files with 99 additions and 4 deletions

View File

@ -17,6 +17,7 @@
from django.shortcuts import render
from django.utils.translation import ugettext as _, ugettext_lazy
from authentic2.a2_rbac.models import OrganizationalUnit as OU
from . import views, app_settings, utils, constants
from .forms import authentication as authentication_forms
@ -37,7 +38,17 @@ class LoginPasswordAuthenticator(object):
context = kwargs.get('context', {})
is_post = request.method == 'POST' and self.submit_name in request.POST
data = request.POST if is_post else None
form = authentication_forms.AuthenticationForm(request=request, data=data)
preferred_ous = utils.get_remember_cookie(request, 'preferred-ous')
if preferred_ous:
preferred_ous = OU.objects.filter(pk__in=preferred_ous)
initial = {}
if preferred_ous:
initial['ou'] = preferred_ous[0]
form = authentication_forms.AuthenticationForm(
request=request,
data=data,
initial=initial,
preferred_ous=preferred_ous)
if app_settings.A2_ACCEPT_EMAIL_AUTHENTICATION:
form.fields['username'].label = _('Username or email')
if app_settings.A2_USERNAME_LABEL:
@ -54,8 +65,11 @@ class LoginPasswordAuthenticator(object):
if form.cleaned_data.get('remember_me'):
request.session['remember_me'] = True
request.session.set_expiry(app_settings.A2_USER_REMEMBER_ME)
return utils.login(request, form.get_user(), how,
service_slug=request.GET.get(constants.SERVICE_FIELD_NAME))
response = utils.login(request, form.get_user(), how,
service_slug=request.GET.get(constants.SERVICE_FIELD_NAME))
if 'ou' in form.fields:
utils.prepend_remember_cookie(request, response, 'preferred-ous', form.cleaned_data['ou'].pk)
return response
context['form'] = form
return render(request, 'authentic2/login_password_form.html', context)

View File

@ -17,7 +17,7 @@
import math
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext_lazy as _, ugettext
from django.contrib.auth import forms as auth_forms
from django.utils import html
@ -41,7 +41,10 @@ class AuthenticationForm(auth_forms.AuthenticationForm):
queryset=OU.objects.all())
def __init__(self, *args, **kwargs):
preferred_ous = kwargs.pop('preferred_ous', [])
super(AuthenticationForm, self).__init__(*args, **kwargs)
self.exponential_backoff = ExponentialRetryTimeout(
key_prefix='login-exp-backoff-',
duration=app_settings.A2_LOGIN_EXPONENTIAL_RETRY_TIMEOUT_DURATION,
@ -52,6 +55,15 @@ class AuthenticationForm(auth_forms.AuthenticationForm):
if not app_settings.A2_LOGIN_FORM_OU_SELECTOR:
del self.fields['ou']
else:
if preferred_ous:
choices = self.fields['ou'].choices
new_choices = [
(ugettext('Preferred organizational units'), [
(ou.pk, ou.name) for ou in preferred_ous]),
(ugettext('All organizational units'), list(choices)),
]
self.fields['ou'].choices = new_choices
if self.request:
self.remote_addr = self.request.META['REMOTE_ADDR']

View File

@ -1152,3 +1152,30 @@ def gettid():
def authenticate(request=None, **kwargs):
# Compatibility layer with Django 1.8
return dj_authenticate(request=request, **kwargs)
def get_remember_cookie(request, name, count=5):
value = request.COOKIES.get(name)
if not value:
return []
try:
parsed = value.split()
except Exception:
return []
values = []
for i, v in zip(range(count), parsed):
try:
values.append(int(v))
except ValueError:
return []
return values
def prepend_remember_cookie(request, response, name, value, count=5):
values = get_remember_cookie(request, name, count=count)
values = [value] + values[:count - 1]
response.set_cookie(name, ' '.join(map(str, values)),
max_age=86400 * 365, # keep preferences for 1 year
path=request.path,
httponly=True)

View File

@ -141,6 +141,7 @@ def test_ou_selector(app, settings, simple_user, ou1):
# Check selector is here and there are no errors
assert not response.pyquery('.errorlist')
assert response.pyquery.find('select#id_ou')
assert len(response.pyquery.find('select#id_ou optgroup')) == 0
assert (set([elt.text for elt in response.pyquery.find('select#id_ou option')])
== set([u'Default organizational unit', u'OU1', u'---------']))
# Check selector is required
@ -160,3 +161,14 @@ def test_ou_selector(app, settings, simple_user, ou1):
response.form.set('ou', str(simple_user.ou.pk))
response = response.form.submit(name='login-password-submit').follow()
assert '_auth_user_id' in app.session
response = response.click('Logout').maybe_follow()
assert '_auth_user_id' not in app.session
assert app.cookies['preferred-ous'] == str(simple_user.ou.pk)
# Check last ou is preselected and shown first
response = app.get('/login/')
assert response.pyquery.find('select#id_ou')
assert len(response.pyquery.find('select#id_ou optgroup')) == 2
assert (set([elt.text for elt in response.pyquery.find('select#id_ou option')])
== set([u'Default organizational unit', u'OU1', u'---------']))
assert response.pyquery.find('select#id_ou option[selected]')[0].text == u'Default organizational unit'

View File

@ -86,3 +86,33 @@ def test_get_authentication_events_hows(rf, simple_user):
assert 'password' not in [ev['how'] for ev in get_authentication_events(request)]
login(request, user, 'password')
assert 'password' in [ev['how'] for ev in get_authentication_events(request)]
def test_remember_cookie(rf):
from authentic2.utils import get_remember_cookie, prepend_remember_cookie
from django.http import HttpResponse
request = rf.get('/')
request.COOKIES['preferrence'] = '1 2'
assert get_remember_cookie(request, 'preferrence') == [1, 2]
request.COOKIES['preferrence'] = '1 2 3 4 5 6'
assert get_remember_cookie(request, 'preferrence') == [1, 2, 3, 4, 5]
request.COOKIES['preferrence'] = '1 2 3 4 x'
assert get_remember_cookie(request, 'preferrence') == []
request.COOKIES['preferrence'] = 'aaa'
assert get_remember_cookie(request, 'preferrence') == []
response = HttpResponse()
request.COOKIES['preferrence'] = '1 2'
prepend_remember_cookie(request, response, 'preferrence', 4)
assert response.cookies['preferrence'].value == '4 1 2'
response = HttpResponse()
request.COOKIES['preferrence'] = '1 2 a'
prepend_remember_cookie(request, response, 'preferrence', 4)
assert response.cookies['preferrence'].value == '4'
response = HttpResponse()
request.COOKIES['preferrence'] = '1 2 3 4 5'
prepend_remember_cookie(request, response, 'preferrence', 7)
assert response.cookies['preferrence'].value == '7 1 2 3 4'