auth: Require the realm_name field in RegistrationForm.

Previously, the only required field in RegistrationForm was the full
name (and possibly ToS, depending on settings).  This meant that if
LDAP was configured, realm creation would break, because the form
would be valid the first time one landed on it, before the user even
filled it out!

The correct fix is to make the extra fields required in
RegistrationForm in the event that we're doing realm creation.

It's possible that a cleaner fix would be to use a subclass.

With a test from Umair Waheed Khan.

Fixes #5387.
This commit is contained in:
Tim Abbott 2017-06-15 10:24:46 -07:00
parent 57d26c1a66
commit 93ea4128ac
2 changed files with 71 additions and 1 deletions

View File

@ -57,7 +57,6 @@ class RegistrationForm(forms.Form):
# actually required for a realm
password = forms.CharField(widget=forms.PasswordInput, max_length=MAX_PASSWORD_LENGTH,
required=False)
realm_name = forms.CharField(max_length=Realm.MAX_REALM_NAME_LENGTH, required=False)
realm_subdomain = forms.CharField(max_length=Realm.MAX_REALM_SUBDOMAIN_LENGTH, required=False)
realm_org_type = forms.ChoiceField(((Realm.COMMUNITY, 'Community'),
(Realm.CORPORATE, 'Corporate')),
@ -74,6 +73,9 @@ class RegistrationForm(forms.Form):
super(RegistrationForm, self).__init__(*args, **kwargs)
if settings.TERMS_OF_SERVICE:
self.fields['terms'] = forms.BooleanField(required=True)
self.fields['realm_name'] = forms.CharField(
max_length=Realm.MAX_REALM_NAME_LENGTH,
required=realm_creation)
def clean_full_name(self):
# type: () -> Text

View File

@ -1506,6 +1506,74 @@ class UserSignUpTest(ZulipTestCase):
"newuser@zulip.com"],
result)
def test_realm_creation_through_ldap(self):
# type: () -> None
password = "testing"
email = "newuser@zulip.com"
subdomain = "zulip"
realm_name = "Zulip"
ldap_user_attr_map = {'full_name': 'fn', 'short_name': 'sn'}
ldap_patcher = patch('django_auth_ldap.config.ldap.initialize')
mock_initialize = ldap_patcher.start()
mock_ldap = MockLDAP()
mock_initialize.return_value = mock_ldap
mock_ldap.directory = {
'uid=newuser,ou=users,dc=zulip,dc=com': {
'userPassword': 'testing',
'fn': ['New User Name']
}
}
with patch('zerver.views.registration.get_subdomain', return_value=subdomain):
result = self.client_post('/register/', {'email': email})
self.assertEqual(result.status_code, 302)
self.assertTrue(result["Location"].endswith(
"/accounts/send_confirm/%s" % (email,)))
result = self.client_get(result["Location"])
self.assert_in_response("Check your email so we can get started.", result)
# Visit the confirmation link.
from django.core.mail import outbox
for message in reversed(outbox):
if email in message.to:
confirmation_link_pattern = re.compile(settings.EXTERNAL_HOST + "(\S+)>")
confirmation_url = confirmation_link_pattern.search(
message.body).groups()[0]
break
else:
raise AssertionError("Couldn't find a confirmation email.")
with self.settings(
POPULATE_PROFILE_VIA_LDAP=True,
LDAP_APPEND_DOMAIN='zulip.com',
AUTH_LDAP_BIND_PASSWORD='',
AUTH_LDAP_USER_ATTR_MAP=ldap_user_attr_map,
AUTHENTICATION_BACKENDS=('zproject.backends.ZulipLDAPAuthBackend',),
AUTH_LDAP_USER_DN_TEMPLATE='uid=%(user)s,ou=users,dc=zulip,dc=com',
TERMS_OF_SERVICE=False,
):
result = self.client_get(confirmation_url)
self.assertEqual(result.status_code, 200)
key = find_key_by_email(email),
confirmation = Confirmation.objects.get(confirmation_key=key[0])
prereg_user = confirmation.content_object
prereg_user.realm_creation = True
prereg_user.save()
result = self.submit_reg_form_for_user(email,
password,
realm_name=realm_name,
realm_subdomain=subdomain,
from_confirmation='1',
# Pass HTTP_HOST for the target subdomain
HTTP_HOST=subdomain + ".testserver")
self.assert_in_success_response(["You're almost there.",
"newuser@zulip.com"],
result)
mock_ldap.reset()
mock_initialize.stop()