Compare commits

..

7 Commits

Author SHA1 Message Date
Benjamin Dauvergne 95030b91f5 base_adresse: add indexes on on geographic models names (#66694)
gitea/passerelle/pipeline/head This commit looks good Details
2023-12-09 09:46:48 +01:00
Nicolas Roche e592c33021 toulouse-maelis: manage fiscal number on RL (#84372)
gitea/passerelle/pipeline/head This commit looks good Details
2023-12-07 15:57:27 +01:00
Nicolas Roche ad4b9de490 toulouse-maelis: update Family WSDL (#84372) 2023-12-07 11:28:24 +01:00
Benjamin Dauvergne b4d637249a cmis: disable logging of requests errors (#84348)
gitea/passerelle/pipeline/head This commit looks good Details
2023-12-06 18:05:17 +01:00
Benjamin Dauvergne f15d802b11 cmis: improve reporting of ObjectNotfound and PermissionDenied (#84348) 2023-12-06 17:42:02 +01:00
Emmanuel Cazenave 2e167a3466 esup_signature: ensure compatibility with requests < 2.27 (#84043)
gitea/passerelle/pipeline/head This commit looks good Details
2023-11-30 10:47:12 +01:00
Frédéric Péters f513f2451d opengis: add support for wfs:FeatureCollection responses (#84053)
gitea/passerelle/pipeline/head This commit looks good Details
2023-11-29 10:34:57 +01:00
11 changed files with 143 additions and 6 deletions

View File

@ -293,11 +293,21 @@ class CMISGateway:
@wrap_cmis_error
def get_object_by_path(self, file_path):
return self.repo.getObjectByPath(file_path)
try:
return self.repo.getObjectByPath(file_path)
except ObjectNotFoundException:
raise APIError('CMIS server did not found path %s' % file_path)
except PermissionDeniedException:
raise APIError('CMIS server denied reading file %s' % file_path)
@wrap_cmis_error
def get_object(self, object_id):
return self.repo.getObject(object_id)
try:
return self.repo.getObject(object_id)
except ObjectNotFoundException:
raise APIError('CMIS server did not found object_id %s' % object_id)
except PermissionDeniedException:
raise APIError('CMIS server denied reading object_id %s' % object_id)
# Mock API from cmilib.net.RESTService

View File

@ -223,7 +223,7 @@ class EsupSignature(BaseResource, HTTPResource):
if expect_json:
try:
return resp.json()
except (json.JSONDecodeError, requests.exceptions.JSONDecodeError) as e:
except (json.JSONDecodeError, requests.exceptions.RequestException) as e:
raise APIError(str(e))
return resp

View File

@ -314,6 +314,9 @@ class OpenGIS(BaseResource):
}
response = self.requests.get(self.wms_service_url, params=params)
element = ET.fromstring(response.content)
if element.tag == '{http://www.opengis.net/wfs}FeatureCollection':
features = element.findall('{http://www.opengis.net/gml}featureMembers/*')
return {'err': 0, 'data': build_dict_from_xml(features[0]) if features else []}
return {'err': 0, 'data': build_dict_from_xml(element)}
# https://carton.entrouvert.org/hydda-tiles/16/33650/23378.pn

View File

@ -329,6 +329,19 @@ CAFINFO_SCHEMA = {
},
}
FISCINFO_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'CAF',
'description': 'Information fiscale',
'type': 'object',
'properties': {
'spi': {
'description': 'Numéro fiscal',
'oneOf': [{'type': 'string'}, {'type': 'null'}],
},
},
}
RLINFO_SCHEMA = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'RL',
@ -350,6 +363,7 @@ RLINFO_SCHEMA = {
'contact': {'oneOf': [CONTACT_SCHEMA, {'type': 'null'}]},
'profession': {'oneOf': [PROFESSION_SCHEMA, {'type': 'null'}]},
'CAFInfo': {'oneOf': [CAFINFO_SCHEMA, {'type': 'null'}]},
'fiscalInfo': {'oneOf': [FISCINFO_SCHEMA, {'type': 'null'}]},
'indicatorList': {
'oneOf': [
{
@ -660,6 +674,7 @@ del CREATE_RL1_SCHEMA['properties']['childList']
del CREATE_RL1_SCHEMA['properties']['rl1']['properties']['contact']
del CREATE_RL1_SCHEMA['properties']['rl1']['properties']['profession']
del CREATE_RL1_SCHEMA['properties']['rl1']['properties']['CAFInfo']
del CREATE_RL1_SCHEMA['properties']['rl1']['properties']['fiscalInfo']
UPDATE_RL1_SCHEMA = copy.deepcopy(RLINFO_SCHEMA)
UPDATE_RL1_SCHEMA['required'] = ['firstname', 'lastname', 'civility', 'quality', 'birth']
@ -667,6 +682,7 @@ del UPDATE_RL1_SCHEMA['properties']['adresse']
del UPDATE_RL1_SCHEMA['properties']['contact']
del UPDATE_RL1_SCHEMA['properties']['profession']
del UPDATE_RL1_SCHEMA['properties']['CAFInfo']
del UPDATE_RL1_SCHEMA['properties']['fiscalInfo']
del UPDATE_RL1_SCHEMA['properties']['indicatorList']
CREATE_RL2_SCHEMA = copy.deepcopy(RLINFO_SCHEMA)
@ -674,6 +690,7 @@ CREATE_RL2_SCHEMA['unflatten'] = True
del CREATE_RL2_SCHEMA['properties']['contact']
del CREATE_RL2_SCHEMA['properties']['profession']
del CREATE_RL2_SCHEMA['properties']['CAFInfo']
del CREATE_RL2_SCHEMA['properties']['fiscalInfo']
del CREATE_RL2_SCHEMA['properties']['indicatorList']
UPDATE_RL2_SCHEMA = copy.deepcopy(UPDATE_RL1_SCHEMA)
@ -699,6 +716,7 @@ UPDATE_COORDINATE_SCHEMA = {
'contact': {'oneOf': [CONTACT_SCHEMA, {'type': 'null'}]},
'profession': {'oneOf': [PROFESSION_SCHEMA, {'type': 'null'}]},
'CAFInfo': {'oneOf': [CAFINFO_SCHEMA, {'type': 'null'}]},
'FiscalInfo': {'oneOf': [FISCINFO_SCHEMA, {'type': 'null'}]},
},
'unflatten': True,
'additionalProperties': False,

View File

@ -168,6 +168,7 @@
<xs:element minOccurs="0" name="contact" type="ns2:contactBean"/>
<xs:element minOccurs="0" name="profession" type="ns2:professionBean"/>
<xs:element minOccurs="0" name="CAFInfo" type="ns2:cafInfoBean"/>
<xs:element minOccurs="0" name="fiscalInfo" type="ns2:fiscalInfoBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="indicatorList" nillable="true" type="ns2:indicatorBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="quotientList" nillable="true" type="tns:familyQuotientRedvBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="subscribeActivityList" nillable="true" type="tns:subscribeActivityBean"/>
@ -324,6 +325,7 @@
<xs:element minOccurs="0" name="contact" type="ns2:contactBean"/>
<xs:element minOccurs="0" name="profession" type="ns2:professionBean"/>
<xs:element minOccurs="0" name="CAFInfo" type="ns2:cafInfoBean"/>
<xs:element minOccurs="0" name="FiscalInfo" type="ns2:fiscalInfoBean"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="updateCoordinateResponse">
@ -410,6 +412,7 @@
<xs:element minOccurs="0" name="contact" type="ns2:contactBean"/>
<xs:element minOccurs="0" name="profession" type="ns2:professionBean"/>
<xs:element minOccurs="0" name="CAFInfo" type="ns2:cafInfoBean"/>
<xs:element minOccurs="0" name="fiscalInfo" type="ns2:fiscalInfoBean"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="indicatorList" nillable="true" type="ns2:indicatorValueAddUpdBean"/>
</xs:sequence>
</xs:complexType>
@ -870,7 +873,7 @@
</xs:sequence>
</xs:complexType>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns1="family.ws.maelis.sigec.com" xmlns="bean.persistence.ws.maelis.sigec.com" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="bean.persistence.ws.maelis.sigec.com">
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns1="family.ws.maelis.sigec.com" targetNamespace="bean.persistence.ws.maelis.sigec.com" version="1.0">
<xs:import namespace="family.ws.maelis.sigec.com"/>
<xs:complexType name="itemBean">
<xs:sequence>
@ -908,7 +911,7 @@
</xs:complexContent>
</xs:complexType>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns1="bean.persistence.family.ws.maelis.sigec.com" xmlns="bean.persistence.site.ws.maelis.sigec.com" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="bean.persistence.site.ws.maelis.sigec.com">
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns1="bean.persistence.family.ws.maelis.sigec.com" targetNamespace="bean.persistence.site.ws.maelis.sigec.com" version="1.0">
<xs:import namespace="bean.persistence.family.ws.maelis.sigec.com"/>
<xs:complexType name="subscribeSchoolYearBean">
<xs:sequence>
@ -916,7 +919,7 @@
</xs:sequence>
</xs:complexType>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="bean.persistence.family.ws.maelis.sigec.com" xmlns:ns3="bean.persistence.site.ws.maelis.sigec.com" xmlns:ns2="bean.persistence.ws.maelis.sigec.com" xmlns:ns1="family.ws.maelis.sigec.com" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="bean.persistence.family.ws.maelis.sigec.com">
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="bean.persistence.family.ws.maelis.sigec.com" xmlns:ns3="bean.persistence.site.ws.maelis.sigec.com" xmlns:ns2="bean.persistence.ws.maelis.sigec.com" xmlns:ns1="family.ws.maelis.sigec.com" targetNamespace="bean.persistence.family.ws.maelis.sigec.com" version="1.0">
<xs:import namespace="family.ws.maelis.sigec.com"/>
<xs:import namespace="bean.persistence.ws.maelis.sigec.com"/>
<xs:import namespace="bean.persistence.site.ws.maelis.sigec.com"/>
@ -966,6 +969,11 @@
<xs:element minOccurs="0" name="organ" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="fiscalInfoBean">
<xs:sequence>
<xs:element minOccurs="0" name="spi" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="indicatorBean">
<xs:complexContent>
<xs:extension base="ns1:abstractSpecBean">
@ -2094,6 +2102,7 @@
adresse : adresse de la personne
contact : informatin de contact de la personne
CAFInfo : information caf de la personne
FiscalInfo : information fiscal de la personne
-----------------------------
Traitement :

View File

@ -124,6 +124,9 @@
<number>789</number>
<organ>A10007752822</organ>
</CAFInfo>
<fiscalInfo>
<spi>00 01 123 456 789 C</spi>
</fiscalInfo>
<subscribeActivityList>
<libelle>CSocial Adult 2021/2022 - Bijoux en cuirs 21/03/22</libelle>
<typeIns>1</typeIns>

View File

@ -124,6 +124,9 @@
<number>789</number>
<organ>A10007752822</organ>
</CAFInfo>
<fiscalInfo>
<spi>00 01 123 456 789 C</spi>
</fiscalInfo>
<subscribeActivityList>
<libelle>CSocial Adult 2021/2022 - Bijoux en cuirs 21/03/22</libelle>
<typeIns>1</typeIns>

View File

@ -124,6 +124,9 @@
<number>789</number>
<organ>A10007752822</organ>
</CAFInfo>
<fiscalInfo>
<spi>00 01 123 456 789 C</spi>
</fiscalInfo>
<subscribeActivityList>
<libelle>CSocial Adult 2021/2022 - Bijoux en cuirs 21/03/22</libelle>
<typeIns>1</typeIns>

View File

@ -646,3 +646,21 @@ def test_get_metadata(app, setup):
response = app.get(url, params={'object_id': '/test/file'})
assert response.json['data']['cmis']['contentStreamFileName'] == 'test2'
assert response.json['data']['rsj']['idInsertis'] == '21N284563'
@responses.activate
def test_get_file_404_error(app, setup, caplog):
with open('%s/tests/data/cmis/cmis1.out.xml' % os.getcwd(), 'rb') as fd:
cmis1_body = fd.read()
responses.add(responses.GET, 'http://example.com/cmisatom', body=cmis1_body, status=200)
responses.add(responses.GET, 'http://example.com/cmisatom/test/path', status=404)
response = app.get('/cmis/slug-cmis/getmetadata', params={'object_id': '/test/file'})
assert 'ERROR' not in caplog.text
assert response.json == {
'err': 1,
'err_class': 'passerelle.utils.jsonresponse.APIError',
'err_desc': 'CMIS server did not found path /test/file',
'data': None,
}

View File

@ -39,6 +39,56 @@ FAKE_FEATURE_INFO = '''<?xml version="1.0" encoding="UTF-8"?>
</cad_cadastre.cadparcelle_layer>
</msGMLOutput>'''
FAKE_FEATURE_INFO_FEATURE_COLLECTION = '''<?xml version="1.0" encoding="UTF-8"?>
<wfs:FeatureCollection xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:wfs="http://www.opengis.net/wfs"
xmlns:gml="http://www.opengis.net/gml"
xmlns:metropole-de-lyon="http://metropole-de-lyon"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="..."
>
<gml:boundedBy>
<gml:Envelope srsDimension="2" srsName="urn:x-ogc:def:crs:EPSG:3857">
<gml:lowerCorner>531238.20604672 5735107.61605308</gml:lowerCorner>
<gml:upperCorner>546464.26335844 5751147.23178471</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<gml:featureMembers>
<metropole-de-lyon:eco_ecologie.zfe gml:id="eco_ecologie.zfe.200046977-ZFE-001">
<gml:boundedBy>
<gml:Envelope srsName="urn:x-ogc:def:crs:EPSG:3857" srsDimension="2">
<gml:lowerCorner>531238.20604672 5735107.61605308</gml:lowerCorner>
<gml:upperCorner>546464.26335844 5751147.23178471</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<metropole-de-lyon:gid>200046977-ZFE-001</metropole-de-lyon:gid>
<metropole-de-lyon:date_debut>2020-01-01</metropole-de-lyon:date_debut>
<metropole-de-lyon:vp_critair>V5</metropole-de-lyon:vp_critair>
<metropole-de-lyon:vp_horaires>24/7</metropole-de-lyon:vp_horaires>
<metropole-de-lyon:vul_critair>V3</metropole-de-lyon:vul_critair>
<metropole-de-lyon:vul_horaires>24/7</metropole-de-lyon:vul_horaires>
<metropole-de-lyon:pl_critair>V3</metropole-de-lyon:pl_critair>
<metropole-de-lyon:pl_horaires>24/7</metropole-de-lyon:pl_horaires>
<metropole-de-lyon:autobus_autocars_critair>V5</metropole-de-lyon:autobus_autocars_critair>
<metropole-de-lyon:autobus_autocars_horaires>24/7</metropole-de-lyon:autobus_autocars_horaires>
<metropole-de-lyon:deux_rm_critair>V5</metropole-de-lyon:deux_rm_critair>
<metropole-de-lyon:deux_rm_horaires>24/7</metropole-de-lyon:deux_rm_horaires>
<metropole-de-lyon:url_arrete>https://agora.grandlyon.com/webdelib/files/unzip//seance_264250/23_d1647427974276.pdf</metropole-de-lyon:url_arrete>
<metropole-de-lyon:url_site_information>https://www.grandlyon.com/actions/zfe.html#c20726</metropole-de-lyon:url_site_information>
<metropole-de-lyon:the_geom>
<gml:Polygon srsName="urn:x-ogc:def:crs:EPSG:3857" srsDimension="2">
<gml:exterior>
<gml:LinearRing>
<gml:posList>...</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</metropole-de-lyon:the_geom>
<metropole-de-lyon:id>200046977-ZFE-001</metropole-de-lyon:id>
</metropole-de-lyon:eco_ecologie.zfe>
</gml:featureMembers>
</wfs:FeatureCollection>'''
FAKE_SERVICE_CAPABILITIES = '''<?xml version="1.0" encoding="UTF-8"?>
<wfs:WFS_Capabilities version="2.0.0"
xmlns:wfs="http://www.opengis.net/wfs/2.0"
@ -448,6 +498,22 @@ def test_feature_info(mocked_get, app, connector):
assert mocked_get.call_args[1]['params']['crs'] == 'EPSG:4326'
@mock.patch('passerelle.utils.Request.get')
def test_feature_info_feature_collection(mocked_get, app, connector):
endpoint = tests.utils.generic_endpoint_url('opengis', 'feature_info', slug=connector.slug)
assert endpoint == '/opengis/test/feature_info'
mocked_get.return_value = tests.utils.FakedResponse(
content=FAKE_FEATURE_INFO_FEATURE_COLLECTION, status_code=200
)
resp = app.get(endpoint, params={'lat': '45.796890', 'lon': '4.784140'})
assert (
mocked_get.call_args[1]['params']['bbox']
== '532556.896735,5747844.261214,532579.160633,5747876.194333'
)
assert mocked_get.call_args[1]['params']['crs'] == 'EPSG:3857'
assert resp.json['data']['autobus_autocars_critair'] == 'V5'
@mock.patch('passerelle.utils.Request.get')
@pytest.mark.parametrize(
'lat,lon',

View File

@ -1715,6 +1715,7 @@ def test_read_family(family_service, xml, con, app):
'isInvoicePdf': True,
},
'CAFInfo': None,
'fiscalInfo': None,
'civility_text': 'Monsieur',
'quality_text': 'PERE',
'subscribeActivityList': [],
@ -2191,6 +2192,7 @@ def test_read_rl2(family_service, con, app):
'organ': 'A10007752822',
'organ_text': 'LA COLLE SUR LOUP',
},
'fiscalInfo': {'spi': '00 01 123 456 789 C'},
'civility_text': 'Madame',
'quality_text': 'MERE',
'quotientList': [],
@ -2567,6 +2569,7 @@ def test_create_family(family_service, con, app):
'rl1/profession/codeCSP': 'ART',
'rl1/profession/situation': '01',
'rl1/CAFInfo/organ': 'A10007752822',
'rl1/fiscalInfo/spi': '00 01 123 456 789 C',
'emergencyPersonList/0/civility': 'MME',
'emergencyPersonList/0/firstname': 'Keny',
'emergencyPersonList/0/lastname': 'Arkana',
@ -3568,6 +3571,7 @@ def test_update_coordinate(family_service, con, app):
'profession/addressPro': {'num': None, 'street': None, 'zipcode': None, 'town': 'Orléans'},
'CAFInfo/number': '789',
'CAFInfo/organ': 'A10007752822',
'FiscalInfo/spi': '00 01 123 456 789 C',
}
resp = app.post_json(url + '?family_id=1312&rl_id=613878', params=params)