source: TI12-security/trunk/ndg_xacml/ndg/xacml/core/attributevalue.py @ 7412

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/ndg_xacml/ndg/xacml/core/attributevalue.py@7412
Revision 7412, 10.3 KB checked in by pjkersha, 9 years ago (diff)

Incomplete - task 2: XACML-Security Integration

  • added explicit class variables for all the standard attribute type URIs
  • Property svn:keywords set to Id
Line 
1"""NDG XACML attribute type definition
2
3NERC DataGrid
4"""
5__author__ = "P J Kershaw"
6__date__ = "25/02/10"
7__copyright__ = "(C) 2010 Science and Technology Facilities Council"
8__contact__ = "Philip.Kershaw@stfc.ac.uk"
9__license__ = "BSD - see LICENSE file in top-level directory"
10__contact__ = "Philip.Kershaw@stfc.ac.uk"
11__revision__ = "$Id$"
12from datetime import datetime, timedelta
13
14from ndg.xacml.utils import VettedDict
15from ndg.xacml.core.expression import Expression
16   
17
18class AttributeValue(Expression):
19    """XACML Attribute Value type
20   
21    @cvar ELEMENT_LOCAL_NAME: XML local name for this element
22    @type ELEMENT_LOCAL_NAME: string 
23    @cvar CLASS_NAME_SUFFIX: all attribute value classes end with this suffix
24    @type CLASS_NAME_SUFFIX: string
25    @cvar IDENTIFIER_PREFIX: geberic prefix for attribute value URNs
26    @type IDENTIFIER_PREFIX: string
27    @cvar IDENTIFIER: URN for attribute value in derived class
28    @type IDENTIFIER: NoneType - derived classes should set to appropriate
29    string
30    @cvar TYPE_URIS: URIs for all the different supported types
31    @type TYPE_URIS: tuple
32    @cvar TYPE_NAMES: corresponding short names for all the types
33    @type TYPE_NAMES: tuple
34    @cvar NATIVE_TYPES: equivalent python types as implemented
35    @cvar TYPE_MAP: mapping from type names to python types
36    @type TYPE_MAP: dict
37    @cvar TYPE_URI_MAP: mapping from type names to type URIs
38    @type TYPE_URI_MAP: dict
39    @cvar TYPE: type name for derived type - set to None in this parent class
40    @type TYPE: NoneType / string in derived type
41   
42    @ivar __value: setting for this attribute value
43    @type __value: any - constrained in derived classes
44    """
45    ELEMENT_LOCAL_NAME = 'AttributeValue'
46    CLASS_NAME_SUFFIX = 'AttributeValue'
47    IDENTIFIER_PREFIX = 'http://www.w3.org/2001/XMLSchema#'
48 
49    IDENTIFIER = None
50   
51    STRING_TYPE_URI = IDENTIFIER_PREFIX + 'string'
52    ANY_TYPE_URI = IDENTIFIER_PREFIX + 'anyURI'
53    INTEGER_TYPE_URI = IDENTIFIER_PREFIX + 'integer'
54    BOOLEAN_TYPE_URI = IDENTIFIER_PREFIX + 'boolean'
55    DOUBLE_TYPE_URI = IDENTIFIER_PREFIX + 'double'
56    DATE_TYPE_URI = IDENTIFIER_PREFIX + 'date'
57    DATETIME_TYPE_URI = IDENTIFIER_PREFIX + 'dateTime'
58    TIME_TYPE_URI = IDENTIFIER_PREFIX + 'time'
59    DAYTIMEDURATION_TYPE_URI = \
60    'http://www.w3.org/TR/2002/WD-xquery-operators-20020816#dayTimeDuration'
61    YEARMONTHDURATION_TYPE_URI = \
62    'http://www.w3.org/TR/2002/WD-xquery-operators-20020816#yearMonthDuration'
63    X500NAME_TYPE_URI = 'urn:oasis:names:tc:xacml:1.0:data-type:x500Name'
64    RFC822NAME_TYPE_URI = 'urn:oasis:names:tc:xacml:1.0:data-type:rfc822Name'
65    HEXBINARY_TYPE_URI = IDENTIFIER_PREFIX + 'hexBinary'
66    BASE64BINARY_TYPE_URI = IDENTIFIER_PREFIX + 'base64Binary'
67    IPADDRESS_TYPE_URI = 'urn:oasis:names:tc:xacml:2.0:data-type:ipAddress'
68    DNSNAME_TYPE_URI = 'urn:oasis:names:tc:xacml:2.0:data-type:dnsName'
69
70    TYPE_URIS = (
71        STRING_TYPE_URI,
72        ANY_TYPE_URI,
73        INTEGER_TYPE_URI,
74        BOOLEAN_TYPE_URI,
75        DOUBLE_TYPE_URI,
76        DATE_TYPE_URI,
77        DATETIME_TYPE_URI,
78        TIME_TYPE_URI,
79        DAYTIMEDURATION_TYPE_URI,
80        YEARMONTHDURATION_TYPE_URI,
81        X500NAME_TYPE_URI,
82        RFC822NAME_TYPE_URI,
83        HEXBINARY_TYPE_URI,
84        BASE64BINARY_TYPE_URI,
85        IPADDRESS_TYPE_URI,
86        DNSNAME_TYPE_URI
87    )
88    TYPE_NAMES = (
89        'String',
90        'AnyURI',
91        'Integer',
92        'Boolean',
93        'Double',
94        'Date',
95        'DateTime',
96        'Time',
97        'DayTimeDuration',
98        'YearMonthDuration',
99        'X500Name',
100        'Rfc822Name',
101        'HexBinary',
102        'Base64Binary',
103        'IpAddress',
104        'DnsName',
105    )
106    NATIVE_TYPES = (
107        basestring,
108        basestring,
109        int,
110        bool,
111        float,
112        datetime,
113        datetime,
114        datetime,
115        timedelta,
116        timedelta,
117        basestring,
118        basestring,
119        int,
120        NotImplemented,
121        basestring,
122        basestring
123    )
124    TYPE_MAP = dict(zip(TYPE_NAMES, NATIVE_TYPES))
125    TYPE_URI_MAP = dict(zip(TYPE_NAMES, TYPE_URIS))
126    TYPE = None
127   
128    __slots__ = ('__value',) 
129   
130    def __init__(self, value=None):
131        """Derived classes must override setting TYPE class variable
132       
133        @param value: initialise the attribute value by setting this keyword
134        @type value: (set by self.__class__.TYPE)
135        """
136       
137        super(AttributeValue, self).__init__()
138        if self.__class__.TYPE is None:
139            raise NotImplementedError('TYPE class variable must be set to a '
140                                      'valid type in a derived class')
141           
142        self.__value = None
143       
144        # Allow derived classes to make an implicit data type setting
145        self.dataType = self.__class__.IDENTIFIER
146       
147        if value is not None:
148            self.value = value
149
150    def __repr__(self):
151        return "%s = %r " % (super(AttributeValue, self).__repr__(),
152                             self.__value)
153
154    def __eq__(self, attrVal):
155        """Check for equality by comparing the value attributes"""
156        if not isinstance(attrVal, self.__class__):
157            raise TypeError('Expecting %r type for "value" '
158                            'attribute; got %r' % (self.__class__.TYPE, 
159                                                   type(attrVal)))
160           
161        return self.__value == attrVal.value
162   
163    def _get_value(self):
164        """Get value
165        @return: setting for this attribute value
166        @rtype: any - constrained in derived classes
167        """
168        return self.__value
169
170    def _set_value(self, value):
171        """Set value
172       
173        @param value: setting for this attribute value
174        @type value: any - constrained in derived classes
175        @raise TypeError: if type doesn't match TYPE class variable.  Derived
176        classes should set this
177        """
178        if not isinstance(value, self.__class__.TYPE):
179            raise TypeError('Expecting %r type for "value" '
180                            'attribute; got %r' % (self.__class__.TYPE, 
181                                                   type(value)))
182           
183        self.__value = value 
184
185    value = property(_get_value, _set_value, None, "expression value") 
186   
187    def evaluate(self, context):
188        """Evaluate the result of the expression in a condition.  In the case of
189        an attribute value it's simply itself
190       
191        @param context: the request context
192        @type context: ndg.xacml.core.context.request.Request
193        @return: this attribute value
194        @rtype: AttributeValue 
195        """ 
196        return self
197
198
199class AttributeValueClassMap(VettedDict):
200    """Specialised dictionary to hold mappings of XML attribute type URIs to
201    their equivalent classes
202    """
203   
204    def __init__(self):
205        """Force entries to derive from AttributeValue and IDs to
206        be string type
207        """       
208        # Filters are defined as staticmethods but reference via self here to
209        # enable derived class to override them as standard methods without
210        # needing to redefine this __init__ method           
211        VettedDict.__init__(self, self.keyFilter, self.valueFilter)
212       
213    @staticmethod
214    def keyFilter(key):
215        """Enforce string type keys
216       
217        @param key: URN for attribute
218        @type key: basestring
219        @return: boolean True indicating key is OK
220        @rtype: bool
221        @raise TypeError: incorrect input type
222        """
223        if not isinstance(key, basestring):
224            raise TypeError('Expecting %r type for key; got %r' % 
225                            (basestring, type(key))) 
226        return True 
227   
228    @staticmethod
229    def valueFilter(value):
230        """Enforce AttributeValue derived types for values
231        @param value: attribute value
232        @type value: ndg.xacml.core.attributevalue.AttributeValue derived type
233        @return: boolean True indicating attribute value is correct type
234        @rtype: bool
235        @raise TypeError: incorrect input type
236        """
237        if not issubclass(value, AttributeValue):
238            raise TypeError('Expecting %r derived type for value; got %r' % 
239                            (AttributeValue, type(value))) 
240        return True 
241
242
243# Dynamically Create classes based on AttributeValue for all the XACML primitive
244# types
245_IDENTIFIER2CLASS_MAP = AttributeValueClassMap()
246
247for typeName, _type in AttributeValue.TYPE_MAP.items():
248    identifier = AttributeValue.TYPE_URI_MAP[typeName]
249
250    className = typeName + AttributeValue.CLASS_NAME_SUFFIX               
251    classVars = {'TYPE': _type, 'IDENTIFIER': identifier}
252   
253    attributeValueClass = type(className, (AttributeValue, ), classVars)
254    AttributeValue.register(attributeValueClass)
255    _IDENTIFIER2CLASS_MAP[identifier] = attributeValueClass
256   
257   
258class AttributeValueClassFactory(object):
259    """Create AttributeValue types based on the XML namespace identifier
260   
261    Convenience wrapper for _IDENTIFIER2CLASS_MAP instance of
262    AttributeValueClassMap
263   
264    @ivar __classMap: mapping object to map attribute value URIs to their
265    implementations as classes
266    @type __classMap: ndg.xacml.core.attributevalue.AttributeValueClassMap
267    """
268    __slots__ = ('__classMap',)
269   
270    def __init__(self, classMap=None):
271        """Set a mapping object to map attribute value URIs to their
272        implementations as classes
273       
274        @param classMap: input an alternative to the default class mapping
275        object _IDENTIFIER2CLASS_MAP, if None, it will default to this setting
276        @type classMap: ndg.xacml.core.attributevalue.AttributeValueClassMap
277        """
278        if classMap is None:
279            self.__classMap = _IDENTIFIER2CLASS_MAP
280        elif isinstance(classMap, AttributeValueClassMap):
281            self.__classMap = classMap
282        else:
283            raise TypeError('Expecting %r derived type for "map" input; got %r'
284                            % (AttributeValueClassMap, type(map)))
285           
286    def __call__(self, identifier):
287        """Return <type>AttributeValue class for given identifier URI or None
288        if no match is found
289       
290        @return: attribute value class
291        @rtype: NoneType / ndg.xacml.core.attributevalue.AttributeValue derived
292        type
293        """
294        return self.__classMap.get(identifier)
295       
Note: See TracBrowser for help on using the repository browser.