diff options
Diffstat (limited to 'django_authopenid')
-rw-r--r-- | django_authopenid/external_login.py | 103 | ||||
-rw-r--r-- | django_authopenid/forms.py | 184 | ||||
-rw-r--r-- | django_authopenid/middleware.py | 4 | ||||
-rw-r--r-- | django_authopenid/models.py | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | django_authopenid/urls.py | 33 | ||||
-rw-r--r-- | django_authopenid/util.py | 19 | ||||
-rwxr-xr-x[-rw-r--r--] | django_authopenid/views.py | 309 |
7 files changed, 274 insertions, 382 deletions
diff --git a/django_authopenid/external_login.py b/django_authopenid/external_login.py deleted file mode 100644 index bd49c009..00000000 --- a/django_authopenid/external_login.py +++ /dev/null @@ -1,103 +0,0 @@ -#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 d4482751..5ec21c1c 100644 --- a/django_authopenid/forms.py +++ b/django_authopenid/forms.py @@ -35,11 +35,12 @@ 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 - +from recaptcha_django import ReCaptchaField +from utils.forms import NextUrlField, UserNameField, UserEmailField, SetPasswordForm +EXTERNAL_LOGIN_APP = settings.LOAD_EXTERNAL_LOGIN_APP() # needed for some linux distributions like debian try: @@ -47,7 +48,7 @@ try: except ImportError: from yadis import xri -from django_authopenid.util import clean_next +from utils.forms import clean_next from django_authopenid.models import ExternalLoginData __all__ = ['OpenidSigninForm', 'ClassicLoginForm', 'OpenidVerifyForm', @@ -55,99 +56,6 @@ __all__ = ['OpenidSigninForm', 'ClassicLoginForm', 'OpenidVerifyForm', 'ChangeEmailForm', 'EmailPasswordForm', 'DeleteForm', 'ChangeOpenidForm'] -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})) @@ -168,7 +76,8 @@ class ClassicLoginForm(forms.Form): next = NextUrlField() username = UserNameField(required=False,skip_clean=True) password = forms.CharField(max_length=128, - widget=forms.widgets.PasswordInput(attrs=attrs_dict), required=False) + 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): @@ -176,17 +85,24 @@ class ClassicLoginForm(forms.Form): prefix, initial) self.user_cache = None - clean_nonempty_field = clean_nonempty_field_method + 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') + return self._clean_nonempty_field('username') def clean_password(self): - return self.clean_nonempty_field('password') + return self._clean_nonempty_field('password') def clean(self): """ - this clean function actuall cleans username and password + this clean function actually cleans username and password test if password is valid for this username this is really the "authenticate" function @@ -201,11 +117,10 @@ class ClassicLoginForm(forms.Form): 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) + pw_ok = EXTERNAL_LOGIN_APP.api.check_password(username,password) except forms.ValidationError, e: error_list.extend(e.messages) if pw_ok: @@ -271,7 +186,7 @@ class OpenidVerifyForm(forms.Form): next = NextUrlField() username = UserNameField(must_exist=True) password = forms.CharField(max_length=128, - widget=forms.widgets.PasswordInput(attrs=attrs_dict)) + widget=forms.widgets.PasswordInput(attrs={'class':'required login'})) def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None): @@ -299,53 +214,19 @@ class OpenidVerifyForm(forms.Form): """ get authenticated user """ return self.user_cache - -attrs_dict = { 'class': 'required' } -username_re = re.compile(r'^[\w ]+$') - -class ClassicRegisterForm(forms.Form): +class ClassicRegisterForm(SetPasswordForm): """ legacy registration form """ next = NextUrlField() username = UserNameField() email = UserEmailField() - password1 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict), - label=_('choose password'), - error_messages={'required':_('password is required')}, - ) - password2 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict), - 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. - - """ - 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'] - else: - del self.cleaned_data['password2'] - del self.cleaned_data['password1'] - raise forms.ValidationError(self.fields['password2'].error_messages['nomatch']) - -class ChangePasswordForm(forms.Form): + #fields password1 and password2 are inherited + recaptcha = ReCaptchaField() + +class ChangePasswordForm(SetPasswordForm): """ change password form """ - oldpw = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict), + oldpw = forms.CharField(widget=forms.PasswordInput(attrs={'class':'required'}), 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: @@ -359,17 +240,6 @@ class ChangePasswordForm(forms.Form): raise forms.ValidationError(_("Old password is incorrect. \ Please enter the correct password.")) return self.cleaned_data['oldpw'] - - 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']: - return self.cleaned_data['password2'] - raise forms.ValidationError(_("new passwords do not match")) - class ChangeEmailForm(forms.Form): """ change email form """ @@ -413,8 +283,8 @@ class ChangeopenidForm(forms.Form): class DeleteForm(forms.Form): """ confirm form to delete an account """ - confirm = forms.CharField(widget=forms.CheckboxInput(attrs=attrs_dict)) - password = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict)) + 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): diff --git a/django_authopenid/middleware.py b/django_authopenid/middleware.py index 2900d54c..2be8da90 100644 --- a/django_authopenid/middleware.py +++ b/django_authopenid/middleware.py @@ -2,6 +2,8 @@ from django_authopenid import mimeparse from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse +from django.conf import settings +import logging __all__ = ["OpenIDMiddleware"] @@ -12,6 +14,7 @@ class OpenIDMiddleware(object): """ def process_request(self, request): request.openid = request.session.get('openid', None) + logging.debug('openid in session is: %s' % str(request.openid)) def process_response(self, request, response): if response.status_code != 200 or len(response.content) < 200: @@ -20,5 +23,6 @@ class OpenIDMiddleware(object): if path == "/" and request.META.has_key('HTTP_ACCEPT') and \ mimeparse.best_match(['text/html', 'application/xrds+xml'], request.META['HTTP_ACCEPT']) == 'application/xrds+xml': + logging.debug('redirecting to yadis_xrdf:%s' % reverse('yadis_xrdf')) return HttpResponseRedirect(reverse('yadis_xrdf')) return response diff --git a/django_authopenid/models.py b/django_authopenid/models.py index 7b2e1c02..a12c2fec 100644 --- a/django_authopenid/models.py +++ b/django_authopenid/models.py @@ -71,6 +71,10 @@ class UserPasswordQueue(models.Model): return self.user.username class ExternalLoginData(models.Model): + """this class was added by Evgeny to associate + external authentication user with django user + probably it just does not belong here... (EF) + """ 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 112cbbe1..e1986d19 100644..100755 --- a/django_authopenid/urls.py +++ b/django_authopenid/urls.py @@ -1,7 +1,21 @@ # -*- coding: utf-8 -*- from django.conf.urls.defaults import patterns, url from django.utils.translation import ugettext as _ +from django.conf import settings +#print 'stuff to import %s' % settings.EXTERNAL_LOGIN_APP.__name__ + '.views' +#try: +# settings.EXTERNAL_LOGIN_APP = __import__('mediawiki.views') +#print 'stuff to import %s' % settings.EXTERNAL_LOGIN_APP.__name__ + '.views' +#try: +# print 'imported fine' +# print settings.EXTERNAL_LOGIN_APP.__dict__.keys() +#except: +# print 'dammit!' +#from mediawiki.views import signup_view +#settings.EXTERNAL_LOGIN_APP.views.signup_view() + +#print settings.EXTERNAL_LOGIN_APP.__dict__.keys() urlpatterns = patterns('django_authopenid.views', # yadis rdf url(r'^yadis.xrdf$', 'xrdf', name='yadis_xrdf'), @@ -12,7 +26,6 @@ urlpatterns = patterns('django_authopenid.views', 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 @@ -29,3 +42,21 @@ urlpatterns = patterns('django_authopenid.views', url(r'^%s$' % _('openid/'), 'changeopenid', name='user_changeopenid'), url(r'^%s$' % _('delete/'), 'delete', name='user_delete'), ) + +#todo move these out of this file completely +if settings.USE_EXTERNAL_LEGACY_LOGIN: + from forum.forms import NotARobotForm + EXTERNAL_LOGIN_APP = settings.LOAD_EXTERNAL_LOGIN_APP() + urlpatterns += patterns('', + url('^%s$' % _('external-login/forgot-password/'),\ + 'django_authopenid.views.external_legacy_login_info', \ + name='user_external_legacy_login_issues'), + url('^%s$' % _('external-login/signup/'), \ + EXTERNAL_LOGIN_APP.views.signup,\ + name='user_external_legacy_login_signup'), +# url('^%s$' % _('external-login/signup/'), \ +# EXTERNAL_LOGIN_APP.forms.RegisterFormWizard( \ +# [EXTERNAL_LOGIN_APP.forms.RegisterForm, \ +# NotARobotForm]),\ +# name='user_external_legacy_login_signup'), + ) diff --git a/django_authopenid/util.py b/django_authopenid/util.py index edb6808e..969af0b9 100644 --- a/django_authopenid/util.py +++ b/django_authopenid/util.py @@ -6,7 +6,6 @@ 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 @@ -15,28 +14,16 @@ try: except: from yadis import xri -import time, base64, hashlib, operator -import urllib +import time, base64, hashlib, operator, logging +from utils.forms import clean_next, get_next_url from models import Association, Nonce __all__ = ['OpenID', 'DjangoOpenIDStore', 'from_openid_response', 'clean_next'] -DEFAULT_NEXT = '/' + getattr(settings, 'FORUM_SCRIPT_ALIAS') -def clean_next(next): - if next is None: - return DEFAULT_NEXT - next = str_to_unicode(urllib.unquote(next), 'utf-8') - next = next.strip() - if next.startswith('/'): - 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): + logging.debug('init janrain openid object') self.openid = openid_ self.issued = issued self.attrs = attrs or {} diff --git a/django_authopenid/views.py b/django_authopenid/views.py index feb6b58f..16a78864 100644..100755 --- a/django_authopenid/views.py +++ b/django_authopenid/views.py @@ -32,7 +32,7 @@ from django.http import HttpResponseRedirect, get_host, Http404, \ HttpResponseServerError -from django.shortcuts import render_to_response as render +from django.shortcuts import render_to_response from django.template import RequestContext, loader, Context from django.conf import settings from django.contrib.auth.models import User @@ -60,37 +60,37 @@ except ImportError: import re import urllib - -from forum.forms import EditUserEmailFeedsForm -from django_authopenid.util import OpenID, DjangoOpenIDStore, from_openid_response, get_next_url +from forum.forms import SimpleEmailSubscribeForm +from django_authopenid.util import OpenID, DjangoOpenIDStore, from_openid_response 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 +from utils.forms import get_next_url + +EXTERNAL_LOGIN_APP = settings.LOAD_EXTERNAL_LOGIN_APP() 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) + EXTERNAL_LOGIN_APP.api.login(request,user) #1) get old session key session_key = request.session.session_key #2) login and get new session key _login(request,user) #3) send signal with old session key as argument + logging.debug('logged in user %s with session key %s' % (user.username, session_key)) 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) + EXTERNAL_LOGIN_APP.api.logout(request) def get_url_host(request): if request.is_secure(): @@ -116,17 +116,22 @@ def ask_openid(request, openid_url, redirect_to, on_failure=None, settings, 'OPENID_DISALLOW_INAMES', False ): msg = _("i-names are not supported") + logging.debug('openid failed becaise i-names are not supported') return on_failure(request, msg) consumer = Consumer(request.session, DjangoOpenIDStore()) try: auth_request = consumer.begin(openid_url) except DiscoveryFailure: msg = _(u"OpenID %(openid_url)s is invalid" % {'openid_url':openid_url}) + logging.debug(msg) return on_failure(request, msg) + logging.debug('openid seemed to work') if sreg_request: + logging.debug('adding sreg_request - wtf it is?') auth_request.addExtension(sreg_request) redirect_url = auth_request.redirectURL(trust_root, redirect_to) + logging.debug('redirecting to %s' % redirect_url) return HttpResponseRedirect(redirect_url) def complete(request, on_success=None, on_failure=None, return_to=None): @@ -134,31 +139,41 @@ def complete(request, on_success=None, on_failure=None, return_to=None): on_success = on_success or default_on_success on_failure = on_failure or default_on_failure + logging.debug('in django_authopenid.complete') + consumer = Consumer(request.session, DjangoOpenIDStore()) # make sure params are encoded in utf8 params = dict((k,smart_unicode(v)) for k, v in request.GET.items()) openid_response = consumer.complete(params, return_to) if openid_response.status == SUCCESS: + logging.debug('SUCCESS') return on_success(request, openid_response.identity_url, openid_response) elif openid_response.status == CANCEL: + logging.debug('CANCEL') return on_failure(request, 'The request was canceled') elif openid_response.status == FAILURE: + logging.debug('FAILURE') return on_failure(request, openid_response.message) elif openid_response.status == SETUP_NEEDED: + logging.debug('SETUP NEEDED') return on_failure(request, 'Setup needed') else: + logging.debug('BAD OPENID STATUS') assert False, "Bad openid status: %s" % openid_response.status def default_on_success(request, identity_url, openid_response): """ default action on openid signin success """ + logging.debug('') request.session['openid'] = from_openid_response(openid_response) + logging.debug('performing default action on openid success %s' % get_next_url(request)) return HttpResponseRedirect(get_next_url(request)) def default_on_failure(request, message): """ default failure action on signin """ - return render('openid_failure.html', { + logging.debug('default openid failure action') + return render_to_response('openid_failure.html', { 'message': message }) @@ -177,21 +192,23 @@ def signin(request,newquestion=False,newanswer=False): """ signin page. It manages the legacy authentification (user/password) and openid authentification - + url: /signin/ template : authopenid/signin.htm """ + logging.debug('in signin view') request.encoding = 'UTF-8' on_failure = signin_failure - email_feeds_form = EditUserEmailFeedsForm() + email_feeds_form = SimpleEmailSubscribeForm() next = get_next_url(request) form_signin = OpenidSigninForm(initial={'next':next}) form_auth = ClassicLoginForm(initial={'next':next}) - if request.POST: + if request.method == 'POST': #'blogin' - password login if 'blogin' in request.POST.keys(): + logging.debug('processing classic login form submission') form_auth = ClassicLoginForm(request.POST) if form_auth.is_valid(): #have login and password and need to login through external website @@ -201,52 +218,49 @@ def signin(request,newquestion=False,newanswer=False): 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 + + #2) try to extract user email and nickname from external service + email = EXTERNAL_LOGIN_APP.api.get_email(username,password) + screen_name = EXTERNAL_LOGIN_APP.api.get_screen_name(username,password) + + #3) 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} + username_taken = User.is_username_taken(screen_name) + + email_feeds_form = SimpleEmailSubscribeForm() + form_data = {'username':screen_name,'email':email,'next':next} form = OpenidRegisterForm(initial=form_data) - template_data = {'form1':form,'username':username,\ + template_data = {'form1':form,'username':screen_name,\ '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,\ + return render_to_response('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) + EXTERNAL_LOGIN_APP.api.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(): + logging.debug('processing classic (login/password) create account form submission') #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) + email_feeds_form = SimpleEmailSubscribeForm(request.POST) form1_is_valid = form.is_valid() form2_is_valid = email_feeds_form.is_valid() if form1_is_valid and form2_is_valid: @@ -254,10 +268,10 @@ def signin(request,newquestion=False,newanswer=False): 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_LOGIN_APP.api.connect_local_user_to_external_user(user,username,password) external_username = request.session['external_username'] eld = ExternalLoginData.objects.get(external_username=external_username) eld.user = user @@ -266,7 +280,9 @@ def signin(request,newquestion=False,newanswer=False): email_feeds_form.save(user) del request.session['external_username'] del request.session['external_password'] - return HttpResponseRedirect(reverse('index')) + response = HttpResponseRedirect(reverse('index')) + EXTERNAL_LOGIN_APP.api.set_login_cookies(response, user) + return response else: if password: del request.session['external_username'] @@ -281,14 +297,16 @@ def signin(request,newquestion=False,newanswer=False): '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, + return render_to_response('authopenid/complete.html',data, context_instance=RequestContext(request)) else: raise Http404 - + elif 'bsignin' in request.POST.keys() or 'openid_username' in request.POST.keys(): + logging.debug('processing signin with openid submission') form_signin = OpenidSigninForm(request.POST) if form_signin.is_valid(): + logging.debug('OpenidSigninForm is valid') next = form_signin.cleaned_data['next'] sreg_req = sreg.SRegRequest(optional=['nickname', 'email']) redirect_to = "%s%s?%s" % ( @@ -301,13 +319,17 @@ def signin(request,newquestion=False,newanswer=False): redirect_to, on_failure=signin_failure, sreg_request=sreg_req) - - + else: + logging.debug('OpenidSigninForm is NOT valid! -> redisplay login view') + #if request is GET + if request.method == 'GET': + logging.debug('request method was GET') question = None if newquestion == True: from forum.models import AnonymousQuestion as AQ session_key = request.session.session_key + logging.debug('retrieving anonymously posted question associated with session %s' % session_key) qlist = AQ.objects.filter(session_key=session_key).order_by('-added_at') if len(qlist) > 0: question = qlist[0] @@ -315,47 +337,59 @@ def signin(request,newquestion=False,newanswer=False): if newanswer == True: from forum.models import AnonymousAnswer as AA session_key = request.session.session_key + logging.debug('retrieving posted answer associated with session %s' % session_key) alist = AA.objects.filter(session_key=session_key).order_by('-added_at') if len(alist) > 0: answer = alist[0] - - return render('authopenid/signin.html', { + + logging.debug('showing signin view') + return render_to_response('authopenid/signin.html', { 'question':question, 'answer':answer, 'form1': form_auth, 'form2': form_signin, 'msg': request.GET.get('msg',''), 'sendpw_url': reverse('user_sendpw'), + 'fb_api_key': settings.FB_API_KEY, }, context_instance=RequestContext(request)) def complete_signin(request): """ in case of complete signin with openid """ + logging.debug('')#blank log just for the trace 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. - + If the openid is already registered, the user is redirected to url set par next or in settings with OPENID_REDIRECT_NEXT variable. If none of these urls are set user is redirectd to /. - + if openid isn't registered user is redirected to register page. """ + logging.debug('') openid_ = from_openid_response(openid_response) #create janrain OpenID object request.session['openid'] = openid_ try: + logging.debug('trying to get user associated with this openid...') rel = UserAssociation.objects.get(openid_url__exact = str(openid_)) + logging.debug('success') except: + logging.debug('failed --> try to register brand new user') # try to register this new user return register(request) user_ = rel.user if user_.is_active: user_.backend = "django.contrib.auth.backends.ModelBackend" + logging.debug('user is active --> attached django auth ModelBackend --> calling login') login(request, user_) - + logging.debug('success') + else: + logging.debug('user is inactive, do not log them in') + logging.debug('redirecting to %s' % get_next_url(request)) return HttpResponseRedirect(get_next_url(request)) def is_association_exist(openid_url): @@ -365,29 +399,32 @@ def is_association_exist(openid_url): uassoc = UserAssociation.objects.get(openid_url__exact = openid_url) except: is_exist = False + logging.debug(str(is_exist)) return is_exist @not_authenticated def register(request): """ register an openid. - + If user is already a member he can associate its openid with its account. - + A new account could also be created and automaticaly associated to the openid. - + url : /complete/ - + template : authopenid/complete.html """ - + + logging.debug('') openid_ = request.session.get('openid', None) next = get_next_url(request) if not openid_: + logging.debug('oops, no openid in session --> go back to signin') return HttpResponseRedirect(reverse('user_signin') + '?next=%s' % next) - + nickname = openid_.sreg.get('nickname', '') email = openid_.sreg.get('email', '') form1 = OpenidRegisterForm(initial={ @@ -399,56 +436,74 @@ def register(request): 'next': next, 'username': nickname, }) - email_feeds_form = EditUserEmailFeedsForm() - + email_feeds_form = SimpleEmailSubscribeForm() + user_ = None is_redirect = False - if request.POST: + logging.debug('request method is %s' % request.method) + if request.method == 'POST': if 'bnewaccount' in request.POST.keys(): + logging.debug('trying to create new account associated with openid') form1 = OpenidRegisterForm(request.POST) - email_feeds_form = EditUserEmailFeedsForm(request.POST) - if form1.is_valid() and email_feeds_form.is_valid(): + email_feeds_form = SimpleEmailSubscribeForm(request.POST) + if not form1.is_valid(): + logging.debug('OpenidRegisterForm is INVALID') + elif not email_feeds_form.is_valid(): + logging.debug('SimpleEmailSubscribeForm is INVALID') + else: + logging.debug('OpenidRegisterForm and SimpleEmailSubscribeForm are valid') next = form1.cleaned_data['next'] is_redirect = True + logging.debug('creatng new django user %s ...' % form1.cleaned_data['username']) 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) + logging.debug('creating new openid user association %s <--> %s' \ + % (user_.username, str(openid_))) + uassoc = UserAssociation(openid_url=str(openid_), user_id=user_.id) uassoc.save() - + # login user_.backend = "django.contrib.auth.backends.ModelBackend" + logging.debug('logging the user in') login(request, user_) + logging.debug('saving email feed settings') email_feeds_form.save(user_) elif 'bverify' in request.POST.keys(): + logging.debug('processing OpenidVerify form') form2 = OpenidVerifyForm(request.POST) if form2.is_valid(): + logging.debug('form is valid') is_redirect = True next = form2.cleaned_data['next'] user_ = form2.get_user() - + logging.debug('creating new openid user association %s <--> %s' \ + % (user_.username, str(openid_))) uassoc = UserAssociation(openid_url=str(openid_), user_id=user_.id) uassoc.save() + logging.debug('logging the user in') login(request, user_) - + #check if we need to post a question that was added anonymously #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: if settings.EMAIL_VALIDATION == 'on': + logging.debug('sending email validation') 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(): + logging.debug('success, send user to main page') return HttpResponseRedirect(reverse('index')) else: + logging.debug('have really strange error') raise Exception('openid login failed')#should not ever get here openid_str = str(openid_) @@ -456,7 +511,7 @@ def register(request): base_url = bits[2] #assume this is base url url_bits = base_url.split('.') provider_name = url_bits[-2].lower() - + providers = {'yahoo':'<font color="purple">Yahoo!</font>', 'flickr':'<font color="#0063dc">flick</font><font color="#ff0084">r</font>™', 'google':'Google™', @@ -465,10 +520,12 @@ def register(request): } if provider_name not in providers: provider_logo = provider_name + logging.error('openid provider named "%s" has no pretty customized logo' % provider_name) else: provider_logo = providers[provider_name] - - return render('authopenid/complete.html', { + + logging.debug('printing authopenid/complete.html output') + return render_to_response('authopenid/complete.html', { 'form1': form1, 'form2': form2, 'email_feeds_form': email_feeds_form, @@ -485,11 +542,12 @@ def signin_failure(request, message): template : "authopenid/signin.html" """ + logging.debug('') next = get_next_url(request) form_signin = OpenidSigninForm(initial={'next': next}) form_auth = ClassicLoginForm(initial={'next': next}) - - return render('authopenid/signin.html', { + + return render_to_response('authopenid/signin.html', { 'msg': message, 'form1': form_auth, 'form2': form_signin, @@ -499,18 +557,21 @@ def signin_failure(request, message): def signup(request): """ signup page. Create a legacy account - + url : /signup/" - + templates: authopenid/signup.html, authopenid/confirm_email.txt """ + logging.debug('') if settings.USE_EXTERNAL_LEGACY_LOGIN == True: - return HttpResponseRedirect(reverse('user_external_legacy_login_issues')) + logging.debug('handling external legacy login registration') + return HttpResponseRedirect(reverse('user_external_legacy_login_signup')) next = get_next_url(request) - if request.POST: + logging.debug('request method was %s' % request.method) + if request.method == 'POST': form = ClassicRegisterForm(request.POST) - email_feeds_form = EditUserEmailFeedsForm(request.POST) - + email_feeds_form = SimpleEmailSubscribeForm(request.POST) + #validation outside if to remember form values form1_is_valid = form.is_valid() form2_is_valid = email_feeds_form.is_valid() @@ -519,11 +580,11 @@ def signup(request): 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) - + EXTERNAL_LOGIN_APP.api.create_user(username,email,password) + user_.backend = "django.contrib.auth.backends.ModelBackend" login(request, user_) email_feeds_form.save(user_) @@ -541,11 +602,15 @@ def signup(request): message = message_template.render(message_context) send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [user_.email]) + logging.debug('new user with login and password created!') return HttpResponseRedirect(next) + else: + logging.debug('create classic account forms were invalid') else: form = ClassicRegisterForm(initial={'next':next}) - email_feeds_form = EditUserEmailFeedsForm() - return render('authopenid/signup.html', { + email_feeds_form = SimpleEmailSubscribeForm() + logging.debug('printing legacy signup form') + return render_to_response('authopenid/signup.html', { 'form': form, 'email_feeds_form': email_feeds_form }, context_instance=RequestContext(request)) @@ -558,19 +623,24 @@ def signout(request): url : /signout/" """ + logging.debug('') try: + logging.debug('deleting openid session var') del request.session['openid'] except KeyError: + logging.debug('failed') pass logout(request) + logging.debug('user logged out') return HttpResponseRedirect(get_next_url(request)) def xrdf(request): url_host = get_url_host(request) + logging.debug('what does this do??') return_to = [ "%s%s" % (url_host, reverse('user_complete_signin')) ] - return render('authopenid/yadis.xrdf', { + return render_to_response('authopenid/yadis.xrdf', { 'return_to': return_to }, context_instance=RequestContext(request)) @@ -587,6 +657,7 @@ def account_settings(request): template : authopenid/settings.html """ + logging.debug('') msg = request.GET.get('msg', '') is_openid = True @@ -598,7 +669,7 @@ def account_settings(request): is_openid = False - return render('authopenid/settings.html', { + return render_to_response('authopenid/settings.html', { 'msg': msg, 'is_openid': is_openid }, context_instance=RequestContext(request)) @@ -611,6 +682,7 @@ def changepw(request): url : /changepw/ template: authopenid/changepw.html """ + logging.debug('') user_ = request.user if user_.has_usable_password(): @@ -632,7 +704,7 @@ def changepw(request): else: form = ChangePasswordForm(user=user_) - return render('authopenid/changepw.html', {'form': form }, + return render_to_response('authopenid/changepw.html', {'form': form }, context_instance=RequestContext(request)) def find_email_validation_messages(user): @@ -696,7 +768,7 @@ def send_email_key(request): if settings.EMAIL_VALIDATION != 'off': if request.user.email_isvalid: - return render('authopenid/changeemail.html', + return render_to_response('authopenid/changeemail.html', { 'email': request.user.email, 'action_type': 'key_not_sent', 'change_link': reverse('user_changeemail')}, @@ -711,7 +783,8 @@ 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', + logging.debug('') + return render_to_response('authopenid/changeemail.html', { 'email': request.user.email, 'change_email_url': reverse('user_changeemail'), 'action_type': 'validate', }, @@ -722,6 +795,7 @@ def verifyemail(request,id=None,key=None): view that is shown when user clicks email validation link url = /email/verify/{{user.id}}/{{user.email_key}}/ """ + logging.debug('') if settings.EMAIL_VALIDATION != 'off': user = User.objects.get(id=id) if user: @@ -729,9 +803,11 @@ def verifyemail(request,id=None,key=None): user.email_isvalid = True clear_email_validation_message(user) user.save() - return render('authopenid/changeemail.html', { + return render_to_response('authopenid/changeemail.html', { 'action_type': 'validation_complete', }, context_instance=RequestContext(request)) + else: + logging.error('hmm, no user found for email validation message - foul play?') raise Http404 @login_required @@ -743,6 +819,7 @@ def changeemail(request, action='change'): template : authopenid/changeemail.html """ + logging.debug('') msg = request.GET.get('msg', None) extension_args = {} user_ = request.user @@ -772,7 +849,7 @@ def changeemail(request, action='change'): form = ChangeEmailForm(initial={'email': user_.email}, user=user_) - output = render('authopenid/changeemail.html', { + output = render_to_response('authopenid/changeemail.html', { 'form': form, 'email': user_.email, 'action_type': action, @@ -787,6 +864,7 @@ def changeemail(request, action='change'): return output def emailopenid_success(request, identity_url, openid_response): + logging.debug('') openid_ = from_openid_response(openid_response) user_ = request.user @@ -816,6 +894,7 @@ def emailopenid_success(request, identity_url, openid_response): def emailopenid_failure(request, message): + logging.debug('') redirect_to = "%s?msg=%s" % ( reverse('user_changeemail'), urlquote_plus(message)) return HttpResponseRedirect(redirect_to) @@ -830,6 +909,7 @@ def changeopenid(request): template: authopenid/changeopenid.html """ + logging.error('change openid view - never tested it yet!!!') extension_args = {} openid_url = '' @@ -856,13 +936,14 @@ def changeopenid(request): changeopenid_failure, redirect_to) form = ChangeopenidForm(initial={'openid_url': openid_url }, user=user_) - return render('authopenid/changeopenid.html', { + return render_to_response('authopenid/changeopenid.html', { 'form': form, 'has_openid': has_openid, 'msg': msg }, context_instance=RequestContext(request)) def changeopenid_success(request, identity_url, openid_response): + logging.error('never tested this worflow') openid_ = from_openid_response(openid_response) is_exist = True try: @@ -896,6 +977,7 @@ def changeopenid_success(request, identity_url, openid_response): def changeopenid_failure(request, message): + logging.error('never tested this workflow') redirect_to = "%s?msg=%s" % ( reverse('user_changeopenid'), urlquote_plus(message)) @@ -906,16 +988,17 @@ def delete(request): """ delete view. Allow user to delete its account. Password/openid are required to confirm it. He should also check the confirm checkbox. - + url : /delete - + template : authopenid/delete.html """ - + logging.error('deleting account - never tested this') + extension_args = {} user_ = request.user - + redirect_to = get_url_host(request) + reverse('user_delete') if request.POST: form = DeleteForm(request.POST, user=user_) @@ -931,14 +1014,15 @@ def delete(request): redirect_to) form = DeleteForm(user=user_) - + msg = request.GET.get('msg','') - return render('authopenid/delete.html', { + return render_to_response('authopenid/delete.html', { 'form': form, 'msg': msg, }, context_instance=RequestContext(request)) def deleteopenid_success(request, identity_url, openid_response): + logging.error('never tested this') openid_ = from_openid_response(openid_response) user_ = request.user @@ -964,29 +1048,38 @@ def deleteopenid_success(request, identity_url, openid_response): def deleteopenid_failure(request, message): + logging.error('never tested this') 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)) + logging.debug('maybe this view does not belong in this library') + feedback_url = reverse('feedback') + return render_to_response('authopenid/external_legacy_login_info.html', + {'feedback_url':feedback_url}, + context_instance=RequestContext(request)) def sendpw(request): """ send a new password to the user. It return a mail with a new pasword and a confirm link in. To activate the new password, the user should click on confirm link. - + url : /sendpw/ - + templates : authopenid/sendpw_email.txt, authopenid/sendpw.html """ + logging.debug('') if settings.USE_EXTERNAL_LEGACY_LOGIN == True: + logging.debug('delegating to view dealing with external password recovery') return HttpResponseRedirect(reverse('user_external_legacy_login_issues')) - + msg = request.GET.get('msg','') - if request.POST: + logging.debug('request method is %s' % request.method) + if request.method == 'POST': form = EmailPasswordForm(request.POST) if form.is_valid(): + logging.debug('EmailPasswordForm is valid') new_pw = User.objects.make_random_password() confirm_key = UserPasswordQueue.objects.get_new_confirm_key() try: @@ -1005,6 +1098,7 @@ def sendpw(request): message_template = loader.get_template( 'authopenid/sendpw_email.txt') key_link = settings.APP_URL + reverse('user_confirmchangepw') + '?key=' + confirm_key + logging.debug('emailing new password for %s' % form.user_cache.username) message_context = Context({ 'site_url': settings.APP_URL + reverse('index'), 'key_link': key_link, @@ -1017,13 +1111,13 @@ def sendpw(request): msg = _("A new password and the activation link were sent to your email address.") else: form = EmailPasswordForm() - - return render('authopenid/sendpw.html', { + + logging.debug('showing reset password form') + return render_to_response('authopenid/sendpw.html', { 'form': form, 'msg': msg }, context_instance=RequestContext(request)) - def confirmchangepw(request): """ view to set new password when the user click on confirm link @@ -1031,14 +1125,16 @@ def confirmchangepw(request): replace old password with new password and remove confirm ley from the queue. Then it redirect the user to signin page. - + url : /sendpw/confirm/?key - + """ + logging.debug('') confirm_key = request.GET.get('key', '') if not confirm_key: + logging.error('someone called confirm password without a key!') return HttpResponseRedirect(reverse('index')) - + try: uqueue = UserPasswordQueue.objects.get( confirm_key__exact=confirm_key @@ -1046,25 +1142,28 @@ def confirmchangepw(request): except: msg = _("Could not change password. Confirmation key '%s'\ is not registered." % confirm_key) + logging.error(msg) redirect = "%s?msg=%s" % ( reverse('user_sendpw'), urlquote_plus(msg)) return HttpResponseRedirect(redirect) - + try: user_ = User.objects.get(id=uqueue.user.id) except: msg = _("Can not change password. User don't exist anymore \ in our database.") + logging.error(msg) redirect = "%s?msg=%s" % (reverse('user_sendpw'), urlquote_plus(msg)) return HttpResponseRedirect(redirect) - + user_.set_password(uqueue.new_password) user_.save() uqueue.delete() msg = _("Password changed for %s. You may now sign in." % user_.username) + logging.debug(msg) redirect = "%s?msg=%s" % (reverse('user_signin'), urlquote_plus(msg)) - + return HttpResponseRedirect(redirect) |