Source

django-authopenid / django_openidconsummer_r19_2.diff

Full commit
Index: util.py
===================================================================
--- util.py	(revision 19)
+++ util.py	(working copy)
@@ -1,10 +1,18 @@
 from openid.store.interface import OpenIDStore
 from openid.association import Association as OIDAssociation
-from yadis import xri
+from django.db.models.query import Q
+from django.conf import settings
 
-import time, base64, md5
+import openid.store
 
-from django.conf import settings
+# needed for some linux distributions like debian
+try:
+    from openid.yadis import xri
+except:
+    from yadis import xri
+
+import time, base64, md5, operator
+
 from models import Association, Nonce
 
 class OpenID:
@@ -70,27 +78,37 @@
         for assoc in assocs:
             assoc.delete()
         return assocs_exist
-    
-    def storeNonce(self, nonce):
-        nonce, created = Nonce.objects.get_or_create(
-            nonce = nonce, defaults={'expires': int(time.time())}
-        )
-    
-    def useNonce(self, nonce):
+
+    def useNonce(self, server_url, timestamp, salt):
+        if abs(timestamp - time.time()) > openid.store.nonce.SKEW:
+            return False
+        
+        query =[
+                Q(server_url__exact=server_url),
+                Q(timestamp__exact=timestamp),
+                Q(salt__exact=salt),
+        ]
         try:
-            nonce = Nonce.objects.get(nonce = nonce)
+            ononce = Nonce.objects.get(reduce(operator.and_, query))
         except Nonce.DoesNotExist:
-            return 0
+            ononce = Nonce(
+                    server_url=server_url,
+                    timestamp=timestamp,
+                    salt=salt
+            );
+            ononce.save()
+            return True
         
-        # Now check nonce has not expired
-        nonce_age = int(time.time()) - nonce.expires
-        if nonce_age > self.max_nonce_age:
-            present = 0
-        else:
-            present = 1
-        nonce.delete()
-        return present
-    
+        ononce.delete()
+
+        return False
+   
+    def cleanupNonce(self):
+        Nonce.objects.filter(timestamp<int(time.time()) - nonce.SKEW).delete()
+
+    def cleaupAssociations(self):
+        Association.objects.extra(where=['issued + lifetimeint<(%s)' % time.time()]).delete()
+
     def getAuthKey(self):
         # Use first AUTH_KEY_LEN characters of md5 hash of SECRET_KEY
         return md5.new(settings.SECRET_KEY).hexdigest()[:self.AUTH_KEY_LEN]
@@ -101,6 +119,6 @@
 def from_openid_response(openid_response):
     issued = int(time.time())
     return OpenID(
-        openid_response.identity_url, issued, openid_response.signed_args, 
-        openid_response.extensionResponse('sreg')
+        openid_response.identity_url, issued, openid_response.signed_fields, 
+        openid_response.extensionResponse('sreg', False)
     )
Index: views.py
===================================================================
--- views.py	(revision 19)
+++ views.py	(working copy)
@@ -2,15 +2,24 @@
 from django.shortcuts import render_to_response as render
 from django.template import RequestContext
 from django.conf import settings
+from django.utils.http import urlquote_plus, urlquote
 
 import md5, re, time, urllib
 from openid.consumer.consumer import Consumer, \
     SUCCESS, CANCEL, FAILURE, SETUP_NEEDED
 from openid.consumer.discover import DiscoveryFailure
-from yadis import xri
 
+# needed for some linux distributions like debian
+try:
+    from openid.yadis import xri
+except:
+    from yadis import xriœ
+
+
 from util import OpenID, DjangoOpenIDStore, from_openid_response
 
+from forms import OpenidSigninForm
+
 from django.utils.html import escape
 
 def get_url_host(request):
@@ -42,67 +51,67 @@
         on_failure=None):
     
     on_failure = on_failure or default_on_failure
-    
-    if request.GET.get('logo'):
-        # Makes for a better demo
-        return logo(request)
-    
     extension_args = extension_args or {}
-    if sreg:
-        extension_args['sreg.optional'] = sreg
-    trust_root = getattr(
-        settings, 'OPENID_TRUST_ROOT', get_url_host(request) + '/'
-    )
-    redirect_to = redirect_to or getattr(
-        settings, 'OPENID_REDIRECT_TO',
-        # If not explicitly set, assume current URL with complete/ appended
-        get_full_url(request).split('?')[0] + 'complete/'
-    )
-    # In case they were lazy...
-    if not redirect_to.startswith('http://'):
-        redirect_to =  get_url_host(request) + redirect_to
     
-    if request.GET.get('next') and is_valid_next_url(request.GET['next']):
-        if '?' in redirect_to:
-            join = '&'
-        else:
-            join = '?'
-        redirect_to += join + urllib.urlencode({
+    next = ''
+    if request.GET.get('next'):
+        next = urllib.urlencode({
             'next': request.GET['next']
         })
-    
-    user_url = request.POST.get('openid_url', None)
-    if not user_url:
-        request_path = request.path
-        if request.GET.get('next'):
-            request_path += '?' + urllib.urlencode({
-                'next': request.GET['next']
-            })
         
-        return render('openid_signin.html', {
-            'action': request_path,
-            'logo': request.path + '?logo=1',
-        })
+  
+    form_signin = OpenidSigninForm(initial={'next':next})
+    if request.POST:
+        form_signin = OpenidSigninForm(request.POST)
+        if form_signin.is_valid():
+            consumer = Consumer(request.session, DjangoOpenIDStore())
+            try:
+                auth_request = consumer.begin(form_signin.cleaned_data['openid_url'])
+            except DiscoveryFailure:
+                return on_failure(request, "The OpenID was invalid")
+
+            if sreg:
+                extension_args['sreg.optional'] = sreg
+            
+            trust_root = getattr(
+                    settings, 'OPENID_TRUST_ROOT', get_url_host(request) + '/'
+                )
+        
+            redirect_to = redirect_to or getattr(
+                settings, 'OPENID_REDIRECT_TO',
+                # If not explicitly set, assume current URL with complete/ appended
+                get_full_url(request).split('?')[0] + 'complete/'
+            )
+
+            # TODO: add redirect_to in form 
+            if not redirect_to.startswith('http://'):
+                redirect_to =  get_url_host(request) + redirect_to
+
+
+            if 'next' in form_signin.cleaned_data and next != "":
+                if '?' in redirect_to:
+                    join = '&'
+                else:
+                    join = '?'
+                redirect_to += join + urllib.urlencode({
+                    'next': form_signin.cleaned_data['next']
+                })
     
-    if xri.identifierScheme(user_url) == 'XRI' and getattr(
-        settings, 'OPENID_DISALLOW_INAMES', False
-        ):
-        return on_failure(request, 'i-names are not supported')
+            # Add extension args (for things like simple registration)
+            for name, value in extension_args.items():
+                namespace, key = name.split('.', 1)
+                auth_request.addExtensionArg(namespace, key, value)
     
-    consumer = Consumer(request.session, DjangoOpenIDStore())
-    try:
-        auth_request = consumer.begin(user_url)
-    except DiscoveryFailure:
-        return on_failure(request, "The OpenID was invalid")
+            redirect_url = auth_request.redirectURL(trust_root, redirect_to)
+            return HttpResponseRedirect(redirect_url)
+
+    return render('openid_signin.html', {
+            'form': form_signin,
+            'action': request.path,
+            'logo': request.path + 'logo/',
+            'openids': request.session['openids'],
+        })
     
-    # Add extension args (for things like simple registration)
-    for name, value in extension_args.items():
-        namespace, key = name.split('.', 1)
-        auth_request.addExtensionArg(namespace, key, value)
-    
-    redirect_url = auth_request.redirectURL(trust_root, redirect_to)
-    return HttpResponseRedirect(redirect_url)
-
 def complete(request, on_success=None, on_failure=None):
     on_success = on_success or default_on_success
     on_failure = on_failure or default_on_failure
Index: models.py
===================================================================
--- models.py	(revision 19)
+++ models.py	(working copy)
@@ -1,11 +1,14 @@
 from django.db import models
 
 class Nonce(models.Model):
-    nonce = models.CharField(maxlength=8)
-    expires = models.IntegerField()
-    def __str__(self):
-        return "Nonce: %s" % self.nonce
+    server_url = models.CharField(maxlength=255)
+    timestamp = models.IntegerField()
+    salt = models.CharField(max_length=40)
+    
+    def __unicode__(self):
+        return u"Nonce: %s" % self.id
 
+    
 class Association(models.Model):
     server_url = models.TextField(maxlength=2047)
     handle = models.CharField(maxlength=255)
@@ -13,5 +16,7 @@
     issued = models.IntegerField()
     lifetime = models.IntegerField()
     assoc_type = models.TextField(maxlength=64)
-    def __str__(self):
-        return "Association: %s, %s" % (self.server_url, self.handle)
+    
+    def __unicode__(self):
+        return u"Association: %s, %s" % (self.server_url, self.handle)
+
Index: urls.py
===================================================================
--- urls.py	(revision 0)
+++ urls.py	(revision 0)
@@ -0,0 +1,10 @@
+from django.conf.urls.defaults import patterns
+
+urlpatterns = patterns('',
+    (r'^$', 'django_openidconsumer.views.begin'),
+    (r'^logo/$', 'django_openidconsumer.views.logo'),
+    (r'^signout/$', 'django_openidconsumer.views.signout'),
+    (r'^complete/$', 'django_openidconsumer.views.complete'),
+
+    
+)
Index: forms.py
===================================================================
--- forms.py	(revision 0)
+++ forms.py	(revision 0)
@@ -0,0 +1,33 @@
+from django import newforms as forms
+from django.utils.translation import ugettext as _
+from django.conf import settings
+
+# needed for some linux distributions like debian
+try:
+    from openid.yadis import xri
+except:
+    from yadis import xri
+
+import re
+
+class OpenidSigninForm(forms.Form):
+    openid_url = forms.CharField(max_length=255, widget=forms.widgets.TextInput(attrs={'class': 'required openid'}))
+    next = forms.CharField(max_length=255,widget=forms.HiddenInput(), required=False)
+
+    def clean_openid_url(self):
+        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']
+
+    def clean_next(self):
+        if 'next' in self.cleaned_data and self.cleaned_data['next'] != "":
+            next_url_re = re.compile('^/[-\w/]+$')
+            if not next_url_re.match(self.cleaned_data['next']):
+                raise forms.ValidationError(_('next url "%s" is invalid' % self.cleaned_data['next']))
+            return self.cleaned_data['next']
+
+
Index: templates/openid_signin.html
===================================================================
--- templates/openid_signin.html	(revision 19)
+++ templates/openid_signin.html	(working copy)
@@ -1,3 +1,5 @@
+{% load i18n %}
+
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
 <html>
@@ -13,10 +15,24 @@
 </head>
 <body>
 <h1>Sign in with your OpenID</h1>
-
-<form action="{{ action }}" method="post">
-<p><input class="openid" type="text" name="openid_url"> <input type="submit" value="Sign in"></p>
-</form>
-
+{% if form.errors %}
+<p class="errors">{% trans "Please correct errors below:" %}<br />
+	{% if form.openid_url.errors %} 
+		<span class="error">{{ form.openid_url.errors|join:", " }}</span>
+	{% endif %}
+	{% if form.next.errors %} 
+		<span class="error">{{ form.next.errors|join:", " }}</span>
+	{% endif %}
+</p>
+{% endif %}
+<form name="fopenid" action="{{ action }}" method="post">
+    {{ form.next }}
+	<fieldset>
+		<legend>{% trans "Sign In Using Your OpenID" %}</legend>
+        <div class="form-row"><label for="id_openid_ul">{% trans "OpenId URL :" %}</label><br />{{ form.openid_url }}</div>     
+        <div class="submit-row "><input name="bsignin" type="submit" value="{% trans "Sign in with OPENID" %}"></div>
+		
+	</fieldset>
+</form>	
 </body>
 </html>