From bd093bb70722e48422b28baa0ab6fcc5b2fd0a1d Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Wed, 27 Feb 2019 10:41:23 +0100
Subject: [PATCH] iparapheur: add endpoint to display raw wsdl (#30257)

---
 passerelle/contrib/iparapheur/models.py       | 10 +++++++-
 passerelle/contrib/iparapheur/soap.py         | 10 +++++++-
 .../iparapheur/iparapheur_detail.html         |  4 ++++
 tests/test_iparapheur.py                      | 23 +++++++++++++++++++
 4 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/passerelle/contrib/iparapheur/models.py b/passerelle/contrib/iparapheur/models.py
index e21ec5a..ca8bff6 100644
--- a/passerelle/contrib/iparapheur/models.py
+++ b/passerelle/contrib/iparapheur/models.py
@@ -31,6 +31,7 @@ from passerelle.utils.api import endpoint
 from passerelle.utils.jsonresponse import APIError
 
 from .soap import get_client as soap_get_client
+from .soap import get_wsdl_string as soap_get_wsdl_string
 
 
 def get_client(model):
@@ -39,7 +40,6 @@ def get_client(model):
     except ConnectionError as e:
         raise APIError('i-Parapheur error: %s' % e)
 
-
 def format_type(t):
     return {'id': unicode(t), 'text': unicode(t)}
 
@@ -111,6 +111,14 @@ class IParapheur(BaseResource):
     def ping(self, request):
         return {'data': self.call('echo', 'ping')}
 
+    @endpoint(perm='can_access')
+    def wsdl(self, request):
+        try:
+            wsdl = soap_get_wsdl_string(self)
+        except ConnectionError as e:
+            raise APIError('i-Parapheur WSDL error: %s' % e)
+        return HttpResponse(wsdl, content_type='text/xml')
+
     @endpoint(perm='can_access')
     def subtypes(self, request, type=None):
         if type:
diff --git a/passerelle/contrib/iparapheur/soap.py b/passerelle/contrib/iparapheur/soap.py
index f1040da..5dbe1d5 100644
--- a/passerelle/contrib/iparapheur/soap.py
+++ b/passerelle/contrib/iparapheur/soap.py
@@ -22,7 +22,7 @@ import StringIO
 
 from suds.client import Client
 from suds.transport.http import HttpAuthenticated
-from suds.transport import Reply, TransportError
+from suds.transport import Request, Reply, TransportError
 from suds.plugin import MessagePlugin, DocumentPlugin
 
 from requests.exceptions import RequestException
@@ -91,3 +91,11 @@ def get_client(instance):
     transport = Transport(instance)
     return Client(instance.wsdl_url, transport=transport,
                   plugins=[Handlewsdl(), Filter()], cache=None)
+
+def get_wsdl_string(instance):
+    '''download wsdl like suds's DocumentReader does it (but do not parse it)'''
+    transport = Transport(instance)
+    fp = transport.open(Request(instance.wsdl_url))
+    content = fp.read()
+    fp.close()
+    return content
diff --git a/passerelle/contrib/iparapheur/templates/iparapheur/iparapheur_detail.html b/passerelle/contrib/iparapheur/templates/iparapheur/iparapheur_detail.html
index 7570445..d33d1ae 100644
--- a/passerelle/contrib/iparapheur/templates/iparapheur/iparapheur_detail.html
+++ b/passerelle/contrib/iparapheur/templates/iparapheur/iparapheur_detail.html
@@ -6,6 +6,10 @@
 
 {% block endpoints %}
 <ul>
+  {% url 'generic-endpoint' connector='iparapheur' slug=object.slug endpoint='wsdl' as wsdl_url %}
+  <li>{% trans 'Download WSDL file:' %}
+    <a href="{{ wsdl_url }}">{{ site_base_uri }}{{ wsdl_url }}</a>[?debug]
+  </li>
   {% url 'generic-endpoint' connector='iparapheur' slug=object.slug endpoint='ping' as ping_url %}
   <li>{% trans 'Check WS availability:' %}
     <a href="{{ ping_url }}">{{ site_base_uri }}{{ ping_url }}</a>[?debug]
diff --git a/tests/test_iparapheur.py b/tests/test_iparapheur.py
index 754fc60..460eb94 100644
--- a/tests/test_iparapheur.py
+++ b/tests/test_iparapheur.py
@@ -422,3 +422,26 @@ def test_get_magic_mime(tmpdir):
         f.write('some text')
     with text_path.open() as f:
         assert 'text/plain' == get_magic_mime(f.read())
+
+@mock.patch('passerelle.utils.Request.get')
+def test_call_wsdl(mocked_get, app, conn, xmlmime, wsdl_file):
+    mocked_get.return_value = mock.Mock(content=file(wsdl_file).read(),
+                                        status_code=200)
+    url = reverse('generic-endpoint', kwargs={'slug': conn.slug,
+                  'connector': 'iparapheur', 'endpoint': 'wsdl'})
+    url += '?apikey=%s' % API_KEY
+    resp = app.get(url)
+    assert resp.headers['content-type'] == 'text/xml'
+    assert resp.content == file(wsdl_file).read()
+
+@mock.patch('passerelle.contrib.iparapheur.models.soap_get_wsdl_string',
+            side_effect=ConnectionError('mocked error'))
+def test_call_wsdl_connectionerror(soap_client, app, conn):
+    url = reverse('generic-endpoint', kwargs={'connector': 'iparapheur',
+                    'endpoint': 'wsdl', 'slug': conn.slug})
+    resp = app.get(url, status=403)
+    url += '?apikey=%s' % API_KEY
+    resp = app.get(url)
+    assert resp.json['err'] == 1
+    assert resp.json['data'] == None
+    assert 'mocked error' in resp.json['err_desc']
-- 
2.20.1

