Merge auth branch.
- Legacy-Id: 1426
This commit is contained in:
parent
26b7eb2f7b
commit
3904c34055
|
@ -1,20 +1,33 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from ietf.ietfauth.models import LegacyLiaisonUser, LegacyWgPassword
|
||||
from ietf.idtracker.models import IESGLogin
|
||||
|
||||
for u in User.objects.all():
|
||||
output = {}
|
||||
|
||||
# we use pseudo-polymorphism to get through all of these objects.
|
||||
for p in list( IESGLogin.objects.all() ) + \
|
||||
list( LegacyLiaisonUser.objects.all() ) + \
|
||||
list( LegacyWgPassword.objects.all() ):
|
||||
# Bad rows in these tables use bad references.
|
||||
if p.person_id == 0 or p.person_id == 999999 or p.person_id == 888888:
|
||||
continue
|
||||
# Skip if we've already output this person
|
||||
if p.login_name in output:
|
||||
continue
|
||||
output[ p.login_name ] = 1
|
||||
if p.person.usermap_set.count() != 1:
|
||||
print "# Can't find user mapping for %s" % p.login_name
|
||||
continue
|
||||
usermap = p.person.usermap_set.all()[0]
|
||||
u = usermap.user
|
||||
( algo, salt, hsh ) = u.password.split( '$' )
|
||||
if algo != 'htdigest':
|
||||
continue
|
||||
# Note: not everyone needs the username one.
|
||||
# Old IESG members and some liaison users do.
|
||||
# Too much work for now to skip the ones that
|
||||
# don't need it.
|
||||
print "%s:IETF:%s" % ( u.username, hsh )
|
||||
try:
|
||||
htdigest = u.get_profile().email_htdigest
|
||||
if htdigest != '':
|
||||
print "%s:IETF:%s" % ( u.email, htdigest )
|
||||
except ObjectDoesNotExist:
|
||||
pass
|
||||
if p.login_name == u.username:
|
||||
print "%s:IETF:%s" % ( u.username, hsh )
|
||||
elif p.login_name == u.email:
|
||||
print "%s:IETF:%s" % ( u.email, usermap.email_htdigest )
|
||||
else:
|
||||
print "# Can't find user mapping for %s (%s/%s)" % ( p.login_name, u.username, u.email )
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright The IETF Trust 2007, All Rights Reserved
|
||||
# Copyright The IETF Trust 2007, 2008, All Rights Reserved
|
||||
#
|
||||
# Import users from all different IETF authentication sources into
|
||||
# django. Map user names to people via the ietf.ietfauth.models.UserMap
|
||||
|
@ -21,9 +21,14 @@
|
|||
# - Liaison tool ('Users')
|
||||
# - Then look for email address
|
||||
#
|
||||
# The LegacyWgPassword table contains a plaintext password, which is
|
||||
# both unconscionable and very useful, as it lets us upgrade their
|
||||
# password to full htdigest style.
|
||||
#
|
||||
#
|
||||
from ietf.idtracker.models import PersonOrOrgInfo, IESGLogin, EmailAddress
|
||||
from ietf.ietfauth.models import LegacyWgPassword, LegacyLiaisonUser
|
||||
from ietf.ietfauth.auth import set_password
|
||||
from ietf.utils import users
|
||||
from django.core.validators import email_re
|
||||
from django.contrib.auth.models import Group
|
||||
|
@ -35,12 +40,17 @@ level2group = {
|
|||
1: 'IESG',
|
||||
2: 'ex-IESG',
|
||||
}
|
||||
if len(sys.argv) != 2:
|
||||
print "usage: import-users htpasswd"
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
f = open(sys.argv[1], 'r')
|
||||
line = f.readline()
|
||||
while line != '':
|
||||
(user, pw) = line.rstrip("\n").split(":")
|
||||
person = None
|
||||
wg = None
|
||||
# Some login names are a different E-Mail
|
||||
# address than the one stored in email_addresses.
|
||||
# If the login name looks like an email address
|
||||
|
@ -73,7 +83,7 @@ while line != '':
|
|||
pass
|
||||
if person is None and email:
|
||||
try:
|
||||
person = PersonOrOrgInfo.objects.distinct().get(emailaddress__address=user)
|
||||
person = PersonOrOrgInfo.objects.distinct().get(emailaddress__address__iexact=user)
|
||||
except PersonOrOrgInfo.DoesNotExist:
|
||||
pass
|
||||
except AssertionError:
|
||||
|
@ -83,6 +93,13 @@ while line != '':
|
|||
u = users.create_user(user, email, person, cryptpw=pw)
|
||||
except users.UserAlreadyExists, (msg, u):
|
||||
print "Already in system as %s when adding %s (%s)" % ( u.username, user, email )
|
||||
if not email_re.search( user ):
|
||||
# If the existing username looks like it's one we made up
|
||||
# (first_last), then change it to the one in the digest file.
|
||||
if "_" in u.username:
|
||||
print "Changing username from %s to %s" % ( u.username, user )
|
||||
u.username = user
|
||||
u.save()
|
||||
if iesg:
|
||||
try:
|
||||
group, created = Group.objects.get_or_create(name = level2group[iesg.user_level])
|
||||
|
@ -91,6 +108,9 @@ while line != '':
|
|||
if group:
|
||||
print "Adding %s to %s (user_level %d)" % (u.username, group.name, iesg.user_level)
|
||||
u.groups.add(group)
|
||||
if wg and wg.password:
|
||||
# Use the plaintext password
|
||||
set_password( u, wg.password )
|
||||
else:
|
||||
print "Could not map %s to person" % ( user )
|
||||
line = f.readline()
|
||||
|
|
|
@ -774,6 +774,11 @@ class EmailAddress(models.Model):
|
|||
#unique_together = (('email_priority', 'person_or_org'), )
|
||||
# with this, I get 'ChangeManipulator' object has no attribute 'isUniqueemail_priority_person_or_org'
|
||||
verbose_name_plural = 'Email addresses'
|
||||
class Admin:
|
||||
# Even though this is edit_inline, we want to be able
|
||||
# to search for email addresses.
|
||||
search_fields = [ 'address' ]
|
||||
list_display = ( 'person_or_org', 'address', 'type', 'priority' )
|
||||
|
||||
class PhoneNumber(models.Model):
|
||||
person_or_org = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag', edit_inline=models.TABULAR, num_in_admin=1)
|
||||
|
|
|
@ -53,7 +53,16 @@ class EmailBackend(ModelBackend):
|
|||
else:
|
||||
user = User.objects.get(username__iexact=username)
|
||||
except User.DoesNotExist:
|
||||
return None
|
||||
#
|
||||
# See if there's an IETF person with this address:
|
||||
try:
|
||||
usermap = UserMap.objects.distinct().get(person__emailaddress__address__iexact=username)
|
||||
except UserMap.DoesNotExist:
|
||||
return None
|
||||
except AssertionError:
|
||||
# multiple UserMaps, should never happen!
|
||||
return None
|
||||
user = usermap.user
|
||||
if compat_check_password(user, password):
|
||||
return user
|
||||
return None
|
||||
|
|
|
@ -14,7 +14,8 @@ class UserMap(models.Model):
|
|||
It also contains a text field for the user's hashed htdigest
|
||||
password. In order to allow logging in with either username
|
||||
or email address, we need to store two hashes. One is in the
|
||||
user model's password field, the other is here.
|
||||
user model's password field, the other is here. We also store
|
||||
a hashed version of just the email address for the RFC Editor.
|
||||
"""
|
||||
user = models.ForeignKey(User, raw_id_admin=True, core=True)
|
||||
# user should have unique=True, but that confuses the
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright The IETF Trust 2007, All Rights Reserved
|
||||
# Copyright The IETF Trust 2007, 2009, All Rights Reserved
|
||||
|
||||
from django.conf.urls.defaults import patterns
|
||||
from ietf.ietfauth import views
|
||||
|
@ -11,6 +11,7 @@ urlpatterns = patterns('django.contrib.auth.views',
|
|||
(r'^password_change/done/$', 'password_change_done'),
|
||||
)
|
||||
urlpatterns += patterns('',
|
||||
(r'^$', 'django.views.generic.simple.direct_to_template', {'template': 'registration/account_info.html'}),
|
||||
(r'^request/$', views.password_request),
|
||||
(r'^return/$', views.password_return),
|
||||
(r'^return/(?P<action>\w+)/$', 'django.views.generic.simple.direct_to_template', {'template': 'registration/action_done.html'}),
|
||||
|
|
|
@ -34,7 +34,9 @@
|
|||
<div id="content">
|
||||
{% if user.is_authenticated %}
|
||||
<span style="float: right; font-size: 80%;">Logged in as {{ user }} |
|
||||
<a href="/accounts/logout/">Log Out</a></span>
|
||||
<a href="{% url django.contrib.auth.views.logout %}">Log Out</a></span>
|
||||
{% else %}
|
||||
<span style="float: right; font-size: 80%;"><a href="{% url django.contrib.auth.views.login %}">Log In</a></span>
|
||||
{% endif %}
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
|
|
|
@ -3,12 +3,27 @@
|
|||
|
||||
{% block content %}
|
||||
<p>
|
||||
{% if me %}
|
||||
Hello, {{ me }}!
|
||||
<h1>Stuff I know about you:</h1>
|
||||
<h2>Internet Drafts that you Author</h2>
|
||||
<ul>
|
||||
{% for doc in me.idauthor_set.all %}
|
||||
<li>{{ doc.document.filename }}: {{ doc.document.status }} / {{ doc.document.idstate }}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
<h2>Username and Email Address for legacy tools:</h2>
|
||||
<dl>
|
||||
{% if me.iesglogin_set.count %}
|
||||
<dt>IESG I-D Tracker</dt>
|
||||
<dd>{{ me.iesglogin_set.all.0.login_name }}</dd>
|
||||
{% endif %}
|
||||
{% if me.legacywgpassword_set.count %}
|
||||
<dt>Working group chair tools (session request, proceedings, etc.)</dt>
|
||||
<dd>{{ me.legacywgpassword_set.all.0.login_name }}</dd>
|
||||
{% endif %}
|
||||
{% if me.legacyliaisonuser_set.count %}
|
||||
<dt>Liaison Manager</dt>
|
||||
<dd>{{ me.legacyliaisonuser_set.all.0.login_name }}</dd>
|
||||
{% endif %}
|
||||
<dt>Username (for other tools, including django)</dt>
|
||||
<dd>{{ user.username }}</dd>
|
||||
<dt>Email Address (for other tools, including django)</dt>
|
||||
<dd>{{ user.email }}</dd>
|
||||
</dl>
|
||||
<p>(A tool to allow you to change your username and/or email address is planned)</p>
|
||||
{% endblock %}
|
||||
|
|
24
ietf/templates/registration/account_info.html
Normal file
24
ietf/templates/registration/account_info.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
{# Copyright The IETF Trust 2009, All Rights Reserved #}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}IETF Account Information{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>IETF Account Information</h1>
|
||||
|
||||
<p>
|
||||
Starting at IETF 74, we have switched to a self-service username/password
|
||||
handling system. We attempted to retain your password, so try
|
||||
<a href="{% url django.contrib.auth.views.login %}">logging in</a>.
|
||||
If you can't find your password, you can
|
||||
<a href="{% url ietf.ietfauth.views.password_request %}">get a new one here</a>.
|
||||
If you don't have an account, you can
|
||||
<a href="{% url ietf.ietfauth.views.password_request %}">create one</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you find that even after you register an account, your tool access
|
||||
does not work (especially the historical cgi-based tools), please
|
||||
contact <a href="mailto:webtools@ietf.org">webtools@ietf.org</a>.
|
||||
</p>
|
||||
{% endblock %}
|
|
@ -1,11 +1,9 @@
|
|||
Hi,
|
||||
|
||||
Someone gave this email address as theirs when requesting a
|
||||
password change or new account at {{ site.name }}. If that
|
||||
was you, please visit this URL to continue the process:
|
||||
{% filter wordwrap:72 %}Someone gave this email address as theirs when requesting a password change or new account at {{ site.name }}. If that was you, please visit this URL to continue the process:{% endfilter %}
|
||||
|
||||
http://{{ site.domain }}{% url ietf.ietfauth.views.password_return %}?timestamp={{ timestamp }}&email={{ email|urlencode }}&hash={{ hash }}
|
||||
|
||||
This link is valid for {{ days }} days.
|
||||
This link is valid for {{ days }} days.
|
||||
|
||||
If that someone wasn't you, then you can ignore this email.
|
||||
If that someone wasn't you, then you can ignore this email.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright The IETF Trust 2007, All Rights Reserved
|
||||
# Copyright The IETF Trust 2007, 2009, All Rights Reserved
|
||||
|
||||
from django.conf.urls.defaults import patterns, include, handler404, handler500
|
||||
|
||||
|
@ -52,7 +52,7 @@ urlpatterns = patterns('',
|
|||
(r'^(?P<path>public|cgi-bin)/', include('ietf.redirects.urls')),
|
||||
(r'^ipr/', include('ietf.ipr.urls')),
|
||||
(r'^meeting/', include('ietf.meeting.urls')),
|
||||
(r'^accounts/', include('ietf.ietfauth.urls')),
|
||||
(r'^account/', include('ietf.ietfauth.urls')),
|
||||
(r'^doc/', include('ietf.idrfc.urls')),
|
||||
(r'^wg/', include('ietf.wginfo.urls')),
|
||||
|
||||
|
@ -75,6 +75,10 @@ urlpatterns = patterns('',
|
|||
|
||||
# Uncomment this for pre-approval tool for initial Internet-Drafts
|
||||
#(r'^wg/', include('ietf.wg.urls')),
|
||||
|
||||
# Django 0.96 hardcodes /accounts/profile/; we want to use
|
||||
# /account/profile.
|
||||
(r'accounts/profile/', 'django.views.generic.simple.redirect_to', { 'url': '/account/profile/' }),
|
||||
)
|
||||
|
||||
if settings.SERVER_MODE in ('development', 'test'):
|
||||
|
|
|
@ -58,9 +58,11 @@ def create_user(user, email, person, pw=None, cryptpw=None):
|
|||
u.last_name = person.last_name
|
||||
u.save()
|
||||
# make sure that the UserMap gets created
|
||||
umap, created = UserMap.objects.get_or_create(user = u)
|
||||
umap.person = person
|
||||
umap.save()
|
||||
umap, created = UserMap.objects.get_or_create(user = u,
|
||||
defaults={'person': person})
|
||||
if not created:
|
||||
umap.person = person
|
||||
umap.save()
|
||||
raise UserAlreadyExists("Already in system as %s when adding %s (%s)" % ( u.username, user, email ), u)
|
||||
else:
|
||||
if cryptpw:
|
||||
|
@ -72,9 +74,10 @@ def create_user(user, email, person, pw=None, cryptpw=None):
|
|||
set_password(u, pw)
|
||||
#print "Saving user: username='%s', email='%s'" % ( u.username, u.email )
|
||||
u.save()
|
||||
umap, created = UserMap.objects.get_or_create(user = u)
|
||||
umap.person = person
|
||||
umap.save()
|
||||
# get_or_create saves umap for us.
|
||||
umap, created = UserMap.objects.get_or_create(user = u,
|
||||
defaults={'person': person})
|
||||
if not created:
|
||||
umap.person = person
|
||||
umap.save()
|
||||
|
||||
return u
|
||||
|
|
Loading…
Reference in a new issue