[open-ils-commits] r928 - in servres/trunk/conifer: . integration integration/linktool syrup templates (gfawcett)

svn at svn.open-ils.org svn at svn.open-ils.org
Fri Jul 16 15:37:14 EDT 2010


Author: gfawcett
Date: 2010-07-16 15:37:09 -0400 (Fri, 16 Jul 2010)
New Revision: 928

Added:
   servres/trunk/conifer/integration/auth_linktool.py
   servres/trunk/conifer/integration/clew-sections-for-site
   servres/trunk/conifer/integration/linktool/
   servres/trunk/conifer/integration/linktool/__init__.py
   servres/trunk/conifer/integration/linktool/app.py
   servres/trunk/conifer/integration/linktool/backend.py
Modified:
   servres/trunk/conifer/integration/uwindsor.py
   servres/trunk/conifer/local_settings.py.example
   servres/trunk/conifer/settings.py
   servres/trunk/conifer/syrup/integration.py
   servres/trunk/conifer/templates/tabbar.xhtml
   servres/trunk/conifer/urls.py
Log:
Preliminary Sakai Linktool support

Merged git branch 'linktool-auth' (6aae15a) into 'master'. I used
'--squash', which loses the merge history, but allows the merge to be
committed to SVN ('linktool-auth' was not an SVN branch).

Added: servres/trunk/conifer/integration/auth_linktool.py
===================================================================
--- servres/trunk/conifer/integration/auth_linktool.py	                        (rev 0)
+++ servres/trunk/conifer/integration/auth_linktool.py	2010-07-16 19:37:09 UTC (rev 928)
@@ -0,0 +1,61 @@
+from django.contrib.auth.models import User
+from django.conf import settings
+from urllib import quote
+from urllib2 import urlopen
+
+def testsign(query_string):
+    url = '%s?data=%s' % (settings.LINKTOOL_AUTH_URL, quote(query_string))
+    result = urlopen(url).read()
+    return (result == 'true')
+
+class LinktoolAuthBackend(object):
+
+    def __init__(self):
+        assert settings.LINKTOOL_AUTH_URL, \
+            'LinktoolAuthBackend requires settings.LINKTOOL_AUTH_URL'
+
+    def authenticate(self, request=None):
+        valid = testsign(request.META['QUERY_STRING'])
+        if valid:
+            username = request.GET['user']
+            return self.maybe_initialize_user(username)
+        return None
+
+    def get_user(self, user_id):
+        try:
+            return User.objects.get(pk=user_id)
+        except User.DoesNotExist:
+            return None
+
+    def maybe_initialize_user(self, username, look_local=True):
+        """Look up user in Django db; if not found, fetch user detail
+        from backend and set up a local user object. Return None if no
+        such user exists in either Django or the backend.
+
+        Setting look_local=False skips the Django search and heads
+        straight to the backend; this shaves a database call when
+        walking a set of backends to initialize a user. Skipping
+        look_local on a username that already exists in Django will
+        certainly lead to an integrity error.
+
+        This method is NOT part of the Django backend interface.
+        """
+        user = None
+        if look_local:
+            try:
+                user = User.objects.get(username=username)
+            except User.DoesNotExist:
+                pass
+        if user is None:
+            u = self.lookup(username)
+            if u:           # user found in LDAP or whatever.
+                user = User(username=username,
+                            first_name = u['first_name'],
+                            last_name  = u['last_name'],
+                            email      = u['email'])
+                user.set_unusable_password()
+                user.save()
+        return user
+
+    def lookup(self, username):
+        return None             # fixme

Added: servres/trunk/conifer/integration/clew-sections-for-site
===================================================================
--- servres/trunk/conifer/integration/clew-sections-for-site	                        (rev 0)
+++ servres/trunk/conifer/integration/clew-sections-for-site	2010-07-16 19:37:09 UTC (rev 928)
@@ -0,0 +1,41 @@
+#!/Users/graham/bin/python-oracle-cgi-wrapper
+# -*- mode: python -*-
+
+import os
+import cx_Oracle
+import re
+import sys
+import warnings
+import simplejson as json
+import time
+import cgitb
+
+#cgitb.enable(display=True)
+
+conn = cx_Oracle.connect('sakai/PASSWORD at clew')
+
+try:
+    siteid = os.environ['PATH_INFO'][1:]
+    assert len(siteid) == 36, 'malformed site id'
+
+    cursor = conn.cursor()
+    query = """
+    select provider_id from sakai_realm
+    where realm_id like '/site/' || :1
+    """
+    cursor.execute(query, (siteid,))
+    try:
+        provider_id = cursor.fetchone()[0] or ''
+    except:
+        raise Exception('site ID not found.')
+
+    providers = provider_id.split('+')
+    output = json.dumps({'status':'ok', 'siteid': siteid, 'providers': providers})
+except Exception, e:
+    output = {'status':'error', 'error': str(e)}
+
+print 'Status: 200 OK'
+print 'Content-Type: application/json'
+print
+print output
+conn.close()


Property changes on: servres/trunk/conifer/integration/clew-sections-for-site
___________________________________________________________________
Name: svn:executable
   + *

Added: servres/trunk/conifer/integration/linktool/__init__.py
===================================================================

Added: servres/trunk/conifer/integration/linktool/app.py
===================================================================
--- servres/trunk/conifer/integration/linktool/app.py	                        (rev 0)
+++ servres/trunk/conifer/integration/linktool/app.py	2010-07-16 19:37:09 UTC (rev 928)
@@ -0,0 +1,14 @@
+from django.contrib.auth import authenticate, login
+from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
+
+
+def linktool_welcome(request):
+    user = authenticate(request=request)
+    if user is None:
+        return HttpResponseForbidden('You are not allowed here.')
+    else:
+        login(request, user)
+        request.session['clew-site'] = request.GET['site']
+        return HttpResponse("""<html><head/><body onload="top.location='/%s';">"""
+                            """Redirecting to the library system...</body></html>""" % (
+                request.META['SCRIPT_NAME']))

Added: servres/trunk/conifer/integration/linktool/backend.py
===================================================================
--- servres/trunk/conifer/integration/linktool/backend.py	                        (rev 0)
+++ servres/trunk/conifer/integration/linktool/backend.py	2010-07-16 19:37:09 UTC (rev 928)
@@ -0,0 +1,65 @@
+from conifer.plumbing.hooksystem import *
+from django.conf                 import settings
+from django.contrib.auth.models  import User
+from urllib                      import quote
+from urllib2                     import urlopen
+
+
+def testsign(query_string):
+    url = '%s?data=%s' % (settings.LINKTOOL_AUTH_URL, quote(query_string))
+    result = urlopen(url).read()
+    return (result == 'true')
+
+
+class LinktoolAuthBackend(object):
+
+    def __init__(self):
+        assert settings.LINKTOOL_AUTH_URL, \
+            'LinktoolAuthBackend requires settings.LINKTOOL_AUTH_URL'
+
+    def authenticate(self, request=None):
+        valid = testsign(request.META['QUERY_STRING'])
+        if valid:
+            username = request.GET['user']
+            return self.maybe_initialize_user(username)
+        return None
+
+    def get_user(self, user_id):
+        try:
+            return User.objects.get(pk=user_id)
+        except User.DoesNotExist:
+            return None
+
+    def maybe_initialize_user(self, username, look_local=True):
+        """Look up user in Django db; if not found, fetch user detail
+        from backend and set up a local user object. Return None if no
+        such user exists in either Django or the backend.
+
+        Setting look_local=False skips the Django search and heads
+        straight to the backend; this shaves a database call when
+        walking a set of backends to initialize a user. Skipping
+        look_local on a username that already exists in Django will
+        certainly lead to an integrity error.
+
+        This method is NOT part of the Django backend interface.
+        """
+        user = None
+        if look_local:
+            try:
+                user = User.objects.get(username=username)
+            except User.DoesNotExist:
+                pass
+        if user is None:
+            u = self.lookup(username)
+            if u:           # user found in LDAP or whatever.
+                user = User(username=username,
+                            first_name = u['given_name'],
+                            last_name  = u['surname'],
+                            email      = u.get('email', None))
+                user.set_unusable_password()
+                user.save()
+        return user
+
+    def lookup(self, username):
+        return callhook('external_person_lookup', username)
+

Modified: servres/trunk/conifer/integration/uwindsor.py
===================================================================
--- servres/trunk/conifer/integration/uwindsor.py	2010-07-16 17:38:23 UTC (rev 927)
+++ servres/trunk/conifer/integration/uwindsor.py	2010-07-16 19:37:09 UTC (rev 928)
@@ -6,8 +6,8 @@
 from conifer.libsystems.z3950 import pyz3950_search as PZ
 from xml.etree import ElementTree as ET
 import re
+import uwindsor_campus_info
 
-
 def department_course_catalogue():
     """
     Return a list of rows representing all known, active courses and
@@ -111,3 +111,13 @@
         return None
 
     
+def external_person_lookup(userid):
+    """
+    Given a userid, return either None (if the user cannot be found),
+    or a dictionary representing the user. The dictionary must contain
+    the keys ('given_name', 'surname') and should contain 'email' if
+    an email address is known.
+    """
+    return uwindsor_campus_info.call('person_lookup', userid)
+
+

Modified: servres/trunk/conifer/local_settings.py.example
===================================================================
--- servres/trunk/conifer/local_settings.py.example	2010-07-16 17:38:23 UTC (rev 927)
+++ servres/trunk/conifer/local_settings.py.example	2010-07-16 19:37:09 UTC (rev 928)
@@ -31,9 +31,11 @@
 SECRET_KEY = 'replace-with-your-own-super-random-key- at vv(tuvt2+yu2r-$dxs$s7=iqjz_s!&'
 
 #----------------------------------------------------------------------
+# Authentication systems
 
 EVERGREEN_AUTHENTICATION = False # Evergreen ILS authentication
 LINKTOOL_AUTHENTICATION  = False # Sakai LMS Linktool authentication
+LINKTOOL_AUTH_URL = 'https://...' # fixme, add documentation
 
 #----------------------------------------------------------------------
 # Stuff that probably belongs in a config table in the database, with

Modified: servres/trunk/conifer/settings.py
===================================================================
--- servres/trunk/conifer/settings.py	2010-07-16 17:38:23 UTC (rev 927)
+++ servres/trunk/conifer/settings.py	2010-07-16 19:37:09 UTC (rev 928)
@@ -77,7 +77,7 @@
 
 TEMPLATE_DIRS = []
 
-INSTALLED_APPS = (
+INSTALLED_APPS = [
     'django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
@@ -85,7 +85,7 @@
     'django.contrib.admin',
     'south',
     'conifer.syrup',
-)
+]
 
 AUTH_PROFILE_MODULE = 'syrup.UserProfile'
 
@@ -94,6 +94,9 @@
     'django.contrib.auth.backends.ModelBackend'
 ]
 
+EVERGREEN_AUTHENTICATION = False
+LINKTOOL_AUTHENTICATION  = False
+
 #---------------------------------------------------------------------------
 # local_settings.py
 
@@ -120,5 +123,9 @@
     AUTHENTICATION_BACKENDS.append(
         'conifer.integration.auth_evergreen.django.EvergreenAuthBackend')
 
-#----------
+if LINKTOOL_AUTHENTICATION:
+    AUTHENTICATION_BACKENDS.append(
+        'conifer.integration.linktool.backend.LinktoolAuthBackend')
+    INSTALLED_APPS.append(
+        'conifer.integration.linktool.app')
 

Modified: servres/trunk/conifer/syrup/integration.py
===================================================================
--- servres/trunk/conifer/syrup/integration.py	2010-07-16 17:38:23 UTC (rev 927)
+++ servres/trunk/conifer/syrup/integration.py	2010-07-16 19:37:09 UTC (rev 928)
@@ -100,3 +100,12 @@
     codes and $u holds the URLs.
     """
 
+ at disable
+def external_person_lookup(userid):
+    """
+    Given a userid, return either None (if the user cannot be found),
+    or a dictionary representing the user. The dictionary must contain
+    the keys ('given_name', 'surname') and should contain 'email' if
+    an email address is known.
+    """
+

Modified: servres/trunk/conifer/templates/tabbar.xhtml
===================================================================
--- servres/trunk/conifer/templates/tabbar.xhtml	2010-07-16 17:38:23 UTC (rev 927)
+++ servres/trunk/conifer/templates/tabbar.xhtml	2010-07-16 19:37:09 UTC (rev 928)
@@ -7,6 +7,9 @@
     use one for now
 -->
 <ul id="tabbar">
+  <li py:if="'clew-site' in request.session">
+    <a href="https://clew.uwindsor.ca/xsl-portal/site/${request.session['clew-site']}/page/0/">Return to CLEW</a>
+  </li>
   <!-- !<li><a href="${ROOT}/">Home</a></li> -->
   <li><a href="${ROOT}/browse/">Browse</a></li>
   <li class="active"><a href="${ROOT}/site/">My Reserves</a></li>

Modified: servres/trunk/conifer/urls.py
===================================================================
--- servres/trunk/conifer/urls.py	2010-07-16 17:38:23 UTC (rev 927)
+++ servres/trunk/conifer/urls.py	2010-07-16 19:37:09 UTC (rev 928)
@@ -37,3 +37,10 @@
 if not settings.DEBUG:
     handler500 = 'conifer.syrup.views.custom_500_handler'
     handler404b = 'conifer.syrup.views.custom_400_handler'
+
+
+if settings.LINKTOOL_AUTHENTICATION:
+    urlpatterns += patterns(
+        'conifer.integration.linktool.app',
+        (r'^linktool-welcome/$', 'linktool_welcome'))
+



More information about the open-ils-commits mailing list