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).
This commit is contained in:
parent
1a2cdb39af
commit
94f4ec8c7d
|
@ -14,6 +14,7 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.db.models import Count
|
||||
from django.shortcuts import render
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
|
@ -35,6 +36,35 @@ class LoginPasswordAuthenticator(object):
|
|||
def id(self):
|
||||
return 'password'
|
||||
|
||||
def get_service_ous(self, request):
|
||||
service_slug = request.GET.get(constants.SERVICE_FIELD_NAME)
|
||||
if not service_slug:
|
||||
return []
|
||||
roles = Role.objects.filter(allowed_services__slug=service_slug).children()
|
||||
if not roles:
|
||||
return []
|
||||
service_ou_ids = []
|
||||
qs = User.objects.filter(roles__in=roles).values_list('ou').annotate(count=Count('ou')).order_by('-count')
|
||||
for ou_id, count in qs:
|
||||
if not ou_id:
|
||||
continue
|
||||
service_ou_ids.append(ou_id)
|
||||
if not service_ou_ids:
|
||||
return []
|
||||
return OU.objects.filter(pk__in=service_ou_ids)
|
||||
|
||||
def get_preferred_ous(self, request):
|
||||
preferred_ous_cookie = utils.get_remember_cookie(request, 'preferred-ous')
|
||||
preferred_ous = []
|
||||
if preferred_ous_cookie:
|
||||
preferred_ous.extend(OU.objects.filter(pk__in=preferred_ous_cookie))
|
||||
# for the special case of services open to only one OU, pre-select it
|
||||
for ou in self.get_service_ous(request):
|
||||
if ou in preferred_ous:
|
||||
continue
|
||||
preferred_ous.append(ou)
|
||||
return preferred_ous
|
||||
|
||||
def login(self, request, *args, **kwargs):
|
||||
service_slug = request.GET.get(constants.SERVICE_FIELD_NAME)
|
||||
context = kwargs.get('context', {})
|
||||
|
@ -45,20 +75,9 @@ class LoginPasswordAuthenticator(object):
|
|||
|
||||
# Special handling when the form contains an OU selector
|
||||
if app_settings.A2_LOGIN_FORM_OU_SELECTOR:
|
||||
default_ou = None
|
||||
# for the special case of services open to only one OU, pre-select it
|
||||
if service_slug:
|
||||
roles = Role.objects.filter(allowed_services__slug=service_slug).children()
|
||||
ous = OU.objects.filter(id__in=User.objects.filter(roles__in=roles).values_list('ou_id', flat=True))
|
||||
if len(ous) == 1:
|
||||
default_ou = ous[0]
|
||||
preferred_ous = utils.get_remember_cookie(request, 'preferred-ous')
|
||||
preferred_ous = self.get_preferred_ous(request)
|
||||
if preferred_ous:
|
||||
preferred_ous = OU.objects.filter(pk__in=preferred_ous)
|
||||
if not default_ou and preferred_ous:
|
||||
default_ou = preferred_ous[0]
|
||||
if default_ou:
|
||||
initial['ou'] = default_ou
|
||||
initial['ou'] = preferred_ous[0]
|
||||
|
||||
form = authentication_forms.AuthenticationForm(
|
||||
request=request,
|
||||
|
|
|
@ -58,10 +58,10 @@ class AuthenticationForm(auth_forms.AuthenticationForm):
|
|||
else:
|
||||
if preferred_ous:
|
||||
choices = self.fields['ou'].choices
|
||||
new_choices = [
|
||||
new_choices = list(choices)[:1] + [
|
||||
(ugettext('Preferred organizational units'), [
|
||||
(ou.pk, ou.name) for ou in preferred_ous]),
|
||||
(ugettext('All organizational units'), list(choices)),
|
||||
(ugettext('All organizational units'), list(choices)[1:]),
|
||||
]
|
||||
self.fields['ou'].choices = new_choices
|
||||
|
||||
|
|
|
@ -189,9 +189,14 @@ def test_ou_selector(app, settings, simple_user, ou1, ou2, user_ou1, role_ou1):
|
|||
response = app.get('/login/?service=service')
|
||||
assert response.pyquery.find('select#id_ou option[selected]')[0].text == u'Default organizational unit'
|
||||
|
||||
# user is added to role_ou1, now the OU of the only user is selected
|
||||
# user is added to role_ou1, default for user is still selected
|
||||
user_ou1.roles.add(role_ou1)
|
||||
response = app.get('/login/?service=service')
|
||||
assert response.pyquery.find('select#id_ou option[selected]')[0].text == u'Default organizational unit'
|
||||
|
||||
# Clear cookies, OU1 is selected
|
||||
app.cookiejar.clear()
|
||||
response = app.get('/login/?service=service')
|
||||
assert response.pyquery.find('select#id_ou option[selected]')[0].text == u'OU1'
|
||||
|
||||
# if we change the user's ou, then default selected OU changes
|
||||
|
|
Loading…
Reference in New Issue