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

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/openid/provider/axinterface/csv.py@6354
Revision 6354, 7.3 KB checked in by pjkersha, 10 years ago (diff)

Old Pylons SSO code moved to separate branch in trunk

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(',\W*', 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.