summaryrefslogtreecommitdiffstats
path: root/django_authopenid
diff options
context:
space:
mode:
authorAdolfo Fitoria <fitoria@fitoria-laptop.(none)>2010-02-09 14:12:05 -0600
committerAdolfo Fitoria <fitoria@fitoria-laptop.(none)>2010-02-09 14:12:05 -0600
commit8de2b9131ddcef647799cf8e1e79921284523073 (patch)
tree81e17d84530990e35a0accba3a7886266a601482 /django_authopenid
parent7e95e6481d1e81e43d4b442cbcf3fe37f20d89cc (diff)
parent9d1fb9890b97beb55461ca34f9757bc685461130 (diff)
downloadaskbot-8de2b9131ddcef647799cf8e1e79921284523073.tar.gz
askbot-8de2b9131ddcef647799cf8e1e79921284523073.tar.bz2
askbot-8de2b9131ddcef647799cf8e1e79921284523073.zip
Merge branch 'evgenyfadeev/master'
Conflicts: .gitignore INSTALL TODO cnprog.wsgi django_authopenid/urls.py django_authopenid/views.py drop-all-tables.sh forum/auth.py forum/managers.py forum/models.py forum/templatetags/extra_tags.py forum/views.py locale/es/LC_MESSAGES/django.mo locale/es/LC_MESSAGES/django.po settings.py settings_local.py.dist sql_scripts/update_2009_01_25_001.sql sql_scripts/update_2009_02_26_001.sql sql_scripts/update_2009_04_10_001.sql templates/authopenid/confirm_email.txt templates/authopenid/sendpw_email.txt templates/content/js/compress.bat templates/content/js/flot-build.bat templates/content/style/style.css templates/footer.html templates/question.html templates/user_reputation.html templates/user_stats.html templates/user_votes.html templates/users_questions.html urls.py
Diffstat (limited to 'django_authopenid')
-rw-r--r--django_authopenid/external_login.py103
-rw-r--r--django_authopenid/forms.py462
-rw-r--r--django_authopenid/models.py5
-rw-r--r--django_authopenid/urls.py13
-rw-r--r--django_authopenid/util.py7
-rw-r--r--django_authopenid/views.py342
6 files changed, 588 insertions, 344 deletions
diff --git a/django_authopenid/external_login.py b/django_authopenid/external_login.py
new file mode 100644
index 00000000..bd49c009
--- /dev/null
+++ b/django_authopenid/external_login.py
@@ -0,0 +1,103 @@
+#this file contains stub functions that can be extended to support
+#connect legacy login with external site
+import settings
+from django_authopenid.models import ExternalLoginData
+import httplib
+import urllib
+import Cookie
+import cookielib
+from django import forms
+import xml.dom.minidom as xml
+import logging
+
+def login(request,user):
+ """performs the additional external login operation
+ """
+ pass
+
+def set_login_cookies(response,user):
+ #should be unique value by design
+ try:
+ eld = ExternalLoginData.objects.get(user=user)
+
+ data = eld.external_session_data
+ dom = xml.parseString(data)
+ login_response = dom.getElementsByTagName('login')[0]
+ userid = login_response.getAttribute('lguserid')
+ username = login_response.getAttribute('lgusername')
+ token = login_response.getAttribute('lgtoken')
+ prefix = login_response.getAttribute('cookieprefix').decode('utf-8')
+ sessionid = login_response.getAttribute('sessionid')
+
+ c = {}
+ c[prefix + 'UserName'] = username
+ c[prefix + 'UserID'] = userid
+ c[prefix + 'Token'] = token
+ c[prefix + '_session'] = sessionid
+
+ #custom code that copies cookies from external site
+ #not sure how to set paths and domain of cookies here
+ for key in c:
+ if c[key]:
+ response.set_cookie(str(key),value=str(c[key]))
+ except ExternalLoginData.DoesNotExist:
+ #this must be an OpenID login
+ pass
+
+#function to perform external logout, if needed
+def logout(request):
+ pass
+
+#should raise User.DoesNotExist or pass
+def clean_username(username):
+ return username
+
+def check_password(username,password):
+ """connects to external site and submits username/password pair
+ return True or False depending on correctness of login
+ saves remote unique id and remote session data in table ExternalLoginData
+ may raise forms.ValidationError
+ """
+ host = settings.EXTERNAL_LEGACY_LOGIN_HOST
+ port = settings.EXTERNAL_LEGACY_LOGIN_PORT
+ ext_site = httplib.HTTPConnection(host,port)
+
+ #custom code. this one does authentication through
+ #MediaWiki API
+ params = urllib.urlencode({'action':'login','format':'xml',
+ 'lgname':username,'lgpassword':password})
+ headers = {"Content-type": "application/x-www-form-urlencoded",
+ 'User-Agent':"User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7",
+ "Accept": "text/xml"}
+ ext_site.request("POST","/wiki/api.php",params,headers)
+ response = ext_site.getresponse()
+ if response.status != 200:
+ raise forms.ValidationError('error ' + response.status + ' ' + response.reason)
+ data = response.read().strip()
+ ext_site.close()
+
+ dom = xml.parseString(data)
+ login = dom.getElementsByTagName('login')[0]
+ result = login.getAttribute('result')
+
+ if result == 'Success':
+ username = login.getAttribute('lgusername')
+ try:
+ eld = ExternalLoginData.objects.get(external_username=username)
+ except ExternalLoginData.DoesNotExist:
+ eld = ExternalLoginData()
+ eld.external_username = username
+ eld.external_session_data = data
+ eld.save()
+ return True
+ else:
+ error = login.getAttribute('details')
+ raise forms.ValidationError(error)
+ return False
+
+def createuser(username,email,password):
+ pass
+
+#retrieve email address
+def get_email(username,password):
+ return ''
diff --git a/django_authopenid/forms.py b/django_authopenid/forms.py
index 690a781f..d4482751 100644
--- a/django_authopenid/forms.py
+++ b/django_authopenid/forms.py
@@ -35,8 +35,10 @@ from django.contrib.auth.models import User
from django.contrib.auth import authenticate
from django.utils.translation import ugettext as _
from django.conf import settings
-
+import external_login
+import types
import re
+from django.utils.safestring import mark_safe
# needed for some linux distributions like debian
@@ -46,16 +48,110 @@ except ImportError:
from yadis import xri
from django_authopenid.util import clean_next
+from django_authopenid.models import ExternalLoginData
+
+__all__ = ['OpenidSigninForm', 'ClassicLoginForm', 'OpenidVerifyForm',
+ 'OpenidRegisterForm', 'ClassicRegisterForm', 'ChangePasswordForm',
+ 'ChangeEmailForm', 'EmailPasswordForm', 'DeleteForm',
+ 'ChangeOpenidForm']
-__all__ = ['OpenidSigninForm', 'OpenidAuthForm', 'OpenidVerifyForm',
- 'OpenidRegisterForm', 'RegistrationForm', 'ChangepwForm',
- 'ChangeemailForm', 'EmailPasswordForm', 'DeleteForm',
- 'ChangeOpenidForm', 'ChangeEmailForm', 'ChangepwForm']
+class NextUrlField(forms.CharField):
+ def __init__(self):
+ super(NextUrlField,self).__init__(max_length = 255,widget = forms.HiddenInput(),required = False)
+ def clean(self,value):
+ return clean_next(value)
+
+attrs_dict = { 'class': 'required login' }
+
+class UserNameField(forms.CharField):
+ username_re = re.compile(r'^[\w ]+$')
+ RESERVED_NAMES = (u'fuck', u'shit', u'ass', u'sex', u'add',
+ u'edit', u'save', u'delete', u'manage', u'update', 'remove', 'new')
+ def __init__(self,must_exist=False,skip_clean=False,label=_('choose a username'),**kw):
+ self.must_exist = must_exist
+ self.skip_clean = skip_clean
+ super(UserNameField,self).__init__(max_length=30,
+ widget=forms.TextInput(attrs=attrs_dict),
+ label=label,
+ error_messages={'required':_('user name is required'),
+ 'taken':_('sorry, this name is taken, please choose another'),
+ 'forbidden':_('sorry, this name is not allowed, please choose another'),
+ 'missing':_('sorry, there is no user with this name'),
+ 'multiple-taken':_('sorry, we have a serious error - user name is taken by several users'),
+ 'invalid':_('user name can only consist of letters, empty space and underscore'),
+ },
+ **kw
+ )
+
+ def clean(self,username):
+ """ validate username """
+ username = super(UserNameField,self).clean(username.strip())
+ if self.skip_clean == True:
+ return username
+ if not username_re.search(username):
+ raise forms.ValidationError(self.error_messages['invalid'])
+ if username in self.RESERVED_NAMES:
+ raise forms.ValidationError(self.error_messages['forbidden'])
+ try:
+ user = User.objects.get(
+ username__exact = username
+ )
+ if user:
+ if self.must_exist:
+ return username
+ else:
+ raise forms.ValidationError(self.error_messages['taken'])
+ except User.DoesNotExist:
+ if self.must_exist:
+ raise forms.ValidationError(self.error_messages['missing'])
+ else:
+ return username
+ except User.MultipleObjectsReturned:
+ raise forms.ValidationError(self.error_messages['multiple-taken'])
+
+class UserEmailField(forms.EmailField):
+ def __init__(self,skip_clean=False,**kw):
+ self.skip_clean = skip_clean
+ super(UserEmailField,self).__init__(widget=forms.TextInput(attrs=dict(attrs_dict,
+ maxlength=200)), label=mark_safe(_('your email address')),
+ error_messages={'required':_('email address is required'),
+ 'invalid':_('please enter a valid email address'),
+ 'taken':_('this email is already used by someone else, please choose another'),
+ },
+ **kw
+ )
+
+ def clean(self,email):
+ """ validate if email exist in database
+ from legacy register
+ return: raise error if it exist """
+ email = super(UserEmailField,self).clean(email.strip())
+ if self.skip_clean:
+ return email
+ if settings.EMAIL_UNIQUE == True:
+ try:
+ user = User.objects.get(email = email)
+ raise forms.ValidationError(self.error_messsages['taken'])
+ except User.DoesNotExist:
+ return email
+ except User.MultipleObjectsReturned:
+ raise forms.ValidationError(self.error_messages['taken'])
+ else:
+ return email
+
+def clean_nonempty_field_method(self,field):
+ value = None
+ if field in self.cleaned_data:
+ value = str(self.cleaned_data[field]).strip()
+ if value == '':
+ value = None
+ self.cleaned_data[field] = value
+ return value
class OpenidSigninForm(forms.Form):
""" signin form """
openid_url = forms.CharField(max_length=255, widget=forms.widgets.TextInput(attrs={'class': 'openid-login-input', 'size':80}))
- next = forms.CharField(max_length=255, widget=forms.HiddenInput(), required=False)
+ next = NextUrlField()
def clean_openid_url(self):
""" test if openid is accepted """
@@ -67,76 +163,98 @@ class OpenidSigninForm(forms.Form):
raise forms.ValidationError(_('i-names are not supported'))
return self.cleaned_data['openid_url']
- def clean_next(self):
- """ validate next """
- if 'next' in self.cleaned_data and self.cleaned_data['next'] != "":
- self.cleaned_data['next'] = clean_next(self.cleaned_data['next'])
- return self.cleaned_data['next']
-
-
-attrs_dict = { 'class': 'required login' }
-username_re = re.compile(r'^\w+$')
-RESERVED_NAMES = (u'fuck', u'shit', u'ass', u'sex', u'add',
- u'edit', u'save', u'delete', u'manage', u'update', 'remove', 'new')
-
-class OpenidAuthForm(forms.Form):
+class ClassicLoginForm(forms.Form):
""" legacy account signin form """
- next = forms.CharField(max_length=255, widget=forms.HiddenInput(),
- required=False)
- username = forms.CharField(max_length=30,
- widget=forms.widgets.TextInput(attrs=attrs_dict))
+ next = NextUrlField()
+ username = UserNameField(required=False,skip_clean=True)
password = forms.CharField(max_length=128,
- widget=forms.widgets.PasswordInput(attrs=attrs_dict))
-
+ widget=forms.widgets.PasswordInput(attrs=attrs_dict), required=False)
+
def __init__(self, data=None, files=None, auto_id='id_%s',
prefix=None, initial=None):
- super(OpenidAuthForm, self).__init__(data, files, auto_id,
+ super(ClassicLoginForm, self).__init__(data, files, auto_id,
prefix, initial)
self.user_cache = None
-
+
+ clean_nonempty_field = clean_nonempty_field_method
+
def clean_username(self):
- """ validate username and test if it exists."""
- if 'username' in self.cleaned_data and \
- 'openid_url' not in self.cleaned_data:
- if not username_re.search(self.cleaned_data['username']):
- raise forms.ValidationError(_("Usernames can only contain \
- letters, numbers and underscores"))
- try:
- user = User.objects.get(
- username__exact = self.cleaned_data['username']
- )
- except User.DoesNotExist:
- raise forms.ValidationError(_("This username does not exist \
- in our database. Please choose another."))
- except User.MultipleObjectsReturned:
- raise forms.ValidationError(u'There is already more than one \
- account registered with that username. Please try \
- another.')
- return self.cleaned_data['username']
+ return self.clean_nonempty_field('username')
def clean_password(self):
- """" test if password is valid for this username """
- if 'username' in self.cleaned_data and \
- 'password' in self.cleaned_data:
- self.user_cache = authenticate(
- username=self.cleaned_data['username'],
- password=self.cleaned_data['password']
- )
+ return self.clean_nonempty_field('password')
+
+ def clean(self):
+ """
+ this clean function actuall cleans username and password
+
+ test if password is valid for this username
+ this is really the "authenticate" function
+ also openid_auth is not an authentication backend
+ since it's written in a way that does not comply with
+ the Django convention
+ """
+
+ error_list = []
+ username = self.cleaned_data['username']
+ password = self.cleaned_data['password']
+
+ self.user_cache = None
+ if username and password:
+
+ if settings.USE_EXTERNAL_LEGACY_LOGIN == True:
+ pw_ok = False
+ try:
+ pw_ok = external_login.check_password(username,password)
+ except forms.ValidationError, e:
+ error_list.extend(e.messages)
+ if pw_ok:
+ external_user = ExternalLoginData.objects.get(external_username=username)
+ if external_user.user == None:
+ return self.cleaned_data
+ user = external_user.user
+ openid_logins = user.userassociation_set.all()
+
+ if len(openid_logins) > 0:
+ msg1 = _('Account with this name already exists on the forum')
+ msg2 = _('can\'t have two logins to the same account yet, sorry.')
+ error_list.append(msg1)
+ error_list.append(msg2)
+ self._errors['__all__'] = forms.util.ErrorList(error_list)
+ return self.cleaned_data
+ else:
+ #synchronize password with external login
+ user.set_password(password)
+ user.save()
+ #this auth will always succeed
+ self.user_cache = authenticate(username=user.username,\
+ password=password)
+ else:
+ #keep self.user_cache == None
+ #nothing to do, error message will be set below
+ pass
+ else:
+ self.user_cache = authenticate(username=username, password=password)
+
if self.user_cache is None:
- raise forms.ValidationError(_("Please enter a valid \
- username and password. Note that both fields are \
- case-sensitive."))
+ del self.cleaned_data['username']
+ del self.cleaned_data['password']
+ error_list.insert(0,(_("Please enter valid username and password "
+ "(both are case-sensitive).")))
elif self.user_cache.is_active == False:
- raise forms.ValidationError(_("This account is inactive."))
- return self.cleaned_data['password']
+ error_list.append(_("This account is inactive."))
+ if len(error_list) > 0:
+ error_list.insert(0,_('Login failed.'))
+ elif password == None and username == None:
+ error_list.append(_('Please enter username and password'))
+ elif password == None:
+ error_list.append(_('Please enter your password'))
+ elif username == None:
+ error_list.append(_('Please enter user name'))
+ if len(error_list) > 0:
+ self._errors['__all__'] = forms.util.ErrorList(error_list)
+ return self.cleaned_data
- def clean_next(self):
- """ validate next url """
- if 'next' in self.cleaned_data and \
- self.cleaned_data['next'] != "":
- self.cleaned_data['next'] = clean_next(self.cleaned_data['next'])
- return self.cleaned_data['next']
-
def get_user(self):
""" get authenticated user """
return self.user_cache
@@ -144,56 +262,14 @@ class OpenidAuthForm(forms.Form):
class OpenidRegisterForm(forms.Form):
""" openid signin form """
- next = forms.CharField(max_length=255, widget=forms.HiddenInput(),
- required=False)
- username = forms.CharField(max_length=30,
- widget=forms.widgets.TextInput(attrs=attrs_dict))
- email = forms.EmailField(widget=forms.TextInput(attrs=dict(attrs_dict,
- maxlength=200)), label=u'Email address')
-
- def clean_username(self):
- """ test if username is valid and exist in database """
- if 'username' in self.cleaned_data:
- if not username_re.search(self.cleaned_data['username']):
- raise forms.ValidationError(_('invalid user name'))
- if self.cleaned_data['username'] in RESERVED_NAMES:
- raise forms.ValidationError(_('sorry, this name can not be used, please try another'))
- if len(self.cleaned_data['username']) < settings.MIN_USERNAME_LENGTH:
- raise forms.ValidationError(_('username too short'))
- try:
- user = User.objects.get(
- username__exact = self.cleaned_data['username']
- )
- except User.DoesNotExist:
- return self.cleaned_data['username']
- except User.MultipleObjectsReturned:
- raise forms.ValidationError(_('this name is already in use - please try anoter'))
- raise forms.ValidationError(_('this name is already in use - please try anoter'))
-
- def clean_email(self):
- """Optionally, for security reason one unique email in database"""
- if 'email' in self.cleaned_data:
- if settings.EMAIL_UNIQUE == True:
- try:
- user = User.objects.get(email = self.cleaned_data['email'])
- except User.DoesNotExist:
- return self.cleaned_data['email']
- except User.MultipleObjectsReturned:
- raise forms.ValidationError(u'There is already more than one \
- account registered with that e-mail address. Please try \
- another.')
- raise forms.ValidationError(_("This email is already \
- registered in our database. Please choose another."))
- else:
- return self.cleaned_data['email']
- #what if not???
-
+ next = NextUrlField()
+ username = UserNameField()
+ email = UserEmailField()
+
class OpenidVerifyForm(forms.Form):
""" openid verify form (associate an openid with an account) """
- next = forms.CharField(max_length=255, widget = forms.HiddenInput(),
- required=False)
- username = forms.CharField(max_length=30,
- widget=forms.widgets.TextInput(attrs=attrs_dict))
+ next = NextUrlField()
+ username = UserNameField(must_exist=True)
password = forms.CharField(max_length=128,
widget=forms.widgets.PasswordInput(attrs=attrs_dict))
@@ -203,24 +279,6 @@ class OpenidVerifyForm(forms.Form):
prefix, initial)
self.user_cache = None
- def clean_username(self):
- """ validate username """
- if 'username' in self.cleaned_data:
- if not username_re.search(self.cleaned_data['username']):
- raise forms.ValidationError(_('invalid user name'))
- try:
- user = User.objects.get(
- username__exact = self.cleaned_data['username']
- )
- except User.DoesNotExist:
- raise forms.ValidationError(_("This username don't exist. \
- Please choose another."))
- except User.MultipleObjectsReturned:
- raise forms.ValidationError(u'Somehow, that username is in \
- use for multiple accounts. Please contact us to get this \
- problem resolved.')
- return self.cleaned_data['username']
-
def clean_password(self):
""" test if password is valid for this user """
if 'username' in self.cleaned_data and \
@@ -236,7 +294,7 @@ class OpenidVerifyForm(forms.Form):
elif self.user_cache.is_active == False:
raise forms.ValidationError(_("This account is inactive."))
return self.cleaned_data['password']
-
+
def get_user(self):
""" get authenticated user """
return self.user_cache
@@ -245,88 +303,54 @@ class OpenidVerifyForm(forms.Form):
attrs_dict = { 'class': 'required' }
username_re = re.compile(r'^[\w ]+$')
-class RegistrationForm(forms.Form):
+class ClassicRegisterForm(forms.Form):
""" legacy registration form """
- next = forms.CharField(max_length=255, widget=forms.HiddenInput(),
- required=False)
- username = forms.CharField(max_length=30,
- widget=forms.TextInput(attrs=attrs_dict),
- label=_('choose a username'))
- email = forms.EmailField(widget=forms.TextInput(attrs=dict(attrs_dict,
- maxlength=200)), label=_('your email address'))
+ next = NextUrlField()
+ username = UserNameField()
+ email = UserEmailField()
password1 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict),
- label=_('choose password'))
+ label=_('choose password'),
+ error_messages={'required':_('password is required')},
+ )
password2 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict),
- label=_('retype password'))
-
- def clean_username(self):
- """
- Validates that the username is alphanumeric and is not already
- in use.
-
- """
- if 'username' in self.cleaned_data:
- if not username_re.search(self.cleaned_data['username']):
- raise forms.ValidationError(u'Usernames can only contain \
- letters, numbers and underscores')
- try:
- user = User.objects.get(
- username__exact = self.cleaned_data['username']
- )
-
- except User.DoesNotExist:
- return self.cleaned_data['username']
- except User.MultipleObjectsReturned:
- raise forms.ValidationError(u'Somehow, that username is in \
- use for multiple accounts. Please contact us to get this \
- problem resolved.')
- raise forms.ValidationError(u'This username is already taken. \
- Please choose another.')
-
- def clean_email(self):
- """ validate if email exist in database
- :return: raise error if it exist """
- if 'email' in self.cleaned_data:
- if settings.EMAIL_UNIQUE == True:
- try:
- user = User.objects.get(email = self.cleaned_data['email'])
- except User.DoesNotExist:
- return self.cleaned_data['email']
- except User.MultipleObjectsReturned:
- raise forms.ValidationError(u'There is already more than one \
- account registered with that e-mail address. Please try \
- another.')
- raise forms.ValidationError(u'This email is already registered \
- in our database. Please choose another.')
- else:
- return self.cleaned_data['email']
- #what if not?
+ label=mark_safe(_('retype password')),
+ error_messages={'required':_('please, retype your password'),
+ 'nomatch':_('sorry, entered passwords did not match, please try again')},
+ required=False
+ )
def clean_password2(self):
"""
Validates that the two password inputs match.
"""
- if 'password1' in self.cleaned_data and \
- 'password2' in self.cleaned_data and \
- self.cleaned_data['password1'] == \
+ self.cleaned_data['password2'] = self.cleaned_data.get('password2','')
+ if self.cleaned_data['password2'] == '':
+ del self.cleaned_data['password2']
+ raise forms.ValidationError(self.fields['password2'].error_messages['required'])
+ if 'password1' in self.cleaned_data \
+ and self.cleaned_data['password1'] == \
self.cleaned_data['password2']:
return self.cleaned_data['password2']
- raise forms.ValidationError(u'You must type the same password each \
- time')
+ else:
+ del self.cleaned_data['password2']
+ del self.cleaned_data['password1']
+ raise forms.ValidationError(self.fields['password2'].error_messages['nomatch'])
-
-class ChangepwForm(forms.Form):
+class ChangePasswordForm(forms.Form):
""" change password form """
- oldpw = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict))
- password1 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict))
- password2 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict))
+ oldpw = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict),
+ label=mark_safe(_('Current password')))
+ password1 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict),
+ label=mark_safe(_('New password')))
+ password2 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict),
+ label=mark_safe(_('Retype new password')))
def __init__(self, data=None, user=None, *args, **kwargs):
if user is None:
raise TypeError("Keyword argument 'user' must be supplied")
- super(ChangepwForm, self).__init__(data, *args, **kwargs)
+ super(ChangePasswordForm, self).__init__(data, *args, **kwargs)
self.user = user
def clean_oldpw(self):
@@ -347,49 +371,35 @@ class ChangepwForm(forms.Form):
raise forms.ValidationError(_("new passwords do not match"))
-class ChangeemailForm(forms.Form):
+class ChangeEmailForm(forms.Form):
""" change email form """
- email = forms.EmailField(widget=forms.TextInput(attrs=dict(attrs_dict,
- maxlength=200)), label=u'Email address')
- password = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict))
+ email = UserEmailField(skip_clean=True)
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, \
initial=None, user=None):
- if user is None:
- raise TypeError("Keyword argument 'user' must be supplied")
- super(ChangeemailForm, self).__init__(data, files, auto_id,
+ super(ChangeEmailForm, self).__init__(data, files, auto_id,
prefix, initial)
- self.test_openid = False
self.user = user
-
-
+
def clean_email(self):
""" check if email don't exist """
if 'email' in self.cleaned_data:
if settings.EMAIL_UNIQUE == True:
- if self.user.email != self.cleaned_data['email']:
- try:
- user = User.objects.get(email = self.cleaned_data['email'])
- except User.DoesNotExist:
+ try:
+ user = User.objects.get(email = self.cleaned_data['email'])
+ if self.user and self.user == user:
return self.cleaned_data['email']
- except User.MultipleObjectsReturned:
- raise forms.ValidationError(u'There is already more than one \
- account registered with that e-mail address. Please try \
- another.')
- raise forms.ValidationError(u'This email is already registered \
- in our database. Please choose another.')
+ except User.DoesNotExist:
+ return self.cleaned_data['email']
+ except User.MultipleObjectsReturned:
+ raise forms.ValidationError(u'There is already more than one \
+ account registered with that e-mail address. Please try \
+ another.')
+ raise forms.ValidationError(u'This email is already registered \
+ in our database. Please choose another.')
else:
return self.cleaned_data['email']
- #what if not?
-
- def clean_password(self):
- """ check if we have to test a legacy account or not """
- if 'password' in self.cleaned_data:
- if not self.user.check_password(self.cleaned_data['password']):
- self.test_openid = True
- return self.cleaned_data['password']
-
class ChangeopenidForm(forms.Form):
""" change openid form """
openid_url = forms.CharField(max_length=255,
@@ -422,8 +432,7 @@ class DeleteForm(forms.Form):
class EmailPasswordForm(forms.Form):
""" send new password form """
- username = forms.CharField(max_length=30,
- widget=forms.TextInput(attrs={'class': "required" }))
+ username = UserNameField(skip_clean=True,label=mark_safe(_('Your user name (<i>required</i>)')))
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None):
@@ -431,7 +440,6 @@ class EmailPasswordForm(forms.Form):
prefix, initial)
self.user_cache = None
-
def clean_username(self):
""" get user for this username """
if 'username' in self.cleaned_data:
diff --git a/django_authopenid/models.py b/django_authopenid/models.py
index e6fb8111..7b2e1c02 100644
--- a/django_authopenid/models.py
+++ b/django_authopenid/models.py
@@ -69,3 +69,8 @@ class UserPasswordQueue(models.Model):
def __unicode__(self):
return self.user.username
+
+class ExternalLoginData(models.Model):
+ external_username = models.CharField(max_length=40, unique=True, null=False)
+ external_session_data = models.TextField()
+ user = models.ForeignKey(User, null=True)
diff --git a/django_authopenid/urls.py b/django_authopenid/urls.py
index 3382434a..112cbbe1 100644
--- a/django_authopenid/urls.py
+++ b/django_authopenid/urls.py
@@ -7,11 +7,12 @@ urlpatterns = patterns('django_authopenid.views',
url(r'^yadis.xrdf$', 'xrdf', name='yadis_xrdf'),
# manage account registration
url(r'^%s$' % _('signin/'), 'signin', name='user_signin'),
- url(r'^%s%s$' % (_('signin/'),_('newquestion/')), 'signin', kwargs = {'newquestion':True}),
- url(r'^%s%s$' % (_('signin/'),_('newanswer/')), 'signin', kwargs = {'newanswer':True}),
+ url(r'^%s%s$' % (_('signin/'),_('newquestion/')), 'signin', kwargs = {'newquestion':True}, name='user_signin_new_question'),
+ url(r'^%s%s$' % (_('signin/'),_('newanswer/')), 'signin', kwargs = {'newanswer':True}, name='user_signin_new_answer'),
url(r'^%s$' % _('signout/'), 'signout', name='user_signout'),
url(r'^%s%s$' % (_('signin/'), _('complete/')), 'complete_signin',
name='user_complete_signin'),
+ url('^%s$' % _('external-login/'),'external_legacy_login_info', name='user_external_legacy_login_issues'),
url(r'^%s$' % _('register/'), 'register', name='user_register'),
url(r'^%s$' % _('signup/'), 'signup', name='user_signup'),
#disable current sendpw function
@@ -21,8 +22,10 @@ urlpatterns = patterns('django_authopenid.views',
# manage account settings
url(r'^$', _('account_settings'), name='user_account_settings'),
url(r'^%s$' % _('password/'), 'changepw', name='user_changepw'),
- url(r'^%s$' % _('email/'), 'changeemail', name='user_changeemail',kwargs = {'action':'change'}),
- url(r'^%s%s$' % (_('email/'),_('validate/')), 'changeemail', name='user_changeemail',kwargs = {'action':'validate'}),
- #url(r'^%s$' % _('openid/'), 'changeopenid', name='user_changeopenid'),
+ url(r'^%s%s$' % (_('email/'),_('validate/')), 'changeemail', name='user_validateemail',kwargs = {'action':'validate'}),
+ url(r'^%s%s$' % (_('email/'), _('change/')), 'changeemail', name='user_changeemail'),
+ url(r'^%s%s$' % (_('email/'), _('sendkey/')), 'send_email_key', name='send_email_key'),
+ url(r'^%s%s(?P<id>\d+)/(?P<key>[\dabcdef]{32})/$' % (_('email/'), _('verify/')), 'verifyemail', name='user_verifyemail'),
+ url(r'^%s$' % _('openid/'), 'changeopenid', name='user_changeopenid'),
url(r'^%s$' % _('delete/'), 'delete', name='user_delete'),
)
diff --git a/django_authopenid/util.py b/django_authopenid/util.py
index 11afe53b..2b9d44a2 100644
--- a/django_authopenid/util.py
+++ b/django_authopenid/util.py
@@ -7,7 +7,7 @@ import openid.store
from django.db.models.query import Q
from django.conf import settings
from django.http import str_to_unicode
-
+from django.core.urlresolvers import reverse
# needed for some linux distributions like debian
try:
@@ -22,7 +22,7 @@ from models import Association, Nonce
__all__ = ['OpenID', 'DjangoOpenIDStore', 'from_openid_response', 'clean_next']
-DEFAULT_NEXT = getattr(settings, 'OPENID_REDIRECT_NEXT', '/')
+DEFAULT_NEXT = '/' + getattr(settings, 'FORUM_SCRIPT_ALIAS')
def clean_next(next):
if next is None:
return DEFAULT_NEXT
@@ -32,6 +32,9 @@ def clean_next(next):
return next
return DEFAULT_NEXT
+def get_next_url(request):
+ return clean_next(request.REQUEST.get('next'))
+
class OpenID:
def __init__(self, openid_, issued, attrs=None, sreg_=None):
self.openid = openid_
diff --git a/django_authopenid/views.py b/django_authopenid/views.py
index fa94c4e5..feb6b58f 100644
--- a/django_authopenid/views.py
+++ b/django_authopenid/views.py
@@ -30,19 +30,20 @@
# (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 django.http import HttpResponseRedirect, get_host, Http404
+from django.http import HttpResponseRedirect, get_host, Http404, \
+ HttpResponseServerError
from django.shortcuts import render_to_response as render
from django.template import RequestContext, loader, Context
from django.conf import settings
from django.contrib.auth.models import User
-from django.contrib.auth import logout #for login I've added wrapper below - called login
from django.contrib.auth.decorators import login_required
+from django.contrib.auth import authenticate
from django.core.urlresolvers import reverse
from django.utils.encoding import smart_unicode
from django.utils.html import escape
from django.utils.translation import ugettext as _
-from django.contrib.sites.models import Site
from django.utils.http import urlquote_plus
+from django.utils.safestring import mark_safe
from django.core.mail import send_mail
from django.views.defaults import server_error
@@ -60,15 +61,24 @@ import re
import urllib
-from django_authopenid.util import OpenID, DjangoOpenIDStore, from_openid_response, clean_next
-from django_authopenid.models import UserAssociation, UserPasswordQueue
-from django_authopenid.forms import OpenidSigninForm, OpenidAuthForm, OpenidRegisterForm, \
- OpenidVerifyForm, RegistrationForm, ChangepwForm, ChangeemailForm, \
+from forum.forms import EditUserEmailFeedsForm
+from django_authopenid.util import OpenID, DjangoOpenIDStore, from_openid_response, get_next_url
+from django_authopenid.models import UserAssociation, UserPasswordQueue, ExternalLoginData
+from django_authopenid.forms import OpenidSigninForm, ClassicLoginForm, OpenidRegisterForm, \
+ OpenidVerifyForm, ClassicRegisterForm, ChangePasswordForm, ChangeEmailForm, \
ChangeopenidForm, DeleteForm, EmailPasswordForm
+import external_login
+import logging
def login(request,user):
from django.contrib.auth import login as _login
from forum.models import user_logged_in #custom signal
+
+ print 'in login call'
+
+ if settings.USE_EXTERNAL_LEGACY_LOGIN == True:
+ external_login.login(request,user)
+
#1) get old session key
session_key = request.session.session_key
#2) login and get new session key
@@ -76,6 +86,12 @@ def login(request,user):
#3) send signal with old session key as argument
user_logged_in.send(user=user,session_key=session_key,sender=None)
+def logout(request):
+ from django.contrib.auth import logout as _logout#for login I've added wrapper below - called login
+ _logout(request)
+ if settings.USE_EXTERNAL_LEGACY_LOGIN == True:
+ external_login.logout(request)
+
def get_url_host(request):
if request.is_secure():
protocol = 'https'
@@ -138,7 +154,7 @@ def complete(request, on_success=None, on_failure=None, return_to=None):
def default_on_success(request, identity_url, openid_response):
""" default action on openid signin success """
request.session['openid'] = from_openid_response(openid_response)
- return HttpResponseRedirect(clean_next(request.GET.get('next')))
+ return HttpResponseRedirect(get_next_url(request))
def default_on_failure(request, message):
""" default failure action on signin """
@@ -152,16 +168,15 @@ def not_authenticated(func):
he is already logged."""
def decorated(request, *args, **kwargs):
if request.user.is_authenticated():
- next = request.GET.get("next", "/")
- return HttpResponseRedirect(next)
+ return HttpResponseRedirect(get_next_url(request))
return func(request, *args, **kwargs)
return decorated
@not_authenticated
def signin(request,newquestion=False,newanswer=False):
"""
- signin page. It manage the legacy authentification (user/password)
- and authentification with openid.
+ signin page. It manages the legacy authentification (user/password)
+ and openid authentification
url: /signin/
@@ -169,27 +184,112 @@ def signin(request,newquestion=False,newanswer=False):
"""
request.encoding = 'UTF-8'
on_failure = signin_failure
- next = clean_next(request.GET.get('next'))
-
+ email_feeds_form = EditUserEmailFeedsForm()
+ next = get_next_url(request)
form_signin = OpenidSigninForm(initial={'next':next})
- form_auth = OpenidAuthForm(initial={'next':next})
+ form_auth = ClassicLoginForm(initial={'next':next})
if request.POST:
-
+ #'blogin' - password login
if 'blogin' in request.POST.keys():
- # perform normal django authentification
- form_auth = OpenidAuthForm(request.POST)
+ form_auth = ClassicLoginForm(request.POST)
if form_auth.is_valid():
- user_ = form_auth.get_user()
- login(request, user_)
- next = clean_next(form_auth.cleaned_data.get('next'))
- print 'next stop is "%s"' % next
- return HttpResponseRedirect(next)
+ #have login and password and need to login through external website
+ if settings.USE_EXTERNAL_LEGACY_LOGIN == True:
+ username = form_auth.cleaned_data['username']
+ password = form_auth.cleaned_data['password']
+ next = form_auth.cleaned_data['next']
+ if form_auth.get_user() == None:
+ #need to create internal user
+
+ #1) save login and password temporarily in session
+ request.session['external_username'] = username
+ request.session['external_password'] = password
+
+ #2) see if username clashes with some existing user
+ #if so, we have to prompt the user to pick a different name
+ username_taken = User.is_username_taken(username)
+ #try:
+ # User.objects.get(username=username)
+ # username_taken = True
+ #except User.DoesNotExist:
+ # username_taken = False
+
+ #3) try to extract user email from external service
+ email = external_login.get_email(username,password)
+
+ email_feeds_form = EditUserEmailFeedsForm()
+ form_data = {'username':username,'email':email,'next':next}
+ form = OpenidRegisterForm(initial=form_data)
+ template_data = {'form1':form,'username':username,\
+ 'email_feeds_form':email_feeds_form,\
+ 'provider':mark_safe(settings.EXTERNAL_LEGACY_LOGIN_PROVIDER_NAME),\
+ 'login_type':'legacy',\
+ 'gravatar_faq_url':reverse('faq') + '#gravatar',\
+ 'external_login_name_is_taken':username_taken}
+ return render('authopenid/complete.html',template_data,\
+ context_instance=RequestContext(request))
+ else:
+ #user existed, external password is ok
+ user = form_auth.get_user()
+ login(request,user)
+ response = HttpResponseRedirect(get_next_url(request))
+ external_login.set_login_cookies(response,user)
+ return response
+ else:
+ #regular password authentication
+ user = form_auth.get_user()
+ login(request, user)
+ return HttpResponseRedirect(get_next_url(request))
+
+ elif 'bnewaccount' in request.POST.keys():
+ #register externally logged in password user with a new local account
+ if settings.USE_EXTERNAL_LEGACY_LOGIN == True:
+ form = OpenidRegisterForm(request.POST)
+ email_feeds_form = EditUserEmailFeedsForm(request.POST)
+ form1_is_valid = form.is_valid()
+ form2_is_valid = email_feeds_form.is_valid()
+ if form1_is_valid and form2_is_valid:
+ #create the user
+ username = form.cleaned_data['username']
+ password = request.session.get('external_password',None)
+ email = form.cleaned_data['email']
+ print 'got email addr %s' % email
+ if password and username:
+ User.objects.create_user(username,email,password)
+ user = authenticate(username=username,password=password)
+ external_username = request.session['external_username']
+ eld = ExternalLoginData.objects.get(external_username=external_username)
+ eld.user = user
+ eld.save()
+ login(request,user)
+ email_feeds_form.save(user)
+ del request.session['external_username']
+ del request.session['external_password']
+ return HttpResponseRedirect(reverse('index'))
+ else:
+ if password:
+ del request.session['external_username']
+ if username:
+ del request.session['external_password']
+ return HttpResponseServerError()
+ else:
+ username = request.POST.get('username',None)
+ provider = mark_safe(settings.EXTERNAL_LEGACY_LOGIN_PROVIDER_NAME)
+ username_taken = User.is_username_taken(username)
+ data = {'login_type':'legacy','form1':form,'username':username,\
+ 'email_feeds_form':email_feeds_form,'provider':provider,\
+ 'gravatar_faq_url':reverse('faq') + '#gravatar',\
+ 'external_login_name_is_taken':username_taken}
+ return render('authopenid/complete.html',data,
+ context_instance=RequestContext(request))
+ else:
+ raise Http404
elif 'bsignin' in request.POST.keys() or 'openid_username' in request.POST.keys():
form_signin = OpenidSigninForm(request.POST)
if form_signin.is_valid():
- next = clean_next(form_signin.cleaned_data.get('next'))
+ next = form_signin.cleaned_data['next']
sreg_req = sreg.SRegRequest(optional=['nickname', 'email'])
redirect_to = "%s%s?%s" % (
get_url_host(request),
@@ -203,6 +303,7 @@ def signin(request,newquestion=False,newanswer=False):
sreg_request=sreg_req)
+ #if request is GET
question = None
if newquestion == True:
from forum.models import AnonymousQuestion as AQ
@@ -232,7 +333,6 @@ def complete_signin(request):
return complete(request, signin_success, signin_failure,
get_url_host(request) + reverse('user_complete_signin'))
-
def signin_success(request, identity_url, openid_response):
"""
openid signin success.
@@ -256,8 +356,7 @@ def signin_success(request, identity_url, openid_response):
user_.backend = "django.contrib.auth.backends.ModelBackend"
login(request, user_)
- next = clean_next(request.GET.get('next'))
- return HttpResponseRedirect(next)
+ return HttpResponseRedirect(get_next_url(request))
def is_association_exist(openid_url):
""" test if an openid is already in database """
@@ -284,15 +383,13 @@ def register(request):
template : authopenid/complete.html
"""
- is_redirect = False
- next = clean_next(request.GET.get('next'))
openid_ = request.session.get('openid', None)
+ next = get_next_url(request)
if not openid_:
- return HttpResponseRedirect(reverse('user_signin') + next)
+ return HttpResponseRedirect(reverse('user_signin') + '?next=%s' % next)
nickname = openid_.sreg.get('nickname', '')
email = openid_.sreg.get('email', '')
-
form1 = OpenidRegisterForm(initial={
'next': next,
'username': nickname,
@@ -302,18 +399,22 @@ def register(request):
'next': next,
'username': nickname,
})
+ email_feeds_form = EditUserEmailFeedsForm()
user_ = None
+ is_redirect = False
if request.POST:
- just_completed = False
if 'bnewaccount' in request.POST.keys():
form1 = OpenidRegisterForm(request.POST)
- if form1.is_valid():
- next = clean_next(form1.cleaned_data.get('next'))
+ email_feeds_form = EditUserEmailFeedsForm(request.POST)
+ if form1.is_valid() and email_feeds_form.is_valid():
+ next = form1.cleaned_data['next']
is_redirect = True
tmp_pwd = User.objects.make_random_password()
user_ = User.objects.create_user(form1.cleaned_data['username'],
form1.cleaned_data['email'], tmp_pwd)
+
+ user_.set_unusable_password()
# make association with openid
uassoc = UserAssociation(openid_url=str(openid_),
user_id=user_.id)
@@ -322,11 +423,12 @@ def register(request):
# login
user_.backend = "django.contrib.auth.backends.ModelBackend"
login(request, user_)
+ email_feeds_form.save(user_)
elif 'bverify' in request.POST.keys():
form2 = OpenidVerifyForm(request.POST)
if form2.is_valid():
is_redirect = True
- next = clean_next(form2.cleaned_data.get('next'))
+ next = form2.cleaned_data['next']
user_ = form2.get_user()
uassoc = UserAssociation(openid_url=str(openid_),
@@ -338,13 +440,16 @@ def register(request):
#this needs to be a function call becase this is also done
#if user just logged in and did not need to create the new account
- if user_ != None and settings.EMAIL_VALIDATION == 'on':
- send_new_email_key(user_,nomessage=True)
- output = validation_email_sent(request)
- set_email_validation_message(user_) #message set after generating view
- return output
- elif user_ != None and user_.is_authenticated():
- return HttpResponseRedirect('/')
+ if user_ != None:
+ if settings.EMAIL_VALIDATION == 'on':
+ send_new_email_key(user_,nomessage=True)
+ output = validation_email_sent(request)
+ set_email_validation_message(user_) #message set after generating view
+ return output
+ if user_.is_authenticated():
+ return HttpResponseRedirect(reverse('index'))
+ else:
+ raise Exception('openid login failed')#should not ever get here
openid_str = str(openid_)
bits = openid_str.split('/')
@@ -366,9 +471,12 @@ def register(request):
return render('authopenid/complete.html', {
'form1': form1,
'form2': form2,
- 'provider':provider_logo,
- 'nickname': nickname,
- 'email': email
+ 'email_feeds_form': email_feeds_form,
+ 'provider':mark_safe(provider_logo),
+ 'username': nickname,
+ 'email': email,
+ 'login_type':'openid',
+ 'gravatar_faq_url':reverse('faq') + '#gravatar',
}, context_instance=RequestContext(request))
def signin_failure(request, message):
@@ -377,9 +485,9 @@ def signin_failure(request, message):
template : "authopenid/signin.html"
"""
- next = clean_next(request.GET.get('next'))
+ next = get_next_url(request)
form_signin = OpenidSigninForm(initial={'next': next})
- form_auth = OpenidAuthForm(initial={'next': next})
+ form_auth = ClassicLoginForm(initial={'next': next})
return render('authopenid/signin.html', {
'msg': message,
@@ -396,42 +504,52 @@ def signup(request):
templates: authopenid/signup.html, authopenid/confirm_email.txt
"""
- action_signin = reverse('user_signin')
- next = clean_next(request.GET.get('next'))
- form = RegistrationForm(initial={'next':next})
- form_signin = OpenidSigninForm(initial={'next':next})
-
+ if settings.USE_EXTERNAL_LEGACY_LOGIN == True:
+ return HttpResponseRedirect(reverse('user_external_legacy_login_issues'))
+ next = get_next_url(request)
if request.POST:
- form = RegistrationForm(request.POST)
- if form.is_valid():
- next = clean_next(form.cleaned_data.get('next'))
- user_ = User.objects.create_user( form.cleaned_data['username'],
- form.cleaned_data['email'], form.cleaned_data['password1'])
+ form = ClassicRegisterForm(request.POST)
+ email_feeds_form = EditUserEmailFeedsForm(request.POST)
+
+ #validation outside if to remember form values
+ form1_is_valid = form.is_valid()
+ form2_is_valid = email_feeds_form.is_valid()
+ if form1_is_valid and form2_is_valid:
+ next = form.cleaned_data['next']
+ username = form.cleaned_data['username']
+ password = form.cleaned_data['password1']
+ email = form.cleaned_data['email']
+
+ user_ = User.objects.create_user( username,email,password )
+ if settings.USE_EXTERNAL_LEGACY_LOGIN == True:
+ external_login.create_user(username,email,password)
user_.backend = "django.contrib.auth.backends.ModelBackend"
login(request, user_)
+ email_feeds_form.save(user_)
# send email
- current_domain = Site.objects.get_current().domain
- subject = _("Welcome")
+ subject = _("Welcome email subject line")
message_template = loader.get_template(
'authopenid/confirm_email.txt'
)
message_context = Context({
- 'site_url': 'http://%s/' % current_domain,
- 'username': form.cleaned_data['username'],
- 'password': form.cleaned_data['password1']
+ 'signup_url': settings.APP_URL + reverse('user_signin'),
+ 'username': username,
+ 'password': password,
})
message = message_template.render(message_context)
send_mail(subject, message, settings.DEFAULT_FROM_EMAIL,
[user_.email])
-
return HttpResponseRedirect(next)
-
+ else:
+ form = ClassicRegisterForm(initial={'next':next})
+ email_feeds_form = EditUserEmailFeedsForm()
return render('authopenid/signup.html', {
- 'form': form,
- 'form2': form_signin,
+ 'form': form,
+ 'email_feeds_form': email_feeds_form
}, context_instance=RequestContext(request))
+ #what if request is not posted?
@login_required
def signout(request):
@@ -444,10 +562,8 @@ def signout(request):
del request.session['openid']
except KeyError:
pass
- next = clean_next(request.GET.get('next'))
logout(request)
-
- return HttpResponseRedirect(next)
+ return HttpResponseRedirect(get_next_url(request))
def xrdf(request):
url_host = get_url_host(request)
@@ -495,11 +611,16 @@ def changepw(request):
url : /changepw/
template: authopenid/changepw.html
"""
-
user_ = request.user
+
+ if user_.has_usable_password():
+ if settings.USE_EXTERNAL_LEGACY_LOGIN == True:
+ return HttpResponseRedirect(reverse('user_external_legacy_login_issues'))
+ else:
+ raise Http404
if request.POST:
- form = ChangepwForm(request.POST, user=user_)
+ form = ChangePasswordForm(request.POST, user=user_)
if form.is_valid():
user_.set_password(form.cleaned_data['password1'])
user_.save()
@@ -509,18 +630,20 @@ def changepw(request):
urlquote_plus(msg))
return HttpResponseRedirect(redirect)
else:
- form = ChangepwForm(user=user_)
+ form = ChangePasswordForm(user=user_)
return render('authopenid/changepw.html', {'form': form },
context_instance=RequestContext(request))
def find_email_validation_messages(user):
- msg_text = _('your email needs to be validated')
+ msg_text = _('your email needs to be validated see %(details_url)s') \
+ % {'details_url':reverse('faq') + '#validate'}
return user.message_set.filter(message__exact=msg_text)
def set_email_validation_message(user):
messages = find_email_validation_messages(user)
- msg_text = _('your email needs to be validated')
+ msg_text = _('your email needs to be validated see %(details_url)s') \
+ % {'details_url':reverse('faq') + '#validate'}
if len(messages) == 0:
user.message_set.create(message=msg_text)
@@ -540,11 +663,11 @@ def _send_email_key(user):
"""private function. sends email containing validation key
to user's email address
"""
- subject = _("Welcome")
+ subject = _("Email verification subject line")
message_template = loader.get_template('authopenid/email_validation.txt')
import settings
message_context = Context({
- 'validation_link': '%s/email/verify/%d/%s/' % (settings.APP_URL ,user.id,user.email_key)
+ 'validation_link': settings.APP_URL + reverse('user_verifyemail', kwargs={'id':user.id,'key':user.email_key})
})
message = message_template.render(message_context)
send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [user.email])
@@ -580,7 +703,7 @@ def send_email_key(request):
context_instance=RequestContext(request)
)
else:
- _send_email_key(request.user)
+ send_new_email_key(request.user)
return validation_email_sent(request)
else:
raise Http404
@@ -589,10 +712,11 @@ def send_email_key(request):
#internal server view used as return value by other views
def validation_email_sent(request):
return render('authopenid/changeemail.html',
- { 'email': request.user.email, 'action_type': 'validate', },
+ { 'email': request.user.email,
+ 'change_email_url': reverse('user_changeemail'),
+ 'action_type': 'validate', },
context_instance=RequestContext(request))
-
def verifyemail(request,id=None,key=None):
"""
view that is shown when user clicks email validation link
@@ -611,53 +735,49 @@ def verifyemail(request,id=None,key=None):
raise Http404
@login_required
-def changeemail(request):
+def changeemail(request, action='change'):
"""
- changeemail view. It require password or openid to allow change.
+ changeemail view. requires openid with request type GET
url: /email/*
template : authopenid/changeemail.html
"""
- msg = request.GET.get('msg', '')
+ msg = request.GET.get('msg', None)
extension_args = {}
user_ = request.user
- redirect_to = get_url_host(request) + reverse('user_changeemail')
- action = 'change'
-
if request.POST:
- form = ChangeemailForm(request.POST, user=user_)
+ if 'cancel' in request.POST:
+ msg = _('your email was not changed')
+ request.user.message_set.create(message=msg)
+ return HttpResponseRedirect(get_next_url(request))
+ form = ChangeEmailForm(request.POST, user=user_)
if form.is_valid():
- if not form.test_openid:
- new_email = form.cleaned_data['email']
- if new_email != user_.email:
- if settings.EMAIL_VALIDATION == 'on':
- action = 'validate'
- else:
- action = 'done_novalidate'
- set_new_email(user_, new_email,nomessage=True)
+ new_email = form.cleaned_data['email']
+ if new_email != user_.email:
+ if settings.EMAIL_VALIDATION == 'on':
+ action = 'validate'
else:
- action = 'keep'
+ action = 'done_novalidate'
+ set_new_email(user_, new_email,nomessage=True)
else:
- #what does this branch do?
- return server_error('')
- request.session['new_email'] = form.cleaned_data['email']
- return ask_openid(request, form.cleaned_data['password'],
- redirect_to, on_failure=emailopenid_failure)
+ action = 'keep'
elif not request.POST and 'openid.mode' in request.GET:
+ redirect_to = get_url_host(request) + reverse('user_changeemail')
return complete(request, emailopenid_success,
emailopenid_failure, redirect_to)
else:
- form = ChangeemailForm(initial={'email': user_.email},
+ form = ChangeEmailForm(initial={'email': user_.email},
user=user_)
-
output = render('authopenid/changeemail.html', {
'form': form,
'email': user_.email,
'action_type': action,
+ 'gravatar_faq_url': reverse('faq') + '#gravatar',
+ 'change_email_url': reverse('user_changeemail'),
'msg': msg
}, context_instance=RequestContext(request))
@@ -666,7 +786,6 @@ def changeemail(request):
return output
-
def emailopenid_success(request, identity_url, openid_response):
openid_ = from_openid_response(openid_response)
@@ -840,7 +959,7 @@ def deleteopenid_success(request, identity_url, openid_response):
identity_url))
msg = _("Account deleted.")
- redirect = "/?msg=%s" % (urlquote_plus(msg))
+ redirect = reverse('index') + u"/?msg=%s" % (urlquote_plus(msg))
return HttpResponseRedirect(redirect)
@@ -848,6 +967,8 @@ def deleteopenid_failure(request, message):
redirect_to = "%s?msg=%s" % (reverse('user_delete'), urlquote_plus(message))
return HttpResponseRedirect(redirect_to)
+def external_legacy_login_info(request):
+ return render('authopenid/external_legacy_login_info.html', context_instance=RequestContext(request))
def sendpw(request):
"""
@@ -859,6 +980,8 @@ def sendpw(request):
templates : authopenid/sendpw_email.txt, authopenid/sendpw.html
"""
+ if settings.USE_EXTERNAL_LEGACY_LOGIN == True:
+ return HttpResponseRedirect(reverse('user_external_legacy_login_issues'))
msg = request.GET.get('msg','')
if request.POST:
@@ -878,21 +1001,20 @@ def sendpw(request):
uqueue.confirm_key = confirm_key
uqueue.save()
# send email
- current_domain = Site.objects.get_current().domain
subject = _("Request for new password")
message_template = loader.get_template(
'authopenid/sendpw_email.txt')
+ key_link = settings.APP_URL + reverse('user_confirmchangepw') + '?key=' + confirm_key
message_context = Context({
- 'site_url': 'http://%s' % current_domain,
- 'confirm_key': confirm_key,
+ 'site_url': settings.APP_URL + reverse('index'),
+ 'key_link': key_link,
'username': form.user_cache.username,
'password': new_pw,
- 'url_confirm': reverse('user_confirmchangepw'),
})
message = message_template.render(message_context)
send_mail(subject, message, settings.DEFAULT_FROM_EMAIL,
[form.user_cache.email])
- msg = _("A new password has been sent to your email address.")
+ msg = _("A new password and the activation link were sent to your email address.")
else:
form = EmailPasswordForm()
@@ -915,7 +1037,7 @@ def confirmchangepw(request):
"""
confirm_key = request.GET.get('key', '')
if not confirm_key:
- return HttpResponseRedirect('/')
+ return HttpResponseRedirect(reverse('index'))
try:
uqueue = UserPasswordQueue.objects.get(