Replaced old authentication/authorization system with new one (which uses Apache's authentication)
- Legacy-Id: 1877
This commit is contained in:
parent
875b97e898
commit
11887ca938
19
changelog
19
changelog
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,)
|
||||
|
||||
|
||||
######################################################
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
302 /account/profile/
|
||||
302 /accounts/profile/
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -54,9 +54,9 @@ IETF = {};
|
|||
</div>
|
||||
<div id="ietf-login" style="position:absolute;top:8px;right:10px;">
|
||||
{% if user.is_authenticated %}
|
||||
{{ user }} | <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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -1,9 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ title }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ title }}</h1>
|
||||
|
||||
<p>You have been logged out.</p>
|
||||
{% endblock %}
|
|
@ -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 %}
|
|
@ -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 %}
|
11
ietf/templates/registration/profile.html
Normal file
11
ietf/templates/registration/profile.html
Normal 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 %}
|
|
@ -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'):
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue