[Python-modules-commits] [python-django-casclient] 02/02: Imported Debian patch 1.2.0-1

Joost van Baal joostvb at moszumanska.debian.org
Tue Mar 15 09:03:33 UTC 2016


This is an automated email from the git hooks/post-receive script.

joostvb pushed a commit to branch master
in repository python-django-casclient.

commit 496d4d7f110901b3d906bda915e950cb7efd06a4
Author: Joost van Baal-Ilić <joostvb at debian.org>
Date:   Fri Mar 11 13:59:58 2016 +0000

    Imported Debian patch 1.2.0-1
---
 debian/changelog                                   |  11 +
 debian/compat                                      |   1 +
 debian/control                                     |  49 ++++
 debian/copyright                                   |  38 +++
 debian/postinst                                    |  39 ++++
 debian/prerm                                       |  38 +++
 .../lib/python2.7/dist-packages/cas/__init__.py    |  32 +++
 .../lib/python2.7/dist-packages/cas/backends.py    | 257 +++++++++++++++++++++
 .../lib/python2.7/dist-packages/cas/decorators.py  |  93 ++++++++
 .../lib/python2.7/dist-packages/cas/exceptions.py  |  17 ++
 .../lib/python2.7/dist-packages/cas/middleware.py  |  92 ++++++++
 .../usr/lib/python2.7/dist-packages/cas/models.py  | 108 +++++++++
 .../python2.7/dist-packages/cas/tests/__init__.py  |   3 +
 .../python2.7/dist-packages/cas/tests/factories.py |  15 ++
 .../dist-packages/cas/tests/test_backend.py        |  30 +++
 .../dist-packages/cas/tests/test_smoke.py          |   7 +
 .../dist-packages/cas/tests/test_views.py          |  46 ++++
 .../usr/lib/python2.7/dist-packages/cas/utils.py   |  26 +++
 .../usr/lib/python2.7/dist-packages/cas/views.py   | 257 +++++++++++++++++++++
 .../django_cas_client-1.2.0.egg-info/PKG-INFO      | 184 +++++++++++++++
 .../dependency_links.txt                           |   1 +
 .../django_cas_client-1.2.0.egg-info/top_level.txt |   1 +
 .../django_cas_client-1.2.0.egg-info/zip-safe      |   1 +
 debian/python-django-casclient-doc.docs            |  14 ++
 .../lib/python3.5/dist-packages/cas/__init__.py    |  32 +++
 .../lib/python3.5/dist-packages/cas/backends.py    | 257 +++++++++++++++++++++
 .../lib/python3.5/dist-packages/cas/decorators.py  |  93 ++++++++
 .../lib/python3.5/dist-packages/cas/exceptions.py  |  17 ++
 .../lib/python3.5/dist-packages/cas/middleware.py  |  92 ++++++++
 .../usr/lib/python3.5/dist-packages/cas/models.py  | 108 +++++++++
 .../python3.5/dist-packages/cas/tests/__init__.py  |   3 +
 .../python3.5/dist-packages/cas/tests/factories.py |  15 ++
 .../dist-packages/cas/tests/test_backend.py        |  30 +++
 .../dist-packages/cas/tests/test_smoke.py          |   7 +
 .../dist-packages/cas/tests/test_views.py          |  46 ++++
 .../usr/lib/python3.5/dist-packages/cas/utils.py   |  26 +++
 .../usr/lib/python3.5/dist-packages/cas/views.py   | 257 +++++++++++++++++++++
 .../django_cas_client-1.2.0.egg-info/PKG-INFO      | 184 +++++++++++++++
 .../dependency_links.txt                           |   1 +
 .../django_cas_client-1.2.0.egg-info/top_level.txt |   1 +
 .../django_cas_client-1.2.0.egg-info/zip-safe      |   1 +
 debian/rules                                       |  22 ++
 debian/source/format                               |   1 +
 debian/watch                                       |  23 ++
 44 files changed, 2576 insertions(+)

diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..dfceb47
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,11 @@
+python-django-casclient (1.2.0-1) unstable; urgency=medium
+
+  * Private release for Tilburg University.
+  * FIXME: tests fail; see debian/rules:
+     ImproperlyConfigured: Requested setting CAS_EXTRA_LOGIN_PARAMS, but
+     settings are not configured. You must either define the environment
+     variable DJANGO_SETTINGS_MODULE or call settings.configure() before
+     accessing settings.
+     Ran 3 tests in 0.000s  FAILED (errors=3)
+
+ -- Joost van Baal-Ilić <joostvb at debian.org>  Fri, 11 Mar 2016 13:59:58 +0000
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..d32660b
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,49 @@
+Source: python-django-casclient
+Section: python
+Priority: optional
+Maintainer: Joost van Baal-Ilić <joostvb at debian.org>
+Build-Depends: debhelper (>=9), dh-python, python-all (>= 2.6.6-3~),
+ python-setuptools, python3-all, python3-setuptools,
+ python-django-appconf, python3-django-appconf
+Standards-Version: 3.9.6
+Homepage: https://github.com/kstateome/django-cas/
+X-Python-Version: >= 2.6
+X-Python3-Version: >= 3.2
+#Vcs-Git: git://anonscm.debian.org/collab-maint/django-cas.git
+#Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/django-cas.git
+
+Package: python-django-casclient
+Architecture: all
+Depends: ${python:Depends}, ${misc:Depends}
+Suggests: python-django-cas-doc
+Description: CAS client library for Django, K-State's version (Python 2)
+ Django-cas is a CAS client library for Django.  It is K-State's
+ fork of the original and includes Edmund Crewe's proxy ticket
+ patch and several additional features as well as features merged
+ from KTHse's django-cas2.
+ .
+ This package installs the library for Python 2.
+
+Package: python3-django-casclient
+Architecture: all
+Depends: ${python3:Depends}, ${misc:Depends}
+Suggests: python-django-cas-doc
+Description: CAS client library for Django, K-State's version (Python 3)
+ Django-cas is a CAS client library for Django.  It is K-State's
+ fork of the original and includes Edmund Crewe's proxy ticket
+ patch and several additional features as well as features merged
+ from KTHse's django-cas2.
+ .
+ This package installs the library for Python 3.
+
+Package: python-django-casclient-doc
+Architecture: all
+Section: doc
+Depends: ${sphinxdoc:Depends}, ${misc:Depends}
+Description: CAS client library for Django, K-State's version (common documentation)
+ Django-cas is a CAS client library for Django.  It is K-State's
+ fork of the original and includes Edmund Crewe's proxy ticket
+ patch and several additional features as well as features merged
+ from KTHse's django-cas2.
+ .
+ This is the common documentation package.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..37bc41a
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,38 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: django-cas
+Source: https://codeload.github.com/kstateome/django-cas
+
+Files: *
+Copyright: <years> <put author's name and email here>
+           <years> <likewise for another author>
+License: <special license>
+ <Put the license of the package here indented by 1 space>
+ <This follows the format of Description: lines in control file>
+ .
+ <Including paragraphs>
+
+# If you want to use GPL v2 or later for the /debian/* files use 
+# the following clauses, or change it to suit. Delete these two lines
+Files: debian/*
+Copyright: 2016 Joost van Baal-Ilić <joostvb at debian.org>
+License: GPL-2+
+ This package is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ .
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
+
+# Please also look if there are files or directories which have a
+# different copyright/license attached and list them here.
+# Please avoid picking licenses with terms that are more restrictive than the
+# packaged work, as it may make Debian's contributions unacceptable upstream.
diff --git a/debian/postinst b/debian/postinst
new file mode 100644
index 0000000..688b92f
--- /dev/null
+++ b/debian/postinst
@@ -0,0 +1,39 @@
+#!/bin/sh
+# postinst script for django-cas
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <postinst> `configure' <most-recently-configured-version>
+#        * <old-postinst> `abort-upgrade' <new version>
+#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+#          <new-version>
+#        * <postinst> `abort-remove'
+#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+#          <failed-install-package> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+    configure)
+    ;;
+
+    abort-upgrade|abort-remove|abort-deconfigure)
+    ;;
+
+    *)
+        echo "postinst called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/prerm b/debian/prerm
new file mode 100644
index 0000000..6d31c40
--- /dev/null
+++ b/debian/prerm
@@ -0,0 +1,38 @@
+#!/bin/sh
+# prerm script for django-cas
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <prerm> `remove'
+#        * <old-prerm> `upgrade' <new-version>
+#        * <new-prerm> `failed-upgrade' <old-version>
+#        * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
+#        * <deconfigured's-prerm> `deconfigure' `in-favour'
+#          <package-being-installed> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+    remove|upgrade|deconfigure)
+    ;;
+
+    failed-upgrade)
+    ;;
+
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/__init__.py b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/__init__.py
new file mode 100644
index 0000000..59ea0eb
--- /dev/null
+++ b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/__init__.py
@@ -0,0 +1,32 @@
+"""Django CAS 1.0/2.0 authentication backend"""
+
+from django.conf import settings
+
+__all__ = []
+
+_DEFAULTS = {
+    'CAS_ADMIN_PREFIX': None,
+    'CAS_EXTRA_LOGIN_PARAMS': None,
+    'CAS_IGNORE_REFERER': False,
+    'CAS_LOGOUT_COMPLETELY': True,
+    'CAS_REDIRECT_URL': '/',
+    'CAS_RETRY_LOGIN': False,
+    'CAS_SERVER_URL': None,
+    'CAS_VERSION': '2',
+    'CAS_GATEWAY': False,
+    'CAS_PROXY_CALLBACK': None,
+    'CAS_RESPONSE_CALLBACKS': None,
+    'CAS_CUSTOM_FORBIDDEN': None,
+    'CAS_PGT_FETCH_WAIT': True,
+    'CAS_FORCE_SSL_SERVICE_URL': False,
+    'CAS_AUTO_CREATE_USER': True,
+}
+
+for key, value in _DEFAULTS.items():
+    try:
+        getattr(settings, key)
+    except AttributeError:
+        setattr(settings, key, value)
+    # Suppress errors from DJANGO_SETTINGS_MODULE not being set
+    except ImportError:
+        pass
diff --git a/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/backends.py b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/backends.py
new file mode 100644
index 0000000..5a646aa
--- /dev/null
+++ b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/backends.py
@@ -0,0 +1,257 @@
+import logging
+from xml.dom import minidom
+import time
+
+try:
+    from xml.etree import ElementTree
+except ImportError:
+    from elementtree import ElementTree
+
+try:
+    from urllib import urlencode
+except ImportError:
+    from urllib.parse import urlencode
+try:
+    from urllib import urlopen
+except ImportError:
+    from urllib.request import urlopen
+try:
+    from urlparse import urljoin
+except ImportError:
+    from urllib.parse import urljoin
+
+
+from django.conf import settings
+from django.contrib.auth import get_user_model
+
+from cas.exceptions import CasTicketException
+from cas.models import Tgt, PgtIOU
+from cas.utils import cas_response_callbacks
+
+__all__ = ['CASBackend']
+
+logger = logging.getLogger(__name__)
+
+
+def _verify_cas1(ticket, service):
+    """
+    Verifies CAS 1.0 authentication ticket.
+
+    :param: ticket
+    :param: service
+
+    Returns username on success and None on failure.
+    """
+
+    params = {'ticket': ticket, 'service': service}
+    url = (urljoin(settings.CAS_SERVER_URL, 'validate') + '?' +
+           urlencode(params))
+    page = urlopen(url)
+
+    try:
+        verified = page.readline().strip()
+        if verified == 'yes':
+            return page.readline().strip()
+        else:
+            return None
+    finally:
+        page.close()
+
+
+def _verify_cas2(ticket, service):
+    """
+    Verifies CAS 2.0+ XML-based authentication ticket.
+
+    :param: ticket
+    :param: service
+    """
+    return _internal_verify_cas(ticket, service, 'proxyValidate')
+
+
+def _verify_cas3(ticket, service):
+    return _internal_verify_cas(ticket, service, 'p3/proxyValidate')
+
+
+def _internal_verify_cas(ticket, service, suffix):
+    """Verifies CAS 2.0 and 3.0 XML-based authentication ticket.
+
+    Returns username on success and None on failure.
+    """
+
+    params = {'ticket': ticket, 'service': service}
+    if settings.CAS_PROXY_CALLBACK:
+        params['pgtUrl'] = settings.CAS_PROXY_CALLBACK
+
+    url = (urljoin(settings.CAS_SERVER_URL, suffix) + '?' +
+           urlencode(params))
+
+    page = urlopen(url)
+
+    username = None
+
+    try:
+        response = page.read()
+        tree = ElementTree.fromstring(response)
+        document = minidom.parseString(response)
+
+        if tree[0].tag.endswith('authenticationSuccess'):
+            if settings.CAS_RESPONSE_CALLBACKS:
+                cas_response_callbacks(tree)
+
+            username = tree[0][0].text
+
+            pgt_el = document.getElementsByTagName('cas:proxyGrantingTicket')
+
+            if pgt_el:
+                pgt = pgt_el[0].firstChild.nodeValue
+                try:
+                    pgtIou = _get_pgtiou(pgt)
+                    tgt = Tgt.objects.get(username=username)
+                    tgt.tgt = pgtIou.tgt
+                    tgt.save()
+                    pgtIou.delete()
+                except Tgt.DoesNotExist:
+                    Tgt.objects.create(username=username, tgt=pgtIou.tgt)
+                    logger.info('Creating TGT ticket for {user}'.format(
+                        user=username
+                    ))
+                    pgtIou.delete()
+                except Exception as e:
+                    logger.warning('Failed to do proxy authentication. {message}'.format(
+                        message=e
+                    ))
+
+        else:
+            failure = document.getElementsByTagName('cas:authenticationFailure')
+            if failure:
+                logger.warn('Authentication failed from CAS server: %s',
+                            failure[0].firstChild.nodeValue)
+
+    except Exception as e:
+        logger.error('Failed to verify CAS authentication: {message}'.format(
+            message=e
+        ))
+
+    finally:
+        page.close()
+
+    return username
+
+
+def verify_proxy_ticket(ticket, service):
+    """
+    Verifies CAS 2.0+ XML-based proxy ticket.
+
+    :param: ticket
+    :param: service
+
+    Returns username on success and None on failure.
+    """
+
+    params = {'ticket': ticket, 'service': service}
+
+    url = (urljoin(settings.CAS_SERVER_URL, 'proxyValidate') + '?' +
+           urlencode(params))
+
+    page = urlopen(url)
+
+    try:
+        response = page.read()
+        tree = ElementTree.fromstring(response)
+        if tree[0].tag.endswith('authenticationSuccess'):
+            username = tree[0][0].text
+            proxies = []
+            if len(tree[0]) > 1:
+                for element in tree[0][1]:
+                    proxies.append(element.text)
+            return {"username": username, "proxies": proxies}
+        else:
+            return None
+    finally:
+        page.close()
+
+_PROTOCOLS = {'1': _verify_cas1, '2': _verify_cas2, '3': _verify_cas3}
+
+if settings.CAS_VERSION not in _PROTOCOLS:
+    raise ValueError('Unsupported CAS_VERSION %r' % settings.CAS_VERSION)
+
+_verify = _PROTOCOLS[settings.CAS_VERSION]
+
+
+def _get_pgtiou(pgt):
+    """
+    Returns a PgtIOU object given a pgt.
+
+    The PgtIOU (tgt) is set by the CAS server in a different request
+    that has completed before this call, however, it may not be found in
+    the database by this calling thread, hence the attempt to get the
+    ticket is retried for up to 5 seconds. This should be handled some
+    better way.
+
+    Users can opt out of this waiting period by setting CAS_PGT_FETCH_WAIT = False
+
+    :param: pgt
+
+    """
+
+    pgtIou = None
+    retries_left = 5
+
+    if not settings.CAS_PGT_FETCH_WAIT:
+        retries_left = 1
+
+    while not pgtIou and retries_left:
+        try:
+            return PgtIOU.objects.get(tgt=pgt)
+        except PgtIOU.DoesNotExist:
+            if settings.CAS_PGT_FETCH_WAIT:
+                time.sleep(1)
+            retries_left -= 1
+            logger.info('Did not fetch ticket, trying again.  {tries} tries left.'.format(
+                tries=retries_left
+            ))
+    raise CasTicketException("Could not find pgtIou for pgt %s" % pgt)
+
+
+class CASBackend(object):
+    """
+    CAS authentication backend
+    """
+
+    supports_object_permissions = False
+    supports_inactive_user = False
+
+    def authenticate(self, ticket, service):
+        """
+        Verifies CAS ticket and gets or creates User object
+        NB: Use of PT to identify proxy
+        """
+
+        User = get_user_model()
+        username = _verify(ticket, service)
+
+        if not username:
+            return None
+
+        try:
+            user = User.objects.get(username__iexact=username)
+        except User.DoesNotExist:
+            # user will have an "unusable" password
+            if settings.CAS_AUTO_CREATE_USER:
+                user = User.objects.create_user(username, '')
+                user.save()
+            else:
+                user = None
+        return user
+
+    def get_user(self, user_id):
+        """
+        Retrieve the user's entry in the User model if it exists
+        """
+
+        User = get_user_model()
+
+        try:
+            return User.objects.get(pk=user_id)
+        except User.DoesNotExist:
+            return None
diff --git a/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/decorators.py b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/decorators.py
new file mode 100644
index 0000000..7cc0e3c
--- /dev/null
+++ b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/decorators.py
@@ -0,0 +1,93 @@
+try:
+    from functools import wraps
+except ImportError:
+    from django.utils.functional import wraps
+
+try:
+    from urllib import urlencode
+except ImportError:
+    from urllib.parse import urlencode
+
+from django.contrib.auth import REDIRECT_FIELD_NAME
+from django.http import HttpResponseForbidden, HttpResponseRedirect
+from django.utils.http import urlquote
+from django.conf import settings
+from django.core.exceptions import ImproperlyConfigured
+
+__all__ = ['permission_required', 'user_passes_test']
+
+
+def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
+    """
+    Replacement for django.contrib.auth.decorators.user_passes_test that
+    returns 403 Forbidden if the user is already logged in.
+    """
+
+    if not login_url:
+        login_url = settings.LOGIN_URL
+
+    def decorator(view_func):
+        @wraps(view_func)
+        def wrapper(request, *args, **kwargs):
+            if test_func(request.user):
+                return view_func(request, *args, **kwargs)
+            elif request.user.is_authenticated():
+                return HttpResponseForbidden('<h1>Permission denied</h1>')
+            else:
+                path = '%s?%s=%s' % (login_url, redirect_field_name,
+                                     urlquote(request.get_full_path()))
+                return HttpResponseRedirect(path)
+        return wrapper
+    return decorator
+
+
+def permission_required(perm, login_url=None):
+    """
+    Replacement for django.contrib.auth.decorators.permission_required that
+    returns 403 Forbidden if the user is already logged in.
+    """
+
+    return user_passes_test(lambda u: u.has_perm(perm), login_url=login_url)
+
+
+def gateway():
+    """
+    Authenticates single sign on session if ticket is available,
+    but doesn't redirect to sign in url otherwise.
+    """
+
+    if settings.CAS_GATEWAY == False:
+        raise ImproperlyConfigured('CAS_GATEWAY must be set to True')
+
+    def wrap(func):
+        def wrapped_f(*args):
+
+            from cas.views import login
+            request = args[0]
+
+            if request.user.is_authenticated():
+                # Is Authed, fine
+                pass
+            else:
+                path_with_params = request.path + '?' + urlencode(request.GET.copy())
+                if request.GET.get('ticket'):
+                    # Not Authed, but have a ticket!
+                    # Try to authenticate
+                    response = login(request, path_with_params, False, True)
+                    if isinstance(response, HttpResponseRedirect):
+                        # For certain instances where a forbidden occurs, we need to pass instead of return a response.
+                        return response
+                else:
+                    #Not Authed, but no ticket
+                    gatewayed = request.GET.get('gatewayed')
+                    if gatewayed == 'true':
+                        pass
+                    else:
+                        # Not Authed, try to authenticate
+                        response = login(request, path_with_params, False, True)
+                        if isinstance(response, HttpResponseRedirect):
+                            return response
+
+            return func(*args)
+        return wrapped_f
+    return wrap
diff --git a/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/exceptions.py b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/exceptions.py
new file mode 100644
index 0000000..c50d3c2
--- /dev/null
+++ b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/exceptions.py
@@ -0,0 +1,17 @@
+from django.core.exceptions import ValidationError
+
+
+class CasTicketException(ValidationError):
+    """
+    The ticket fails to validate
+    """
+
+    pass
+
+
+class CasConfigException(ValidationError):
+    """
+    The config is wrong
+    """
+
+    pass
diff --git a/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/middleware.py b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/middleware.py
new file mode 100644
index 0000000..771a1d1
--- /dev/null
+++ b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/middleware.py
@@ -0,0 +1,92 @@
+"""CAS authentication middleware"""
+
+try:
+    from urllib import urlencode
+except ImportError:
+    from urllib.parse import urlencode
+
+from django.conf import settings
+from django.contrib.auth import REDIRECT_FIELD_NAME
+from django.contrib.auth import logout as do_logout
+from django.contrib.auth.views import login, logout
+from django.core.urlresolvers import reverse
+from django.http import HttpResponseRedirect, HttpResponseForbidden
+from django.core.exceptions import ImproperlyConfigured
+
+from cas.exceptions import CasTicketException
+from cas.views import login as cas_login, logout as cas_logout
+
+__all__ = ['CASMiddleware']
+
+
+class CASMiddleware(object):
+    """
+    Middleware that allows CAS authentication on admin pages
+    """
+
+    def process_request(self, request):
+        """
+        Checks that the authentication middleware is installed
+
+        :param: request
+
+        """
+
+        error = ("The Django CAS middleware requires authentication "
+                 "middleware to be installed. Edit your MIDDLEWARE_CLASSES "
+                 "setting to insert 'django.contrib.auth.middleware."
+                 "AuthenticationMiddleware'.")
+        assert hasattr(request, 'user'), error
+
+    def process_view(self, request, view_func, view_args, view_kwargs):
+        """
+        Forwards unauthenticated requests to the admin page to the CAS
+        login URL, as well as calls to django.contrib.auth.views.login and
+        logout.
+        """
+
+        if view_func == login:
+            return cas_login(request, *view_args, **view_kwargs)
+        elif view_func == logout:
+            return cas_logout(request, *view_args, **view_kwargs)
+
+        if settings.CAS_ADMIN_PREFIX:
+            if not request.path.startswith(settings.CAS_ADMIN_PREFIX):
+                return None
+        elif not view_func.__module__.startswith('django.contrib.admin.'):
+            return None
+
+        if request.user.is_authenticated():
+            if request.user.is_staff:
+                return None
+            else:
+                error = ('<h1>Forbidden</h1><p>You do not have staff '
+                         'privileges.</p>')
+                return HttpResponseForbidden(error)
+
+        params = urlencode({REDIRECT_FIELD_NAME: request.get_full_path()})
+        return HttpResponseRedirect(reverse(cas_login) + '?' + params)
+
+    def process_exception(self, request, exception):
+        """
+        When we get a CasTicketException, that is probably caused by the ticket timing out.
+        So logout/login and get the same page again.
+        """
+
+        if isinstance(exception, CasTicketException):
+            do_logout(request)
+            # This assumes that request.path requires authentication.
+            return HttpResponseRedirect(request.path)
+        else:
+            return None
+
+
+class ProxyMiddleware(object):
+
+    # Middleware used to "fake" the django app that it lives at the Proxy Domain
+    def process_request(self, request):
+        proxy = getattr(settings, 'PROXY_DOMAIN', None)
+        if not proxy:
+            raise ImproperlyConfigured('To use Proxy Middleware you must set a PROXY_DOMAIN setting.')
+        else:
+            request.META['HTTP_HOST'] = proxy
diff --git a/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/models.py b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/models.py
new file mode 100644
index 0000000..54b1606
--- /dev/null
+++ b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/models.py
@@ -0,0 +1,108 @@
+import logging
+from datetime import datetime
+try:
+    from xml.etree import ElementTree
+except ImportError:
+    from elementtree import ElementTree
+try:
+    from urlparse import urljoin
+except ImportError:
+    from urllib.parse import urljoin
+try:
+    from urllib import urlencode
+except ImportError:
+    from urllib.parse import urlencode
+try:
+    from urllib import urlopen
+except ImportError:
+    from urllib.request import urlopen
+
+from django.db import models
+from django.conf import settings
+from django.core.exceptions import ObjectDoesNotExist
+from django.db.models.signals import post_save
+
+
+from cas.exceptions import CasTicketException, CasConfigException
+
+
+logger = logging.getLogger(__name__)
+
+
+class Tgt(models.Model):
+    username = models.CharField(max_length=255, unique=True)
+    tgt = models.CharField(max_length=255)
+
+    def get_proxy_ticket_for(self, service):
+        """
+        Verifies CAS 2.0+ XML-based authentication ticket.
+
+        :param: service
+
+        Returns username on success and None on failure.
+        """
+
+        if not settings.CAS_PROXY_CALLBACK:
+            raise CasConfigException("No proxy callback set in settings")
+
+        params = {'pgt': self.tgt, 'targetService': service}
+
+        url = (urljoin(settings.CAS_SERVER_URL, 'proxy') + '?' +
+               urlencode(params))
+
+        page = urlopen(url)
+
+        try:
+            response = page.read()
+            tree = ElementTree.fromstring(response)
+            if tree[0].tag.endswith('proxySuccess'):
+                return tree[0][0].text
+            else:
+                logger.warning('Failed to get proxy ticket')
+                raise CasTicketException('Failed to get proxy ticket: %s' % \
+                                         tree[0].text.strip())
+        finally:
+            page.close()
+
+
+class PgtIOU(models.Model):
+    """
+    Proxy granting ticket and IOU
+    """
+    pgtIou = models.CharField(max_length = 255, unique = True)
+    tgt = models.CharField(max_length = 255)
+    created = models.DateTimeField(auto_now = True)
+
+
+def get_tgt_for(user):
+    """
+    Fetch a ticket granting ticket for a given user.
+
+    :param user: UserObj
+
+    :return: TGT or Exepction
+    """
+    if not settings.CAS_PROXY_CALLBACK:
+        raise CasConfigException("No proxy callback set in settings")
+
+    try:
+        return Tgt.objects.get(username=user.username)
+    except ObjectDoesNotExist:
+        logger.warning('No ticket found for user {user}'.format(
+            user=user.username
+        ))
+        raise CasTicketException("no ticket found for user " + user.username)
+
+
+def delete_old_tickets(**kwargs):
+    """
+    Delete tickets if they are over 2 days old
+    kwargs = ['raw', 'signal', 'instance', 'sender', 'created']
+
+    """
+    sender = kwargs.get('sender', None)
+    now = datetime.now()
+    expire = datetime(now.year, now.month, now.day - 2)
+    sender.objects.filter(created__lt=expire).delete()
+
+post_save.connect(delete_old_tickets, sender=PgtIOU)
diff --git a/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/__init__.py b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/__init__.py
new file mode 100644
index 0000000..3b172cc
--- /dev/null
+++ b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/__init__.py
@@ -0,0 +1,3 @@
+from cas.tests.test_smoke import *
+from cas.tests.test_backend import *
+from cas.tests.test_views import *
\ No newline at end of file
diff --git a/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/factories.py b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/factories.py
new file mode 100644
index 0000000..865d348
--- /dev/null
+++ b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/factories.py
@@ -0,0 +1,15 @@
+from django.contrib.auth.models import User
+
+
+import factory
+
+
+class UserFactory(factory.DjangoModelFactory):
+    class Meta:
+        model = User
+
+    username = "derekst"
+    first_name = "new"
+    last_name = "user"
+    is_staff = True
+    password = factory.PostGenerationMethodCall('set_password', '1234')
\ No newline at end of file
diff --git a/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/test_backend.py b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/test_backend.py
new file mode 100644
index 0000000..cdcb2c9
--- /dev/null
+++ b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/test_backend.py
@@ -0,0 +1,30 @@
+import mock
+from django.test import TestCase
+
+from cas.backends import CASBackend
+from cas.tests import factories
+
+
+class CASBackendTest(TestCase):
+
+    def setUp(self):
+        self.user = factories.UserFactory.create()
+
+    def test_get_user(self):
+        backend = CASBackend()
+
+        self.assertEqual(backend.get_user(self.user.pk), self.user)
+
+    @mock.patch('cas.backends._verify')
+    def test_user_auto_create(self, verify):
+        username = 'faker'
+        verify.return_value = username
+        backend = CASBackend()
+
+        with self.settings(CAS_AUTO_CREATE_USER=False):
+            user = backend.authenticate('fake', 'fake')
+            self.assertIsNone(user)
+
+        with self.settings(CAS_AUTO_CREATE_USER=True):
+            user = backend.authenticate('fake', 'fake')
+            self.assertEquals(user.username, username)
diff --git a/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/test_smoke.py b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/test_smoke.py
new file mode 100644
index 0000000..19f78d8
--- /dev/null
+++ b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/test_smoke.py
@@ -0,0 +1,7 @@
+from cas.models import *
+from cas.backends import *
+from cas.middleware import *
+from cas.views import *
+from cas.decorators import *
+from cas.exceptions import *
+from cas.utils import *
diff --git a/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/test_views.py b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/test_views.py
new file mode 100644
index 0000000..1f5643a
--- /dev/null
+++ b/debian/python-django-cas/usr/lib/python2.7/dist-packages/cas/tests/test_views.py
@@ -0,0 +1,46 @@
+from django.test import TestCase, RequestFactory
+from django.test.utils import override_settings
+
+from cas.views import _redirect_url, _login_url, _logout_url, _service_url
+
+
+class RequestFactoryRemix(RequestFactory):
+
+    path = '/'
+
+    def get_host(self):
+        return 'signin.k-state.edu'
+
+    def is_secure(self):
... 1896 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-django-casclient.git



More information about the Python-modules-commits mailing list