Replaced old authentication/authorization system with new one (which uses Apache's authentication)

- Legacy-Id: 1877
This commit is contained in:
Pasi Eronen 2009-11-26 19:10:11 +00:00
parent 875b97e898
commit 11887ca938
20 changed files with 363 additions and 301 deletions

View file

@ -1,3 +1,22 @@
ietfdb (2.39)
* Replaced old authentication/authorization system with a new one
(which uses Apache's authentication). This requires applying
database fixups as follows:
cd /a/www/ietf-datatracker/2.39/ietf
PYTHONPATH=../ python manage.py dbshell < ../test/sql_fixup.sql
PYTHONPATH=../ python manage.py syncdb
And adding something like this to Apache configuration:
<LocationMatch "^/accounts/login/">
AuthType Basic
AuthName "IETF Datatracker"
AuthUserFile /a/www/htpasswd
Require valid-user
</LocationMatch>
ietfdb (2.38)
Miscellaneous minor fixes:

View file

@ -1,97 +1,111 @@
# Portions Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# * Neither the name of the Nokia Corporation and/or its
# subsidiary(-ies) nor the names of its contributors may be used
# to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Copyright The IETF Trust 2007, All Rights Reserved
from django.contrib.auth.backends import ModelBackend
from django.forms.fields import email_re
from django.contrib.auth.models import User
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from ietf.ietfauth.models import UserMap
import md5
from django.contrib.auth.backends import RemoteUserBackend
from django.contrib.auth.models import Group
from ietf.idtracker.models import IESGLogin, Role, PersonOrOrgInfo
from ietf.ietfauth.models import LegacyWgPassword, IetfUserProfile
def compat_check_password(user, raw_password):
"""
Returns a boolean of whether the raw_password was correct. Handles
crypt and htdigest formats, and updates the password to htdigest
on first use. This is like User.check_password().
"""
enc_password = user.password
algo, salt, hsh = enc_password.split('$')
if algo == 'crypt':
import crypt
is_correct = ( salt + hsh == crypt.crypt(raw_password, salt) )
if is_correct:
# upgrade to htdigest
set_password(user, raw_password)
return is_correct
if algo == 'htdigest':
# Check username hash.
is_correct = ( hsh == htdigest( user.username, raw_password ) )
if not is_correct:
# Try to check email hash, which we stored in the profile.
# If the profile doesn't exist, that's odd but we shouldn't
# completely fail, so try/except it.
try:
is_correct = ( user.get_profile().email_htdigest == htdigest( user.email, raw_password ) )
except ObjectDoesNotExist:
# no user profile to store the htdigest, so can't check it.
pass
return is_correct
# permit django passwords, but upgrade to htdigest
is_correct = user.check_password(raw_password)
if is_correct:
# upgrade to htdigest
set_password(user, raw_password)
return is_correct
from ietf.utils import log
# Based on http://www.djangosnippets.org/snippets/74/
# but modified to use compat_check_password for all users.
class EmailBackend(ModelBackend):
def authenticate(self, username=None, password=None):
try:
if email_re.search(username):
user = User.objects.get(email__iexact=username)
else:
user = User.objects.get(username__iexact=username)
except User.DoesNotExist:
#
# 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
class IetfUserBackend(RemoteUserBackend):
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
def find_groups(username):
"""
Role/Group:
Area_Director currently sitting AD
IETF_Chair currently sitting IETF Chair
IAB_Chair currently sitting IAB Chair
IRTF_Chair currently sitting IRTF Chair
Secretariat secretariat staff
def htdigest( username, password, realm=None ):
"""Returns a hashed password in the Apache htdigest format, which
is used in an AuthDigestFile ."""
if realm is None:
try:
realm = settings.DIGEST_REALM
except AttributeError:
realm = 'IETF'
return md5.md5( ':'.join( [ username, realm, password ] ) ).hexdigest()
Roles/Groups NOT YET IMPLEMENTED
WG_Chair currently sitting chair of some WG
IESG_Liaison non-ADs on iesg@ietf.org and telechats
Session_Chair chairing a non-WG session in IETF meeting
Ex_Area_Director past AD
"""
groups = []
try:
login = IESGLogin.objects.get(login_name=username)
if login.user_level == 1:
groups.append("Area_Director")
elif login.user_level == 0:
groups.append("Secretariat")
try:
person = login.person
for role in person.role_set.all():
if role.id == Role.IETF_CHAIR:
groups.append("IETF_Chair")
elif role.id == Role.IAB_CHAIR:
groups.append("IAB_Chair")
elif role.id == Role.IRTF_CHAIR:
groups.append("IRTF_Chair")
except PersonOrOrgInfo.DoesNotExist:
pass
except IESGLogin.DoesNotExist:
pass
#
# Additional sources of group memberships:
# - wg_password table
# - other Roles
# - the /etc/.../*.perms files
return groups
def set_password( user, password, realm=None ):
# The username-hashed digest goes in the user database;
# the email-address-hashed digest goes in the userprof.
user.password = '$'.join( [ 'htdigest', '',
htdigest( user.username, password, realm ) ] )
user.save()
( userprof, created ) = UserMap.objects.get_or_create( user=user )
userprof.email_htdigest = htdigest( user.email, password, realm )
userprof.rfced_htdigest = htdigest( user.email, password, 'RFC Editor' )
userprof.save()
find_groups = staticmethod(find_groups)
def authenticate(self, remote_user):
user = RemoteUserBackend.authenticate(self, remote_user)
if not user:
return user
# Create profile if it doesn't exist
try:
profile = user.get_profile()
except IetfUserProfile.DoesNotExist:
profile = IetfUserProfile(user=user)
profile.save()
# Update group memberships
group_names = IetfUserBackend.find_groups(user.username)
groups = []
for group_name in group_names:
# Create groups as needed
group,created = Group.objects.get_or_create(name=group_name)
if created:
log("IetfUserBackend created Group '%s'" % (group_name,))
groups.append(group)
user.groups = groups
return user
# changes done by convert-096.py:changed email_re import

View file

@ -1,30 +1,68 @@
# Portions Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# * Neither the name of the Nokia Corporation and/or its
# subsidiary(-ies) nor the names of its contributors may be used
# to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Copyright The IETF Trust 2007, All Rights Reserved
from django.db import models
from django.contrib.auth.models import User
from ietf.idtracker.models import PersonOrOrgInfo
from ietf.idtracker.models import PersonOrOrgInfo, IESGLogin
class UserMap(models.Model):
"""
This is a 1:1 mapping of django-user -> IETF user.
This can't represent the users in the existing tool that
have multiple accounts with multiple privilege levels: they
need extra IETF users.
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. We also store
a hashed version of just the email address for the RFC Editor.
"""
user = models.ForeignKey(User)
# user should have unique=True, but that confuses the
# admin edit_inline interface.
person = models.ForeignKey(PersonOrOrgInfo, unique=True, null=True)
email_htdigest = models.CharField(max_length=32, blank=True, null=True)
rfced_htdigest = models.CharField(max_length=32, blank=True, null=True)
def find_person(username):
try:
person = IESGLogin.objects.get(login_name=username).person
return person
except IESGLogin.DoesNotExist, PersonOrOrgInfo.DoesNotExist:
pass
# TODO: try LegacyWgPassword next
return None
class IetfUserProfile(models.Model):
user = models.ForeignKey(User,unique=True)
def person(self):
return find_person(self.user.username)
def iesg_login_id(self):
person = self.person()
if not person:
return None
try:
return person.iesglogin_set.all()[0].id
except:
return None
def __str__(self):
return "Mapping django user %s to IETF person %s" % ( self.user, self.person )
return "IetfUserProfile(%s)" % (self.user,)
######################################################

View file

@ -1,6 +1,98 @@
# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# * Neither the name of the Nokia Corporation and/or its
# subsidiary(-ies) nor the names of its contributors may be used
# to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from ietf.utils.test_utils import SimpleUrlTestCase
import unittest
from django.contrib.auth.models import User
from django.test.client import Client
from ietf.utils.test_utils import SimpleUrlTestCase, RealDatabaseTest
from ietf.idtracker.models import Role
from urlparse import urlsplit
class IetfAuthUrlTestCase(SimpleUrlTestCase):
def testUrls(self):
self.doTestUrls(__file__)
class IetfAuthTestCase(unittest.TestCase,RealDatabaseTest):
def setUp(self):
self.setUpRealDatabase()
def tearDown(self):
self.tearDownRealDatabase()
def _doLogin(self, username):
c = Client()
response = c.get('/accounts/login/', {}, False, REMOTE_USER=username)
self.assertEquals(response.status_code, 302)
nexturl = urlsplit(response['Location'])
self.assertEquals(nexturl[2], "/accounts/loggedin/")
response = c.get(nexturl[2], {}, False, REMOTE_USER=username)
self.assertEquals(response.status_code, 302)
nexturl = urlsplit(response['Location'])
self.assertEquals(nexturl[2], "/accounts/profile/")
response = c.get(nexturl[2], {}, False, REMOTE_USER=username)
self.assertEquals(response.status_code, 200)
self.assert_("Roles/Groups:" in response.content)
return response
def testLogin(self):
TEST_USERNAME = '__testuser'
print "Testing login with "+TEST_USERNAME
# Delete test user (if it exists)
try:
testuser = User.objects.get(username=TEST_USERNAME)
testuser.delete()
except User.DoesNotExist:
pass
self._doLogin(TEST_USERNAME)
# Delete test user after test
testuser = User.objects.get(username=TEST_USERNAME)
testuser.delete()
print "OK"
def testGroups(self):
print "Testing group assignment"
username = Role.objects.get(id=Role.IETF_CHAIR).person.iesglogin_set.all()[0].login_name
print "(with username "+str(username)+")"
self._doLogin(username)
user = User.objects.get(username=username)
groups = [x.name for x in user.groups.all()]
self.assert_("Area_Director" in groups)
self.assert_("IETF_Chair" in groups)
print "OK"

View file

@ -1 +1 @@
302 /account/profile/
302 /accounts/profile/

View file

@ -3,11 +3,8 @@
from django.conf.urls.defaults import patterns
from ietf.ietfauth import views
urlpatterns = patterns('django.contrib.auth.views',
(r'^login/$', 'login'),
(r'^logout/$', 'logout'),
)
urlpatterns += patterns('',
(r'^$', 'django.views.generic.simple.direct_to_template', {'template': 'registration/account_info.html'}),
(r'^profile/$', views.my)
urlpatterns = patterns('',
(r'^login/$', views.ietf_login),
(r'^loggedin/$', views.ietf_loggedin),
(r'^profile/$', views.profile)
)

View file

@ -1,17 +1,62 @@
# Portions Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# * Neither the name of the Nokia Corporation and/or its
# subsidiary(-ies) nor the names of its contributors may be used
# to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Copyright The IETF Trust 2007, All Rights Reserved
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponseRedirect, HttpResponse
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.conf import settings
from django.utils.http import urlquote
def ietf_login(request):
if not request.user.is_authenticated():
# This probably means an exception occured inside IetfUserBackend
return HttpResponse("Not authenticated?", status=500)
redirect_to = request.REQUEST.get(REDIRECT_FIELD_NAME, '')
request.session.set_test_cookie()
return HttpResponseRedirect('/accounts/loggedin/?%s=%s' % (REDIRECT_FIELD_NAME, urlquote(redirect_to)))
def ietf_loggedin(request):
if not request.session.test_cookie_worked():
return HttpResponse("You need to enable cookies")
request.session.delete_test_cookie()
redirect_to = request.REQUEST.get(REDIRECT_FIELD_NAME, '')
if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
redirect_to = settings.LOGIN_REDIRECT_URL
return HttpResponseRedirect(redirect_to)
@login_required
def my(request, addr=None):
try:
profile = request.user.get_profile()
person = profile.person
except ObjectDoesNotExist:
person = None
return render_to_response('registration/my.html', {
'me': person,
}, context_instance=RequestContext(request))
def profile(request):
return render_to_response('registration/profile.html', context_instance=RequestContext(request))

View file

@ -71,14 +71,10 @@ MEDIA_URL = ''
# Examples: "http://foo.com/media/", "/media/".
ADMIN_MEDIA_PREFIX = '/media/'
# Link django user to IETF user
AUTH_PROFILE_MODULE = 'ietfauth.UserMap'
# Allow specification of email address as username,
# and handle htpasswd crypt() format passwords.
AUTHENTICATION_BACKENDS = (
"ietf.ietfauth.auth.EmailBackend",
)
AUTH_PROFILE_MODULE = 'ietfauth.IetfUserProfile'
AUTHENTICATION_BACKENDS = ( "ietf.ietfauth.auth.IetfUserBackend", )
SESSION_COOKIE_AGE = 43200 # 12 hours
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
@ -91,6 +87,7 @@ MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.RemoteUserMiddleware',
'django.middleware.doc.XViewMiddleware',
# 'ietf.middleware.PrettifyMiddleware',
'ietf.middleware.SQLLogMiddleware',
@ -113,6 +110,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.request',
'ietf.context_processors.server_mode',
'ietf.context_processors.revision_info',
'ietf.context_processors.yui_url'
@ -186,8 +184,6 @@ else:
IPR_EMAIL_TO = ['ietf-ipr@ietf.org', ]
# The number of days for which a password-request URL is valid
PASSWORD_DAYS = 3
# Base URL for YUI library
YUI_URL = "https://ajax.googleapis.com/ajax/libs/yui"

View file

@ -32,10 +32,9 @@
<td class="column">
<div id="content">
{% if user.is_authenticated %}
<span style="float: right; font-size: 80%;">Logged in as {{ user }} |
<a href="{% url django.contrib.auth.views.logout %}">Log Out</a></span>
<span style="float: right; font-size: 80%;">Logged in as {{ user }}</span>
{% else %}
<span style="float: right; font-size: 80%;"><a href="{% url django.contrib.auth.views.login %}">Log In</a></span>
<span style="float: right; font-size: 80%;"><a href="/accounts/login/?next={{request.path|urlencode}}">Sign In</a></span>
{% endif %}
{% block content %}{% endblock %}
</div>

View file

@ -54,9 +54,9 @@ IETF = {};
</div>
<div id="ietf-login" style="position:absolute;top:8px;right:10px;">
{% if user.is_authenticated %}
{{ user }}&nbsp;|&nbsp;<a id="ietf-login-signout" href="javascript:signOut();">Sign out</a>
{{ user }}
{% else %}
<a id="ietf-login-signin" href="javascript:signIn();">Sign in</a>
<a href="/accounts/login/?next={{request.path|urlencode}}">Sign In</a>
{% endif %}
</div>

View file

@ -35,9 +35,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{% load wg_menu %}
{% load ietf_filters %}
<ul>
{% if user|in_group:"IESG" %}
<li class="sect first">IESG Dashboard</li>
<li><a href="/doc/ad/{{user.first_name|lower}}.{{user.last_name|lower}}/">My Documents (as AD)</a></li>
{% if user|in_group:"Area_Director" %}
<li class="sect first">AD Dashboard</li>
<li><a href="/doc/ad/{{user.get_profile.person.first_name|lower}}.{{user.get_profile.person.last_name|lower}}/">My Documents (as AD)</a></li>
<li><a href="/iesg/agenda/documents/">Reviews for next telechat</a></li>
<li><a href="/iesg/discusses/">Discusses</a></li>
</li>

View file

@ -1,19 +0,0 @@
{# 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>
Accounts for this system are created by the IETF secretariat.
<a href="{% url django.contrib.auth.views.login %}">Log in</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 %}

View file

@ -1,16 +0,0 @@
{% extends "base.html" %}
{% block title %}Manual Handling Required{% endblock %}
{% block content %}
<h1>Manual Handling Required</h1>
<p>We're sorry, but while the algorithms used to create accounts
automatically cover many IETF participants, they failed in your
case. If you use a different email address for IETF participation,
please use that one to create your account.</p>
<p>Please contact <a href="mailto:ietf-action@ietf.org">ietf-action@ietf.org</a>
for assistance with your account. Please share the steps that got you
to this page.</p>
{% endblock %}

View file

@ -1,9 +0,0 @@
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<h1>{{ title }}</h1>
<p>You have been logged out.</p>
{% endblock %}

View file

@ -1,22 +0,0 @@
{# Copyright The IETF Trust 2007, All Rights Reserved #}
{% extends "base.html" %}
{% block title %}Log In{% endblock %}
{% block content %}
<h1>Log In</h1>
{{ form.errors }}
{{ form.username.errors }}
<form method="post" action=".">
<table>
<tr><td><label for="id_username">Username (or email address):</label></td><td>{{ form.username }}</td></tr>
<tr><td><label for="id_password">Password:</label></td><td>{{ form.password }}</td></tr>
</table>
<input type="submit" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
{% endblock %}

View file

@ -1,29 +0,0 @@
{# Copyright The IETF Trust 2007, All Rights Reserved #}
{% extends "base.html" %}
{% block content %}
<p>
{% if me %}
Hello, {{ me }}!
{% 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 %}

View file

@ -0,0 +1,11 @@
{# Copyright The IETF Trust 2007, All Rights Reserved #}
{% extends "base.html" %}
{% block content %}
<h1>User information</h1>
<p>User name: {{ user.username }}<br />
Roles/Groups: {{ user.groups.all|join:", "|default:"(none)" }}<br />
Person: {{ user.get_profile.person|default:"?" }} {% if user.get_profile.person %}({{user.get_profile.person.person_or_org_tag}}){% endif %}<br />
IESG Login ID: {{ user.get_profile.iesg_login_id|default:"(none)" }} </p>
{% endblock %}

View file

@ -49,7 +49,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'^account/', include('ietf.ietfauth.urls')),
(r'^accounts/', include('ietf.ietfauth.urls')),
(r'^doc/', include('ietf.idrfc.urls')),
(r'^wg/', include('ietf.wginfo.urls')),
@ -57,10 +57,6 @@ urlpatterns = patterns('',
# Google webmaster tools verification url
(r'^googlea30ad1dacffb5e5b.html', 'django.views.generic.simple.direct_to_template', { 'template': 'googlea30ad1dacffb5e5b.html' }),
# Django 0.96 hardcodes /accounts/; we want to use
# /account/.
(r'^accounts/(?P<dir>\w+)/', 'django.views.generic.simple.redirect_to', { 'url': '/account/%(dir)s/' }),
)
if settings.SERVER_MODE in ('development', 'test'):

View file

@ -70,58 +70,3 @@ function showBallot(draftName, trackerId) {
}, null);
}
function signIn() {
document.cookie = "mytestcookie=worked; path=/";
if (document.cookie.length == 0) {
alert("You must enable cookies to sign in");
return;
}
// Initialize Django session cookie
YAHOO.util.Connect.asyncRequest('GET', '/account/login/', {}, null);
var onSuccess = function(o) {
if (o.status != 200) {
document.getElementById("signin_msg").innerHTML = o.statusText;
} else {
var t = o.responseText;
if (t.search("Please enter a correct username and password") >= 0) {
document.getElementById("signin_msg").innerHTML = "The username or password you entered is incorrect.";
} else if (t.search("Username and Email Address for legacy tools") >= 0) {
IETF.signinDialog.hide();
window.location.reload();
} else {
alert(t);
document.getElementById("signin_msg").innerHTML = "Internal error?";
}
}
};
var onFailure = function(o) {
document.getElementById("signin_msg").innerHTML = o.statusText;
};
var handleOk = function() {
document.getElementById("signin_msg").innerHTML = "Signing in...";
document.cookie = "testcookie=worked; path=/";
YAHOO.util.Connect.setForm(document.signin_form);
YAHOO.util.Connect.asyncRequest('POST',
'/account/login/', {success:onSuccess,failure:onFailure});
return false;
};
if (!IETF.signinDialog) {
var dialog = new YAHOO.widget.Panel("signin_dlg", {
draggable:false, modal:true,
width:"350px", fixedcenter:true, constraintoviewport:true });
var kl1 = new YAHOO.util.KeyListener(document, { keys: 27 }, function() { dialog.cancel();});
var kl2 = new YAHOO.util.KeyListener("signin_password", { keys: 13 }, function () { } );
dialog.cfg.queueProperty("keylisteners", [kl1,kl2]);
dialog.render();
YAHOO.util.Event.addListener(document.signin_form, "submit", handleOk);
var cancelButton = new YAHOO.widget.Button("signin_button2");
cancelButton.on("click", function() {dialog.hide();});
IETF.signinDialog = dialog;
}
document.getElementById("signin_msg").innerHTML = "";
IETF.signinDialog.show();
}
function signOut() {
YAHOO.util.Connect.asyncRequest('GET', '/account/logout/', { success: function(o) { window.location.reload(); } }, null);
};

View file

@ -1,2 +1,7 @@
-- This file holds needed corrections to the database until they have been applied to
-- the live database. This file is applied after importing a new dump of the live DB.
delete from auth_user;
delete from auth_user_groups;
delete from auth_group;
delete from auth_group_permissions;
drop table ietfauth_usermap;