iparapheur: get_file, allow missing element in xsd sequence (#34299)

This commit is contained in:
Emmanuel Cazenave 2019-06-25 17:18:18 +02:00
parent caf4899f99
commit 09cb70cd1e
2 changed files with 29 additions and 29 deletions

View File

@ -22,7 +22,7 @@ from django.utils.text import slugify
from django.utils.translation import ugettext_lazy as _
from django.http import HttpResponse, Http404
from zeep.exceptions import Fault as WebFault, TransportError
from zeep.exceptions import Fault as WebFault, TransportError, XMLSyntaxError
from passerelle.base.models import BaseResource, HTTPResource
from passerelle.utils.api import endpoint
@ -76,23 +76,6 @@ CREATE_FILE_SCHEMA = {
}
def get_client(model):
try:
soap_client = model.soap_client()
# overrides the service port address URL defined in the WSDL.
if model.wsdl_endpoint_location:
soap_client.overridden_service = soap_client.create_service(
# picks the first binding in the WSDL as the default
soap_client.wsdl.bindings.keys()[0],
model.wsdl_endpoint_location)
else:
soap_client.overridden_service = soap_client.service
return soap_client
except ConnectionError as exc:
raise APIError('i-Parapheur error: %s' % exc)
def format_type(t):
return {'id': unicode(t), 'text': unicode(t)}
@ -124,8 +107,25 @@ class IParapheur(BaseResource, HTTPResource):
def get_verbose_name(cls):
return cls._meta.verbose_name
def get_client(self, strict_mode=True):
try:
soap_client = self.soap_client(strict=strict_mode)
# overrides the service port address URL defined in the WSDL.
if self.wsdl_endpoint_location:
soap_client.overridden_service = soap_client.create_service(
# picks the first binding in the WSDL as the default
soap_client.wsdl.bindings.keys()[0],
self.wsdl_endpoint_location)
else:
soap_client.overridden_service = soap_client.service
return soap_client
except ConnectionError as exc:
raise APIError('i-Parapheur error: %s' % exc)
def call(self, service_name, *args, **kwargs):
client = get_client(self)
strict_mode = kwargs.pop('strict_mode', True)
client = self.get_client(strict_mode=strict_mode)
try:
result = getattr(client.overridden_service, service_name)(*args, **kwargs)
except WebFault as exc:
@ -135,6 +135,8 @@ class IParapheur(BaseResource, HTTPResource):
raise APIError('Transport Error: %s' % exc)
except TypeError as exc:
raise APIError('Type Error: %s' % exc)
except XMLSyntaxError as exc:
raise APIError('XMLSyntax Error: %s' % exc)
return result
@endpoint(perm='can_access')
@ -183,7 +185,7 @@ class IParapheur(BaseResource, HTTPResource):
raise APIError('Invalid base64 string')
content_type = post_data['file']['content_type']
soap_client = get_client(self)
soap_client = self.get_client()
if post_data['visibility'] not in ['PUBLIC', 'SERVICE', 'CONFIDENTIEL']:
raise FileError('Unknown value for "visibility". Should be "PUBLIC", "SERVICE" or "CONFIDENTIEL"')
@ -212,7 +214,9 @@ class IParapheur(BaseResource, HTTPResource):
@endpoint(perm='can_access', name='get-file', pattern='(?P<file_id>[\w-]+)')
def get_file(self, request, file_id, appendix=None):
resp = self.call('GetDossier', file_id)
# We need to disable strict mode since the response
# can be non compliant with the xsd
resp = self.call('GetDossier', file_id, strict_mode=False)
filename = None
if not resp or not resp.MessageRetour:

View File

@ -66,7 +66,7 @@ def iph_mocked_get(url, params=None, **kwargs):
response.status_code = 200
return response
@mock.patch('passerelle.contrib.iparapheur.models.get_client')
@mock.patch('passerelle.contrib.iparapheur.models.IParapheur.get_client')
def test_call_ping(soap_client, app, conn):
service = mock.Mock()
service.echo.return_value = 'pong'
@ -330,10 +330,8 @@ def test_get_file(mocked_post, mocked_get, app, conn):
mocked_post.return_value = response
resp = app.get(url, status=500)
assert resp.json['err'] == 1
#assert 'FileError' in resp.json['err_class']
#assert resp.json['err_desc'] == 'KOmessage'
assert 'zeep.exceptions.XMLParseError' in resp.json['err_class']
assert resp.json['err_desc'] == "Unexpected element u'{http://www.adullact.org/spring-ws/iparapheur/1.0}MessageRetour', expected u'{http://www.adullact.org/spring-ws/iparapheur/1.0}TypeTechnique'"
assert 'FileError' in resp.json['err_class']
assert resp.json['err_desc'] == 'KOmessage'
# unknown response
soap_response = """<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><CreerDossierResponse xmlns="http://www.adullact.org/spring-ws/iparapheur/1.0" xmlns:xmime="http://www.w3.org/2005/05/xmlmime"></CreerDossierResponse></S:Body></S:Envelope>"""
@ -348,12 +346,10 @@ def test_get_file(mocked_post, mocked_get, app, conn):
soap_response = """<nada>"""
response._content = soap_response
mocked_post.return_value = response
#resp = app.get(url, status=500)
resp = app.get(url)
assert resp.json['err'] == 1
#assert 'zeep.exceptions.TransportError' in resp.json['err_class']
assert 'passerelle.utils.jsonresponse.APIError' in resp.json['err_class']
assert 'Server returned HTTP status 200 (<nada>)' in resp.json['err_desc']
assert 'XMLSyntax Error' in resp.json['err_desc']
@mock.patch('passerelle.utils.Request.get', side_effect=iph_mocked_get)
@mock.patch('passerelle.utils.Request.post')