From cf268ea57fc9e0e7c75192bd5dca1cec77b1afba Mon Sep 17 00:00:00 2001 From: Etienne Trimaille Date: Mon, 3 Jun 2024 10:46:35 +0200 Subject: [PATCH] API key - check for Google or Bing layers without an API key --- README.md | 7 + lizmap_server/lizmap_accesscontrol.py | 44 +- lizmap_server/server_info_handler.py | 9 + lizmap_server/tos_definitions.py | 26 + test/data/external_providers_tos.qgs | 1282 +++++++++++++++++++++++++ test/run-tests.sh | 3 + test/test_lizmap_accesscontrol.py | 48 + test/test_server_info.py | 32 + 8 files changed, 1444 insertions(+), 7 deletions(-) create mode 100644 lizmap_server/tos_definitions.py create mode 100644 test/data/external_providers_tos.qgs diff --git a/README.md b/README.md index 50d2c878..0a3f0c65 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,13 @@ [![QGIS.org](https://img.shields.io/badge/QGIS.org-published-green)](https://plugins.qgis.org/plugins/lizmap_server/) [![Tests 🎳](https://github.com/3liz/qgis-lizmap-server-plugin/actions/workflows/ci.yml/badge.svg)](https://github.com/3liz/qgis-lizmap-server-plugin/actions/workflows/ci.yml) +## Environment variables + +* `QGIS_SERVER_LIZMAP_REVEAL_SETTINGS`, read + [docs.lizmap.com documentation](https://docs.lizmap.com/current/en/install/pre_requirements.html#qgis-server-plugins) +* `STRICT_BING_TOS_CHECK` and `STRICT_GOOGLE_TOS_CHECK`, if set to `TRUE`, an API key will be checked and required for + these layers + ## Download ### Stable diff --git a/lizmap_server/lizmap_accesscontrol.py b/lizmap_server/lizmap_accesscontrol.py index bd254b2d..a27eaaa3 100755 --- a/lizmap_server/lizmap_accesscontrol.py +++ b/lizmap_server/lizmap_accesscontrol.py @@ -22,6 +22,13 @@ ) from lizmap_server.logger import Logger, profiling from lizmap_server.tools import to_bool +from lizmap_server.tos_definitions import ( + BING_DOMAIN, + BING_KEY, + GOOGLE_DOMAIN, + GOOGLE_KEY, + strict_tos_check, +) class LizmapAccessControlFilter(QgsAccessControlFilter): @@ -30,6 +37,10 @@ def __init__(self, server_iface: QgsServerInterface) -> None: super().__init__(server_iface) self.iface = server_iface + self._strict_google = strict_tos_check(GOOGLE_KEY) + self._strict_bing = strict_tos_check(BING_KEY) + + Logger.info(f"LayerAccessControl : Google {self._strict_google}, Bing {self._strict_bing}") # def layerFilterExpression(self, layer: QgsVectorLayer) -> str: # """ Return an additional expression filter """ @@ -77,8 +88,7 @@ def layerPermissions(self, layer: QgsMapLayer) -> QgsAccessControlFilter.LayerPe # Discard invalid layers for other services than WMS if not layer.isValid() and request_handler.parameter('service').upper() != 'WMS': Logger.info(f"layerPermission: Layer {layer_name} is invalid in {project.fileName()}!") - rights.canRead = False - rights.canInsert = rights.canUpdate = rights.canDelete = False + rights.canRead = rights.canInsert = rights.canUpdate = rights.canDelete = False return rights # Get Lizmap user groups provided by the request @@ -94,20 +104,40 @@ def layerPermissions(self, layer: QgsMapLayer) -> QgsAccessControlFilter.LayerPe # Try to override filter expression cache is_wfs = request_handler.parameter('service').upper() == 'WFS' - if is_wfs and request_handler.parameter('request') == 'getfeature': + if is_wfs and request_handler.parameter('request').upper() == 'GETFEATURE': self.iface.accessControls().resolveFilterFeatures([layer]) - # If groups is empty, no Lizmap user groups provided by the request - # The default layer rights is applied - if len(groups) == 0: - return rights + datasource = layer.source().lower() + is_google = GOOGLE_DOMAIN in datasource + is_bing = BING_DOMAIN in datasource + if is_google or is_bing: + Logger.info(f"Layer '{layer_name}' has been detected as an external layer which might need a API key.") # Get Lizmap config cfg = get_lizmap_config(self.iface.configFilePath()) if not cfg: + if is_google: + rights.canRead = rights.canInsert = rights.canUpdate = rights.canDelete = not self._strict_google + elif is_bing: + rights.canRead = rights.canInsert = rights.canUpdate = rights.canDelete = not self._strict_bing # Default layer rights applied return rights + # If groups is empty, no Lizmap user groups provided by the request + # The default layer rights is applied + if len(groups) == 0 and not (is_google or is_bing): + return rights + + api_key = cfg['options'].get('googleKey', '') + if is_google and not api_key and strict_tos_check(GOOGLE_KEY): + rights.canRead = rights.canInsert = rights.canUpdate = rights.canDelete = False + return rights + + api_key = cfg['options'].get('bingKey', '') + if is_bing and not api_key and strict_tos_check(BING_KEY): + rights.canRead = rights.canInsert = rights.canUpdate = rights.canDelete = False + return rights + # Get layers config cfg_layers = get_lizmap_layers_config(cfg) if not cfg_layers: diff --git a/lizmap_server/server_info_handler.py b/lizmap_server/server_info_handler.py index 6865e179..0a3b6129 100755 --- a/lizmap_server/server_info_handler.py +++ b/lizmap_server/server_info_handler.py @@ -19,6 +19,11 @@ from lizmap_server.exception import ServiceError from lizmap_server.tools import check_environment_variable, to_bool +from lizmap_server.tos_definitions import ( + BING_KEY, + GOOGLE_KEY, + strict_tos_check, +) try: # Py-QGIS-Server @@ -208,6 +213,10 @@ def handleRequest(self, context): 'commit_id': py_qgis_server_metadata.commit_id, 'stable': py_qgis_server_metadata.is_stable, }, + 'external_providers_tos_checks': { + GOOGLE_KEY.lower(): strict_tos_check(GOOGLE_KEY), + BING_KEY.lower(): strict_tos_check(BING_KEY), + }, # 'support_custom_headers': self.support_custom_headers(), 'services': services_available, 'plugins': plugins, diff --git a/lizmap_server/tos_definitions.py b/lizmap_server/tos_definitions.py new file mode 100644 index 00000000..f4dbaa39 --- /dev/null +++ b/lizmap_server/tos_definitions.py @@ -0,0 +1,26 @@ +__copyright__ = 'Copyright 2024, 3Liz' +__license__ = 'GPL version 3' +__email__ = 'info@3liz.org' + +import os + +from lizmap_server.tools import to_bool + +GOOGLE_KEY = 'GOOGLE' +BING_KEY = 'BING' + +GOOGLE_DOMAIN = 'google.com' +BING_DOMAIN = 'virtualearth.net' + + +def strict_tos_check_key(provider: str) -> str: + """ Check the environment variable for this provider. """ + return f'STRICT_{provider}_TOS_CHECK' + + +def strict_tos_check(provider: str) -> bool: + """ Check the environment variable for this provider. """ + env = os.getenv(strict_tos_check_key(provider)) + if env is None: + env = True + return to_bool(env) diff --git a/test/data/external_providers_tos.qgs b/test/data/external_providers_tos.qgs new file mode 100644 index 00000000..1390462e --- /dev/null +++ b/test/data/external_providers_tos.qgs @@ -0,0 +1,1282 @@ + + + + + + + + PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],MEMBER["World Geodetic System 1984 (G2139)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]] + +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + EPSG:7030 + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OSM_Standard_afe62a8c_ef34_4e5d_ae47_8074138cc9e4 + Google_Satellite_e9b3399e_2756_4860_9e3b_e218940941dd + Bing_Map_0a3243c2_d29e_43a6_8776_ee808cbd238e + Bing_Satellite_c502bdb3_c667_4627_a906_7d81f48d5596 + + + + + + + + + meters + + -43784.73350132367340848 + 4946730.56542463228106499 + 580300.16175846592523158 + 6350709.79752139747142792 + + 0 + + + PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],MEMBER["World Geodetic System 1984 (G2139)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]] + +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + EPSG:7030 + false + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Annotations_a97d0d2a_19e8_4a84_b6ca_a79ffb0853c5 + + + + + + + + PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],MEMBER["World Geodetic System 1984 (G2139)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]] + +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + EPSG:7030 + false + + + + + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + + + + 1 + 1 + 1 + 0 + + + + + 1 + 0 + + + + + + -20037508.34278924390673637 + -20037508.34278924763202667 + 20037508.34278924390673637 + 20037508.34278924763202667 + + + -180 + -85.05112877980660357 + 179.99999999999997158 + 85.05112877980660357 + + Bing_Map_0a3243c2_d29e_43a6_8776_ee808cbd238e + type=xyz&zmin=1&zmax=19&url=https://ecn.dynamic.t0.tiles.virtualearth.net/comp/CompositionHandler/{q}?mkt%3Den-us%26it%3DG,VE,BX,L,LA%26shading%3Dhill + bing-map + + + + bing-map + + + PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],MEMBER["World Geodetic System 1984 (G2139)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]] + +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + EPSG:7030 + false + + + + + + + dataset + + + + + + + + + + + 0 + 0 + + + + + false + + + + + wms + + + + + + + + + 1 + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + None + WholeRaster + Estimated + 0.02 + 0.98 + 2 + + + + + + resamplingFilter + + 0 + + + + -20037508.34278924390673637 + -20037508.34278924763202667 + 20037508.34278924390673637 + 20037508.34278924763202667 + + + -180 + -85.05112877980660357 + 179.99999999999997158 + 85.05112877980660357 + + Bing_Satellite_c502bdb3_c667_4627_a906_7d81f48d5596 + type=xyz&zmin=1&zmax=18&url=https://ecn.t3.tiles.virtualearth.net/tiles/a{q}.jpeg?g%3D0%26dir%3Ddir_n' + bing-satellite + + + + bing-satellite + + + PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],MEMBER["World Geodetic System 1984 (G2139)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]] + +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + EPSG:7030 + false + + + + + + + dataset + + + + + + + + + + + 0 + 0 + + + + + false + + + + + wms + + + + + + + + + 1 + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + None + WholeRaster + Estimated + 0.02 + 0.98 + 2 + + + + + + resamplingFilter + + 0 + + + + -20037508.34278924390673637 + -20037508.34278924763202667 + 20037508.34278924390673637 + 20037508.34278924763202667 + + + -180 + -85.05112877980660357 + 179.99999999999997158 + 85.05112877980660357 + + Google_Satellite_e9b3399e_2756_4860_9e3b_e218940941dd + type=xyz&zmin=0&zmax=20&url=https://mt1.google.com/vt/lyrs%3Ds%26x%3D{x}%26y%3D{y}%26z%3D{z} + google-satellite + + + + Map data ©2015 Google + google-satellite + + + PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],MEMBER["World Geodetic System 1984 (G2139)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]] + +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + EPSG:7030 + false + + + + + + + dataset + + + + + + + + + + + 0 + 0 + + + + + false + + + + + wms + + + + + + + + + 1 + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + None + WholeRaster + Estimated + 0.02 + 0.98 + 2 + + + + + + resamplingFilter + + 0 + + + + -20037508.34278924390673637 + -20037508.34278924763202667 + 20037508.34278924390673637 + 20037508.34278924763202667 + + + -180 + -85.05112877980660357 + 179.99999999999997158 + 85.05112877980660357 + + OSM_Standard_afe62a8c_ef34_4e5d_ae47_8074138cc9e4 + type=xyz&zmin=0&zmax=19&url=http://tile.openstreetmap.org/{z}/{x}/{y}.png + osm + + + + © OpenStreetMap contributors, CC-BY-SA + osm + + + PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],MEMBER["World Geodetic System 1984 (G2139)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]] + +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + EPSG:7030 + false + + + + OpenStreetMap tiles + + + dataset + OpenStreetMap tiles + OpenStreetMap is built by a community of mappers that contribute and maintain data about roads, trails, cafés, railway stations, and much more, all over the world. + + + + + + Base map and data from OpenStreetMap and OpenStreetMap Foundation (CC-BY-SA). © https://www.openstreetmap.org and contributors. + Open Data Commons Open Database License (ODbL) + Creative Commons Attribution-ShareAlike (CC-BY-SA) + + + + PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],MEMBER["World Geodetic System 1984 (G2139)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]] + +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + EPSG:7030 + false + + + + + + + wms + + + + + + + + + 1 + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + None + WholeRaster + Estimated + 0.02 + 0.98 + 2 + + + + + + resamplingFilter + + 0 + + + + + + + + + + + 0 + + + 255 + 255 + 255 + 255 + 0 + 255 + 255 + + + false + + + EPSG:7030 + + + m2 + meters + + + 5 + 2.5 + false + false + false + 1 + 0 + false + false + true + 0 + 255,0,0,255 + + + false + + + true + 2 + + + 1 + + + + lizmap_repository + lizmap_user + lizmap_user_groups + + + debug + + + + + + -425713.3289431425 + 4946730.565424632 + 962228.7572002847 + 6350709.7975213975 + + 1 + external_providers_tos + True + external_providers_tos + + + + + + + + + + + + + + + + + + + + + Etienne Trimaille + 2024-05-31T14:54:12 + + + + + + + + + + + PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],MEMBER["World Geodetic System 1984 (G2139)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]] + +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + EPSG:7030 + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],MEMBER["World Geodetic System 1984 (G2139)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],CS[ellipsoidal,2],AXIS["geodetic latitude (Lat)",north,ORDER[1],ANGLEUNIT["degree",0.0174532925199433]],AXIS["geodetic longitude (Lon)",east,ORDER[2],ANGLEUNIT["degree",0.0174532925199433]],USAGE[SCOPE["Horizontal component of 3D system."],AREA["World."],BBOX[-90,-180,90,180]],ID["EPSG",4326]] + +proj=longlat +datum=WGS84 +no_defs + 3452 + 4326 + EPSG:4326 + WGS 84 + longlat + EPSG:7030 + true + + + + + + + \ No newline at end of file diff --git a/test/run-tests.sh b/test/run-tests.sh index a8d45330..45399127 100755 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -25,6 +25,9 @@ export QT_LOGGING_RULES="*.debug=false;*.warning=false" export QGIS_DISABLE_MESSAGE_HOOKS=1 export QGIS_NO_OVERRIDE_IMPORT=1 export CI=True +#export STRICT_BING_TOS_CHECK=True +#export STRICT_GOOGLE_TOS_CHECK=True +#export QGIS_SERVER_CAPABILITIES_CACHE_SIZE=0 pytest -vv --qgis-plugins=/src $@ exit $? diff --git a/test/test_lizmap_accesscontrol.py b/test/test_lizmap_accesscontrol.py index c55aac93..b58e0842 100644 --- a/test/test_lizmap_accesscontrol.py +++ b/test/test_lizmap_accesscontrol.py @@ -3,16 +3,24 @@ __email__ = 'info@3liz.org' import logging +import os from pathlib import Path from test.utils import _build_query_string, _check_request from qgis.core import QgsVectorLayer +from lizmap_server.tos_definitions import ( + BING_KEY, + GOOGLE_KEY, + strict_tos_check_key, +) + LOGGER = logging.getLogger('server') PROJECT_FILE = "france_parts.qgs" PROJECT_LIZ_FILE = "france_parts_liz.qgs" PROJECT_FILE_GROUP_V = "france_parts_liz_grp_v.qgs" +PROJECT_TOS_PROVIDERS = "external_providers_tos.qgs" def test_no_lizmap_config(client): @@ -542,3 +550,43 @@ def test_layer_filter_login(client): layers = rv.xpath('//gml:featureMember') assert layers is not None assert len(layers) == 0 + + +def _make_get_capabilities_tos_layers(client, strict: bool): + """ Make the GetCapabilities request for TOS layers. """ + os.environ[strict_tos_check_key(GOOGLE_KEY)] = str(strict) + os.environ[strict_tos_check_key(BING_KEY)] = str(strict) + qs = { + "SERVICE": "WMS", + "REQUEST": "GetCapabilities", + "MAP": PROJECT_TOS_PROVIDERS, + } + rv = client.get(_build_query_string(qs), PROJECT_TOS_PROVIDERS) + _check_request(rv, 'text/xml') + del os.environ[strict_tos_check_key(GOOGLE_KEY)] + del os.environ[strict_tos_check_key(BING_KEY)] + return rv + + +def test_tos_strict_layers_false(client): + """ Test TOS layers restricted. """ + rv = _make_get_capabilities_tos_layers(client, False) + content = rv.content.decode('utf-8') + layers = rv.xpath('//wms:Layer') + assert len(layers) == 2 + assert "osm" in content + assert "google-satellite" not in content + assert "bing-map" not in content + assert "bing-satellite" not in content + + +def tet_tos_strict_layers_true(client): + """ Test TOS layers not restricted. """ + rv = _make_get_capabilities_tos_layers(client, True) + content = rv.content.decode('utf-8') + layers = rv.xpath('//wms:Layer') + assert len(layers) == 5 + assert "osm" in content + assert "google-satellite" in content + assert "bing-map" in content + assert "bing-satellite" in content diff --git a/test/test_server_info.py b/test/test_server_info.py index 9b0edf30..72bfc414 100644 --- a/test/test_server_info.py +++ b/test/test_server_info.py @@ -3,6 +3,12 @@ from qgis.core import Qgis +from lizmap_server.tos_definitions import ( + BING_KEY, + GOOGLE_KEY, + strict_tos_check_key, +) + __copyright__ = 'Copyright 2021, 3Liz' __license__ = 'GPL version 3' __email__ = 'info@3liz.org' @@ -16,6 +22,12 @@ def test_lizmap_server_info(client): # The environment variable is already there assert os.getenv(KEY) == 'TRUE' + # Test default values + if strict_tos_check_key(GOOGLE_KEY) in os.environ: + del os.environ[strict_tos_check_key(GOOGLE_KEY)] + if strict_tos_check_key(BING_KEY) in os.environ: + del os.environ[strict_tos_check_key(BING_KEY)] + # The query must work rv = client.get(QUERY) assert rv.status_code == 200 @@ -25,6 +37,12 @@ def test_lizmap_server_info(client): json_content = json.loads(rv.content.decode('utf-8')) assert 'qgis_server' in json_content + expected = { + 'google': True, + 'bing': True, + } + assert json_content['qgis_server']['external_providers_tos_checks'] == expected + if 33000 <= Qgis.QGIS_VERSION_INT < 33200: assert json_content['qgis_server']['metadata']['name'] == "'s-Hertogenbosch" elif 32800 <= Qgis.QGIS_VERSION_INT < 32800: @@ -40,6 +58,20 @@ def test_lizmap_server_info(client): assert len(json_content['qgis_server']['fonts']) >= 1 +def test_tos_checks(client): + """ Test when TOS for external providers are checked. """ + os.environ[strict_tos_check_key(GOOGLE_KEY)] = str(False) + os.environ[strict_tos_check_key(GOOGLE_KEY)] = str(True) + rv = client.get(QUERY) + json_content = json.loads(rv.content.decode('utf-8')) + expected = { + 'google': False, + 'bing': True, + } + assert json_content['qgis_server']['external_providers_tos_checks'] == expected + del os.environ[strict_tos_check_key(GOOGLE_KEY)] + + def test_lizmap_server_info_env_check(client): """ Check the environment variable check. """ # Remove the security environment variable, the query mustn't work