from django.contrib.auth.middleware import RemoteUserMiddleware
from django.contrib import auth
from django.core.exceptions import ImproperlyConfigured

from shibboleth.app_settings import SHIB_ATTRIBUTE_MAP, LOGOUT_SESSION_KEY

class ShibbolethRemoteUserMiddleware(RemoteUserMiddleware):
    """
    Authentication Middleware for use with Shibboleth.  Uses the recommended pattern 
    for remote authentication from: http://code.djangoproject.com/svn/django/tags/releases/1.3/django/contrib/auth/middleware.py
    """
    def parse_attributes(self, request):
        """
        From: https://github.com/russell/django-shibboleth/blob/master/django_shibboleth/utils.py
        Pull the mapped attributes from the apache headers.
        """
        shib_attrs = {}
        error = False
        meta = request.META
        for header, attr in SHIB_ATTRIBUTE_MAP.items():
            required, name = attr
            value = meta.get(header, None)
            shib_attrs[name] = value
            if not value or value == '':
                if required:
                    error = True
        return shib_attrs, error

    def process_request(self, request):
        # AuthenticationMiddleware is required so that request.user exists.
        if not hasattr(request, 'user'):
            raise ImproperlyConfigured(
                "The Django remote user auth middleware requires the"
                " authentication middleware to be installed.  Edit your"
                " MIDDLEWARE_CLASSES setting to insert"
                " 'django.contrib.auth.middleware.AuthenticationMiddleware'"
                " before the RemoteUserMiddleware class.")

        #To support logout.  If this variable is True, do not 
        #authenticate user and return now.
        if request.session.get(LOGOUT_SESSION_KEY) == True:
            return 
        else:
            #Delete the shib reauth session key if present.
	    request.session.pop(LOGOUT_SESSION_KEY, None)
	#Locate the remote user header.  
        try:
            username = request.META[self.header]
        except KeyError:
            # If specified header doesn't exist then return (leaving
            # request.user set to AnonymousUser by the
            # AuthenticationMiddleware).
            return
        # If the user is already authenticated and that user is the user we are
        # getting passed in the headers, then the correct user is already
        # persisted in the session and we don't need to continue.
        if request.user.is_authenticated():
            if request.user.username == self.clean_username(username, request):
                return

        # Make sure we have all required Shiboleth elements before proceeding.
        shib_meta, error = self.parse_attributes(request)
        # Add parsed attributes to the session.
        request.session['shib'] = shib_meta
        if error:
            raise ShibbolethValidationError("All required Shibboleth elements"
                                            " not found.  %s" % shib_meta)

        # We are seeing this user for the first time in this session, attempt
        # to authenticate the user.
        user = auth.authenticate(remote_user=username)
        if user:
            # User is valid.  Set request.user and persist user in the session
            # by logging the user in.
            request.user = user
            auth.login(request, user)
            user.set_unusable_password()
            user.first_name = shib_meta.get('first_name', '')
            user.last_name = shib_meta.get('last_name', '')
            #import ipdb; ipdb.set_trace()
            user.email = shib_meta.get('email', '')
            user.save()
            # call make profile.
            self.make_profile(user, shib_meta)

    def make_profile(self, user, shib_meta):
        """
        This is here as a stub to allow subclassing of ShibbolethRemoteUserMiddleware
        to include a make_profile method that will create a Django user profile
        from the Shib provided attributes.  By default it does noting.
        """
        return

class ShibbolethValidationError(Exception):
    pass

@@ -528,629 +528,8 @@
 %22%22%0D%0A
-    def parse_attributes(self, request):%0D%0A        %22%22%22%0D%0A        From: https://github.com/russell/django-shibboleth/blob/master/django_shibboleth/utils.py%0D%0A        Pull the mapped attributes from the apache headers.%0D%0A        %22%22%22%0D%0A        shib_attrs = %7B%7D%0D%0A        error = False%0D%0A        meta = request.META%0D%0A        for header, attr in SHIB_ATTRIBUTE_MAP.items():%0D%0A            required, name = attr%0D%0A            value = meta.get(header, None)%0D%0A            shib_attrs%5Bname%5D = value%0D%0A            if not value or value == '':%0D%0A                if required:%0D%0A                    error = True%0D%0A        return shib_attrs, error%0D%0A%0D%0A
     
@@ -1334,24 +1334,28 @@
 sent.%0D%0A%09    
+    
 request.sess
@@ -1390,16 +1390,29 @@
 None)%0D%0A%09
+   %0D%0A        
 #Locate 
@@ -3581,16 +3581,693 @@
  return%0D
+%0A    %0D%0A    def parse_attributes(self, request):%0D%0A        %22%22%22%0D%0A        Parse the incoming Shibboleth attributes. %0D%0A        From: https://github.com/russell/django-shibboleth/blob/master/django_shibboleth/utils.py%0D%0A        Pull the mapped attributes from the apache headers.%0D%0A        %22%22%22%0D%0A        shib_attrs = %7B%7D%0D%0A        error = False%0D%0A        meta = request.META%0D%0A        for header, attr in SHIB_ATTRIBUTE_MAP.items():%0D%0A            required, name = attr%0D%0A            value = meta.get(header, None)%0D%0A            shib_attrs%5Bname%5D = value%0D%0A            if not value or value == '':%0D%0A                if required:%0D%0A                    error = True%0D%0A        return shib_attrs, error%0D
 %0A%0D%0Aclass

Move parse_attributes.