Ignore:
Timestamp:
28/10/10 13:24:59 (10 years ago)
Author:
pjkersha
Message:

Added SOAPFault handling for ndg.soap package. Needs integration into ndg.saml.saml2.binding.soap.server.wsgi.queryinterface to enable SAML query interface to do better error reporting.

Location:
TI12-security/trunk/ndg_saml
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/ndg_saml

    • Property svn:ignore
      •  

        old new  
        22dist 
        33ndg_saml.egg-info 
         4ndg_saml_env.sh 
  • TI12-security/trunk/ndg_saml/ndg/soap/etree.py

    r7560 r7662  
    2222 
    2323from ndg.soap import (SOAPObject, SOAPEnvelopeBase, SOAPHeaderBase,  
    24                       SOAPBodyBase, SOAPFault) 
     24                      SOAPBodyBase, SOAPFaultBase) 
     25from ndg.soap import SOAPFaultException as SOAPFaultExceptionBase 
    2526 
    2627 
     
    6869        return xml 
    6970 
    70     def _parse(self, source): 
     71    @staticmethod 
     72    def _parse(source): 
    7173        """Read in the XML from source 
    7274        @type source: basestring/file 
     
    124126                           tag=SOAPBodyBase.DEFAULT_ELEMENT_LOCAL_NAME,  
    125127                           prefix=SOAPBodyBase.DEFAULT_ELEMENT_NS_PREFIX) 
     128        self.__fault = None 
     129         
     130    # Test for SOAPFault present 
     131    @property 
     132    def hasSOAPFault(self): 
     133        """Boolean True if this SOAP BOdy contains a SOAPFault instance""" 
     134        return self.fault is not None 
     135     
     136    def _getFault(self): 
     137        return self.__fault 
     138     
     139    def _setFault(self, value): 
     140        if not isinstance(value, SOAPFault): 
     141            raise TypeError('Expecting %r type for "fault" attribute; got %r' % 
     142                            (SOAPFault, type(value))) 
     143        self.__fault = value 
     144        
     145    fault = property(_getFault, _setFault, doc="SOAP Fault") 
    126146         
    127147    def create(self): 
    128148        """Create header ElementTree element""" 
    129149        self.elem = ElementTree.Element(str(self.qname)) 
     150        if self.hasSOAPFault: 
     151            self.fault.create() 
     152            self.elem.append(self.fault.elem) 
    130153     
    131154    def serialize(self): 
    132155        """Serialise element tree into string""" 
    133156        return ETreeSOAPExtensions._serialize(self.elem) 
    134      
     157  
     158    def parse(self, source): 
     159        """This method ONLY parses a SOAPFault IF one is found""" 
     160        if ElementTree.iselement(source): 
     161            self.elem = source 
     162        else: 
     163            self.elem = self._parse(source) 
     164                   
     165        for elem in self.elem: 
     166            localName = QName.getLocalPart(elem.tag) 
     167            if localName == SOAPFault.DEFAULT_ELEMENT_LOCAL_NAME: 
     168                if self.fault is None: 
     169                    self.fault = SOAPFault() 
     170                     
     171                self.fault.parse(elem) 
     172                 
     173                # Only one SOAPFault element is expected 
     174                break 
     175             
    135176    def prettyPrint(self): 
    136177        """Basic pretty printing separating each element on to a new line""" 
     
    138179     
    139180 
     181class SOAPFault(SOAPFaultBase, ETreeSOAPExtensions): 
     182    """Extend SOAP Fault for ElementTree parsing and serialisation""" 
     183     
     184    DEFAULT_ELEMENT_NAME = QName(SOAPFaultBase.DEFAULT_ELEMENT_NS, 
     185                                 tag=SOAPFaultBase.DEFAULT_ELEMENT_LOCAL_NAME, 
     186                                 prefix=SOAPFaultBase.DEFAULT_ELEMENT_NS_PREFIX) 
     187     
     188    FAULT_CODE_ELEMENT_NAME = QName(SOAPFaultBase.DEFAULT_ELEMENT_NS, 
     189                             tag=SOAPFaultBase.FAULT_CODE_ELEMENT_LOCAL_NAME, 
     190                             prefix=SOAPFaultBase.DEFAULT_ELEMENT_NS_PREFIX) 
     191     
     192    FAULT_STRING_ELEMENT_NAME = QName(SOAPFaultBase.DEFAULT_ELEMENT_NS, 
     193                             tag=SOAPFaultBase.FAULT_STRING_ELEMENT_LOCAL_NAME, 
     194                             prefix=SOAPFaultBase.DEFAULT_ELEMENT_NS_PREFIX) 
     195     
     196    FAULT_ACTOR_ELEMENT_NAME = QName(SOAPFaultBase.DEFAULT_ELEMENT_NS, 
     197                             tag=SOAPFaultBase.FAULT_ACTOR_ELEMENT_LOCAL_NAME, 
     198                             prefix=SOAPFaultBase.DEFAULT_ELEMENT_NS_PREFIX) 
     199     
     200    DETAIL_ELEMENT_NAME = QName(SOAPFaultBase.DEFAULT_ELEMENT_NS, 
     201                                tag=SOAPFaultBase.DETAIL_ELEMENT_LOCAL_NAME, 
     202                                prefix=SOAPFaultBase.DEFAULT_ELEMENT_NS_PREFIX) 
     203     
     204    def __init__(self, *arg, **kw): 
     205        SOAPFaultBase.__init__(self, *arg, **kw) 
     206        ETreeSOAPExtensions.__init__(self) 
     207         
     208        self.qname = QName(SOAPFaultBase.DEFAULT_ELEMENT_NS,  
     209                           tag=SOAPFaultBase.DEFAULT_ELEMENT_LOCAL_NAME,  
     210                           prefix=SOAPFaultBase.DEFAULT_ELEMENT_NS_PREFIX) 
     211     
     212    def _setFaultCode(self, value): 
     213        """Override to enable ns prefix to be inferred if not added in already 
     214        """ 
     215        if value.startswith(self.__class__.FAULT_CODE_ELEMENT_NAME.prefix): 
     216            _value = value 
     217        else: 
     218            _value = "%s:%s" % (SOAPFaultBase.DEFAULT_ELEMENT_NS_PREFIX, value) 
     219         
     220        SOAPFaultBase._setFaultCode(self, _value) 
     221         
     222    faultCode = property(SOAPFaultBase._getFaultCode, _setFaultCode, 
     223                         doc="Fault code") 
     224     
     225    def create(self): 
     226        """Create Fault ElementTree element""" 
     227        self.elem = ElementTree.Element(str(self.qname)) 
     228         
     229        faultStringElem = ElementTree.Element( 
     230                                str(self.__class__.FAULT_STRING_ELEMENT_NAME)) 
     231        faultStringElem.text = self.faultString 
     232        self.elem.append(faultStringElem) 
     233         
     234        faultCodeElem = ElementTree.Element( 
     235                                str(self.__class__.FAULT_CODE_ELEMENT_NAME)) 
     236        faultCodeElem.text = self.faultCode 
     237        self.elem.append(faultCodeElem) 
     238                          
     239        if self.faultActor is not None: 
     240            faultActorElem = ElementTree.Element( 
     241                                str(self.__class__.FAULT_ACTOR_ELEMENT_NAME)) 
     242            faultActorElem.text = self.faultActor 
     243            self.elem.append(faultActorElem) 
     244                              
     245        if self.detail is not None: 
     246            detailElem = ElementTree.Element( 
     247                                str(self.__class__.DETAIL_ELEMENT_NAME)) 
     248             
     249            if ElementTree.iselement(self.detail): 
     250                detailElem.append(self.detail) 
     251                 
     252            elif isinstance(self.detail, basestring):  
     253                detailElem.text = self.detail 
     254            else: 
     255                raise TypeError('Expecting ElementTree.Element or string ' 
     256                                'type for SOAPFault detail; got %r' % 
     257                                type(self.detail)) 
     258                 
     259            self.elem.append(detailElem) 
     260     
     261    def parse(self, source): 
     262        """Parse SOAPFault element""" 
     263        if ElementTree.iselement(source): 
     264            self.elem = source 
     265        else: 
     266            self.elem = self._parse(source) 
     267                   
     268        for elem in self.elem: 
     269            localName = QName.getLocalPart(elem.tag) 
     270            if localName == SOAPFault.FAULT_CODE_ELEMENT_LOCAL_NAME: 
     271                self.faultCode = elem.text.strip()  
     272                 
     273            elif localName == SOAPFault.FAULT_STRING_ELEMENT_LOCAL_NAME: 
     274                self.faultString = elem.text.strip() 
     275             
     276            elif localName == SOAPFault.FAULT_ACTOR_ELEMENT_LOCAL_NAME: 
     277                self.faultActor = elem.text.strip()     
     278             
     279            elif localName == SOAPFault.DETAIL_ELEMENT_LOCAL_NAME: 
     280                # Make no assumptions about the content, simply assing the  
     281                # element to the detail attribute 
     282                self.detail = elem    
     283                  
     284            else: 
     285                faultCode = str(QName(SOAPFault.DEFAULT_ELEMENT_NS,  
     286                                  tag=SOAPFault.CLIENT_FAULT_CODE,  
     287                                  prefix=SOAPFault.DEFAULT_ELEMENT_NS_PREFIX)) 
     288                 
     289                raise SOAPFaultException('Invalid child element in SOAP ' 
     290                                         'Fault "%s" for stream %r' %  
     291                                         (localName, source), 
     292                                         faultCode) 
     293             
     294    def serialize(self): 
     295        """Serialise element tree into string""" 
     296        return ETreeSOAPExtensions._serialize(self.elem) 
     297     
     298    def prettyPrint(self): 
     299        """Basic pretty printing separating each element on to a new line""" 
     300        return ETreeSOAPExtensions._prettyPrint(self.elem) 
     301 
     302 
     303class SOAPFaultException(SOAPFaultExceptionBase): 
     304    """Extend SOAP Fault Exception base class to use ElementTree based  
     305    SOAP Fault implementation for parsing and serialisation""" 
     306    SOAP_FAULT_CLASS = SOAPFault 
     307     
     308     
    140309class SOAPEnvelope(SOAPEnvelopeBase, ETreeSOAPExtensions): 
    141310    """ElementTree based SOAP implementation""" 
     
    195364     
    196365    def parse(self, source): 
    197         self.elem = ETreeSOAPExtensions._parse(self, source)  
     366        """Parse SOAP Envelope""" 
     367        self.elem = self._parse(source)  
    198368         
    199369        for elem in self.elem: 
     
    203373                 
    204374            elif localName == SOAPBody.DEFAULT_ELEMENT_LOCAL_NAME: 
    205                 self.body.elem = elem 
    206                  
     375                self.body.parse(elem) 
    207376            else: 
    208                 raise SOAPFault('Invalid child element in SOAP Envelope "%s" ' 
    209                                 'for stream %r' % (localName, source)) 
     377                faultCode = str(QName(SOAPEnvelopeBase.DEFAULT_ELEMENT_NS,  
     378                                  tag=SOAPFault.CLIENT_FAULT_CODE,  
     379                                  prefix=SOAPFault.DEFAULT_ELEMENT_NS_PREFIX)) 
     380                 
     381                raise SOAPFaultException('Invalid child element in SOAP ' 
     382                                         'Envelope "%s" for stream %r' %  
     383                                         (localName, source), 
     384                                         faultCode) 
Note: See TracChangeset for help on using the changeset viewer.