From 627be58a7ef03fc43a16bb22f57b883a085dcd28 Mon Sep 17 00:00:00 2001 From: Tom Kralidis Date: Mon, 9 Dec 2024 04:52:33 -0500 Subject: [PATCH] safeguard contact info (#1835) (#1862) --- pygeoapi/openapi.py | 91 ++++++++++++++++++++-------- pygeoapi/templates/landing_page.html | 11 ++-- tests/pygeoapi-test-openapi.yml | 21 +++++++ tests/test_openapi.py | 37 ++++++++++- 4 files changed, 130 insertions(+), 30 deletions(-) diff --git a/pygeoapi/openapi.py b/pygeoapi/openapi.py index fe390b742..1f10f9751 100644 --- a/pygeoapi/openapi.py +++ b/pygeoapi/openapi.py @@ -144,38 +144,81 @@ def gen_contact(cfg: dict) -> dict: :returns: `dict` of OpenAPI contact object """ + has_addresses = False + has_phones = False + contact = { - 'name': cfg['metadata']['provider']['name'], - 'url': cfg['metadata']['provider']['url'], - 'email': cfg['metadata']['contact']['email'] + 'name': cfg['metadata']['provider']['name'] } + for key in ['url', 'email']: + if key in cfg['metadata']['provider']: + contact[key] = cfg['metadata']['provider'][key] + contact['x-ogc-serviceContact'] = { 'name': cfg['metadata']['contact']['name'], - 'position': cfg['metadata']['contact']['position'], - 'addresses': [{ - 'deliveryPoint': [cfg['metadata']['contact']['address']], - 'city': cfg['metadata']['contact']['city'], - 'administrativeArea': cfg['metadata']['contact']['stateorprovince'], # noqa - 'postalCode': cfg['metadata']['contact']['postalcode'], - 'country': cfg['metadata']['contact']['country'] - }], - 'phones': [{ - 'type': 'main', 'value': cfg['metadata']['contact']['phone'] - }, { - 'type': 'fax', 'value': cfg['metadata']['contact']['fax'] - }], - 'emails': [{ + 'addresses': [] + } + + if 'position' in cfg['metadata']['contact']: + contact['x-ogc-serviceContact']['position'] = cfg['metadata']['contact']['position'] # noqa + + if any(address in ['address', 'city', 'stateorprovince', 'postalcode', 'country'] for address in cfg['metadata']['contact']): # noqa + has_addresses = True + + if has_addresses: + address = {} + if 'address' in cfg['metadata']['contact']: + address['deliveryPoint'] = [cfg['metadata']['contact']['address']] + + if 'city' in cfg['metadata']['contact']: + address['city'] = cfg['metadata']['contact']['city'] + + if 'stateorprovince' in cfg['metadata']['contact']: + address['administrativeArea'] = cfg['metadata']['contact']['stateorprovince'] # noqa + + if 'postalCode' in cfg['metadata']['contact']: + address['administrativeArea'] = cfg['metadata']['contact']['postalCode'] # noqa + + if 'country' in cfg['metadata']['contact']: + address['administrativeArea'] = cfg['metadata']['contact']['country'] # noqa + + contact['x-ogc-serviceContact']['addresses'].append(address) + + if any(phone in ['phone', 'fax'] for phone in cfg['metadata']['contact']): + has_phones = True + contact['x-ogc-serviceContact']['phones'] = [] + + if has_phones: + if 'phone' in cfg['metadata']['contact']: + contact['x-ogc-serviceContact']['phones'].append({ + 'type': 'main', 'value': cfg['metadata']['contact']['phone'] + }) + + if 'fax' in cfg['metadata']['contact']: + contact['x-ogc-serviceContact']['phones'].append({ + 'type': 'fax', 'value': cfg['metadata']['contact']['fax'] + }) + + if 'email' in cfg['metadata']['contact']: + contact['x-ogc-serviceContact']['emails'] = [{ 'value': cfg['metadata']['contact']['email'] - }], - 'contactInstructions': cfg['metadata']['contact']['instructions'], - 'links': [{ + }] + + if 'url' in cfg['metadata']['contact']: + contact['x-ogc-serviceContact']['links'] = [{ 'type': 'text/html', 'href': cfg['metadata']['contact']['url'] - }], - 'hoursOfService': cfg['metadata']['contact']['hours'], - 'roles': [cfg['metadata']['contact']['role']] - } + }] + + if 'instructions' in cfg['metadata']['contact']: + contact['x-ogc-serviceContact']['contactInstructions'] = cfg['metadata']['contact']['instructions'] # noqa + + if 'hours' in cfg['metadata']['contact']: + contact['x-ogc-serviceContact']['hoursOfService'] = cfg['metadata']['contact']['hours'] # noqa + + if 'role' in cfg['metadata']['contact']: + contact['x-ogc-serviceContact']['hoursOfService'] = cfg['metadata']['contact']['role'] # noqa return contact diff --git a/pygeoapi/templates/landing_page.html b/pygeoapi/templates/landing_page.html index e135ddb86..147b2a9c6 100644 --- a/pygeoapi/templates/landing_page.html +++ b/pygeoapi/templates/landing_page.html @@ -121,11 +121,12 @@

{% trans %}Tile Matrix Sets{% endtrans %}

{% trans %}Address{% endtrans %}
- {{ config['metadata']['contact']['address'] }}
- {{ config['metadata']['contact']['city'] }}, - {{ config['metadata']['contact']['stateorprovince'] }}
- {{ config['metadata']['contact']['postalcode'] }}
- {{ config['metadata']['contact']['country'] }} + {{ config['metadata']['contact']['name'] }}
+ {% for key in ['address', 'city', 'stateorprovince', 'postalcode', 'country'] %} + {% if key in config['metadata']['contact'] %} + {{ config['metadata']['contact'][key] }}
+ {% endif %} + {% endfor %}
{% trans %}Email{% endtrans %}
diff --git a/tests/pygeoapi-test-openapi.yml b/tests/pygeoapi-test-openapi.yml index 809d18f50..5f370e92b 100644 --- a/tests/pygeoapi-test-openapi.yml +++ b/tests/pygeoapi-test-openapi.yml @@ -83,6 +83,27 @@ info: email: you@example.org name: Organization Name url: https://pygeoapi.io + x-ogc-serviceContact: + addresses: + - administrativeArea: Country + city: + - City + deliveryPoint: + - Mailing Address + contactInstructions: During hours of service. Off on weekends. + emails: + - value: you@example.org + hoursOfService: pointOfContact + links: + - href: Contact URL + type: text/html + name: Lastname, Firstname + phones: + - type: main + value: +xx-xxx-xxx-xxxx + - type: fax + value: +xx-xxx-xxx-xxxx + position: Position Title description: pygeoapi provides an API to geospatial data license: name: CC-BY 4.0 license diff --git a/tests/test_openapi.py b/tests/test_openapi.py index 9f89f16d1..5d99aefe9 100644 --- a/tests/test_openapi.py +++ b/tests/test_openapi.py @@ -74,7 +74,7 @@ def test_str2bool(): osl = get_ogc_schemas_location(default) -def test_get_oas(config, openapi): +def test_get_oas(config): openapi_doc = get_oas(config) assert isinstance(openapi_doc, dict) @@ -84,6 +84,41 @@ def test_get_oas(config, openapi): assert is_valid +def test_get_oas_ogc_service_contact(config): + + ogc_service_contact = { + 'addresses': [{ + 'administrativeArea': 'Country', + 'city': 'City', + 'deliveryPoint': ['Mailing Address'] + }], + 'contactInstructions': 'During hours of service. Off on weekends.', + 'emails': [{ + 'value': 'you@example.org' + }], + 'hoursOfService': 'pointOfContact', + 'links': [{ + 'href': 'Contact URL', + 'type': 'text/html' + }], + 'name': 'Lastname, Firstname', + 'phones': [{ + 'type': 'main', + 'value': '+xx-xxx-xxx-xxxx' + }, { + 'type': 'fax', + 'value': '+xx-xxx-xxx-xxxx' + }], + 'position': 'Position Title' + } + + openapi_doc = get_oas(config) + + assert isinstance(openapi_doc, dict) + + assert openapi_doc['info']['contact']['x-ogc-serviceContact'] == ogc_service_contact # noqa + + def test_validate_openapi_document(openapi): is_valid = validate_openapi_document(openapi) assert is_valid