"""NDG Security Basic OpenID Authentication Interface.

A demonstration implementation of an authentication interface for 
OpenIDProviderMiddleware WSGI.  Username/password and OpenId user identifier
details are read from a config file and passed as keywords.  This class is not 
intended for production use.

NERC DataGrid Project

"""
__author__ = "P J Kershaw"
__date__ = "01/08/08"
__copyright__ = "(C) 2009 Science and Technology Facilities Council"
__contact__ = "Philip.Kershaw@stfc.ac.uk"
__revision__ = "$Id$"
import logging
log = logging.getLogger(__name__)

from ndg.security.server.wsgi.openid.provider.authninterface import \
    AbstractAuthNInterface, AuthNInterfaceInvalidCredentials, \
    AuthNInterfaceRetrieveError, AuthNInterfaceConfigError, \
    AuthNInterfaceUsername2IdentifierMismatch
 
    
class BasicAuthNInterface(AbstractAuthNInterface):
    '''Basic Authentication interface class for OpenIDProviderMiddleware 
    
    it uses username/password details retrieved from config file / keyword
    entry.  This class is for testing only.  NOT for production use'''
    
    IDENTITY_URI_TMPL_KEYNAME = 'identityUriTemplate'
    USERCREDS_PROPERTY_KEYNAME = 'userCreds'
    USERCREDS_KEYNAMES = ('password', 'identifiers')
    
    propertyKeyNames = (
        USERCREDS_PROPERTY_KEYNAME
    )
    
    getUserIdentifier = staticmethod(lambda identityURI: 
                                     identityURI.rsplit('/')[-1])
    
    def __init__(self, **prop):
        """Make any initial settings
        
        Settings are held in a dictionary which can be set from **prop,
        a call to setProperties() or by passing settings in an XML file
        given by propFilePath
        
        @type **prop: dict
        @param **prop: set properties via keywords 
        @raise AuthNInterfaceConfigError: error with configuration
        """
        # Test/Admin username/password set from ini/kw args
        self._identityUriTemplate = prop.get(
                                BasicAuthNInterface.IDENTITY_URI_TMPL_KEYNAME)
        userCredsField = prop.get(
                                BasicAuthNInterface.USERCREDS_PROPERTY_KEYNAME)
        if not userCredsField:
            raise AuthNInterfaceConfigError('No "%s" config option found' %
                                BasicAuthNInterface.USERCREDS_PROPERTY_KEYNAME)

        self._userCreds = {}
        for userEntry in userCredsField.split(): 
            # Split username, password and OpenID name list  
            userCreds = userEntry.strip().split(':')
            
            # Split OpenID name list
            userCreds[-1] = tuple(userCreds[-1].split(','))
            
            # Convert into a dictionary indexed by username
            userCredsKeys = BasicAuthNInterface.USERCREDS_KEYNAMES
            self._userCreds[userCreds[0]] = dict(zip(userCredsKeys, 
                                                     userCreds[1:]))  
    
    def logon(self, environ, identityURI, username, password):
        """Interface login method
        
        @type environ: dict
        @param environ: standard WSGI environ parameter

        @type identityURI: basestring
        @param identityURI: user's identity URL e.g. 