Explorar el Código

HUE-7624 [core] Support multi-authentication with AllowFirstUserDjangoBackend and LdapBackend

Ying Chen hace 8 años
padre
commit
eb50610947

+ 18 - 3
desktop/core/src/desktop/auth/forms.py

@@ -18,7 +18,7 @@
 import datetime
 
 from django.conf import settings
-from django.contrib.auth import authenticate
+from django.contrib.auth import authenticate, get_backends
 from django.contrib.auth.models import User
 from django.contrib.auth.forms import AuthenticationForm as AuthAuthenticationForm, UserCreationForm as AuthUserCreationForm
 from django.forms import CharField, TextInput, PasswordInput, ChoiceField, ValidationError
@@ -29,11 +29,26 @@ from desktop import conf
 from useradmin.password_policy import get_password_validators
 
 
+def get_backend_names():
+  return get_backends and [backend.__class__.__name__ for backend in get_backends()]
+
+def is_active_directory():
+  return 'LdapBackend' in get_backend_names() and \
+                          (bool(conf.LDAP.NT_DOMAIN.get()) or bool(conf.LDAP.LDAP_SERVERS.get()) or conf.LDAP.LDAP_URL.get() is not None)
+
+def get_ldap_server_keys():
+  return [(ldap_server_record_key) for ldap_server_record_key in conf.LDAP.LDAP_SERVERS.get()]
+
 def get_server_choices():
   if conf.LDAP.LDAP_SERVERS.get():
-    return [(ldap_server_record_key, ldap_server_record_key) for ldap_server_record_key in conf.LDAP.LDAP_SERVERS.get()]
+    auth_choices = [(ldap_server_record_key, ldap_server_record_key) for ldap_server_record_key in conf.LDAP.LDAP_SERVERS.get()]
   else:
-    return [('LDAP', 'LDAP')]
+    auth_choices = [('LDAP', 'LDAP')]
+
+  if is_active_directory() and 'AllowFirstUserDjangoBackend' in get_backend_names():
+    auth_choices.append(('Local', _('Local')))
+
+  return auth_choices
 
 
 class AuthenticationForm(AuthAuthenticationForm):

+ 5 - 7
desktop/core/src/desktop/auth/views.py

@@ -80,19 +80,17 @@ def first_login_ever():
   return False
 
 
-def get_backend_names():
-  return get_backends and [backend.__class__.__name__ for backend in get_backends()]
-
-
 @login_notrequired
 @watch_login
 def dt_login(request, from_modal=False):
   redirect_to = request.REQUEST.get('next', '/')
   is_first_login_ever = first_login_ever()
-  backend_names = get_backend_names()
-  is_active_directory = 'LdapBackend' in backend_names and ( bool(LDAP.NT_DOMAIN.get()) or bool(LDAP.LDAP_SERVERS.get()) )
+  backend_names = auth_forms.get_backend_names()
+  is_active_directory = auth_forms.is_active_directory()
+  is_ldap_option_selected = 'server' not in request.POST or request.POST['server'] == 'LDAP' \
+                            or request.POST['server'] in auth_forms.get_ldap_server_keys()
 
-  if is_active_directory:
+  if is_active_directory and is_ldap_option_selected:
     UserCreationForm = auth_forms.LdapUserCreationForm
     AuthenticationForm = auth_forms.LdapAuthenticationForm
   else:

+ 66 - 0
desktop/core/src/desktop/auth/views_test.py

@@ -539,6 +539,72 @@ class TestMultipleBackendLogin(PseudoHdfsTestBase):
     assert_true(self.fs.exists("/user/%s" % self.test_username))
 
 
+class TestMultipleBackendLoginNoHadoop(object):
+  reset = []
+  test_username = "test_mlogin_no_hadoop"
+
+  @classmethod
+  def setup_class(cls):
+    # Simulate first login ever
+    User.objects.all().delete()
+
+    cls.ldap_backend = django_auth_ldap_backend.LDAPBackend
+    django_auth_ldap_backend.LDAPBackend = MockLdapBackend
+
+    # Override auth backend, settings are only loaded from conf at initialization so we can't use set_for_testing
+    cls.auth_backends = settings.AUTHENTICATION_BACKENDS
+    settings.AUTHENTICATION_BACKENDS = (['desktop.auth.backend.LdapBackend', 'desktop.auth.backend.AllowFirstUserDjangoBackend'])
+
+    # Need to recreate LdapBackend class with new monkey patched base class
+    reload(backend)
+
+  @classmethod
+  def teardown_class(cls):
+    django_auth_ldap_backend.LDAPBackend = cls.ldap_backend
+
+    settings.AUTHENTICATION_BACKENDS = cls.auth_backends
+
+    reload(backend)
+
+  def setUp(self):
+    self.c = Client()
+    self.reset.append( conf.AUTH.BACKEND.set_for_testing(['AllowFirstUserDjangoBackend', 'LdapBackend']) )
+    self.reset.append(conf.LDAP.LDAP_URL.set_for_testing('does not matter'))
+
+  def tearDown(self):
+    User.objects.all().delete()
+
+    for finish in self.reset:
+      finish()
+
+  def test_login(self):
+    response = self.c.get('/hue/accounts/login/')
+    assert_equal(200, response.status_code, "Expected ok status.")
+    assert_true(response.context['first_login_ever'])
+
+    response = self.c.post('/hue/accounts/login/', {
+        'username': self.test_username,
+        'password': "ldap1",
+        'password1': "ldap1",
+        'password2': "ldap1",
+        'server': "Local"
+    })
+    assert_equal(302, response.status_code, "Expected ok redirect status.")
+
+    response = self.c.get('/hue/accounts/login/')
+    assert_equal(200, response.status_code, "Expected ok status.")
+    assert_false(response.context['first_login_ever'])
+
+    self.c.get('/accounts/logout')
+
+    response = self.c.post('/hue/accounts/login/', {
+        'username': self.test_username,
+        'password': "ldap1",
+        'server': "LDAP"
+    })
+    assert_equal(200, response.status_code, "Expected ok status.")
+
+
 class TestLogin(PseudoHdfsTestBase):
 
   reset = []