diff --git a/passerelle/contrib/greco/formdata.py b/passerelle/contrib/greco/formdata.py
index 97b0ba69..ad18f0a8 100644
--- a/passerelle/contrib/greco/formdata.py
+++ b/passerelle/contrib/greco/formdata.py
@@ -101,6 +101,7 @@ class FormData:
# extract/create/validate fields according to schema
self.fields = {}
+ self.json = {}
for fieldname in schema:
if isinstance(fieldname, tuple):
value = values.get(fieldname[0])
@@ -114,6 +115,22 @@ class FormData:
value = values.get(fieldname)
if value is not None:
self.fields[fieldname] = value
+ if isinstance(value, datetime):
+ value = value.strftime('%Y-%m-%dT%H:%M:%S')
+ if '_' not in fieldname:
+ self.json[fieldname] = value
+ continue
+ key, subkey = fieldname.split('_')
+ if key not in self.json:
+ self.json[key] = {}
+ self.json[key][subkey] = value
+
+ # https://dev.entrouvert.org/issues/75259
+ danger = self.json.get('danger', '')
+ if danger:
+ self.json['danger'] = 'true'
+ else:
+ self.json['danger'] = 'false'
# extract attachments
self.attachments = []
diff --git a/passerelle/contrib/greco/migrations/0001_initial.py b/passerelle/contrib/greco/migrations/0001_initial.py
index 9721fb81..69d78931 100644
--- a/passerelle/contrib/greco/migrations/0001_initial.py
+++ b/passerelle/contrib/greco/migrations/0001_initial.py
@@ -37,7 +37,7 @@ class Migration(migrations.Migration):
('application', models.CharField(max_length=200, verbose_name='Application identifier')),
('token_url', models.URLField(max_length=256, verbose_name='Token URL')),
('token_authorization', models.CharField(max_length=128, verbose_name='Token Authorization')),
- ('wsdl_url', models.CharField(max_length=256, verbose_name='WSDL URL')),
+ ('wsdl_url', models.CharField(max_length=256, verbose_name='WSDL or REST URL')),
(
'verify_cert',
models.BooleanField(default=True, verbose_name='Check HTTPS Certificate validity'),
diff --git a/passerelle/contrib/greco/migrations/0004_rest_api.py b/passerelle/contrib/greco/migrations/0004_rest_api.py
new file mode 100644
index 00000000..93d825d2
--- /dev/null
+++ b/passerelle/contrib/greco/migrations/0004_rest_api.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.2.26 on 2023-02-01 11:11
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('greco', '0003_remove_greco_log_level'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='greco',
+ name='api_type',
+ field=models.CharField(
+ choices=[('soap', 'SOAP'), ('rest', 'REST')],
+ default='soap',
+ max_length=4,
+ verbose_name='API Type',
+ ),
+ ),
+ ]
diff --git a/passerelle/contrib/greco/models.py b/passerelle/contrib/greco/models.py
index e1de739a..f593055c 100644
--- a/passerelle/contrib/greco/models.py
+++ b/passerelle/contrib/greco/models.py
@@ -14,12 +14,15 @@
# along with this program. If not, see .
import base64
+import io
import json
import re
+import urllib
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
+import requests
import suds.sudsobject
from django.core.cache import cache
from django.db import models
@@ -34,6 +37,12 @@ from passerelle.utils.api import APIError, endpoint
from .formdata import CREATION_SCHEMA, FormData, list_schema_fields
+API_TYPES = (
+ ('soap', 'SOAP'),
+ ('rest', 'REST'),
+)
+
+
# taken from https://lsimons.wordpress.com/2011/03/17/stripping-illegal-characters-out-of-xml-in-python/
_illegal_xml_chars_RE = re.compile('[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]')
@@ -69,8 +78,9 @@ class Greco(BaseResource):
application = models.CharField(_('Application identifier'), max_length=200)
token_url = models.URLField(_('Token URL'), max_length=256)
token_authorization = models.CharField(_('Token Authorization'), max_length=128)
- wsdl_url = models.CharField(_('WSDL URL'), max_length=256) # not URLField, it can be file://
+ wsdl_url = models.CharField(_('WSDL or REST URL'), max_length=256) # not URLField, it can be file://
verify_cert = models.BooleanField(default=True, verbose_name=_('Check HTTPS Certificate validity'))
+ api_type = models.CharField(_('API Type'), max_length=4, choices=API_TYPES, default='soap')
hide_description_fields = ['token_authorization']
category = _('Business Process Connectors')
@@ -78,6 +88,10 @@ class Greco(BaseResource):
class Meta:
verbose_name = _('GRECO Webservices')
+ @property
+ def use_soap(self):
+ return self.api_type == 'soap'
+
def get_token(self, renew=False):
cache_key = 'greco-%s-token' % self.id
if not renew:
@@ -215,8 +229,60 @@ class Greco(BaseResource):
return Client(url=self.wsdl_url, transport=Transport(self, attachments))
+ def _rest_call(self, path, method='get', json_data=None, params=None, files=None):
+ headers = {'Authorization': self.get_token()}
+ url = urllib.parse.urljoin(self.wsdl_url, path)
+ try:
+ resp = self.requests.request(
+ method=method,
+ url=url,
+ headers=headers,
+ json=json_data,
+ params=params,
+ files=files,
+ )
+ except (requests.Timeout, requests.RequestException) as e:
+ raise APIError(str(e))
+ if resp.status_code == 401:
+ # ask for a new token, and retry
+ headers['Authorization'] = self.get_token(renew=True)
+ try:
+ resp = self.requests.request(
+ method=method,
+ url=url,
+ headers=headers,
+ json=json_data,
+ params=params,
+ files=files,
+ )
+ except (requests.Timeout, requests.RequestException) as e:
+ raise APIError(str(e))
+
+ try:
+ resp.raise_for_status()
+ except requests.RequestException as e:
+ try:
+ err_data = resp.json()
+ except (json.JSONDecodeError, requests.RequestException):
+ err_data = {'response_text': resp.text}
+ raise APIError(str(e), data=err_data)
+
+ content_type = resp.headers.get('Content-Type')
+ if content_type and content_type.startswith('application/json'):
+ try:
+ return resp.json()
+ except (json.JSONDecodeError, requests.RequestException) as e:
+ err_data = {'response_text': resp.text}
+ raise APIError(str(e), data=err_data)
+
+ raise APIError(resp.text)
+
def check_status(self):
- if self.get_client().service.communicationTest('ping') is None:
+ if self.use_soap:
+ response = self.get_client().service.communicationTest('ping')
+ else:
+ response = self._rest_call('communicationTest/ping').get('reponse')
+ if not response:
raise Exception('empty answer to communication test')
@endpoint(
@@ -227,8 +293,12 @@ class Greco(BaseResource):
display_order=1,
)
def ping(self, request):
- resp = self.get_client().service.communicationTest('ping')
- if resp is None:
+ if self.use_soap:
+ resp = self.get_client().service.communicationTest('ping')
+ else:
+ json_data = self._rest_call('communicationTest/ping')
+ resp = json_data.get('reponse')
+ if not resp:
raise APIError('empty response from communicationTest()')
return {'data': resp}
@@ -261,16 +331,32 @@ Response :
formdata = FormData(json.loads(request.body), CREATION_SCHEMA)
except ValueError as e:
raise ParameterTypeError(str(e))
- # create suds object from formdata
- client = self.get_client(formdata.attachments)
- creation = client.factory.create('DemandeCreation')
- creation.application = self.application
- fill_sudsobject_with_dict(creation, formdata.fields)
- # send it to "creer"
- resp = client.service.creer(creation)
- if resp is None:
- raise APIError('empty response from creer()')
- return {'data': sudsobject_to_dict(resp)}
+ if self.use_soap:
+ # create suds object from formdata
+ client = self.get_client(formdata.attachments)
+ creation = client.factory.create('DemandeCreation')
+ creation.application = self.application
+ fill_sudsobject_with_dict(creation, formdata.fields)
+ # send it to "creer"
+ resp = client.service.creer(creation)
+ if resp is None:
+ raise APIError('empty response from creer()')
+ data = sudsobject_to_dict(resp)
+ else:
+ files = []
+ for num, attachment in enumerate(formdata.attachments):
+ filename = attachment.get('filename') or 'file%s.bin' % num
+ content = base64.b64decode(attachment.get('content') or '')
+ content_type = attachment.get('content_type') or 'application/octet-stream'
+ files.append(('files', (filename, content, content_type)))
+ files.append(
+ (
+ 'creerRequest',
+ (None, io.BytesIO(json.dumps(formdata.json).encode('utf-8')), 'application/json'),
+ )
+ )
+ data = self._rest_call('creer', method='post', files=files)
+ return {'data': data}
@classmethod
def creation_fields(cls):
@@ -289,15 +375,18 @@ Response :
display_order=3,
)
def status(self, request, idgreco, iddemande=None):
- resp = self.get_client().service.consulter(
- {
- 'idgreco': idgreco,
- 'iddemande': iddemande,
- }
- )
- if resp is None:
- raise APIError('empty response from status()')
- return {'data': sudsobject_to_dict(resp)}
+ params = {
+ 'idgreco': idgreco,
+ 'iddemande': iddemande,
+ }
+ if self.use_soap:
+ resp = self.get_client().service.consulter(params)
+ if resp is None:
+ raise APIError('empty response from status()')
+ data = sudsobject_to_dict(resp)
+ else:
+ data = self._rest_call('consulter', params=params)
+ return {'data': data}
@endpoint(
perm='can_access',
@@ -313,10 +402,14 @@ Response :
}
if code:
params['taCode'] = code
- resp = self.get_client().service.getMail(params)
- if resp is None:
- raise APIError('empty response from consulter()')
- return {'data': sudsobject_to_dict(resp)}
+ if self.use_soap:
+ resp = self.get_client().service.getMail(params)
+ if resp is None:
+ raise APIError('empty response from consulter()')
+ data = sudsobject_to_dict(resp)
+ else:
+ data = self._rest_call('getMail', params=params)
+ return {'data': data}
@endpoint(
perm='can_access',
@@ -335,16 +428,19 @@ Response :
idgreco = payload.get('idgreco') or idgreco
iddemande = payload.get('iddemande') or iddemande
information = payload.get('information') or information
- resp = self.get_client().service.ajouterComplementInformation(
- {
- 'idgreco': idgreco,
- 'iddemande': iddemande,
- 'complementInfo': information,
- }
- )
- if resp is None:
- raise APIError('empty response from ajouterComplementInformation()')
- return {'data': sudsobject_to_dict(resp)}
+ json_body = {
+ 'idgreco': idgreco,
+ 'iddemande': iddemande,
+ 'complementInfo': information,
+ }
+ if self.use_soap:
+ resp = self.get_client().service.ajouterComplementInformation(json_body)
+ if resp is None:
+ raise APIError('empty response from ajouterComplementInformation()')
+ data = sudsobject_to_dict(resp)
+ else:
+ data = self._rest_call('ajouterComplementInformation', method='post', json_data=json_body)
+ return {'data': data}
@endpoint(
perm='can_access',
@@ -362,16 +458,19 @@ Response :
idgreco = payload.get('idgreco') or idgreco
iddemande = payload.get('iddemande') or iddemande
comment = payload.get('comment') or comment
- resp = self.get_client().service.relancer(
- {
- 'idgreco': idgreco,
- 'iddemande': iddemande,
- 'commentaire': comment,
- }
- )
- if resp is None:
- raise APIError('empty response from relancer()')
- return {'data': sudsobject_to_dict(resp)}
+ params = {
+ 'idgreco': idgreco,
+ 'iddemande': iddemande,
+ 'commentaire': comment,
+ }
+ if self.use_soap:
+ resp = self.get_client().service.relancer(params)
+ if resp is None:
+ raise APIError('empty response from relancer()')
+ data = sudsobject_to_dict(resp)
+ else:
+ data = self._rest_call('relancer', params=params)
+ return {'data': data}
@endpoint(
perm='can_access',
@@ -389,13 +488,16 @@ Response :
idgreco = payload.get('idgreco')
iddemande = payload.get('iddemande')
nbr = payload.get('nbconfirmation')
- resp = self.get_client().service.confirmer(
- {
- 'idGreco': idgreco,
- 'idDemande': iddemande,
- 'nbconfirmation': nbr,
- }
- )
- if resp is None:
- raise APIError('empty response from confirmer()')
- return {'data': sudsobject_to_dict(resp)}
+ params = {
+ 'idGreco': idgreco,
+ 'idDemande': iddemande,
+ 'nbconfirmation': nbr,
+ }
+ if self.use_soap:
+ resp = self.get_client().service.confirmer(params)
+ if resp is None:
+ raise APIError('empty response from confirmer()')
+ data = sudsobject_to_dict(resp)
+ else:
+ data = self._rest_call('confirmer', params=params)
+ return {'data': data}
diff --git a/tests/test_greco.py b/tests/test_greco.py
index d022c855..3da5c787 100644
--- a/tests/test_greco.py
+++ b/tests/test_greco.py
@@ -14,15 +14,18 @@
# along with this program. If not, see .
import copy
+import json
import os
import xml.etree.ElementTree as ET
from base64 import b64encode
from unittest import mock
import pytest
+import responses
from django.contrib.contenttypes.models import ContentType
from django.urls import reverse
from django.utils.encoding import force_str
+from requests_toolbelt import MultipartDecoder
import tests.utils
from passerelle.base.models import AccessRight, ApiUser
@@ -104,6 +107,7 @@ CREATE_PAYLOAD = {
'transmetteur_service': 'GNM',
'transmetteur_nom': 'Vertommen',
'transmetteur_prenom': 'Agent 15',
+ 'danger': False,
}
@@ -126,6 +130,14 @@ def conn():
return connector
+@pytest.fixture
+def rest_conn(conn):
+ conn.wsdl_url = 'http://greco.example.net'
+ conn.api_type = 'rest'
+ conn.save()
+ return conn
+
+
@mock.patch('passerelle.utils.Request.post', side_effect=(RESP_503,))
def test_greco_no_api_key(mocked_post, app, conn):
url = reverse('generic-endpoint', kwargs={'connector': 'greco', 'endpoint': 'ping', 'slug': conn.slug})
@@ -204,6 +216,51 @@ def test_greco_create_ok(mocked_post, app, conn):
}
+def test_greco_rest_create_ok(app, rest_conn):
+ url = reverse(
+ 'generic-endpoint', kwargs={'connector': 'greco', 'endpoint': 'create', 'slug': rest_conn.slug}
+ )
+ url += '?apikey=grecokey'
+ with responses.RequestsMock() as rsps:
+ rsps.post(
+ 'http://greco.example.net/token',
+ status=200,
+ body=get_json_file('token'),
+ )
+ rsps.post(
+ 'http://greco.example.net/creer',
+ status=200,
+ json={
+ 'iddemande': 'MDFGDZRF',
+ 'idgreco': '538593',
+ 'etat': '1 - Créée',
+ 'application': '69999',
+ },
+ )
+ resp = app.post_json(url, params=CREATE_PAYLOAD)
+ create_request = rsps.calls[-1].request
+
+ decoder = MultipartDecoder(create_request.body, create_request.headers['content-type'])
+ assert len(decoder.parts) == 1
+ json_part = decoder.parts[0]
+ assert json_part.headers[b'Content-Type'] == b'application/json'
+ demande_creation = json.loads(json_part.content)
+ assert demande_creation['application'] == '69999'
+ assert demande_creation['localisation']['xgeoloc'] == '50.89491'
+ assert demande_creation['localisation']['ygeoloc'] == '4.34151'
+ assert demande_creation['transmetteur']['nom'] == 'Vertommen'
+ assert demande_creation['transmetteur']['prenom'] == 'Agent 15'
+ assert demande_creation['danger'] == 'false'
+
+ assert not resp.json['err']
+ assert resp.json['data'] == {
+ 'iddemande': 'MDFGDZRF',
+ 'idgreco': '538593',
+ 'etat': '1 - Créée',
+ 'application': '69999',
+ }
+
+
@mock.patch('passerelle.utils.Request.post', side_effect=(TOKEN, CREATE_OK))
def test_greco_create_ok_no_application(mocked_post, app, conn):
url = reverse('generic-endpoint', kwargs={'connector': 'greco', 'endpoint': 'create', 'slug': conn.slug})
@@ -271,6 +328,59 @@ def test_greco_create_enclosed(mocked_post, app, conn):
assert not resp.json['err']
+def test_greco_rest_create_enclosed(app, rest_conn):
+ url = reverse(
+ 'generic-endpoint', kwargs={'connector': 'greco', 'endpoint': 'create', 'slug': rest_conn.slug}
+ )
+ url += '?apikey=grecokey'
+
+ payload = CREATE_PAYLOAD
+ payload['iddemande'] = ('MDFGDARF',)
+ payload['piece_jointe1'] = {
+ 'content': force_str(b64encode(b'my picture content')),
+ 'filename': 'foo.png',
+ 'content_type': 'image/png',
+ }
+
+ with responses.RequestsMock() as rsps:
+ rsps.post(
+ 'http://greco.example.net/token',
+ status=200,
+ body=get_json_file('token'),
+ )
+ rsps.post(
+ 'http://greco.example.net/creer',
+ status=200,
+ json={
+ 'iddemande': 'MDFGDZRF',
+ 'idgreco': '538593',
+ 'etat': '1 - Créée',
+ 'application': '69999',
+ },
+ )
+ resp = app.post_json(url, params=payload)
+ create_request = rsps.calls[-1].request
+
+ assert create_request.headers['content-type'].startswith('multipart/form-data')
+ decoder = MultipartDecoder(create_request.body, create_request.headers['content-type'])
+ assert len(decoder.parts) == 2
+
+ file_part = decoder.parts[0]
+ assert file_part.headers[b'Content-Type'] == b'image/png'
+ assert file_part.content == b'my picture content'
+
+ json_part = decoder.parts[1]
+ assert json_part.headers[b'Content-Type'] == b'application/json'
+ demande_creation = json.loads(json_part.content)
+ assert demande_creation['application'] == '69999'
+ assert demande_creation['localisation']['xgeoloc'] == '50.89491'
+ assert demande_creation['localisation']['ygeoloc'] == '4.34151'
+ assert demande_creation['transmetteur']['nom'] == 'Vertommen'
+ assert demande_creation['transmetteur']['prenom'] == 'Agent 15'
+
+ assert not resp.json['err']
+
+
@mock.patch('passerelle.utils.Request.post', side_effect=(TOKEN, STATUS_OK))
def test_greco_status_ok(mocked_post, app, conn):
url = reverse('generic-endpoint', kwargs={'connector': 'greco', 'endpoint': 'status', 'slug': conn.slug})
@@ -294,6 +404,54 @@ def test_greco_status_ok(mocked_post, app, conn):
}
+def test_greco_rest_status_ok(app, rest_conn):
+ url = reverse(
+ 'generic-endpoint', kwargs={'connector': 'greco', 'endpoint': 'status', 'slug': rest_conn.slug}
+ )
+ url += '?apikey=grecokey'
+ with responses.RequestsMock() as rsps:
+ rsps.post(
+ 'http://greco.example.net/token',
+ status=200,
+ body=get_json_file('token'),
+ )
+ rsps.get(
+ 'http://greco.example.net/consulter?iddemande=MDFGDZRF&idgreco=538593',
+ status=200,
+ json={
+ 'iddemande': 'MDFGDZRF',
+ 'idgreco': '538593',
+ 'motifsrejet': None,
+ 'etat': '1 - Créée',
+ 'commentaireReponse': None,
+ 'comptesRendus': None,
+ 'dateResolutionEffective': None,
+ 'dateResolutionPrevue': '2021-03-16T14:14:23Z',
+ 'groupeResponsable': 'DRTU/SPS/CIC-Centre info et contact',
+ 'suiteDonnee': None,
+ 'idOrganismeExterne': None,
+ 'nomOrganisme': None,
+ },
+ )
+ resp = app.get(url, params={'idgreco': '538593', 'iddemande': 'MDFGDZRF'})
+
+ assert not resp.json['err']
+ assert resp.json['data'] == {
+ 'iddemande': 'MDFGDZRF',
+ 'idgreco': '538593',
+ 'motifsrejet': None,
+ 'etat': '1 - Créée',
+ 'commentaireReponse': None,
+ 'comptesRendus': None,
+ 'dateResolutionEffective': None,
+ 'dateResolutionPrevue': '2021-03-16T14:14:23Z',
+ 'groupeResponsable': 'DRTU/SPS/CIC-Centre info et contact',
+ 'suiteDonnee': None,
+ 'idOrganismeExterne': None,
+ 'nomOrganisme': None,
+ }
+
+
@mock.patch('passerelle.utils.Request.post', side_effect=(TOKEN, STATUS_KO))
def test_greco_status_ko(mocked_post, app, conn):
url = reverse('generic-endpoint', kwargs={'connector': 'greco', 'endpoint': 'status', 'slug': conn.slug})
@@ -343,6 +501,57 @@ def test_greco_answer_ok(mocked_post, app, conn):
}
+def test_greco_rest_answer_ok(app, rest_conn):
+ url = reverse(
+ 'generic-endpoint', kwargs={'connector': 'greco', 'endpoint': 'answer', 'slug': rest_conn.slug}
+ )
+ url += '?apikey=grecokey'
+
+ with responses.RequestsMock() as rsps:
+ rsps.post(
+ 'http://greco.example.net/token',
+ status=200,
+ body=get_json_file('token'),
+ )
+ rsps.get(
+ 'http://greco.example.net/getMail?iddemande=MDFGDZRF&idgreco=538593',
+ status=200,
+ json={
+ 'iddemande': 'DWPQGCTS',
+ 'idgreco': '538554',
+ 'motifsrejet': None,
+ 'etat': None,
+ 'message': {
+ 'bcc': {'item': []},
+ 'cc': {'item': []},
+ 'content': '...',
+ 'date': '10/02/2021 10:27:47',
+ 'subject': 'Métropole de Lyon : réponse à votre demande n° 538554',
+ 'to': {'item': ['gbaud@grandlyon.com']},
+ },
+ },
+ )
+ resp = app.get(url, params={'idgreco': '538593', 'iddemande': 'MDFGDZRF'})
+
+ assert not resp.json['err']
+ data = resp.json['data']
+ data['message']['content'] = '...'
+ assert data == {
+ 'iddemande': 'DWPQGCTS',
+ 'idgreco': '538554',
+ 'motifsrejet': None,
+ 'etat': None,
+ 'message': {
+ 'bcc': {'item': []},
+ 'cc': {'item': []},
+ 'content': '...',
+ 'date': '10/02/2021 10:27:47',
+ 'subject': 'Métropole de Lyon : réponse à votre demande n° 538554',
+ 'to': {'item': ['gbaud@grandlyon.com']},
+ },
+ }
+
+
@mock.patch('passerelle.utils.Request.post', side_effect=(TOKEN, ANSWER_KO))
def test_greco_answer_ko(mocked_post, app, conn):
url = reverse('generic-endpoint', kwargs={'connector': 'greco', 'endpoint': 'answer', 'slug': conn.slug})
@@ -375,6 +584,38 @@ def test_greco_add_information_ok(mocked_post, app, conn):
}
+def test_greco_rest_add_information_ok(app, rest_conn):
+ url = reverse(
+ 'generic-endpoint',
+ kwargs={'connector': 'greco', 'endpoint': 'add-information', 'slug': rest_conn.slug},
+ )
+ url += '?apikey=grecokey'
+
+ with responses.RequestsMock() as rsps:
+ rsps.post(
+ 'http://greco.example.net/token',
+ status=200,
+ body=get_json_file('token'),
+ )
+ rsps.post(
+ 'http://greco.example.net/ajouterComplementInformation',
+ status=200,
+ json={
+ 'iddemande': 'ZHRNMWVP',
+ 'idgreco': '538634',
+ 'motifsrejet': None,
+ },
+ )
+ resp = app.get(url, params={'idgreco': '538593', 'iddemande': 'MDFGDZRF', 'information': 'my info'})
+
+ assert not resp.json['err']
+ assert resp.json['data'] == {
+ 'iddemande': 'ZHRNMWVP',
+ 'idgreco': '538634',
+ 'motifsrejet': None,
+ }
+
+
@mock.patch('passerelle.utils.Request.post', side_effect=(TOKEN, ADD_INFORMATION_KO))
def test_greco_add_information_ko(mocked_post, app, conn):
url = reverse(
@@ -405,6 +646,37 @@ def test_greco_update_ok(mocked_post, app, conn):
}
+def test_greco_rest_update_ok(app, rest_conn):
+ url = reverse(
+ 'generic-endpoint', kwargs={'connector': 'greco', 'endpoint': 'update', 'slug': rest_conn.slug}
+ )
+ url += '?apikey=grecokey'
+ with responses.RequestsMock() as rsps:
+ rsps.post(
+ 'http://greco.example.net/token',
+ status=200,
+ body=get_json_file('token'),
+ )
+ rsps.get(
+ 'http://greco.example.net/relancer?iddemande=KPZDXCLL&idgreco=538640&commentaire=mycomment',
+ status=200,
+ json={
+ 'iddemande': 'KPZDXCLL',
+ 'idgreco': '538640',
+ 'motifsrejet': None,
+ },
+ )
+
+ resp = app.get(url, params={'idgreco': '538640', 'iddemande': 'KPZDXCLL', 'comment': 'mycomment'})
+
+ assert not resp.json['err']
+ assert resp.json['data'] == {
+ 'iddemande': 'KPZDXCLL',
+ 'idgreco': '538640',
+ 'motifsrejet': None,
+ }
+
+
@mock.patch('passerelle.utils.Request.post', side_effect=(TOKEN, UPDATE_KO))
def test_greco_update_ko(mocked_post, app, conn):
url = reverse('generic-endpoint', kwargs={'connector': 'greco', 'endpoint': 'update', 'slug': conn.slug})
@@ -435,6 +707,40 @@ def test_greco_add_confirmation_ok(mocked_post, app, conn):
}
+def test_greco_rest_add_confirmation_ok(app, rest_conn):
+ url = reverse(
+ 'generic-endpoint',
+ kwargs={'connector': 'greco', 'endpoint': 'add-confirmation', 'slug': rest_conn.slug},
+ )
+ url += '?apikey=grecokey'
+
+ with responses.RequestsMock() as rsps:
+ rsps.post(
+ 'http://greco.example.net/token',
+ status=200,
+ body=get_json_file('token'),
+ )
+ rsps.get(
+ 'http://greco.example.net/confirmer?idDemande=MDFGDZRF&idGreco=538593&nbconfirmation=2',
+ status=200,
+ json={
+ 'iddemande': 'MDFGDZRF',
+ 'idgreco': '538593',
+ 'motifsrejet': None,
+ },
+ )
+ resp = app.post_json(
+ url, params={'idgreco': '538593', 'iddemande': 'MDFGDZRF', 'nbconfirmation': '2'}
+ )
+
+ assert not resp.json['err']
+ assert resp.json['data'] == {
+ 'iddemande': 'MDFGDZRF',
+ 'idgreco': '538593',
+ 'motifsrejet': None,
+ }
+
+
@mock.patch('passerelle.utils.Request.post', side_effect=(TOKEN, ADD_CONFIRMATION_KO))
def test_greco_add_confirmation_ko(mocked_post, app, conn):
url = reverse(
@@ -451,3 +757,49 @@ def test_greco_add_confirmation_ko(mocked_post, app, conn):
'idgreco': None,
'motifsrejet': 'Le nombre de confirmation doit être un entier\\r\\n',
}
+
+
+def test_greco_rest_no_json_err(app, rest_conn):
+ url = reverse(
+ 'generic-endpoint', kwargs={'connector': 'greco', 'endpoint': 'status', 'slug': rest_conn.slug}
+ )
+ url += '?apikey=grecokey'
+ with responses.RequestsMock() as rsps:
+ rsps.post(
+ 'http://greco.example.net/token',
+ status=200,
+ body=get_json_file('token'),
+ )
+ rsps.get(
+ 'http://greco.example.net/consulter?iddemande=MDFGDZRF&idgreco=538593',
+ status=200,
+ content_type='text/html; charset=utf-8',
+ body='some error',
+ )
+ resp = app.get(url, params={'idgreco': '538593', 'iddemande': 'MDFGDZRF'})
+
+ assert resp.json['err'] == 1
+ assert resp.json['err_desc'] == 'some error'
+
+
+def test_greco_rest_bad_json_err(app, rest_conn):
+ url = reverse(
+ 'generic-endpoint', kwargs={'connector': 'greco', 'endpoint': 'ping', 'slug': rest_conn.slug}
+ )
+ url += '?apikey=grecokey'
+ with responses.RequestsMock() as rsps:
+ rsps.post(
+ 'http://greco.example.net/token',
+ status=200,
+ body=get_json_file('token'),
+ )
+ rsps.get(
+ 'http://greco.example.net/communicationTest/ping',
+ status=200,
+ content_type='application/json;charset=UTF-8',
+ body='{reponse:"Test de communication ok : ping"}',
+ )
+ resp = app.get(url)
+
+ assert resp.json['err'] == 1
+ assert resp.json['data']['response_text'] == '{reponse:"Test de communication ok : ping"}'
diff --git a/tox.ini b/tox.ini
index 33d96511..d063f8bf 100644
--- a/tox.ini
+++ b/tox.ini
@@ -44,6 +44,7 @@ deps =
phonenumbers
dnspython
pyquery
+ requests_toolbelt
responses
zeep<3.3
codestyle: pre-commit