summaryrefslogtreecommitdiff
path: root/postgresqleu/auth.py
diff options
context:
space:
mode:
authorMagnus Hagander2014-12-30 19:11:46 +0000
committerMagnus Hagander2014-12-30 19:11:46 +0000
commitbaab4644ea89a3ba36c4376387362711584e535c (patch)
tree6b0a1a2fef82abf4784041e5e1d5f661ed969b12 /postgresqleu/auth.py
parente05b66b3033b5fdc1c1e2c4eb278c5d6262c7198 (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.py62
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()