Projet

Général

Profil

0001-iparapheur-get_file-allow-missing-element-in-xsd-seq.patch

Emmanuel Cazenave, 25 juin 2019 17:21

Télécharger (7,94 ko)

Voir les différences:

Subject: [PATCH] iparapheur: get_file, allow missing element in xsd sequence
 (#34299)

 passerelle/contrib/iparapheur/models.py | 54 +++++++++++++------------
 tests/test_iparapheur.py                | 12 ++----
 2 files changed, 32 insertions(+), 34 deletions(-)
passerelle/contrib/iparapheur/models.py
22 22
from django.utils.translation import ugettext_lazy as _
23 23
from django.http import HttpResponse, Http404
24 24

  
25
from zeep.exceptions import Fault as WebFault, TransportError
25
from zeep.exceptions import Fault as WebFault, TransportError, XMLSyntaxError
26 26

  
27 27
from passerelle.base.models import BaseResource, HTTPResource
28 28
from passerelle.utils.api import endpoint
......
76 76
}
77 77

  
78 78

  
79
def get_client(model):
80
    try:
81
        soap_client = model.soap_client()
82

  
83
        # overrides the service port address URL defined in the WSDL.
84
        if model.wsdl_endpoint_location:
85
            soap_client.overridden_service = soap_client.create_service(
86
                # picks the first binding in the WSDL as the default
87
                soap_client.wsdl.bindings.keys()[0],
88
                model.wsdl_endpoint_location)
89
        else:
90
            soap_client.overridden_service = soap_client.service
91
        return soap_client
92
    except ConnectionError as exc:
93
        raise APIError('i-Parapheur error: %s' % exc)
94

  
95

  
96 79
def format_type(t):
97 80
    return {'id': unicode(t), 'text': unicode(t)}
98 81

  
......
124 107
    def get_verbose_name(cls):
125 108
        return cls._meta.verbose_name
126 109

  
127
    def call(self, service_name, *args, **kwargs):
128
        client = get_client(self)
110
    def get_client(self, strict=True):
111
        try:
112
            soap_client = self.soap_client(strict=strict)
113

  
114
            # overrides the service port address URL defined in the WSDL.
115
            if self.wsdl_endpoint_location:
116
                soap_client.overridden_service = soap_client.create_service(
117
                    # picks the first binding in the WSDL as the default
118
                    soap_client.wsdl.bindings.keys()[0],
119
                    self.wsdl_endpoint_location)
120
            else:
121
                soap_client.overridden_service = soap_client.service
122
            return soap_client
123
        except ConnectionError as exc:
124
            raise APIError('i-Parapheur error: %s' % exc)
125

  
126
    def call(self, service_name, args=[], kwargs={}, strict=True):
127
        client = self.get_client(strict=strict)
129 128
        try:
130 129
            result = getattr(client.overridden_service, service_name)(*args, **kwargs)
131 130
        except WebFault as exc:
......
135 134
            raise APIError('Transport Error: %s' % exc)
136 135
        except TypeError as exc:
137 136
            raise APIError('Type Error: %s' % exc)
137
        except XMLSyntaxError as exc:
138
            raise APIError('XMLSyntax Error: %s' % exc)
138 139
        return result
139 140

  
140 141
    @endpoint(perm='can_access')
......
143 144

  
144 145
    @endpoint(perm='can_access')
145 146
    def ping(self, request):
146
        return {'data': self.call('echo', 'ping')}
147
        return {'data': self.call('echo', args=['ping'])}
147 148

  
148 149
    @endpoint()
149 150
    def wsdl(self, request):
......
156 157
    @endpoint(perm='can_access')
157 158
    def subtypes(self, request, type=None):
158 159
        if type:
159
            return {'data': [format_type(t) for t in self.call('GetListeSousTypes', type)]}
160
            return {'data': [format_type(t) for t in self.call('GetListeSousTypes', args=[type])]}
160 161
        return {'data': [format_type(t) for t in self.call('GetListeSousTypes')]}
161 162

  
162 163
    @endpoint(perm='can_access')
163 164
    def files(self, request, status=None):
164 165
        if status:
165
            return {'data': [format_file(f) for f in self.call('RechercherDossiers', Status=status)]}
166
            return {'data': [format_file(f) for f in self.call(
167
                'RechercherDossiers', kwargs={'Status': status})]}
166 168
        return {'data': [format_file(f) for f in self.call('RechercherDossiers')]}
167 169

  
168 170
    @endpoint(
......
183 185
            raise APIError('Invalid base64 string')
184 186
        content_type = post_data['file']['content_type']
185 187

  
186
        soap_client = get_client(self)
188
        soap_client = self.get_client()
187 189
        if post_data['visibility'] not in ['PUBLIC', 'SERVICE', 'CONFIDENTIEL']:
188 190
            raise FileError('Unknown value for "visibility". Should be "PUBLIC", "SERVICE" or "CONFIDENTIEL"')
189 191

  
......
212 214

  
213 215
    @endpoint(perm='can_access', name='get-file', pattern='(?P<file_id>[\w-]+)')
214 216
    def get_file(self, request, file_id, appendix=None):
215
        resp = self.call('GetDossier', file_id)
217
        resp = self.call('GetDossier', args=[file_id], strict=False)
216 218
        filename = None
217 219

  
218 220
        if not resp or not resp.MessageRetour:
......
251 253

  
252 254
    @endpoint(perm='can_access', name='get-file-status', pattern='(?P<file_id>[\w-]+)')
253 255
    def get_file_status(self, request, file_id):
254
        resp = self.call('GetHistoDossier', file_id)
256
        resp = self.call('GetHistoDossier', args=[file_id])
255 257
        if not resp or not resp.MessageRetour:
256 258
            raise FileError('unknown error, no response')
257 259
        if resp.MessageRetour.codeRetour == 'KO':
tests/test_iparapheur.py
66 66
    response.status_code = 200
67 67
    return response
68 68

  
69
@mock.patch('passerelle.contrib.iparapheur.models.get_client')
69
@mock.patch('passerelle.contrib.iparapheur.models.IParapheur.get_client')
70 70
def test_call_ping(soap_client, app, conn):
71 71
    service = mock.Mock()
72 72
    service.echo.return_value = 'pong'
......
330 330
    mocked_post.return_value = response
331 331
    resp = app.get(url, status=500)
332 332
    assert resp.json['err'] == 1
333
    #assert 'FileError' in resp.json['err_class']
334
    #assert resp.json['err_desc'] == 'KOmessage'
335
    assert 'zeep.exceptions.XMLParseError' in resp.json['err_class']
336
    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'"
333
    assert 'FileError' in resp.json['err_class']
334
    assert resp.json['err_desc'] == 'KOmessage'
337 335

  
338 336
    # unknown response
339 337
    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 346
    soap_response = """<nada>"""
349 347
    response._content = soap_response
350 348
    mocked_post.return_value = response
351
    #resp = app.get(url, status=500)
352 349
    resp = app.get(url)
353 350
    assert resp.json['err'] == 1
354
    #assert 'zeep.exceptions.TransportError' in resp.json['err_class']
355 351
    assert 'passerelle.utils.jsonresponse.APIError' in resp.json['err_class']
356
    assert 'Server returned HTTP status 200 (<nada>)' in resp.json['err_desc']
352
    assert 'XMLSyntax Error' in resp.json['err_desc']
357 353

  
358 354
@mock.patch('passerelle.utils.Request.get', side_effect=iph_mocked_get)
359 355
@mock.patch('passerelle.utils.Request.post')
360
-