From f9402f85625a7b67c5a2d0c6a61128b5fe4b5250 Mon Sep 17 00:00:00 2001
From: Ben Adida <ben@adida.net>
Date: Wed, 6 Oct 2010 21:13:36 -0700
Subject: [PATCH] updated CAS

---
 auth/auth_systems/cas.py       |  17 +++++++++++++----
 auth/media/login-icons/cas.png | Bin 0 -> 6826 bytes
 2 files changed, 13 insertions(+), 4 deletions(-)
 create mode 100644 auth/media/login-icons/cas.png

diff --git a/auth/auth_systems/cas.py b/auth/auth_systems/cas.py
index 24935e9..55f0c4a 100644
--- a/auth/auth_systems/cas.py
+++ b/auth/auth_systems/cas.py
@@ -34,7 +34,8 @@ def _get_service_url():
   
   return settings.URL_HOST + reverse(after)
   
-def get_auth_url(request):
+def get_auth_url(request, redirect_url):
+  request.session['cas_redirect_url'] = redirect_url
   return CAS_URL + 'login?service=' + urllib.quote(_get_service_url())
 
 def get_user_category(user_id):
@@ -93,7 +94,10 @@ def get_user_info(user_id):
   # get the value elements (a bit of a hack but no big deal)
   values = response_doc.getElementsByTagName('value')
   
-  return {'name' : values[0].firstChild.wholeText, 'category' : values[1].firstChild.wholeText}
+  if len(values)>0:
+    return {'name' : values[0].firstChild.wholeText, 'category' : values[1].firstChild.wholeText}
+  else:
+    return None
   
 def get_user_info_after_auth(request):
   ticket = request.GET.get('ticket', None)
@@ -113,9 +117,14 @@ def get_user_info_after_auth(request):
     netid = r[1].strip()
     
     category = get_user_category(netid)
-    info = {'name': netid, 'category': category}
+    user_info = get_user_info(netid)
+
+    if user_info:
+      info = {'name': user_info['name'], 'category': category}
+    else:
+      info = {'name': netid, 'category': category}
       
-    return {'type': 'cas', 'user_id': netid, 'name': netid, 'info': info, 'token': None}
+    return {'type': 'cas', 'user_id': netid, 'name': info['name'], 'info': info, 'token': None}
   else:
     return None
     
diff --git a/auth/media/login-icons/cas.png b/auth/media/login-icons/cas.png
new file mode 100644
index 0000000000000000000000000000000000000000..75b58495ddbd3e92ef9e1244522e956eb683412b
GIT binary patch
literal 6826
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
WF5&GmKNuJo7(8A5T-G@yGywqCgD_P9

literal 0
HcmV?d00001

-- 
GitLab