summaryrefslogtreecommitdiffstats
path: root/forum/deps/django_authopenid/forms.py
diff options
context:
space:
mode:
Diffstat (limited to 'forum/deps/django_authopenid/forms.py')
-rw-r--r--forum/deps/django_authopenid/forms.py322
1 files changed, 322 insertions, 0 deletions
diff --git a/forum/deps/django_authopenid/forms.py b/forum/deps/django_authopenid/forms.py
new file mode 100644
index 00000000..dd66591e
--- /dev/null
+++ b/forum/deps/django_authopenid/forms.py
@@ -0,0 +1,322 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2007, 2008, BenoƮt Chesneau
+#
+# All rights reserved.
+#
+# 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 <ORGANIZATION> 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 django import forms
+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
+from forum.conf import settings as forum_settings
+import types
+import re
+from django.utils.safestring import mark_safe
+from recaptcha_django import ReCaptchaField
+from forum.utils.forms import NextUrlField, UserNameField, UserEmailField, SetPasswordForm
+EXTERNAL_LOGIN_APP = settings.LOAD_EXTERNAL_LOGIN_APP()
+
+# needed for some linux distributions like debian
+try:
+ from openid.yadis import xri
+except ImportError:
+ from yadis import xri
+
+from forum.utils.forms import clean_next
+from forum.deps.django_authopenid.models import ExternalLoginData
+
+__all__ = ['OpenidSigninForm', 'ClassicLoginForm', 'OpenidVerifyForm',
+ 'OpenidRegisterForm', 'ClassicRegisterForm', 'ChangePasswordForm',
+ 'ChangeEmailForm', 'EmailPasswordForm', 'DeleteForm',
+ 'ChangeOpenidForm']
+
+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 = NextUrlField()
+
+ def clean_openid_url(self):
+ """ test if openid is accepted """
+ if 'openid_url' in self.cleaned_data:
+ openid_url = self.cleaned_data['openid_url']
+ if xri.identifierScheme(openid_url) == 'XRI' and getattr(
+ settings, 'OPENID_DISALLOW_INAMES', False
+ ):
+ raise forms.ValidationError(_('i-names are not supported'))
+ return self.cleaned_data['openid_url']
+
+class ClassicLoginForm(forms.Form):
+ """ legacy account signin form """
+ next = NextUrlField()
+ username = UserNameField(required=False,skip_clean=True)
+ password = forms.CharField(max_length=128,
+ widget=forms.widgets.PasswordInput(attrs={'class':'required login'}),
+ required=False)
+
+ def __init__(self, data=None, files=None, auto_id='id_%s',
+ prefix=None, initial=None):
+ super(ClassicLoginForm, self).__init__(data, files, auto_id,
+ prefix, initial)
+ self.user_cache = None
+
+ def _clean_nonempty_field(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
+
+ def clean_username(self):
+ return self._clean_nonempty_field('username')
+
+ def clean_password(self):
+ return self._clean_nonempty_field('password')
+
+ def clean(self):
+ """
+ this clean function actually 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_APP.api.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:
+ 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:
+ 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 get_user(self):
+ """ get authenticated user """
+ return self.user_cache
+
+
+class OpenidRegisterForm(forms.Form):
+ """ openid signin form """
+ next = NextUrlField()
+ username = UserNameField()
+ email = UserEmailField()
+
+class OpenidVerifyForm(forms.Form):
+ """ openid verify form (associate an openid with an account) """
+ next = NextUrlField()
+ username = UserNameField(must_exist=True)
+ password = forms.CharField(max_length=128,
+ widget=forms.widgets.PasswordInput(attrs={'class':'required login'}))
+
+ def __init__(self, data=None, files=None, auto_id='id_%s',
+ prefix=None, initial=None):
+ super(OpenidVerifyForm, self).__init__(data, files, auto_id,
+ prefix, initial)
+ self.user_cache = None
+
+ def clean_password(self):
+ """ test if password is valid for this user """
+ 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']
+ )
+ if self.user_cache is None:
+ raise forms.ValidationError(_("Please enter a valid \
+ username and password. Note that both fields are \
+ case-sensitive."))
+ 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
+
+class ClassicRegisterForm(SetPasswordForm):
+ """ legacy registration form """
+
+ next = NextUrlField()
+ username = UserNameField()
+ email = UserEmailField()
+ #fields password1 and password2 are inherited
+ recaptcha = ReCaptchaField()
+
+class ChangePasswordForm(SetPasswordForm):
+ """ change password form """
+ oldpw = forms.CharField(widget=forms.PasswordInput(attrs={'class':'required'}),
+ label=mark_safe(_('Current password')))
+
+ def __init__(self, data=None, user=None, *args, **kwargs):
+ if user is None:
+ raise TypeError("Keyword argument 'user' must be supplied")
+ super(ChangePasswordForm, self).__init__(data, *args, **kwargs)
+ self.user = user
+
+ def clean_oldpw(self):
+ """ test old password """
+ if not self.user.check_password(self.cleaned_data['oldpw']):
+ raise forms.ValidationError(_("Old password is incorrect. \
+ Please enter the correct password."))
+ return self.cleaned_data['oldpw']
+
+class ChangeEmailForm(forms.Form):
+ """ change email form """
+ email = UserEmailField(skip_clean=True)
+
+ def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, \
+ initial=None, user=None):
+ super(ChangeEmailForm, self).__init__(data, files, auto_id,
+ prefix, initial)
+ self.user = user
+
+ def clean_email(self):
+ """ check if email don't exist """
+ if 'email' in self.cleaned_data:
+ if forum_settings.EMAIL_UNIQUE == True:
+ try:
+ user = User.objects.get(email = self.cleaned_data['email'])
+ if self.user and self.user == user:
+ return 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']
+
+class ChangeopenidForm(forms.Form):
+ """ change openid form """
+ openid_url = forms.CharField(max_length=255,
+ widget=forms.TextInput(attrs={'class': "required" }))
+
+ def __init__(self, data=None, user=None, *args, **kwargs):
+ if user is None:
+ raise TypeError("Keyword argument 'user' must be supplied")
+ super(ChangeopenidForm, self).__init__(data, *args, **kwargs)
+ self.user = user
+
+class DeleteForm(forms.Form):
+ """ confirm form to delete an account """
+ confirm = forms.CharField(widget=forms.CheckboxInput(attrs={'class':'required'}))
+ password = forms.CharField(widget=forms.PasswordInput(attrs={'class':'required'}))
+
+ def __init__(self, data=None, files=None, auto_id='id_%s',
+ prefix=None, initial=None, user=None):
+ super(DeleteForm, self).__init__(data, files, auto_id, prefix, initial)
+ self.test_openid = False
+ self.user = user
+
+ 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 EmailPasswordForm(forms.Form):
+ """ send new password form """
+ 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):
+ super(EmailPasswordForm, self).__init__(data, files, auto_id,
+ prefix, initial)
+ self.user_cache = None
+
+ def clean_username(self):
+ """ get user for this username """
+ if 'username' in self.cleaned_data:
+ try:
+ self.user_cache = User.objects.get(
+ username = self.cleaned_data['username'])
+ except:
+ raise forms.ValidationError(_("Incorrect username."))
+ return self.cleaned_data['username']