# -*- coding: utf-8 -*- from openid.store.interface import OpenIDStore from openid.association import Association as OIDAssociation from openid.extensions import sreg import openid.store from django.db.models.query import Q from django.conf import settings from django.http import str_to_unicode # needed for some linux distributions like debian try: from openid.yadis import xri except: from yadis import xri import time, base64, hashlib, operator import urllib from models import Association, Nonce __all__ = ['OpenID', 'DjangoOpenIDStore', 'from_openid_response', 'clean_next'] DEFAULT_NEXT = getattr(settings, 'OPENID_REDIRECT_NEXT', '/') 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 class OpenID: def __init__(self, openid_, issued, attrs=None, sreg_=None): self.openid = openid_ self.issued = issued self.attrs = attrs or {} self.sreg = sreg_ or {} self.is_iname = (xri.identifierScheme(openid_) == 'XRI') def __repr__(self): return '' % self.openid def __str__(self): return self.openid class DjangoOpenIDStore(OpenIDStore): def __init__(self): self.max_nonce_age = 6 * 60 * 60 # Six hours def storeAssociation(self, server_url, association): assoc = Association( server_url = server_url, handle = association.handle, secret = base64.encodestring(association.secret), issued = association.issued, lifetime = association.issued, assoc_type = association.assoc_type ) assoc.save() def getAssociation(self, server_url, handle=None): assocs = [] if handle is not None: assocs = Association.objects.filter( server_url = server_url, handle = handle ) else: assocs = Association.objects.filter( server_url = server_url ) if not assocs: return None associations = [] for assoc in assocs: association = OIDAssociation( assoc.handle, base64.decodestring(assoc.secret), assoc.issued, assoc.lifetime, assoc.assoc_type ) if association.getExpiresIn() == 0: self.removeAssociation(server_url, assoc.handle) else: associations.append((association.issued, association)) if not associations: return None return associations[-1][1] def removeAssociation(self, server_url, handle): assocs = list(Association.objects.filter( server_url = server_url, handle = handle )) assocs_exist = len(assocs) > 0 for assoc in assocs: assoc.delete() return assocs_exist 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: ononce = Nonce.objects.get(reduce(operator.and_, query)) except Nonce.DoesNotExist: ononce = Nonce( server_url=server_url, timestamp=timestamp, salt=salt ) ononce.save() return True ononce.delete() return False def cleanupNonce(self): Nonce.objects.filter(timestamp