source: TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/openid/provider/axinterface/csv.py @ 7077

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg-security/TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/openid/provider/axinterface/csv.py@7077
Revision 7077, 7.2 KB checked in by pjkersha, 11 years ago (diff)
  • Property svn:keywords set to Id
Line 
1"""NDG Security OpenID Provider AX Interface for CSV file based attribute store
2
3For test purposes only
4
5NERC DataGrid Project
6"""
7__author__ = "P J Kershaw"
8__date__ = "30/09/09"
9__copyright__ = "(C) 2009 Science and Technology Facilities Council"
10__license__ = "BSD - see LICENSE file in top-level directory"
11__contact__ = "Philip.Kershaw@stfc.ac.uk"
12__revision__ = "$Id$"
13import logging
14log = logging.getLogger(__name__)
15
16import re
17
18from ndg.security.server.wsgi.openid.provider.axinterface import (AXInterface, 
19    AXInterfaceConfigError, MissingRequiredAttrs)
20from ndg.security.server.wsgi.openid.provider import (AbstractAuthNInterface, 
21    OpenIDProviderMiddleware)
22
23
24class CSVFileAXInterface(AXInterface):
25    """OpenID Provider Attribute Exchange Interface based on a Comma Separated
26    Variable file containing user identities and associated attributes. 
27    For test/development purposes
28    only.
29   
30    The expected file format is:
31   
32    <OpenID>, <attr 1>, <attr 2>, ... <attr N>
33    """
34    ATTR_NAMES = (
35        "csvFilePath",
36        "attributeNames",
37        "attributeMap",
38    )
39    __slots__ = tuple(["__%s" % n for n in ATTR_NAMES])
40    del n
41   
42    IDENTITY_URI_SESSION_KEYNAME = \
43                        OpenIDProviderMiddleware.IDENTITY_URI_SESSION_KEYNAME
44   
45    def __init__(self, **properties):
46        """
47        @param properties: file path to Comma Separated file
48        containing user ids and roles
49        @type properties: dict
50        """
51        self.__csvFilePath = None
52        self.__attributeNames = []
53        self.__attributeMap = {}
54       
55        self.setProperties(**properties)
56        if self.csvFilePath is not None:
57            self.read()
58
59    def _getAttributeNames(self):
60        return self.__attributeNames
61
62    def _setAttributeNames(self, value):
63        """@param value: if a string, it will be parsed into a list delimiting
64        elements by whitespace
65        @type value: basestring/tuple or list
66        """
67        if isinstance(value, (list, tuple)):
68            self.__attributeNames = list(value)
69           
70        elif isinstance(value, basestring):
71            self.__attributeNames = value.split() 
72        else:
73            raise TypeError('Expecting string, list or tuple type for '
74                            '"attributeNames"; got %r' % type(value))
75       
76    attributeNames = property(fget=_getAttributeNames, 
77                              fset=_setAttributeNames, 
78                              doc="list of attribute names supported.  The "
79                                  "order of the names is important and "
80                                  "determines the order in which they will be "
81                                  "assigned from the columns in the CSV file")
82
83    def setProperties(self, **properties):
84        for name, val in properties.items():
85            setattr(self, name, val)
86   
87    def read(self):
88        csvFile = open(self.csvFilePath)
89        lines = csvFile.readlines()
90       
91        nAttributes = len(self.attributeNames)
92        for line in lines:
93            fields = re.split(',\s*', line.strip())
94           
95            # Dictionary keyed by user ID with each val itself a dict keyed
96            # by attribute name
97            self.attributeMap[fields[0]] = dict(zip(self.attributeNames,
98                                                    fields[1:nAttributes+1]))
99               
100    def _getCsvFilePath(self):
101        return self.__csvFilePath
102
103    def _setCsvFilePath(self, value):
104        if not isinstance(value, basestring):
105            raise TypeError('Expecting string type for "csvFilePath"; got %r'
106                            % type(value))
107        self.__csvFilePath = value
108
109    csvFilePath = property(fget=_getCsvFilePath, 
110                           fset=_setCsvFilePath, 
111                           doc="file path to Comma Separated Variable format "
112                               "file containing user IDs and attributes")
113   
114    def _getAttributeMap(self):
115        return self.__attributeMap
116
117    def _setAttributeMap(self, value):
118        self.__attributeMap = value
119
120    attributeMap = property(fget=_getAttributeMap, 
121                            fset=_setAttributeMap, 
122                            doc="Dictionary of attributes keyed by user ID")
123   
124    def __call__(self, ax_req, ax_resp, authnInterface, authnCtx):
125        """Add the attributes to the ax_resp object requested in the ax_req
126        object.  If it is not possible to return them, raise
127        MissingRequiredAttrs error
128       
129        @type ax_req: openid.extensions.ax.FetchRequest
130        @param ax_req: attribute exchange request object.  To find out what
131        attributes the Relying Party has requested for example, call
132        ax_req.getRequiredAttrs()
133        @type ax_resp: openid.extensions.ax.FetchResponse
134        @param ax_resp: attribute exchange response object.  This method should
135        update the settings in this object.  Use addValue and setValues methods
136        @type authnInterface: AbstractAuthNInterface
137        @param authnInterface: custom authentication interface set at login. 
138        See ndg.security.server.openid.provider.AbstractAuthNInterface for more
139        information
140        @type authnCtx: dict like
141        @param authnCtx: session containing authentication context information
142        such as username and OpenID user identifier URI snippet
143        """
144        log.debug('CSVFileAXInterface.__call__  ...')
145       
146        identityURI = authnCtx.get(
147                                CSVFileAXInterface.IDENTITY_URI_SESSION_KEYNAME)
148        if identityURI is None:
149            raise AXInterfaceConfigError("No OpenID user identifier set in "
150                                         "session context")
151       
152        requiredAttributeURIs = ax_req.getRequiredAttrs()
153           
154        userAttributeMap = self.attributeMap.get(identityURI)
155        if userAttributeMap is None:
156            raise AXInterfaceConfigError("No attribute entry for user [%s] " %
157                                         identityURI)
158                                     
159        missingAttributeURIs = [
160            requiredAttributeURI
161            for requiredAttributeURI in requiredAttributeURIs
162            if requiredAttributeURI not in self.attributeNames
163        ]
164        if len(missingAttributeURIs) > 0:
165            raise MissingRequiredAttrs("OpenID Provider does not support "
166                                       "release of these attributes required "
167                                       "by the Relying Party: %s" %
168                                       ', '.join(missingAttributeURIs))
169       
170        # Add the requested attributes
171        for requestedAttributeURI in ax_req.requested_attributes.keys():
172            if requestedAttributeURI in self.attributeNames:
173                log.info("Adding requested AX parameter %s=%s ...", 
174                         requestedAttributeURI,
175                         userAttributeMap[requestedAttributeURI])
176               
177                ax_resp.addValue(requestedAttributeURI,
178                                 userAttributeMap[requestedAttributeURI])
179            else:
180                log.info("Skipping Relying Party requested AX parameter %s: "
181                         "this parameter is not available", 
182                         requestedAttributeURI)
183               
Note: See TracBrowser for help on using the repository browser.