diff options
author | Magnus Hagander | 2014-12-30 19:11:46 +0000 |
---|---|---|
committer | Magnus Hagander | 2014-12-30 19:11:46 +0000 |
commit | baab4644ea89a3ba36c4376387362711584e535c (patch) | |
tree | 6b0a1a2fef82abf4784041e5e1d5f661ed969b12 /postgresqleu/auth.py | |
parent | e05b66b3033b5fdc1c1e2c4eb278c5d6262c7198 (diff) |
Add suppot for importing upstream users
Initially, support this for invoices and for managers of sponsorships,
which are the most likely usecases for it. More usecases can be added
in the future as they are found.
Diffstat (limited to 'postgresqleu/auth.py')
-rw-r--r-- | postgresqleu/auth.py | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/postgresqleu/auth.py b/postgresqleu/auth.py index ecb3d486..888aa9dd 100644 --- a/postgresqleu/auth.py +++ b/postgresqleu/auth.py @@ -6,7 +6,7 @@ # # To integrate with django, you need the following: # * Make sure the view "login" from this module is used for login -# * Map an url somwehere (typicall /auth_receive/) to the auth_receive +# * Map an url somwehere (typically /auth_receive/) to the auth_receive # view. # * In settings.py, set AUTHENTICATION_BACKENDS to point to the class # AuthBackend in this module. @@ -26,6 +26,8 @@ from django.contrib.auth import logout as django_logout from django.conf import settings import base64 +import simplejson +import socket import urlparse import urllib from Crypto.Cipher import AES @@ -168,3 +170,61 @@ We apologize for the inconvenience. if hasattr(settings, 'PGAUTH_REDIRECT_SUCCESS'): return HttpResponseRedirect(settings.PGAUTH_REDIRECT_SUCCESS) raise Exception("Authentication successful, but don't know where to redirect!") + + +# Perform a search in the central system. Note that the results are returned as an +# array of dicts, and *not* as User objects. To be able to for example reference the +# user through a ForeignKey, a User object must be materialized locally. We don't do +# that here, as this search might potentially return a lot of unrelated users since +# it's a wildcard match. +# Unlike the authentication, searching does not involve the browser - we just make +# a direct http call. +def user_search(searchterm=None, userid=None): + # If upsteam isn't responding quickly, it's not going to respond at all, and + # 10 seconds is already quite long. + socket.setdefaulttimeout(10) + if userid: + q = {'u': userid} + else: + q = {'s': searchterm} + + u = urllib.urlopen('%ssearch/?%s' % ( + settings.PGAUTH_REDIRECT, + urllib.urlencode(q), + )) + (ivs, datas) = u.read().split('&') + u.close() + + # Decryption time + decryptor = AES.new(base64.b64decode(settings.PGAUTH_KEY), + AES.MODE_CBC, + base64.b64decode(ivs, "-_")) + s = decryptor.decrypt(base64.b64decode(datas, "-_")).rstrip(' ') + j = simplejson.loads(s) + + return j + +# Import a user into the local authentication system. Will initially +# make a search for it, and if anything other than one entry is returned +# the import will fail. +# Import is only supported based on userid - so a search should normally +# be done first. This will result in multiple calls to the upstream +# server, but they are cheap... +# The call to this function should normally be wrapped in a transaction, +# and this function itself will make no attempt to do anything about that. +def user_import(uid): + u = user_search(userid=uid) + if len(u) != 1: + raise Exception("Internal error, duplicate or no user found") + + u = u[0] + + if User.objects.filter(username=u['u']).exists(): + raise Exception("User already exists") + + User(username=u['u'], + first_name=u['f'], + last_name=u['l'], + email=u['e'], + password='setbypluginnotsha1', + ).save() |