Use LDAP-provided information if available for real names

If authoritative data is available from say the LDAP database, we now
ignore the POSTed user name, and don't offer it as a form field.

We fall back to giving the user a text field if they aren't in LDAP.

If users do not have any form fields to fill out, we simply bring them
to the app without the registration page, logging them in using a dummy
backend.

(imported from commit 6bee87430ba46ff753ea3408251e8a80c45c713f)
This commit is contained in:
Luke Faraone 2013-11-20 22:57:23 -05:00
parent af02e45a17
commit dff03fafda
4 changed files with 136 additions and 89 deletions

View File

@ -39,14 +39,18 @@ Form is validated both client-side using jquery-validate (see signup.js) and ser
<div class="control-group">
<label for="id_full_name" class="control-label">Full name</label>
<div class="controls">
{% if lock_name %}
<p class="fakecontrol">{{ full_name }}</p>
{% else %}
<input id="id_full_name" class="required" type="text" name="full_name"
value="{% if form.full_name.value %}{{ form.full_name.value }}{% elif full_name %}{{ full_name }}{% endif %}"
value="{% if full_name %}{{ full_name }}{% elif form.full_name.value %}{{ form.full_name.value }}{% endif %}"
maxlength="100" />
{% if form.full_name.errors %}
{% for error in form.full_name.errors %}
<div class="alert alert-error">{{ error }}</div>
{% endfor %}
{% endif %}
{% endif %}
</div>
</div>
{% if password_auth_enabled %}

View File

@ -247,32 +247,62 @@ def accounts_register(request):
except ValidationError:
return HttpResponseRedirect(reverse('django.contrib.auth.views.login') + '?email=' + urllib.quote_plus(email))
name_validated = False
full_name = None
if request.POST.get('from_confirmation'):
try:
del request.session['authenticated_full_name']
except KeyError:
pass
if domain == "mit.edu":
hesiod_name = compute_mit_user_fullname(email)
form = RegistrationForm(
initial={'full_name': hesiod_name if "@" not in hesiod_name else ""})
name_validated = True
elif settings.POPULATE_PROFILE_VIA_LDAP:
for backend in get_backends():
if isinstance(backend, LDAPBackend):
ldap_attrs = _LDAPUser(backend, backend.django_to_ldap_username(email)).attrs
# TODO: check if ldap_attributes are none
try:
request.session['authenticated_full_name'] = ldap_attrs[settings.AUTH_LDAP_USER_ATTR_MAP['full_name']][0]
name_validated = True
# We don't use initial= here, because if the form is
# complete (that is, no additional fields need to be
# filled out by the user) we want the form to validate,
# so they can be directly registered without having to
# go through this interstitial.
form = RegistrationForm(
initial={'full_name': ldap_attrs[
settings.AUTH_LDAP_USER_ATTR_MAP['full_name']
][0]})
{'full_name': request.session['authenticated_full_name']})
# FIXME: This will result in the user getting
# validation errors if they have to enter a password.
# Not relevant for ONLY_SSO, though.
break
except TypeError:
# Let the user fill out a name and/or try another backend
form = RegistrationForm()
else:
form = RegistrationForm()
else:
form = RegistrationForm(request.POST)
postdata = request.POST.copy()
if settings.NAME_CHANGES_DISABLED:
# If we populate profile information via LDAP and we have a
# verified name from you on file, use that. Otherwise, fall
# back to the full name in the request.
try:
postdata.update({'full_name': request.session['authenticated_full_name']})
name_validated = True
except KeyError:
pass
form = RegistrationForm(postdata)
if form.is_valid():
if password_auth_enabled():
password = form.cleaned_data['password']
else:
# SSO users don't need no passwords
password = None
full_name = form.cleaned_data['full_name']
short_name = email_to_username(email)
(realm, _) = Realm.objects.get_or_create(domain=domain)
@ -340,10 +370,9 @@ def accounts_register(request):
},
lambda event: None)
if settings.ONLY_SSO:
login(request, authenticate(remote_user=short_name if settings.SSO_APPEND_DOMAIN else email))
else:
login(request, authenticate(username=email, password=password))
# This logs you in using the ZulipDummyBackend, since honestly nothing
# more fancy than this is required.
login(request, authenticate(username=email, use_dummy_backend=True))
if first_in_realm:
assign_perm("administer", user_profile, user_profile.realm)
@ -356,7 +385,8 @@ def accounts_register(request):
'company_name': domain,
'email': email,
'key': key,
'full_name': request.POST.get('full_name', False),
'full_name': request.session.get('authenticated_full_name', None),
'lock_name': name_validated and settings.NAME_CHANGES_DISABLED
},
context_instance=RequestContext(request))

View File

@ -25,6 +25,18 @@ class ZulipAuthMixin(object):
except UserProfile.DoesNotExist:
return None
class ZulipDummyBackend(ZulipAuthMixin):
"""
Used when we want to log you in but we don't know which backend to use.
"""
def authenticate(self, username=None, use_dummy_backend=False):
if use_dummy_backend:
try:
return get_user_profile_by_email(username)
except UserProfile.DoesNotExist:
pass
return None
class EmailAuthBackend(ZulipAuthMixin):
"""
Email Authentication Backend

View File

@ -733,6 +733,7 @@ else:
HOME_NOT_LOGGED_IN = '/login'
ONLY_SSO = False
AUTHENTICATION_BACKENDS += ('guardian.backends.ObjectPermissionBackend',)
AUTHENTICATION_BACKENDS += ('zproject.backends.ZulipDummyBackend',)
POPULATE_PROFILE_VIA_LDAP = bool(AUTH_LDAP_BIND_DN)