Projet

Général

Profil

0001-authenticators-add-easy-accesible-OU-based-on-servic.patch

Benjamin Dauvergne, 10 octobre 2019 19:27

Télécharger (5,57 ko)

Voir les différences:

Subject: [PATCH] authenticators: add easy accesible OU based on service's ACL
 (#36783)

It replaces changes from #35213. OU are added after OU remembered
through cookies; they are ordered based on their user subset's count
(how many of their users can access the targeted service).
 src/authentic2/authenticators.py       | 45 ++++++++++++++++++--------
 src/authentic2/forms/authentication.py |  4 +--
 tests/test_login.py                    |  7 +++-
 3 files changed, 40 insertions(+), 16 deletions(-)
src/authentic2/authenticators.py
14 14
# You should have received a copy of the GNU Affero General Public License
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17
from django.db.models import Count
17 18
from django.shortcuts import render
18 19
from django.utils.translation import ugettext as _, ugettext_lazy
19 20

  
......
35 36
    def id(self):
36 37
        return 'password'
37 38

  
39
    def get_service_ous(self, request):
40
        service_slug = request.GET.get(constants.SERVICE_FIELD_NAME)
41
        if not service_slug:
42
            return []
43
        roles = Role.objects.filter(allowed_services__slug=service_slug).children()
44
        if not roles:
45
            return []
46
        service_ou_ids = []
47
        qs = User.objects.filter(roles__in=roles).values_list('ou').annotate(count=Count('ou')).order_by('-count')
48
        for ou_id, count in qs:
49
            if not ou_id:
50
                continue
51
            service_ou_ids.append(ou_id)
52
        if not service_ou_ids:
53
            return []
54
        return OU.objects.filter(pk__in=service_ou_ids)
55

  
56
    def get_preferred_ous(self, request):
57
        preferred_ous_cookie = utils.get_remember_cookie(request, 'preferred-ous')
58
        preferred_ous = []
59
        if preferred_ous_cookie:
60
            preferred_ous.extend(OU.objects.filter(pk__in=preferred_ous_cookie))
61
        # for the special case of services open to only one OU, pre-select it
62
        for ou in self.get_service_ous(request):
63
            if ou in preferred_ous:
64
                continue
65
            preferred_ous.append(ou)
66
        return preferred_ous
67

  
38 68
    def login(self, request, *args, **kwargs):
39 69
        service_slug = request.GET.get(constants.SERVICE_FIELD_NAME)
40 70
        context = kwargs.get('context', {})
......
45 75

  
46 76
        # Special handling when the form contains an OU selector
47 77
        if app_settings.A2_LOGIN_FORM_OU_SELECTOR:
48
            default_ou = None
49
            # for the special case of services open to only one OU, pre-select it
50
            if service_slug:
51
                roles = Role.objects.filter(allowed_services__slug=service_slug).children()
52
                ous = OU.objects.filter(id__in=User.objects.filter(roles__in=roles).values_list('ou_id', flat=True))
53
                if len(ous) == 1:
54
                    default_ou = ous[0]
55
            preferred_ous = utils.get_remember_cookie(request, 'preferred-ous')
78
            preferred_ous = self.get_preferred_ous(request)
56 79
            if preferred_ous:
57
                preferred_ous = OU.objects.filter(pk__in=preferred_ous)
58
            if not default_ou and preferred_ous:
59
                default_ou = preferred_ous[0]
60
            if default_ou:
61
                initial['ou'] = default_ou
80
                initial['ou'] = preferred_ous[0]
62 81

  
63 82
        form = authentication_forms.AuthenticationForm(
64 83
            request=request,
src/authentic2/forms/authentication.py
58 58
        else:
59 59
            if preferred_ous:
60 60
                choices = self.fields['ou'].choices
61
                new_choices = [
61
                new_choices = list(choices)[:1] + [
62 62
                    (ugettext('Preferred organizational units'), [
63 63
                        (ou.pk, ou.name) for ou in preferred_ous]),
64
                    (ugettext('All organizational units'), list(choices)),
64
                    (ugettext('All organizational units'), list(choices)[1:]),
65 65
                ]
66 66
                self.fields['ou'].choices = new_choices
67 67

  
tests/test_login.py
189 189
    response = app.get('/login/?service=service')
190 190
    assert response.pyquery.find('select#id_ou option[selected]')[0].text == u'Default organizational unit'
191 191

  
192
    # user is added to role_ou1, now the OU of the only user is selected
192
    # user is added to role_ou1, default for user is still selected
193 193
    user_ou1.roles.add(role_ou1)
194 194
    response = app.get('/login/?service=service')
195
    assert response.pyquery.find('select#id_ou option[selected]')[0].text == u'Default organizational unit'
196

  
197
    # Clear cookies, OU1 is selected
198
    app.cookiejar.clear()
199
    response = app.get('/login/?service=service')
195 200
    assert response.pyquery.find('select#id_ou option[selected]')[0].text == u'OU1'
196 201

  
197 202
    # if we change the user's ou, then default selected OU changes
198
-