caluire-axel: link endpoint (#53704)
This commit is contained in:
parent
183e7700eb
commit
81ad4a3f79
|
@ -0,0 +1,24 @@
|
|||
import pytest
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--url", help="Url of a passerelle Caluire Axel connector instance")
|
||||
parser.addoption("--nameid", help="Publik Name ID")
|
||||
parser.addoption("--firstname", help="first name of a user")
|
||||
parser.addoption("--lastname", help="Last name of a user")
|
||||
parser.addoption("--family", help="Family ID")
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def conn(request):
|
||||
return request.config.getoption("--url")
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def user(request):
|
||||
return {
|
||||
'name_id': request.config.getoption("--nameid"),
|
||||
'first_name': request.config.getoption("--firstname"),
|
||||
'last_name': request.config.getoption("--lastname"),
|
||||
'family': request.config.getoption("--family"),
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import pprint
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
def test_link(conn, user):
|
||||
name_id = user['name_id']
|
||||
url = conn + '/link?NameID=%s' % name_id
|
||||
payload = {
|
||||
'IDENTFAMILLE': user['family'],
|
||||
'NOM': user['last_name'],
|
||||
'PRENOM': user['first_name'],
|
||||
}
|
||||
print("Creating link with the following payload:")
|
||||
pprint.pprint(payload)
|
||||
resp = requests.post(url, json=payload)
|
||||
resp.raise_for_status()
|
||||
res = resp.json()
|
||||
pprint.pprint(res)
|
||||
assert res['err'] == 0
|
||||
print('\n')
|
|
@ -0,0 +1,65 @@
|
|||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('base', '0029_auto_20210202_1627'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CaluireAxel',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('title', models.CharField(max_length=50, verbose_name='Title')),
|
||||
('slug', models.SlugField(unique=True, verbose_name='Identifier')),
|
||||
('description', models.TextField(verbose_name='Description')),
|
||||
(
|
||||
'wsdl_url',
|
||||
models.CharField(
|
||||
help_text='Caluire Axel WSDL URL', max_length=128, verbose_name='WSDL URL'
|
||||
),
|
||||
),
|
||||
(
|
||||
'users',
|
||||
models.ManyToManyField(
|
||||
blank=True,
|
||||
related_name='_caluireaxel_users_+',
|
||||
related_query_name='+',
|
||||
to='base.ApiUser',
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Caluire Axel',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Link',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('name_id', models.CharField(max_length=256)),
|
||||
('family_id', models.CharField(max_length=128)),
|
||||
('person_id', models.CharField(max_length=128)),
|
||||
(
|
||||
'resource',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to='caluire_axel.CaluireAxel'
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('resource', 'name_id')},
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,119 @@
|
|||
# passerelle - uniform access to multiple data sources and services
|
||||
# Copyright (C) 2021 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from passerelle.base.models import BaseResource
|
||||
from passerelle.contrib.utils import axel
|
||||
from passerelle.utils.api import endpoint
|
||||
from passerelle.utils.jsonresponse import APIError
|
||||
|
||||
from . import schemas
|
||||
|
||||
|
||||
class CaluireAxel(BaseResource):
|
||||
|
||||
wsdl_url = models.CharField(
|
||||
max_length=128, blank=False, verbose_name=_('WSDL URL'), help_text=_('Caluire Axel WSDL URL')
|
||||
)
|
||||
|
||||
category = _('Business Process Connectors')
|
||||
_category_ordering = [_('Family')]
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Caluire Axel')
|
||||
|
||||
def check_status(self):
|
||||
response = self.requests.get(self.wsdl_url)
|
||||
response.raise_for_status()
|
||||
|
||||
def check_individu(self, post_data):
|
||||
family_id = post_data.pop('IDENTFAMILLE')
|
||||
for key in ['NAISSANCE', 'CODEPOSTAL', 'VILLE', 'TEL', 'MAIL']:
|
||||
post_data[key] = None
|
||||
try:
|
||||
result = schemas.find_individus(self, {'PORTAIL': {'FINDINDIVIDU': post_data}})
|
||||
except axel.AxelError as e:
|
||||
raise APIError(
|
||||
'Axel error: %s' % e,
|
||||
err_code='error',
|
||||
data={'xml_request': e.xml_request, 'xml_response': e.xml_response},
|
||||
)
|
||||
data = result.json_response['DATA']['PORTAIL']['FINDINDIVIDUS']
|
||||
for individu in data.get('INDIVIDU') or []:
|
||||
for famille in individu['FAMILLE']:
|
||||
if famille['IDENTFAMILLE'] == family_id:
|
||||
place = famille['PLACE']
|
||||
if place not in ['1', '2']:
|
||||
# not RL1 or RL2
|
||||
raise APIError('Wrong place in family', err_code='family-place-error-%s' % place)
|
||||
return individu, result
|
||||
|
||||
raise APIError('Person not found', err_code='not-found')
|
||||
|
||||
@endpoint(
|
||||
display_category=_('Family'),
|
||||
display_order=1,
|
||||
description=_('Create link between user and Caluire Axel'),
|
||||
perm='can_access',
|
||||
parameters={
|
||||
'NameID': {'description': _('Publik ID')},
|
||||
},
|
||||
post={
|
||||
'request_body': {
|
||||
'schema': {
|
||||
'application/json': schemas.LINK_SCHEMA,
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
def link(self, request, NameID, post_data):
|
||||
if not NameID:
|
||||
raise APIError('NameID is empty', err_code='bad-request', http_status=400)
|
||||
|
||||
family_id = post_data['IDENTFAMILLE']
|
||||
try:
|
||||
data, result = self.check_individu(post_data)
|
||||
except APIError as e:
|
||||
if not hasattr(e, 'err_code') or e.err_code == 'error':
|
||||
raise
|
||||
raise APIError('Person not found', err_code='not-found')
|
||||
|
||||
link, created = self.link_set.get_or_create(
|
||||
name_id=NameID, defaults={'family_id': family_id, 'person_id': data['IDENT']}
|
||||
)
|
||||
if not created and (link.family_id != family_id or link.person_id != data['IDENT']):
|
||||
raise APIError('Data conflict', err_code='conflict')
|
||||
return {
|
||||
'link': link.pk,
|
||||
'created': created,
|
||||
'family_id': link.family_id,
|
||||
'data': {
|
||||
'xml_request': result.xml_request,
|
||||
'xml_response': result.xml_response,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class Link(models.Model):
|
||||
resource = models.ForeignKey(CaluireAxel, on_delete=models.CASCADE)
|
||||
name_id = models.CharField(blank=False, max_length=256)
|
||||
family_id = models.CharField(blank=False, max_length=128)
|
||||
person_id = models.CharField(blank=False, max_length=128)
|
||||
|
||||
class Meta:
|
||||
unique_together = ('resource', 'name_id')
|
|
@ -0,0 +1,39 @@
|
|||
# passerelle - uniform access to multiple data sources and services
|
||||
# Copyright (C) 2021 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import copy
|
||||
import os
|
||||
|
||||
from passerelle.contrib.utils import axel
|
||||
|
||||
BASE_XSD_PATH = os.path.join(os.path.dirname(__file__), 'xsd')
|
||||
|
||||
|
||||
class Operation(axel.Operation):
|
||||
base_xsd_path = BASE_XSD_PATH
|
||||
|
||||
|
||||
find_individus = Operation('FindIndividus')
|
||||
|
||||
|
||||
LINK_SCHEMA = copy.deepcopy(
|
||||
find_individus.request_schema['properties']['PORTAIL']['properties']['FINDINDIVIDU']
|
||||
)
|
||||
for key in ['NAISSANCE', 'CODEPOSTAL', 'VILLE', 'TEL', 'MAIL']:
|
||||
LINK_SCHEMA['properties'].pop(key)
|
||||
LINK_SCHEMA['required'].remove(key)
|
||||
LINK_SCHEMA['properties']['IDENTFAMILLE'] = {'type': 'string', 'maxLength': 8}
|
||||
LINK_SCHEMA['required'].append('IDENTFAMILLE')
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<xsd:schema xmlns:all="urn:AllAxelTypes" targetNamespace="urn:Adresse" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:adr="urn:Adresse">
|
||||
|
||||
<xsd:import schemaLocation="./AllAxelTypes.xsd" namespace="urn:AllAxelTypes"/>
|
||||
|
||||
<xsd:simpleType name="NPAIType">
|
||||
<xsd:union memberTypes="all:ONType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:complexType name="ADRESSEType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="ADRESSE3" type="all:COMPLEMENTType"/>
|
||||
<xsd:element name="ADRESSE4" type="all:COMPLEMENTType"/>
|
||||
<xsd:element name="NORUE" type="all:NUMVOIEType"/>
|
||||
<xsd:element name="ADRESSE1" type="all:COMPLEMENTType"/>
|
||||
<xsd:element name="ADRESSE2" type="all:COMPLEMENTType"/>
|
||||
<xsd:element name="CODEPOSTAL" type="all:CODEPOSTALType"/>
|
||||
<xsd:element name="VILLE" type="all:VILLEType"/>
|
||||
<xsd:element name="PAYS" type="all:PAYSType"/>
|
||||
<xsd:element name="NPAI" type="adr:NPAIType"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:schema>
|
|
@ -0,0 +1,301 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<xsd:schema targetNamespace="urn:AllAxelTypes" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:all="urn:AllAxelTypes">
|
||||
|
||||
<xsd:simpleType name="empty-string">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="decimal-or-empty">
|
||||
<xsd:union memberTypes="xsd:decimal all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="unsignedInt-or-empty">
|
||||
<xsd:union memberTypes="xsd:unsignedInt all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="TELREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="1" />
|
||||
<xsd:maxLength value="10" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="TEL2REQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="1" />
|
||||
<xsd:maxLength value="16" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="COURRIELREQUIREDType">
|
||||
<xsd:restriction base="xsd:string" >
|
||||
<xsd:pattern value="[^@]+@[^\.]+\..+" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="NOMREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="1" />
|
||||
<xsd:maxLength value="50" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="PRENOMREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="1" />
|
||||
<xsd:maxLength value="30" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="NOMType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="0" />
|
||||
<xsd:maxLength value="50" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="PRENOMType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="0" />
|
||||
<xsd:maxLength value="30" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="DATEREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="((0[1-9])|([12][0-9])|(3[01]))/((0[1-9])|(1[012]))/((000[1-9])|(00[1-9][0-9])|(0[1-9][0-9]{2})|([1-9][0-9]{3}))" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="DATEType">
|
||||
<xsd:union memberTypes="all:DATEREQUIREDType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="DATETIMEType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="((0[1-9])|([12][0-9])|(3[01]))/((0[1-9])|(1[012]))/((000[1-9])|(00[1-9][0-9])|(0[1-9][0-9]{2})|([1-9][0-9]{3})) (([01][0-9])|(2[0-3]))(:[0-5][0-9]){2}(\.[0-9]+)?" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="TIMEType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="(([01][0-9])|(2[0-3]))(:[0-5][0-9])" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="IDENTType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:maxLength value="8" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="IDENTREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="1"/>
|
||||
<xsd:maxLength value="8"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="IDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:maxLength value="10" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="IDREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="1"/>
|
||||
<xsd:maxLength value="10"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="TELType">
|
||||
<xsd:union memberTypes="all:TELREQUIREDType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="TEL2Type">
|
||||
<xsd:union memberTypes="all:TEL2REQUIREDType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="COURRIELType" >
|
||||
<xsd:union memberTypes="all:COURRIELREQUIREDType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="ANNEEType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="[0-9]{4}"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="MOISType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="[0-1][0-9]"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="OUINONREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="[Oo][Uu][Ii]" />
|
||||
<xsd:pattern value="[Nn][Oo][Nn]" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="BOOLEANREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="0" />
|
||||
<xsd:pattern value="1" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="OUINONType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="|" />
|
||||
<xsd:pattern value="[Oo][Uu][Ii]" />
|
||||
<xsd:pattern value="[Nn][Oo][Nn]" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="NUMVOIEREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="1" />
|
||||
<xsd:maxLength value="5" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="NUMVOIEType">
|
||||
<xsd:union memberTypes="all:NUMVOIEREQUIREDType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="COMPLEMENTNUMType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="|" />
|
||||
<xsd:pattern value="[Bb][Ii][Ss]" />
|
||||
<xsd:pattern value="[Tt][Ee][Rr]" />
|
||||
<xsd:pattern value="[Qq][Uu][Aa][Tt][Ee][Rr]" />
|
||||
<xsd:pattern value="[Qq][Uu][Ii][Nn][Qq][Uu][Ii][Ee][Ss]" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="TYPEVOIEType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="[Aa][Vv][Ee][Nn][Uu][Ee]" />
|
||||
<xsd:pattern value="[Rr][Uu][Ee]" />
|
||||
<xsd:pattern value="[Ff][Aa][Uu][Bb][Oo][Uu][Rr][Gg]" />
|
||||
<xsd:pattern value="[Cc][Hh][Ee][Mm][Ii][Nn]" />
|
||||
<xsd:pattern value="[Cc][Oo][Uu][Rr][Ss]" />
|
||||
<xsd:pattern value="[Bb][Oo][Uu][Ll][Ee][Vv][Aa][Rr][Dd]" />
|
||||
<xsd:pattern value="[Ii][Mm][Pp][Aa][Ss][Ss][Ee]" />
|
||||
<xsd:pattern value="[Ll][Ii][Ee][Uu] [Dd][Ii][Tt]" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="COMPLEMENTREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="1" />
|
||||
<xsd:maxLength value="40" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="COMPLEMENTType">
|
||||
<xsd:union memberTypes="all:COMPLEMENTREQUIREDType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="CODEPOSTALREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="[0-9]{5}"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="VILLEREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="1" />
|
||||
<xsd:maxLength value="35" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="PAYSREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="1" />
|
||||
<xsd:maxLength value="30" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="CODEPOSTALType">
|
||||
<xsd:union memberTypes="all:CODEPOSTALREQUIREDType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="VILLEType">
|
||||
<xsd:union memberTypes="all:VILLEREQUIREDType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="PAYSType">
|
||||
<xsd:union memberTypes="all:PAYSREQUIREDType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="CODEINSEEVILLEREQUIREDType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="[0-9]{5}"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="CODEINSEEVILLEType">
|
||||
<xsd:union memberTypes="all:CODEINSEEVILLEREQUIREDType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="ONEmptyType">
|
||||
<xsd:union memberTypes="all:ONType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="ONType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="[Oo]" />
|
||||
<xsd:pattern value="[Nn]" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="MONTANTREQUIREDType">
|
||||
<xsd:restriction base="xsd:decimal">
|
||||
<xsd:totalDigits value="10"/>
|
||||
<xsd:fractionDigits value="2"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="MONTANTType">
|
||||
<xsd:union memberTypes="all:MONTANTREQUIREDType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="PRIXREQUIREDType">
|
||||
<xsd:restriction base="xsd:decimal">
|
||||
<xsd:totalDigits value="10"/>
|
||||
<xsd:fractionDigits value="5"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="PRIXType">
|
||||
<xsd:union memberTypes="all:PRIXREQUIREDType all:empty-string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="LIBELLEType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="0" />
|
||||
<xsd:maxLength value="40" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="LIBELLE100Type">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="0" />
|
||||
<xsd:maxLength value="100" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="FOOBARType"><!-- CUSTOM -->
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="0" />
|
||||
<xsd:maxLength value="256" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
</xsd:schema>
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<xsd:schema xmlns:adr="urn:Adresse" xmlns:all="urn:AllAxelTypes" targetNamespace="urn:Individu" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ind="urn:Individu" >
|
||||
|
||||
<xsd:import schemaLocation="./AllAxelTypes.xsd" namespace="urn:AllAxelTypes" />
|
||||
<xsd:import schemaLocation="./Adresse.xsd" namespace="urn:Adresse" />
|
||||
|
||||
<xsd:simpleType name="SEXEType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="" />
|
||||
<xsd:enumeration value="M" />
|
||||
<xsd:enumeration value="F" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="CIVILITEType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="0" />
|
||||
<xsd:maxLength value="4" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:complexType name="INDIVIDUType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="IDENT" type="all:IDENTType"/>
|
||||
<xsd:element name="CIVILITE" type="ind:CIVILITEType"/>
|
||||
<xsd:element name="NOM" type="all:NOMREQUIREDType"/>
|
||||
<xsd:element name="PRENOM" type="all:PRENOMType"/>
|
||||
<xsd:element name="NAISSANCE" type="all:DATEType"/>
|
||||
<xsd:element name="SEXE" type="ind:SEXEType"/>
|
||||
<xsd:element name="NOMJF" type="all:NOMType"/>
|
||||
<xsd:element name="TELFIXE" type="all:TEL2Type"/>
|
||||
<xsd:element name="TELPORTABLE" type="all:TEL2Type"/>
|
||||
<xsd:element name="MAIL" type="all:COURRIELType"/>
|
||||
<xsd:element name="CSP" type="all:FOOBARType"/><!-- CUSTOM -->
|
||||
<xsd:element name="EMPLOYEUR" type="all:FOOBARType"/><!-- CUSTOM -->
|
||||
<xsd:element name="VILLEEMP" type="all:FOOBARType"/><!-- CUSTOM -->
|
||||
<xsd:element name="PAI" type="all:FOOBARType"/><!-- CUSTOM -->
|
||||
<xsd:element name="GARDEALTERNEE" type="all:FOOBARType"/><!-- CUSTOM -->
|
||||
<xsd:element name="ADRESSE" type="adr:ADRESSEType" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
</xsd:schema>
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:all="urn:AllAxelTypes">
|
||||
|
||||
<xsd:import schemaLocation="./AllAxelTypes.xsd" namespace="urn:AllAxelTypes" />
|
||||
|
||||
|
||||
<xsd:complexType name="FINDINDIVIDUType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="NOM" />
|
||||
<xsd:element ref="PRENOM" />
|
||||
<xsd:element ref="NAISSANCE" />
|
||||
<xsd:element ref="CODEPOSTAL" />
|
||||
<xsd:element ref="VILLE" />
|
||||
<xsd:element ref="TEL" />
|
||||
<xsd:element ref="MAIL" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="PORTAILType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="FINDINDIVIDU" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="NOM" type="all:NOMREQUIREDType"/>
|
||||
<xsd:element name="PRENOM" type="all:PRENOMREQUIREDType"/> <!-- CUSTOM, it should be PRENOMType -->
|
||||
<xsd:element name="NAISSANCE" type="all:DATEType"/>
|
||||
<xsd:element name="CODEPOSTAL" type="all:CODEPOSTALType"/>
|
||||
<xsd:element name="VILLE" type="all:VILLEType"/>
|
||||
<xsd:element name="TEL" type="all:TEL2Type"/>
|
||||
<xsd:element name="MAIL" type="all:COURRIELType"/>
|
||||
|
||||
<xsd:element name="FINDINDIVIDU" type="FINDINDIVIDUType"/>
|
||||
|
||||
<xsd:element name="PORTAIL" type="PORTAILType"/>
|
||||
|
||||
</xsd:schema>
|
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<xsd:schema xmlns:all="urn:AllAxelTypes" xmlns:ind="urn:Individu" xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
|
||||
|
||||
<xsd:import schemaLocation="./Individu.xsd" namespace="urn:Individu" />
|
||||
<xsd:import schemaLocation="./AllAxelTypes.xsd" namespace="urn:AllAxelTypes" />
|
||||
|
||||
<xsd:redefine schemaLocation="./R_ShemaResultat.xsd">
|
||||
<xsd:simpleType name="TYPEType">
|
||||
<xsd:restriction base="TYPEType">
|
||||
<xsd:enumeration value="FindIndividus" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:complexType name="PORTAILType">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="PORTAILType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="FINDINDIVIDUS" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:redefine>
|
||||
|
||||
<xsd:complexType name="INDIType">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="ind:INDIVIDUType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="FAMILLE" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="FAMILLEType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="IDENTFAMILLE" />
|
||||
<xsd:element ref="PLACE"/>
|
||||
<xsd:element ref="SITUATION" minOccurs="0" maxOccurs="1"/><!-- CUSTOM -->
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:simpleType name="PLACEType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="" />
|
||||
<xsd:enumeration value="1" />
|
||||
<xsd:enumeration value="2" />
|
||||
<xsd:enumeration value="3" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:complexType name="FINDINDIVIDUSType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="CODE" />
|
||||
<xsd:element ref="INDIVIDU" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="CODE" type="xsd:integer"/>
|
||||
<xsd:element name="INDIVIDU" type="INDIType"/>
|
||||
<xsd:element name="FAMILLE" type="FAMILLEType"/>
|
||||
<xsd:element name="IDENTFAMILLE" type="all:IDENTType"/>
|
||||
<xsd:element name="PLACE" type="PLACEType"/>
|
||||
<xsd:element name="SITUATION" type="all:FOOBARType"/><!-- CUSTOM -->
|
||||
|
||||
<xsd:element name="FINDINDIVIDUS" type="FINDINDIVIDUSType"/>
|
||||
|
||||
</xsd:schema>
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:all="urn:AllAxelTypes">
|
||||
|
||||
<xsd:import schemaLocation="./AllAxelTypes.xsd" namespace="urn:AllAxelTypes" />
|
||||
|
||||
<xsd:simpleType name="TYPEType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="STATUSType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="OK" />
|
||||
<xsd:enumeration value="NOK" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:complexType name="PORTAILType">
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="RESULTATType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="TYPE" />
|
||||
<xsd:element ref="STATUS" />
|
||||
<xsd:element ref="DATE" />
|
||||
<xsd:element ref="COMMENTAIRES" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="DATAType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="PORTAIL"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="PORTAILSERVICEType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="RESULTAT" />
|
||||
<xsd:element ref="DATA" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="TYPE" type="TYPEType"/>
|
||||
<xsd:element name="STATUS" type="STATUSType"/>
|
||||
<xsd:element name="DATE" type="all:DATETIMEType"/>
|
||||
<xsd:element name="COMMENTAIRES" type="xsd:string"/>
|
||||
|
||||
<xsd:element name="PORTAIL" type="PORTAILType"/>
|
||||
|
||||
<xsd:element name="RESULTAT" type="RESULTATType"/>
|
||||
<xsd:element name="DATA" type="DATAType"/>
|
||||
|
||||
<xsd:element name="PORTAILSERVICE" type="PORTAILSERVICEType"/>
|
||||
</xsd:schema>
|
|
@ -16,6 +16,7 @@ KNOWN_SERVICES = {
|
|||
# include all contrib apps
|
||||
INSTALLED_APPS += (
|
||||
'passerelle.contrib.adict',
|
||||
'passerelle.contrib.caluire_axel',
|
||||
'passerelle.contrib.dpark',
|
||||
'passerelle.contrib.fake_family',
|
||||
'passerelle.contrib.gdema',
|
||||
|
|
|
@ -0,0 +1,351 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# passerelle - uniform access to multiple data sources and services
|
||||
# Copyright (C) 2021 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
import mock
|
||||
import pytest
|
||||
import utils
|
||||
import xmlschema
|
||||
|
||||
from passerelle.contrib.caluire_axel import schemas
|
||||
from passerelle.contrib.caluire_axel.models import CaluireAxel, Link
|
||||
from passerelle.contrib.utils.axel import AxelError
|
||||
from passerelle.utils.soap import SOAPError
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def resource(db):
|
||||
return utils.make_resource(
|
||||
CaluireAxel, slug='test', wsdl_url='http://example.net/AXEL_WS/AxelWS.php?wsdl'
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def link_params():
|
||||
return {
|
||||
'IDENTFAMILLE': '12345',
|
||||
'NOM': 'Doe',
|
||||
'PRENOM': 'John',
|
||||
}
|
||||
|
||||
|
||||
@contextmanager
|
||||
def mock_getdata(content, operation):
|
||||
with mock.patch('passerelle.contrib.caluire_axel.models.CaluireAxel.soap_client') as client:
|
||||
resp = '''
|
||||
<?xml version="1.0"?>
|
||||
<PORTAILSERVICE>
|
||||
<RESULTAT>
|
||||
<TYPE>%s</TYPE>
|
||||
<STATUS>OK</STATUS>
|
||||
<DATE>10/10/2010 10:10:01</DATE>
|
||||
<COMMENTAIRES><![CDATA[]]></COMMENTAIRES>
|
||||
</RESULTAT>
|
||||
<DATA>
|
||||
%s
|
||||
</DATA>
|
||||
</PORTAILSERVICE>
|
||||
'''.strip() % (
|
||||
operation,
|
||||
content,
|
||||
)
|
||||
client.return_value.service.getData.return_value = resp
|
||||
yield
|
||||
|
||||
|
||||
def test_operation_status_error(resource):
|
||||
resp = '''
|
||||
<?xml version="1.0"?>
|
||||
<PORTAILSERVICE>
|
||||
<RESULTAT>
|
||||
<TYPE>FindIndividus</TYPE>
|
||||
<STATUS>NOK</STATUS>
|
||||
<COMMENTAIRES><![CDATA[Foo reason]]></COMMENTAIRES>
|
||||
</RESULTAT>
|
||||
<DATA>
|
||||
<PORTAIL/>
|
||||
</DATA>
|
||||
</PORTAILSERVICE>
|
||||
'''.strip()
|
||||
with mock.patch('passerelle.contrib.caluire_axel.models.CaluireAxel.soap_client') as client:
|
||||
client.return_value.service.getData.return_value = resp
|
||||
with pytest.raises(AxelError, match='Foo reason'):
|
||||
schemas.find_individus(
|
||||
resource,
|
||||
{
|
||||
'PORTAIL': {
|
||||
'FINDINDIVIDU': {
|
||||
'NOM': 'Doe',
|
||||
'PRENOM': 'John',
|
||||
'NAISSANCE': None,
|
||||
'CODEPOSTAL': None,
|
||||
'VILLE': None,
|
||||
'TEL': None,
|
||||
'MAIL': None,
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'content',
|
||||
[
|
||||
'<PORTAIL><FINDINDIVIDUS/></PORTAIL>',
|
||||
],
|
||||
)
|
||||
def test_operation_find_individus(resource, content):
|
||||
with mock_getdata(content, 'FindIndividus'):
|
||||
with pytest.raises(AxelError):
|
||||
schemas.find_individus(
|
||||
resource,
|
||||
{
|
||||
'PORTAIL': {
|
||||
'FINDINDIVIDU': {
|
||||
'NOM': 'Doe',
|
||||
'PRENOM': 'John',
|
||||
'NAISSANCE': None,
|
||||
'CODEPOSTAL': None,
|
||||
'VILLE': None,
|
||||
'TEL': None,
|
||||
'MAIL': None,
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def test_link_endpoint_nameid_empty(app, resource, link_params):
|
||||
resp = app.post_json('/caluire-axel/test/link?NameID=', params=link_params, status=400)
|
||||
assert resp.json['err_desc'] == "NameID is empty"
|
||||
assert resp.json['err'] == 'bad-request'
|
||||
|
||||
|
||||
def test_link_endpoint_axel_error(app, resource, link_params):
|
||||
with mock.patch('passerelle.contrib.caluire_axel.schemas.find_individus') as operation:
|
||||
operation.side_effect = AxelError('FooBar')
|
||||
resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params)
|
||||
assert resp.json['err_desc'] == "Axel error: FooBar"
|
||||
assert resp.json['err'] == 'error'
|
||||
assert resp.json['data'] == {'xml_request': None, 'xml_response': None}
|
||||
|
||||
# test xml_request and xml_response only for this endpoint
|
||||
xml_request = """<PORTAIL>
|
||||
<FINDINDIVIDU>
|
||||
<NOM>Doe</NOM>
|
||||
<PRENOM>John</PRENOM>
|
||||
<NAISSANCE />
|
||||
<CODEPOSTAL />
|
||||
<VILLE />
|
||||
<TEL />
|
||||
<MAIL />
|
||||
</FINDINDIVIDU>
|
||||
</PORTAIL>
|
||||
"""
|
||||
|
||||
with mock_getdata('', 'FindIndividus'):
|
||||
with mock.patch('xmlschema.XMLSchema.validate') as xml_validate:
|
||||
xml_validate.side_effect = xmlschema.XMLSchemaValidationError(None, None)
|
||||
resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params)
|
||||
assert resp.json['err_desc'].startswith("Axel error: invalid request")
|
||||
assert resp.json['err'] == 'error'
|
||||
assert resp.json['data']['xml_request'] == xml_request
|
||||
assert resp.json['data']['xml_response'] is None
|
||||
|
||||
xml_response = """<PORTAILSERVICE>
|
||||
<RESULTAT>
|
||||
<TYPE>FINDINDIVIDUS</TYPE>
|
||||
<STATUS>NOK</STATUS>
|
||||
<COMMENTAIRES>Foo reason</COMMENTAIRES>
|
||||
</RESULTAT>
|
||||
<DATA>
|
||||
<PORTAIL />
|
||||
</DATA>
|
||||
</PORTAILSERVICE>"""
|
||||
response = """
|
||||
<?xml version="1.0"?>
|
||||
<PORTAILSERVICE>
|
||||
<RESULTAT>
|
||||
<TYPE>FINDINDIVIDUS</TYPE>
|
||||
<STATUS>NOK</STATUS>
|
||||
<COMMENTAIRES><![CDATA[Foo reason]]></COMMENTAIRES>
|
||||
</RESULTAT>
|
||||
<DATA>
|
||||
<PORTAIL/>
|
||||
</DATA>
|
||||
</PORTAILSERVICE>
|
||||
""".strip()
|
||||
with mock.patch('passerelle.contrib.caluire_axel.models.CaluireAxel.soap_client') as client:
|
||||
client.return_value.service.getData.return_value = response
|
||||
resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params)
|
||||
assert resp.json['err_desc'] == 'Axel error: Foo reason'
|
||||
assert resp.json['err'] == 'error'
|
||||
assert resp.json['data']['xml_request'] == xml_request
|
||||
assert resp.json['data']['xml_response'] == xml_response
|
||||
|
||||
content = """<PORTAIL>
|
||||
<FINDINDIVIDUS>
|
||||
<INDIVIDU>
|
||||
<IDENT>123</IDENT>
|
||||
<NOM>Doe</NOM>
|
||||
<PRENOM>John</PRENOM>
|
||||
<FAMILLE>
|
||||
<IDENTFAMILLE>12345</IDENTFAMILLE>
|
||||
<PLACE>2</PLACE>
|
||||
</FAMILLE>
|
||||
</INDIVIDU>
|
||||
</FINDINDIVIDUS>
|
||||
</PORTAIL>"""
|
||||
xml_response = (
|
||||
"""<PORTAILSERVICE>
|
||||
<RESULTAT>
|
||||
<TYPE>FindIndividus</TYPE>
|
||||
<STATUS>OK</STATUS>
|
||||
<DATE>10/10/2010 10:10:01</DATE>
|
||||
<COMMENTAIRES />
|
||||
</RESULTAT>
|
||||
<DATA>
|
||||
%s
|
||||
</DATA>
|
||||
</PORTAILSERVICE>"""
|
||||
% content
|
||||
)
|
||||
with mock_getdata(content, 'FindIndividus'):
|
||||
with mock.patch('passerelle.contrib.utils.axel.AxelSchema.decode') as decode:
|
||||
decode.side_effect = xmlschema.XMLSchemaValidationError(None, None)
|
||||
resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params)
|
||||
assert resp.json['err_desc'].startswith("Axel error: invalid response")
|
||||
assert resp.json['err'] == 'error'
|
||||
assert resp.json['data']['xml_request'] == xml_request
|
||||
assert resp.json['data']['xml_response'] == xml_response
|
||||
|
||||
with mock.patch('passerelle.contrib.caluire_axel.models.CaluireAxel.soap_client') as client:
|
||||
client.side_effect = SOAPError('SOAP service is down')
|
||||
resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params)
|
||||
assert resp.json['err_desc'] == "SOAP service is down"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'xml_response',
|
||||
[
|
||||
'',
|
||||
"""<INDIVIDU>
|
||||
<IDENT>123</IDENT>
|
||||
<CIVILITE/><NOM>A</NOM><PRENOM/><NAISSANCE/><SEXE/><NOMJF/><TELFIXE/><TELPORTABLE/><MAIL/><CSP/><EMPLOYEUR/><VILLEEMP/><PAI/><GARDEALTERNEE/>
|
||||
<FAMILLE>
|
||||
<IDENTFAMILLE>12346</IDENTFAMILLE>
|
||||
<PLACE>2</PLACE>
|
||||
<SITUATION/>
|
||||
</FAMILLE>
|
||||
<FAMILLE>
|
||||
<IDENTFAMILLE>12347</IDENTFAMILLE>
|
||||
<PLACE>1</PLACE>
|
||||
</FAMILLE>
|
||||
</INDIVIDU>""",
|
||||
"""<INDIVIDU>
|
||||
<IDENT>123</IDENT>
|
||||
<CIVILITE/><NOM>A</NOM><PRENOM/><NAISSANCE/><SEXE/><NOMJF/><TELFIXE/><TELPORTABLE/><MAIL/><CSP/><EMPLOYEUR/><VILLEEMP/><PAI/><GARDEALTERNEE/>
|
||||
<FAMILLE>
|
||||
<IDENTFAMILLE>12345</IDENTFAMILLE>
|
||||
<PLACE>3</PLACE>
|
||||
<SITUATION/>
|
||||
</FAMILLE>
|
||||
</INDIVIDU>""",
|
||||
],
|
||||
)
|
||||
def test_link_endpoint_no_result(app, resource, link_params, xml_response):
|
||||
content = (
|
||||
'''<PORTAIL>
|
||||
<FINDINDIVIDUS>
|
||||
<CODE>42</CODE>
|
||||
%s
|
||||
</FINDINDIVIDUS>
|
||||
</PORTAIL>'''
|
||||
% xml_response
|
||||
)
|
||||
with mock_getdata(content, 'FindIndividus'):
|
||||
resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params)
|
||||
assert resp.json['err_desc'] == "Person not found"
|
||||
assert resp.json['err'] == 'not-found'
|
||||
|
||||
|
||||
def test_link_endpoint_conflict(app, resource, link_params):
|
||||
content = """<PORTAIL><FINDINDIVIDUS>
|
||||
<CODE>42</CODE>
|
||||
<INDIVIDU>
|
||||
<IDENT>123</IDENT>
|
||||
<CIVILITE/><NOM>A</NOM><PRENOM/><NAISSANCE/><SEXE/><NOMJF/><TELFIXE/><TELPORTABLE/><MAIL/><CSP/><EMPLOYEUR/><VILLEEMP/><PAI/><GARDEALTERNEE/>
|
||||
<FAMILLE>
|
||||
<IDENTFAMILLE>12345</IDENTFAMILLE>
|
||||
<PLACE>2</PLACE>
|
||||
<SITUATION/>
|
||||
</FAMILLE>
|
||||
</INDIVIDU>
|
||||
</FINDINDIVIDUS></PORTAIL>"""
|
||||
# existing link but family_id is wrong
|
||||
link = Link.objects.create(resource=resource, name_id='yyy', family_id='YYY', person_id='42')
|
||||
with mock_getdata(content, 'FindIndividus'):
|
||||
resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params)
|
||||
assert resp.json['err_desc'] == "Data conflict"
|
||||
assert resp.json['err'] == 'conflict'
|
||||
|
||||
# existing link but person_id is wrong
|
||||
link.family_id = '12345'
|
||||
link.person_id = '35'
|
||||
link.save()
|
||||
with mock_getdata(content, 'FindIndividus'):
|
||||
resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params)
|
||||
assert resp.json['err_desc'] == "Data conflict"
|
||||
assert resp.json['err'] == 'conflict'
|
||||
|
||||
|
||||
@pytest.mark.parametrize('place', [1, 2])
|
||||
def test_link_endpoint(app, resource, link_params, place):
|
||||
content = (
|
||||
"""<PORTAIL><FINDINDIVIDUS>
|
||||
<CODE>42</CODE>
|
||||
<INDIVIDU>
|
||||
<IDENT>123</IDENT>
|
||||
<CIVILITE/><NOM>A</NOM><PRENOM/><NAISSANCE/><SEXE/><NOMJF/><TELFIXE/><TELPORTABLE/><MAIL/><CSP/><EMPLOYEUR/><VILLEEMP/><PAI/><GARDEALTERNEE/>
|
||||
<FAMILLE>
|
||||
<IDENTFAMILLE>12345</IDENTFAMILLE>
|
||||
<PLACE>%s</PLACE>
|
||||
<SITUATION/>
|
||||
</FAMILLE>
|
||||
</INDIVIDU>
|
||||
</FINDINDIVIDUS></PORTAIL>"""
|
||||
% place
|
||||
)
|
||||
with mock_getdata(content, 'FindIndividus'):
|
||||
resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params)
|
||||
assert set(resp.json.keys()) == set(['err', 'link', 'created', 'family_id', 'data'])
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['family_id'] == '12345'
|
||||
assert resp.json['created'] is True
|
||||
assert 'xml_request' in resp.json['data']
|
||||
assert 'xml_response' in resp.json['data']
|
||||
|
||||
# again
|
||||
with mock_getdata(content, 'FindIndividus'):
|
||||
resp = app.post_json('/caluire-axel/test/link?NameID=yyy', params=link_params)
|
||||
assert set(resp.json.keys()) == set(['err', 'link', 'created', 'family_id', 'data'])
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['family_id'] == '12345'
|
||||
assert resp.json['created'] is False # link already exists
|
||||
assert 'xml_request' in resp.json['data']
|
||||
assert 'xml_response' in resp.json['data']
|
Loading…
Reference in New Issue