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

svn at svn.open-ils.org svn at svn.open-ils.org
Sat Apr 2 21:53:00 EDT 2011


Author: gfawcett
Date: 2011-04-02 21:52:58 -0400 (Sat, 02 Apr 2011)
New Revision: 1314

Added:
   servres/trunk/conifer/integration/sakai_linktool/
   servres/trunk/conifer/integration/sakai_linktool/__init__.py
   servres/trunk/conifer/integration/sakai_linktool/app.py
   servres/trunk/conifer/integration/sakai_linktool/backend.py
   servres/trunk/conifer/integration/sakai_linktool/templates/
   servres/trunk/conifer/integration/sakai_linktool/templates/associate.xhtml
   servres/trunk/conifer/integration/sakai_linktool/templates/index.xhtml
   servres/trunk/conifer/integration/sakai_linktool/templates/linktoolmaster.xhtml
   servres/trunk/conifer/integration/sakai_linktool/templates/new_site_cannot.xhtml
   servres/trunk/conifer/integration/sakai_linktool/templates/whichsite.xhtml
Removed:
   servres/trunk/conifer/integration/auth_linktool.py
   servres/trunk/conifer/integration/linktool/__init__.py
   servres/trunk/conifer/integration/linktool/app.py
   servres/trunk/conifer/integration/linktool/backend.py
   servres/trunk/conifer/integration/linktool/templates/associate.xhtml
   servres/trunk/conifer/integration/linktool/templates/index.xhtml
   servres/trunk/conifer/integration/linktool/templates/linktoolmaster.xhtml
   servres/trunk/conifer/integration/linktool/templates/new_site_cannot.xhtml
   servres/trunk/conifer/integration/linktool/templates/whichsite.xhtml
   servres/trunk/conifer/integration/uwindsor_campus_info.py
Modified:
   servres/trunk/conifer/integration/uwindsor.py
   servres/trunk/conifer/local_settings.py.example
   servres/trunk/conifer/settings.py
   servres/trunk/conifer/urls.py
Log:
tidy up some UWindsor and Sakai stuff.

Deleted: servres/trunk/conifer/integration/auth_linktool.py
===================================================================
--- servres/trunk/conifer/integration/auth_linktool.py	2011-04-03 01:52:54 UTC (rev 1313)
+++ servres/trunk/conifer/integration/auth_linktool.py	2011-04-03 01:52:58 UTC (rev 1314)
@@ -1,61 +0,0 @@
-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

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

Deleted: servres/trunk/conifer/integration/linktool/app.py
===================================================================
--- servres/trunk/conifer/integration/linktool/app.py	2011-04-03 01:52:54 UTC (rev 1313)
+++ servres/trunk/conifer/integration/linktool/app.py	2011-04-03 01:52:58 UTC (rev 1314)
@@ -1,162 +0,0 @@
-from conifer.here                    import HERE
-from conifer.plumbing.genshi_support import TemplateSet
-from datetime                        import date, timedelta
-from django.http                     import (HttpResponse, HttpResponseRedirect,
-                                             HttpResponseNotFound,
-                                             HttpResponseForbidden)
-from django.contrib.auth             import authenticate, login
-from conifer.syrup import models
-from django.utils.translation    import ugettext as _
-from conifer.plumbing.hooksystem import gethook, callhook
-
-g = TemplateSet([HERE('integration/linktool/templates'),
-                 HERE('templates')], 
-                {'models': models, '_': _})
-
-
-def linktool_welcome(request):
-    user = authenticate(request=request)
-    if user is None:
-        return HttpResponseForbidden('You are not allowed here.')
-    else:
-        login(request, user)
-        _role   = request.GET['role']
-        extrole = request.session['clew-role'] = callhook('decode_role', _role) or _role
-        extsite = request.session['clew-site'] = request.GET['site']
-
-        related_sites = list(models.Site.objects.filter(group__external_id=extsite))
-
-        if len(related_sites) == 1:
-            site_url = related_sites[0].site_url()
-            html     = ("<html><head/><body onload=\"top.location='%s';\">"
-                        "Redirecting..."
-                        "</body></html>") % site_url
-            return HttpResponse(html)
-        elif len(related_sites):
-            return g.render('whichsite.xhtml', **locals())
-        elif extrole == 'INSTR':
-            # TODO: This reminds me that it should be a warning to
-            # edit an old site (one in a past Term). Otherwise, profs
-            # will add items to old sites, and think they are actually
-            # ordering stuff.
-            today     = date.today()
-            possibles = list(models.Site.taught_by(user))
-            current   = [s for s in possibles if s.term.midpoint() >= today]
-            ancient   = [s for s in possibles if s.term.midpoint() < today]
-            extsite   = ExternalSiteInfo(request)
-            return g.render('associate.xhtml', **locals())
-        else:
-            # redirect the toplevel window to the 'browse' page
-            html = ("<html><head><script>window.onload=function() { "
-                    "top.location='../browse/'; }</script></head></html>")
-            return HttpResponse(html)
-
-class ExternalSiteInfo(object):
-    def __init__(self, request):
-        extsite   = request.session['clew-site']
-        extgroups = callhook('external_memberships', request.user.username)
-        extsite   = [d for d in extgroups if d['group'] == extsite][0]
-        self.__dict__.update(extsite)
-        self.termcode   = self.terms and self.terms[0] or None
-        self.coursecode = extsite['course']
-        try:
-            course = models.Course.objects.get(code=self.coursecode)
-        except models.Course.DoesNotExist:
-            course = None
-        try:
-            term = models.Term.objects.get(code=self.termcode)
-        except models.Term.DoesNotExist:
-            term = None
-        self.course_obj = course
-        self.term_obj = term
-
-    def is_currentish(self):
-        today = date.today()
-        return not (self.term_obj and self.term_obj.midpoint() < today)
-
-def linktool_new_site(request):
-    extrole = request.session['clew-role']
-    assert extrole == 'INSTR'
-    assert request.user.can_create_sites(), \
-        'Sorry, but you are not allowed to create sites.'
-    extsite = ExternalSiteInfo(request)
-    extgroups  = callhook('external_memberships', request.user.username)
-    desk = models.ServiceDesk.default()
-    site = models.Site.objects.create(
-        course = extsite.course_obj,
-        start_term   = extsite.term_obj,
-        end_term   = extsite.term_obj,
-        owner  = request.user,
-        service_desk = desk)
-    group = models.Group.objects.create(
-        site        = site,
-        external_id = extsite.group)
-    models.Membership.objects.create(
-        group = group, 
-        user  = request.user, 
-        role  = 'INSTR')
-    return HttpResponseRedirect(site.site_url())
-
-def linktool_associate(request):
-    site = models.Site.objects.get(pk=request.GET['site'])
-    assert site in request.user.sites(role='INSTR'), \
-        'Not an instructor on this site! Cannot copy.'
-    assert request.user.can_create_sites(), \
-        'Sorry, but you are not allowed to create sites.'
-    today = date.today()
-    assert site.term.midpoint() >= today, \
-        'Sorry, but you cannot associate to such an old site.'
-
-    extsite = request.session['clew-site']
-    extrole = request.session['clew-role']
-    assert extrole == 'INSTR', \
-        'Sorry, you are not an instructor on this Sakai site.'
-    group = models.Group.objects.create(
-        site        = site,
-        external_id = extsite)
-    models.Membership.objects.create(
-        group = group, 
-        user  = request.user, 
-        role  = 'INSTR')
-    return HttpResponseRedirect(site.site_url())
-
-def linktool_copy_old(request):
-    oldsite = models.Site.objects.get(pk=request.GET['site'])
-    assert oldsite in request.user.sites(role='INSTR'), \
-        'Not an instructor on this site! Cannot copy.'
-    assert request.user.can_create_sites(), \
-        'Sorry, but you are not allowed to create sites.'
-
-    extsite = request.session['clew-site']
-    extrole = request.session['clew-role']
-    assert extrole == 'INSTR', \
-        'Sorry, you are not an instructor on this Sakai site.'
-
-    extgroups  = callhook('external_memberships', request.user.username)
-    extsite    = [d for d in extgroups if d['group'] == extsite][0]
-    coursecode = extsite['course']
-    termcode   = extsite['terms'][0]
-
-    course = oldsite.course     # fixme, this isn't right.
-    try:
-        #course = models.Course.objects.get(code=coursecode)
-        term   = models.Term.objects.get(code=termcode)
-    except:
-        # note, this doesn't have to be an exception. I could provide
-        # them with a form to specify the correct course and term
-        # codes. But for now, we bail.
-        return g.render('new_site_cannot.xhtml', **locals())
-    site = models.Site.objects.create(
-        course = course,
-        term   = term,
-        owner  = request.user,
-        service_desk = models.ServiceDesk.default())
-    group = models.Group.objects.create(
-        site        = site,
-        external_id = extsite)
-    models.Membership.objects.create(
-        group = group, 
-        user  = request.user, 
-        role  = 'INSTR')
-    site.copy_resources_from(oldsite)
-    return HttpResponseRedirect(site.site_url())

Deleted: servres/trunk/conifer/integration/linktool/backend.py
===================================================================
--- servres/trunk/conifer/integration/linktool/backend.py	2011-04-03 01:52:54 UTC (rev 1313)
+++ servres/trunk/conifer/integration/linktool/backend.py	2011-04-03 01:52:58 UTC (rev 1314)
@@ -1,65 +0,0 @@
-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)
-

Deleted: servres/trunk/conifer/integration/linktool/templates/associate.xhtml
===================================================================
--- servres/trunk/conifer/integration/linktool/templates/associate.xhtml	2011-04-03 01:52:54 UTC (rev 1313)
+++ servres/trunk/conifer/integration/linktool/templates/associate.xhtml	2011-04-03 01:52:58 UTC (rev 1314)
@@ -1,55 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml"
-      xmlns:xi="http://www.w3.org/2001/XInclude"
-      xmlns:py="http://genshi.edgewall.org/">
-  <xi:include href="linktoolmaster.xhtml"/>
-  <head>
-    <style type="text/css">
-      	ol ul { margin-bottom: 1.5em; }
-      	ul li { margin-top: 0.5em; }
-	ol { margin: 1em; }
-    </style>
-  </head>
-  <body>
-    <h1>No associated reserves items.</h1>
-    <div py:if="extsite.is_currentish()">
-      <p>There are no reserves materials associated with this course
-      site. As an instructor, you can choose one of the following
-      options:</p>
-      <ol>
-	<li>
-	  <div><b>Link this course site to one of my current reserves list</b></div>
-	  <ul>
-	    <li py:if="not current">None available.</li>
-	    <li py:for="site in current">
-	      <a href="associate?site=${site.id}">${site}</a>
-	    </li>
-	  </ul>
-	</li>
-<!--
-	<li>
-	  <div><b>Copy a reserves list I've used in the past</b></div>
-	  <ul>
-	    <li py:if="not ancient">None available.</li>
-	    <li py:for="site in ancient">
-	      <a href="copy_old?site=${site.id}">${site}</a>
-	    </li>
-	  </ul>
-	</li>
-	<li>
-	  <div><b><a href="new_site">Start a new reserves list for this site</a></b></div>
-	</li>
--->
-      </ol>
-      <p>Or, you can just <a href="${ROOT}/browse/">browse the reserves</a>.</p>
-    </div>
-    <div py:if="not extsite.is_currentish()"
-	 py:with="t=extsite.term_obj or 'unknown'; c=extsite.coursecode or 'unknown'">
-      <p>There are no reserves materials associated with this course
-      site.</p> <p>You can create reserves lists for course sites
-      associated with a current or future term. But this site is
-      associated with the term "${t}" and the course "${c}" &mdash; so
-      a reserves list cannot be created.</p>
-      <p><a href="${ROOT}/browse/">Browse the reserves</a></p>
-    </div>
-  </body>
-</html>

Deleted: servres/trunk/conifer/integration/linktool/templates/index.xhtml
===================================================================
--- servres/trunk/conifer/integration/linktool/templates/index.xhtml	2011-04-03 01:52:54 UTC (rev 1313)
+++ servres/trunk/conifer/integration/linktool/templates/index.xhtml	2011-04-03 01:52:58 UTC (rev 1314)
@@ -1,16 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml"
-      xmlns:xi="http://www.w3.org/2001/XInclude"
-      xmlns:py="http://genshi.edgewall.org/">
-<xi:include href="master.xhtml"/>
-<head>
-  <title>testing</title>
-  <script type="text/javascript"
-	  py:if="False">
-    window.onload = function() { top.location='${request.META['SCRIPT_NAME'] or '/'}'; };
-  </script>
-</head>
-<body>
-<h1>Welcome</h1>
-${repr(list(related_sites))}
-</body>
-</html>

Deleted: servres/trunk/conifer/integration/linktool/templates/linktoolmaster.xhtml
===================================================================
--- servres/trunk/conifer/integration/linktool/templates/linktoolmaster.xhtml	2011-04-03 01:52:54 UTC (rev 1313)
+++ servres/trunk/conifer/integration/linktool/templates/linktoolmaster.xhtml	2011-04-03 01:52:58 UTC (rev 1314)
@@ -1,19 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml"
-      xmlns:xi="http://www.w3.org/2001/XInclude"
-      xmlns:py="http://genshi.edgewall.org/"
-      py:strip="True">
-  <xi:include href="master.xhtml"/>
-  <py:match path="div[@id='header']" once="true"/>
-  <py:match path="ul[@id='tabbar']" once="true"/>
-  <py:match path="div[@id='brandheader']" once="true"/>
-  <py:match path="head" once="True">
-    <head py:attrs="select('@*')">
-      ${select('*')}
-      <base target="_top"/>
-      <style type="text/css">
-	div#outer { width: inherit; max-width: 960px; }
-	h1 { padding-top: 1em; }
-      </style>
-    </head>
-  </py:match>
-</html>

Deleted: servres/trunk/conifer/integration/linktool/templates/new_site_cannot.xhtml
===================================================================
--- servres/trunk/conifer/integration/linktool/templates/new_site_cannot.xhtml	2011-04-03 01:52:54 UTC (rev 1313)
+++ servres/trunk/conifer/integration/linktool/templates/new_site_cannot.xhtml	2011-04-03 01:52:58 UTC (rev 1314)
@@ -1,23 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml"
-      xmlns:xi="http://www.w3.org/2001/XInclude"
-      xmlns:py="http://genshi.edgewall.org/">
-  <xi:include href="linktoolmaster.xhtml"/>
-  <head>
-    <title>testing</title>
-    <script type="text/javascript"
-	    py:if="False">
-      window.onload = function() { top.location='${request.META['SCRIPT_NAME'] or '/'}'; };
-    </script>
-  </head>
-  <body>
-    <h1>Cannot create site...</h1>
-    <p>Sorry, but your site's course code (${coursecode or 'unknown'})
-    and/or term code (${termcode or 'unknown'}) do not match any known
-    codes in the reserves system.</p>
-    <p> 
-      <a href="https://clew.uwindsor.ca/xsl-portal/site/${request.session['clew-site']}/">
-	Go back
-      </a>
-    </p>
-  </body>
-</html>

Deleted: servres/trunk/conifer/integration/linktool/templates/whichsite.xhtml
===================================================================
--- servres/trunk/conifer/integration/linktool/templates/whichsite.xhtml	2011-04-03 01:52:54 UTC (rev 1313)
+++ servres/trunk/conifer/integration/linktool/templates/whichsite.xhtml	2011-04-03 01:52:58 UTC (rev 1314)
@@ -1,15 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml"
-      xmlns:xi="http://www.w3.org/2001/XInclude"
-      xmlns:py="http://genshi.edgewall.org/">
-  <xi:include href="linktoolmaster.xhtml"/>
-  <head/>
-  <body>
-    <h1 style="padding-top: 1em;">Please choose a set of reserves materials</h1>
-    <p>There is more than one set of reserves materials related to this
-    site. Please choose from the list below:</p>
-    <ul>
-      <li py:for="site in related_sites"
-	  style="margin-bottom: 1em;"><a href="${site.site_url()}">${site}</a></li>
-    </ul>
-  </body>
-</html>

Copied: servres/trunk/conifer/integration/sakai_linktool/__init__.py (from rev 1313, servres/trunk/conifer/integration/linktool/__init__.py)
===================================================================

Copied: servres/trunk/conifer/integration/sakai_linktool/app.py (from rev 1313, servres/trunk/conifer/integration/linktool/app.py)
===================================================================
--- servres/trunk/conifer/integration/sakai_linktool/app.py	                        (rev 0)
+++ servres/trunk/conifer/integration/sakai_linktool/app.py	2011-04-03 01:52:58 UTC (rev 1314)
@@ -0,0 +1,162 @@
+from conifer.here                    import HERE
+from conifer.plumbing.genshi_support import TemplateSet
+from datetime                        import date, timedelta
+from django.http                     import (HttpResponse, HttpResponseRedirect,
+                                             HttpResponseNotFound,
+                                             HttpResponseForbidden)
+from django.contrib.auth             import authenticate, login
+from conifer.syrup import models
+from django.utils.translation    import ugettext as _
+from conifer.plumbing.hooksystem import gethook, callhook
+
+g = TemplateSet([HERE('integration/linktool/templates'),
+                 HERE('templates')], 
+                {'models': models, '_': _})
+
+
+def linktool_welcome(request):
+    user = authenticate(request=request)
+    if user is None:
+        return HttpResponseForbidden('You are not allowed here.')
+    else:
+        login(request, user)
+        _role   = request.GET['role']
+        extrole = request.session['clew-role'] = callhook('decode_role', _role) or _role
+        extsite = request.session['clew-site'] = request.GET['site']
+
+        related_sites = list(models.Site.objects.filter(group__external_id=extsite))
+
+        if len(related_sites) == 1:
+            site_url = related_sites[0].site_url()
+            html     = ("<html><head/><body onload=\"top.location='%s';\">"
+                        "Redirecting..."
+                        "</body></html>") % site_url
+            return HttpResponse(html)
+        elif len(related_sites):
+            return g.render('whichsite.xhtml', **locals())
+        elif extrole == 'INSTR':
+            # TODO: This reminds me that it should be a warning to
+            # edit an old site (one in a past Term). Otherwise, profs
+            # will add items to old sites, and think they are actually
+            # ordering stuff.
+            today     = date.today()
+            possibles = list(models.Site.taught_by(user))
+            current   = [s for s in possibles if s.term.midpoint() >= today]
+            ancient   = [s for s in possibles if s.term.midpoint() < today]
+            extsite   = ExternalSiteInfo(request)
+            return g.render('associate.xhtml', **locals())
+        else:
+            # redirect the toplevel window to the 'browse' page
+            html = ("<html><head><script>window.onload=function() { "
+                    "top.location='../browse/'; }</script></head></html>")
+            return HttpResponse(html)
+
+class ExternalSiteInfo(object):
+    def __init__(self, request):
+        extsite   = request.session['clew-site']
+        extgroups = callhook('external_memberships', request.user.username)
+        extsite   = [d for d in extgroups if d['group'] == extsite][0]
+        self.__dict__.update(extsite)
+        self.termcode   = self.terms and self.terms[0] or None
+        self.coursecode = extsite['course']
+        try:
+            course = models.Course.objects.get(code=self.coursecode)
+        except models.Course.DoesNotExist:
+            course = None
+        try:
+            term = models.Term.objects.get(code=self.termcode)
+        except models.Term.DoesNotExist:
+            term = None
+        self.course_obj = course
+        self.term_obj = term
+
+    def is_currentish(self):
+        today = date.today()
+        return not (self.term_obj and self.term_obj.midpoint() < today)
+
+def linktool_new_site(request):
+    extrole = request.session['clew-role']
+    assert extrole == 'INSTR'
+    assert request.user.can_create_sites(), \
+        'Sorry, but you are not allowed to create sites.'
+    extsite = ExternalSiteInfo(request)
+    extgroups  = callhook('external_memberships', request.user.username)
+    desk = models.ServiceDesk.default()
+    site = models.Site.objects.create(
+        course = extsite.course_obj,
+        start_term   = extsite.term_obj,
+        end_term   = extsite.term_obj,
+        owner  = request.user,
+        service_desk = desk)
+    group = models.Group.objects.create(
+        site        = site,
+        external_id = extsite.group)
+    models.Membership.objects.create(
+        group = group, 
+        user  = request.user, 
+        role  = 'INSTR')
+    return HttpResponseRedirect(site.site_url())
+
+def linktool_associate(request):
+    site = models.Site.objects.get(pk=request.GET['site'])
+    assert site in request.user.sites(role='INSTR'), \
+        'Not an instructor on this site! Cannot copy.'
+    assert request.user.can_create_sites(), \
+        'Sorry, but you are not allowed to create sites.'
+    today = date.today()
+    assert site.term.midpoint() >= today, \
+        'Sorry, but you cannot associate to such an old site.'
+
+    extsite = request.session['clew-site']
+    extrole = request.session['clew-role']
+    assert extrole == 'INSTR', \
+        'Sorry, you are not an instructor on this Sakai site.'
+    group = models.Group.objects.create(
+        site        = site,
+        external_id = extsite)
+    models.Membership.objects.create(
+        group = group, 
+        user  = request.user, 
+        role  = 'INSTR')
+    return HttpResponseRedirect(site.site_url())
+
+def linktool_copy_old(request):
+    oldsite = models.Site.objects.get(pk=request.GET['site'])
+    assert oldsite in request.user.sites(role='INSTR'), \
+        'Not an instructor on this site! Cannot copy.'
+    assert request.user.can_create_sites(), \
+        'Sorry, but you are not allowed to create sites.'
+
+    extsite = request.session['clew-site']
+    extrole = request.session['clew-role']
+    assert extrole == 'INSTR', \
+        'Sorry, you are not an instructor on this Sakai site.'
+
+    extgroups  = callhook('external_memberships', request.user.username)
+    extsite    = [d for d in extgroups if d['group'] == extsite][0]
+    coursecode = extsite['course']
+    termcode   = extsite['terms'][0]
+
+    course = oldsite.course     # fixme, this isn't right.
+    try:
+        #course = models.Course.objects.get(code=coursecode)
+        term   = models.Term.objects.get(code=termcode)
+    except:
+        # note, this doesn't have to be an exception. I could provide
+        # them with a form to specify the correct course and term
+        # codes. But for now, we bail.
+        return g.render('new_site_cannot.xhtml', **locals())
+    site = models.Site.objects.create(
+        course = course,
+        term   = term,
+        owner  = request.user,
+        service_desk = models.ServiceDesk.default())
+    group = models.Group.objects.create(
+        site        = site,
+        external_id = extsite)
+    models.Membership.objects.create(
+        group = group, 
+        user  = request.user, 
+        role  = 'INSTR')
+    site.copy_resources_from(oldsite)
+    return HttpResponseRedirect(site.site_url())

Copied: servres/trunk/conifer/integration/sakai_linktool/backend.py (from rev 1313, servres/trunk/conifer/integration/linktool/backend.py)
===================================================================
--- servres/trunk/conifer/integration/sakai_linktool/backend.py	                        (rev 0)
+++ servres/trunk/conifer/integration/sakai_linktool/backend.py	2011-04-03 01:52:58 UTC (rev 1314)
@@ -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)
+

Copied: servres/trunk/conifer/integration/sakai_linktool/templates/associate.xhtml (from rev 1313, servres/trunk/conifer/integration/linktool/templates/associate.xhtml)
===================================================================
--- servres/trunk/conifer/integration/sakai_linktool/templates/associate.xhtml	                        (rev 0)
+++ servres/trunk/conifer/integration/sakai_linktool/templates/associate.xhtml	2011-04-03 01:52:58 UTC (rev 1314)
@@ -0,0 +1,55 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:xi="http://www.w3.org/2001/XInclude"
+      xmlns:py="http://genshi.edgewall.org/">
+  <xi:include href="linktoolmaster.xhtml"/>
+  <head>
+    <style type="text/css">
+      	ol ul { margin-bottom: 1.5em; }
+      	ul li { margin-top: 0.5em; }
+	ol { margin: 1em; }
+    </style>
+  </head>
+  <body>
+    <h1>No associated reserves items.</h1>
+    <div py:if="extsite.is_currentish()">
+      <p>There are no reserves materials associated with this course
+      site. As an instructor, you can choose one of the following
+      options:</p>
+      <ol>
+	<li>
+	  <div><b>Link this course site to one of my current reserves list</b></div>
+	  <ul>
+	    <li py:if="not current">None available.</li>
+	    <li py:for="site in current">
+	      <a href="associate?site=${site.id}">${site}</a>
+	    </li>
+	  </ul>
+	</li>
+<!--
+	<li>
+	  <div><b>Copy a reserves list I've used in the past</b></div>
+	  <ul>
+	    <li py:if="not ancient">None available.</li>
+	    <li py:for="site in ancient">
+	      <a href="copy_old?site=${site.id}">${site}</a>
+	    </li>
+	  </ul>
+	</li>
+	<li>
+	  <div><b><a href="new_site">Start a new reserves list for this site</a></b></div>
+	</li>
+-->
+      </ol>
+      <p>Or, you can just <a href="${ROOT}/browse/">browse the reserves</a>.</p>
+    </div>
+    <div py:if="not extsite.is_currentish()"
+	 py:with="t=extsite.term_obj or 'unknown'; c=extsite.coursecode or 'unknown'">
+      <p>There are no reserves materials associated with this course
+      site.</p> <p>You can create reserves lists for course sites
+      associated with a current or future term. But this site is
+      associated with the term "${t}" and the course "${c}" &mdash; so
+      a reserves list cannot be created.</p>
+      <p><a href="${ROOT}/browse/">Browse the reserves</a></p>
+    </div>
+  </body>
+</html>

Copied: servres/trunk/conifer/integration/sakai_linktool/templates/index.xhtml (from rev 1313, servres/trunk/conifer/integration/linktool/templates/index.xhtml)
===================================================================
--- servres/trunk/conifer/integration/sakai_linktool/templates/index.xhtml	                        (rev 0)
+++ servres/trunk/conifer/integration/sakai_linktool/templates/index.xhtml	2011-04-03 01:52:58 UTC (rev 1314)
@@ -0,0 +1,16 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:xi="http://www.w3.org/2001/XInclude"
+      xmlns:py="http://genshi.edgewall.org/">
+<xi:include href="master.xhtml"/>
+<head>
+  <title>testing</title>
+  <script type="text/javascript"
+	  py:if="False">
+    window.onload = function() { top.location='${request.META['SCRIPT_NAME'] or '/'}'; };
+  </script>
+</head>
+<body>
+<h1>Welcome</h1>
+${repr(list(related_sites))}
+</body>
+</html>

Copied: servres/trunk/conifer/integration/sakai_linktool/templates/linktoolmaster.xhtml (from rev 1313, servres/trunk/conifer/integration/linktool/templates/linktoolmaster.xhtml)
===================================================================
--- servres/trunk/conifer/integration/sakai_linktool/templates/linktoolmaster.xhtml	                        (rev 0)
+++ servres/trunk/conifer/integration/sakai_linktool/templates/linktoolmaster.xhtml	2011-04-03 01:52:58 UTC (rev 1314)
@@ -0,0 +1,19 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:xi="http://www.w3.org/2001/XInclude"
+      xmlns:py="http://genshi.edgewall.org/"
+      py:strip="True">
+  <xi:include href="master.xhtml"/>
+  <py:match path="div[@id='header']" once="true"/>
+  <py:match path="ul[@id='tabbar']" once="true"/>
+  <py:match path="div[@id='brandheader']" once="true"/>
+  <py:match path="head" once="True">
+    <head py:attrs="select('@*')">
+      ${select('*')}
+      <base target="_top"/>
+      <style type="text/css">
+	div#outer { width: inherit; max-width: 960px; }
+	h1 { padding-top: 1em; }
+      </style>
+    </head>
+  </py:match>
+</html>

Copied: servres/trunk/conifer/integration/sakai_linktool/templates/new_site_cannot.xhtml (from rev 1313, servres/trunk/conifer/integration/linktool/templates/new_site_cannot.xhtml)
===================================================================
--- servres/trunk/conifer/integration/sakai_linktool/templates/new_site_cannot.xhtml	                        (rev 0)
+++ servres/trunk/conifer/integration/sakai_linktool/templates/new_site_cannot.xhtml	2011-04-03 01:52:58 UTC (rev 1314)
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:xi="http://www.w3.org/2001/XInclude"
+      xmlns:py="http://genshi.edgewall.org/">
+  <xi:include href="linktoolmaster.xhtml"/>
+  <head>
+    <title>testing</title>
+    <script type="text/javascript"
+	    py:if="False">
+      window.onload = function() { top.location='${request.META['SCRIPT_NAME'] or '/'}'; };
+    </script>
+  </head>
+  <body>
+    <h1>Cannot create site...</h1>
+    <p>Sorry, but your site's course code (${coursecode or 'unknown'})
+    and/or term code (${termcode or 'unknown'}) do not match any known
+    codes in the reserves system.</p>
+    <p> 
+      <a href="https://clew.uwindsor.ca/xsl-portal/site/${request.session['clew-site']}/">
+	Go back
+      </a>
+    </p>
+  </body>
+</html>

Copied: servres/trunk/conifer/integration/sakai_linktool/templates/whichsite.xhtml (from rev 1313, servres/trunk/conifer/integration/linktool/templates/whichsite.xhtml)
===================================================================
--- servres/trunk/conifer/integration/sakai_linktool/templates/whichsite.xhtml	                        (rev 0)
+++ servres/trunk/conifer/integration/sakai_linktool/templates/whichsite.xhtml	2011-04-03 01:52:58 UTC (rev 1314)
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:xi="http://www.w3.org/2001/XInclude"
+      xmlns:py="http://genshi.edgewall.org/">
+  <xi:include href="linktoolmaster.xhtml"/>
+  <head/>
+  <body>
+    <h1 style="padding-top: 1em;">Please choose a set of reserves materials</h1>
+    <p>There is more than one set of reserves materials related to this
+    site. Please choose from the list below:</p>
+    <ul>
+      <li py:for="site in related_sites"
+	  style="margin-bottom: 1em;"><a href="${site.site_url()}">${site}</a></li>
+    </ul>
+  </body>
+</html>

Modified: servres/trunk/conifer/integration/uwindsor.py
===================================================================
--- servres/trunk/conifer/integration/uwindsor.py	2011-04-03 01:52:54 UTC (rev 1313)
+++ servres/trunk/conifer/integration/uwindsor.py	2011-04-03 01:52:58 UTC (rev 1314)
@@ -3,9 +3,10 @@
 from evergreen_site     import EvergreenIntegration
 import csv
 import subprocess
-import uwindsor_campus_info
 import uwindsor_fuzzy_lookup
 from django.conf                          import settings
+from urllib2 import urlopen
+from django.utils import simplejson
 
 
 class UWindsorIntegration(EvergreenIntegration):
@@ -59,6 +60,11 @@
             ('2011F', '2011 Fall', date(2011,9,1), date(2011,12,31)),
             ]
 
+    def _campus_info(name, *args):
+        url = '%s%s?%s' % (settings.CAMPUS_INFO_SERVICE, name, simplejson.dumps(args))
+        raw = urlopen(url).read()
+        return simplejson.loads(raw)
+
     def external_person_lookup(self, userid):
         """
         Given a userid, return either None (if the user cannot be found),
@@ -67,7 +73,7 @@
         an email address is known, and 'patron_id' if a library-system ID
         is known.
         """
-        return uwindsor_campus_info.call('person_lookup', userid)
+        return self._campus_info('person_lookup', userid)
 
 
     def external_memberships(self, userid):
@@ -78,7 +84,7 @@
         'group': a group-code, externally defined;
         'role':          the user's role in that group, one of (INSTR, ASSIST, STUDT).
         """
-        memberships = uwindsor_campus_info.call('membership_ids', userid)
+        memberships = self._campus_info('membership_ids', userid)
         for m in memberships:
             m['role'] = self._decode_role(m['role'])
         return memberships

Deleted: servres/trunk/conifer/integration/uwindsor_campus_info.py
===================================================================
--- servres/trunk/conifer/integration/uwindsor_campus_info.py	2011-04-03 01:52:54 UTC (rev 1313)
+++ servres/trunk/conifer/integration/uwindsor_campus_info.py	2011-04-03 01:52:58 UTC (rev 1314)
@@ -1,12 +0,0 @@
-from urllib2 import *
-from django.utils import simplejson
-from django.conf import settings
-
-def call(name, *args):
-    url = '%s%s?%s' % (settings.CAMPUS_INFO_SERVICE, name, simplejson.dumps(args))
-    raw = urlopen(url).read()
-    return simplejson.loads(raw)
-
-if __name__ == '__main__':
-    print call('methods_supported')
-    print call('person_lookup', 'fawcett')

Modified: servres/trunk/conifer/local_settings.py.example
===================================================================
--- servres/trunk/conifer/local_settings.py.example	2011-04-03 01:52:54 UTC (rev 1313)
+++ servres/trunk/conifer/local_settings.py.example	2011-04-03 01:52:58 UTC (rev 1314)
@@ -34,8 +34,8 @@
 # Authentication systems
 
 EVERGREEN_AUTHENTICATION = False # Evergreen ILS authentication
-LINKTOOL_AUTHENTICATION  = False # Sakai LMS Linktool authentication
-LINKTOOL_AUTH_URL = 'https://...' # fixme, add documentation
+SAKAI_LINKTOOL_AUTHENTICATION  = False # Sakai LMS Linktool authentication
+SAKAI_LINKTOOL_AUTH_URL = 'https://...' # fixme, add documentation
 
 # CAS authentication. See conifer/integration/cas.py, or
 # http://code.google.com/p/django-cas/ .

Modified: servres/trunk/conifer/settings.py
===================================================================
--- servres/trunk/conifer/settings.py	2011-04-03 01:52:54 UTC (rev 1313)
+++ servres/trunk/conifer/settings.py	2011-04-03 01:52:58 UTC (rev 1314)
@@ -97,7 +97,7 @@
 ]
 
 EVERGREEN_AUTHENTICATION = False
-LINKTOOL_AUTHENTICATION  = False
+SAKAI_LINKTOOL_AUTHENTICATION  = False
 
 # CAS authentication requires 'django-cas', 
 # http://code.google.com/p/django-cas/
@@ -129,9 +129,9 @@
     AUTHENTICATION_BACKENDS.append(
         'conifer.integration.auth_evergreen.django.EvergreenAuthBackend')
 
-if LINKTOOL_AUTHENTICATION:
+if SAKAI_LINKTOOL_AUTHENTICATION:
     AUTHENTICATION_BACKENDS.append(
-        'conifer.integration.linktool.backend.LinktoolAuthBackend')
+        'conifer.integration.sakai_linktool.backend.LinktoolAuthBackend')
 
 if CAS_AUTHENTICATION:
     AUTHENTICATION_BACKENDS.append('conifer.integration.cas.CASBackend')

Modified: servres/trunk/conifer/urls.py
===================================================================
--- servres/trunk/conifer/urls.py	2011-04-03 01:52:54 UTC (rev 1313)
+++ servres/trunk/conifer/urls.py	2011-04-03 01:52:58 UTC (rev 1314)
@@ -39,9 +39,9 @@
     handler404b = 'conifer.syrup.views.custom_400_handler'
 
 
-if settings.LINKTOOL_AUTHENTICATION:
+if settings.SAKAI_LINKTOOL_AUTHENTICATION:
     urlpatterns += patterns(
-        'conifer.integration.linktool.app',
+        'conifer.integration.sakai_linktool.app',
         (r'^linktool-welcome/$', 'linktool_welcome'),
         (r'^linktool-welcome/new_site$', 'linktool_new_site'),
         (r'^linktool-welcome/copy_old$', 'linktool_copy_old'),



More information about the open-ils-commits mailing list