c2cgeoportal-geoportal 2.6.0__py2.py3-none-any.whl → 2.7.1.86__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- c2cgeoportal_geoportal/__init__.py +224 -84
- c2cgeoportal_geoportal/lib/__init__.py +64 -42
- c2cgeoportal_geoportal/lib/authentication.py +50 -22
- c2cgeoportal_geoportal/lib/bashcolor.py +17 -13
- c2cgeoportal_geoportal/lib/cacheversion.py +16 -8
- c2cgeoportal_geoportal/lib/caching.py +61 -191
- c2cgeoportal_geoportal/lib/check_collector.py +17 -10
- c2cgeoportal_geoportal/lib/checker.py +61 -63
- c2cgeoportal_geoportal/lib/common_headers.py +170 -0
- c2cgeoportal_geoportal/lib/dbreflection.py +54 -39
- c2cgeoportal_geoportal/lib/filter_capabilities.py +119 -87
- c2cgeoportal_geoportal/lib/fulltextsearch.py +6 -5
- c2cgeoportal_geoportal/lib/functionality.py +20 -17
- c2cgeoportal_geoportal/lib/headers.py +14 -5
- c2cgeoportal_geoportal/lib/i18n.py +4 -4
- c2cgeoportal_geoportal/lib/layers.py +30 -11
- c2cgeoportal_geoportal/lib/lingua_extractor.py +361 -237
- c2cgeoportal_geoportal/lib/loader.py +10 -15
- c2cgeoportal_geoportal/lib/metrics.py +28 -17
- c2cgeoportal_geoportal/lib/oauth2.py +214 -145
- c2cgeoportal_geoportal/lib/wmstparsing.py +115 -90
- c2cgeoportal_geoportal/lib/xsd.py +26 -16
- c2cgeoportal_geoportal/resources.py +15 -9
- c2cgeoportal_geoportal/scaffolds/advance_create/ci/config.yaml +26 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/cookiecutter.json +18 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/.dockerignore +6 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/.eslintrc.yaml +19 -0
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/+dot+prospector.yaml → advance_create/{{cookiecutter.project}}/geoportal/.prospector.yaml} +8 -2
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/Dockerfile_tmpl → advance_create/{{cookiecutter.project}}/geoportal/Dockerfile} +18 -9
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/alembic.yaml_tmpl → advance_create/{{cookiecutter.project}}/geoportal/alembic.yaml} +1 -1
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/development.ini_tmpl → advance_create/{{cookiecutter.project}}/geoportal/development.ini} +34 -15
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/gunicorn.conf.py +104 -0
- c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/lingua-client.cfg +1 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/production.ini +38 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/requirements.txt +2 -0
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/setup.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/setup.py} +6 -7
- c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/tools/extract-messages.js +8 -6
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/tsconfig.json +8 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.api.js +75 -0
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/webpack.apps.js_tmpl → advance_create/{{cookiecutter.project}}/geoportal/webpack.apps.js} +31 -28
- c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/webpack.commons.js +3 -7
- c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/webpack.config.js +1 -1
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal/__init__.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/__init__.py} +11 -22
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/authentication.py +10 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/dev.py +14 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/models.py +8 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/multi_organization.py +7 -0
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/resources.py +4 -3
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal/static-ngeo/api/index.js_tmpl → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static-ngeo/api/index.js} +1 -2
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal/static-ngeo/js/+package+module.js_tmpl → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static-ngeo/js/{{cookiecutter.package}}module.js} +4 -4
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal/subscribers.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/subscribers.py} +1 -3
- c2cgeoportal_geoportal/scaffolds/advance_update/cookiecutter.json +18 -0
- c2cgeoportal_geoportal/scaffolds/{update/geoportal/CONST_Makefile_tmpl → advance_update/{{cookiecutter.project}}/geoportal/CONST_Makefile} +3 -7
- c2cgeoportal_geoportal/scaffolds/create/cookiecutter.json +18 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.dockerignore +14 -0
- c2cgeoportal_geoportal/scaffolds/create/{+dot+editorconfig → {{cookiecutter.project}}/.editorconfig} +2 -5
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/main.yaml +43 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/rebuild.yaml +46 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/update_l10n.yaml +65 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.gitignore +16 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.prettierignore +1 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.prettierrc.yaml +2 -0
- c2cgeoportal_geoportal/scaffolds/create/{Dockerfile_tmpl → {{cookiecutter.project}}/Dockerfile} +20 -11
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Makefile +14 -0
- c2cgeoportal_geoportal/scaffolds/create/{README.rst_tmpl → {{cookiecutter.project}}/README.rst} +4 -4
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/build +158 -0
- c2cgeoportal_geoportal/scaffolds/create/{ci/config.yaml_tmpl → {{cookiecutter.project}}/ci/config.yaml} +7 -5
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/requirements.txt +1 -0
- c2cgeoportal_geoportal/scaffolds/create/{docker-compose-lib.yaml → {{cookiecutter.project}}/docker-compose-lib.yaml} +133 -17
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.override.sample.yaml +66 -0
- c2cgeoportal_geoportal/scaffolds/create/{docker-compose.yaml → {{cookiecutter.project}}/docker-compose.yaml} +17 -12
- c2cgeoportal_geoportal/scaffolds/create/{env.default_tmpl → {{cookiecutter.project}}/env.default} +29 -14
- c2cgeoportal_geoportal/scaffolds/create/{env.project_tmpl → {{cookiecutter.project}}/env.project} +16 -4
- c2cgeoportal_geoportal/scaffolds/create/{geoportal/vars.yaml_tmpl → {{cookiecutter.project}}/geoportal/vars.yaml} +93 -27
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/mobile.css +0 -0
- c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/data/Readme.txt +1 -1
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/demo.map.tmpl +224 -0
- c2cgeoportal_geoportal/scaffolds/create/{mapserver/mapserver.map.tmpl_tmpl → {{cookiecutter.project}}/mapserver/mapserver.map.tmpl} +7 -15
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A3_Landscape.jrxml +8 -8
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A3_Portrait.jrxml +8 -8
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A4_Landscape.jrxml +8 -8
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A4_Portrait.jrxml +8 -8
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/config.yaml.tmpl +5 -4
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/localisation.properties +4 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/localisation_fr.properties +4 -0
- c2cgeoportal_geoportal/scaffolds/create/{project.yaml_tmpl → {{cookiecutter.project}}/project.yaml} +6 -6
- c2cgeoportal_geoportal/scaffolds/create/{qgisserver/pg_service.conf.tmpl_tmpl → {{cookiecutter.project}}/qgisserver/pg_service.conf.tmpl} +2 -2
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-backup +107 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-restore +111 -0
- c2cgeoportal_geoportal/scaffolds/create/{setup.cfg_tmpl → {{cookiecutter.project}}/setup.cfg} +1 -1
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/spell-ignore-words.txt +3 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tilegeneration/config.yaml.tmpl +195 -0
- c2cgeoportal_geoportal/scaffolds/update/cookiecutter.json +18 -0
- c2cgeoportal_geoportal/scaffolds/update/{+dot+upgrade.yaml_tmpl → {{cookiecutter.project}}/.upgrade.yaml} +49 -39
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_CHANGELOG.txt +1153 -0
- c2cgeoportal_geoportal/scaffolds/update/{geoportal → {{cookiecutter.project}}/geoportal}/CONST_config-schema.yaml +47 -2
- c2cgeoportal_geoportal/scaffolds/update/{geoportal/CONST_vars.yaml_tmpl → {{cookiecutter.project}}/geoportal/CONST_vars.yaml} +350 -15
- c2cgeoportal_geoportal/scripts/__init__.py +15 -31
- c2cgeoportal_geoportal/scripts/c2cupgrade.py +271 -232
- c2cgeoportal_geoportal/scripts/create_demo_theme.py +3 -6
- c2cgeoportal_geoportal/scripts/manage_users.py +34 -39
- c2cgeoportal_geoportal/scripts/pcreate.py +312 -0
- c2cgeoportal_geoportal/scripts/theme2fts.py +72 -23
- c2cgeoportal_geoportal/scripts/urllogin.py +17 -9
- c2cgeoportal_geoportal/templates/login.html +88 -84
- c2cgeoportal_geoportal/templates/notlogin.html +59 -59
- c2cgeoportal_geoportal/templates/testi18n.html +6 -8
- c2cgeoportal_geoportal/views/__init__.py +23 -4
- c2cgeoportal_geoportal/views/dev.py +9 -7
- c2cgeoportal_geoportal/views/dynamic.py +54 -18
- c2cgeoportal_geoportal/views/entry.py +93 -24
- c2cgeoportal_geoportal/views/fulltextsearch.py +28 -22
- c2cgeoportal_geoportal/views/geometry_processing.py +15 -7
- c2cgeoportal_geoportal/views/i18n.py +91 -9
- c2cgeoportal_geoportal/views/layers.py +160 -126
- c2cgeoportal_geoportal/views/login.py +106 -93
- c2cgeoportal_geoportal/views/mapserverproxy.py +45 -28
- c2cgeoportal_geoportal/views/memory.py +12 -12
- c2cgeoportal_geoportal/views/ogcproxy.py +48 -30
- c2cgeoportal_geoportal/views/pdfreport.py +26 -22
- c2cgeoportal_geoportal/views/printproxy.py +56 -50
- c2cgeoportal_geoportal/views/profile.py +24 -23
- c2cgeoportal_geoportal/views/proxy.py +84 -67
- c2cgeoportal_geoportal/views/raster.py +35 -24
- c2cgeoportal_geoportal/views/resourceproxy.py +13 -11
- c2cgeoportal_geoportal/views/shortener.py +27 -24
- c2cgeoportal_geoportal/views/theme.py +427 -321
- c2cgeoportal_geoportal/views/tinyowsproxy.py +46 -39
- c2cgeoportal_geoportal/views/vector_tiles.py +80 -0
- {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.86.dist-info}/METADATA +24 -20
- c2cgeoportal_geoportal-2.7.1.86.dist-info/RECORD +185 -0
- {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.86.dist-info}/WHEEL +1 -1
- {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.86.dist-info}/entry_points.txt +3 -1
- tests/__init__.py +7 -3
- tests/test_cachebuster.py +0 -2
- tests/test_caching.py +17 -25
- tests/test_checker.py +0 -2
- tests/test_decimaljson.py +4 -4
- tests/test_headerstween.py +0 -2
- tests/test_i18n.py +1 -1
- tests/test_init.py +4 -7
- tests/test_locale_negociator.py +0 -2
- tests/test_mapserverproxy_route_predicate.py +0 -2
- tests/test_raster.py +0 -2
- tests/test_wmstparsing.py +0 -2
- c2cgeoportal_geoportal/scaffolds/__init__.py +0 -227
- c2cgeoportal_geoportal/scaffolds/create/+dot+dockerignore_tmpl +0 -12
- c2cgeoportal_geoportal/scaffolds/create/+dot+github/workflows/main.yaml_tmpl +0 -89
- c2cgeoportal_geoportal/scaffolds/create/+dot+github/workflows/rebuild.yaml_tmpl +0 -78
- c2cgeoportal_geoportal/scaffolds/create/+dot+gitignore_tmpl +0 -16
- c2cgeoportal_geoportal/scaffolds/create/Makefile +0 -3
- c2cgeoportal_geoportal/scaffolds/create/build_tmpl +0 -167
- c2cgeoportal_geoportal/scaffolds/create/ci/requirements.txt +0 -1
- c2cgeoportal_geoportal/scaffolds/create/ci/trigger +0 -68
- c2cgeoportal_geoportal/scaffolds/create/docker-compose.override.sample.yaml +0 -54
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+dot+dockerignore_tmpl +0 -6
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+dot+eslintrc_tmpl +0 -15
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/models.py_tmpl +0 -10
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/static/robot.txt +0 -3
- c2cgeoportal_geoportal/scaffolds/create/geoportal/production.ini_tmpl +0 -106
- c2cgeoportal_geoportal/scaffolds/create/geoportal/requirements.txt +0 -2
- c2cgeoportal_geoportal/scaffolds/create/geoportal/tsconfig.json_tmpl +0 -9
- c2cgeoportal_geoportal/scaffolds/create/geoportal/webpack.api.js_tmpl +0 -72
- c2cgeoportal_geoportal/scaffolds/create/mapserver/demo.map.tmpl_tmpl +0 -262
- c2cgeoportal_geoportal/scaffolds/create/mapserver/tinyows.xml +0 -36
- c2cgeoportal_geoportal/scaffolds/create/print/print-apps/+package+/config.yaml +0 -168
- c2cgeoportal_geoportal/scaffolds/create/qgisserver/geomapfish.yaml.tmpl_tmpl +0 -16
- c2cgeoportal_geoportal/scaffolds/create/spell-ignore-words.txt +0 -1
- c2cgeoportal_geoportal/scaffolds/create/tilegeneration/config.yaml.tmpl_tmpl +0 -185
- c2cgeoportal_geoportal/scaffolds/create/yamllint.yaml +0 -11
- c2cgeoportal_geoportal/scaffolds/update/CONST_CHANGELOG.txt_tmpl +0 -454
- c2cgeoportal_geoportal/templates/dynamic.js +0 -21
- c2cgeoportal_geoportal-2.6.0.dist-info/RECORD +0 -173
- /c2cgeoportal_geoportal/{scaffolds/create/geoportal/+package+_geoportal/static/css/desktop.css → py.typed} +0 -0
- /c2cgeoportal_geoportal/scaffolds/{create/geoportal/Makefile_tmpl → advance_create/{{cookiecutter.project}}/geoportal/Makefile} +0 -0
- /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/alembic.ini +0 -0
- /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/language_mapping +0 -0
- /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/lingua-server.cfg +0 -0
- /c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/views/__init__.py +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal/locale/en/LC_MESSAGES/+package+_geoportal-client.po → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/locale/en/LC_MESSAGES/{{cookiecutter.package}}_geoportal-client.po} +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal/static/css/iframe_api.css → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/desktop.css} +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal/static/css/mobile.css → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/iframe_api.css} +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/banner_left.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/banner_right.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/blank.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-blue.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-gold.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-green.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/robot.txt.tmpl +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/data/TM_EUROPE_BORDERS-0.3.sql +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arial.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arialbd.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arialbi.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Ariali.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Bold.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-BoldItalic.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Italic.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Regular.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdana.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanab.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanai.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanaz.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts.conf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/tinyows.xml.tmpl +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/legend.jrxml +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/logo.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/north.svg +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/results.jrxml +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{pyproject.toml → {{cookiecutter.project}}/pyproject.toml} +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{run_alembic.sh → {{cookiecutter.project}}/run_alembic.sh} +0 -0
- {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.86.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2014-2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2014-2023, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -30,51 +28,58 @@
|
|
30
28
|
|
31
29
|
import copy
|
32
30
|
import logging
|
33
|
-
import xml.sax.handler
|
31
|
+
import xml.sax.handler # nosec
|
34
32
|
from io import StringIO
|
35
|
-
from typing import Callable, Dict, List
|
36
|
-
from
|
37
|
-
from xml.sax.saxutils import XMLFilterBase, XMLGenerator
|
33
|
+
from typing import Any, Callable, Dict, List, Optional, Set, Union
|
34
|
+
from xml.sax.saxutils import XMLFilterBase, XMLGenerator # nosec
|
38
35
|
|
39
36
|
import defusedxml.expatreader
|
37
|
+
import pyramid.request
|
40
38
|
import requests
|
39
|
+
from owslib.map.wms111 import ContentMetadata as ContentMetadata111
|
40
|
+
from owslib.map.wms130 import ContentMetadata as ContentMetadata130
|
41
41
|
from owslib.wms import WebMapService
|
42
42
|
from pyramid.httpexceptions import HTTPBadGateway
|
43
43
|
|
44
|
-
from c2cgeoportal_commons.lib.url import
|
44
|
+
from c2cgeoportal_commons.lib.url import Url
|
45
45
|
from c2cgeoportal_geoportal.lib import caching, get_ogc_server_wfs_url_ids, get_ogc_server_wms_url_ids
|
46
46
|
from c2cgeoportal_geoportal.lib.layers import get_private_layers, get_protected_layers, get_writable_layers
|
47
47
|
|
48
48
|
CACHE_REGION = caching.get_region("std")
|
49
49
|
LOG = logging.getLogger(__name__)
|
50
|
+
ContentMetadata = Union[ContentMetadata111, ContentMetadata130]
|
50
51
|
|
51
52
|
|
52
|
-
@CACHE_REGION.cache_on_arguments()
|
53
|
-
def wms_structure(wms_url, host, request):
|
54
|
-
|
55
|
-
|
53
|
+
@CACHE_REGION.cache_on_arguments() # type: ignore
|
54
|
+
def wms_structure(wms_url: Url, host: str, request: pyramid.request.Request) -> Dict[str, List[str]]:
|
55
|
+
"""Get a simple serializable structure of the WMS capabilities."""
|
56
|
+
url = wms_url.clone().add_query({"SERVICE": "WMS", "VERSION": "1.1.1", "REQUEST": "GetCapabilities"})
|
56
57
|
|
57
58
|
# Forward request to target (without Host Header)
|
58
|
-
headers =
|
59
|
-
if url.hostname == "localhost" and host is not None:
|
59
|
+
headers = {}
|
60
|
+
if url.hostname == "localhost" and host is not None:
|
60
61
|
headers["Host"] = host
|
61
62
|
try:
|
62
|
-
response = requests.get(
|
63
|
-
|
64
|
-
|
63
|
+
response = requests.get(
|
64
|
+
url.url(), headers=headers, **request.registry.settings.get("http_options", {})
|
65
|
+
)
|
66
|
+
except Exception:
|
67
|
+
LOG.exception("Unable to GetCapabilities from wms_url '%s'", wms_url)
|
68
|
+
raise HTTPBadGateway( # pylint: disable=raise-missing-from
|
69
|
+
"Unable to GetCapabilities, see logs for details"
|
70
|
+
)
|
65
71
|
|
66
|
-
if not response.ok:
|
72
|
+
if not response.ok:
|
67
73
|
raise HTTPBadGateway(
|
68
|
-
"GetCapabilities from wms_url {
|
69
|
-
|
70
|
-
)
|
74
|
+
f"GetCapabilities from wms_url {url.url()} return the error: "
|
75
|
+
f"{response.status_code:d} {response.reason}"
|
71
76
|
)
|
72
77
|
|
73
78
|
try:
|
74
79
|
wms = WebMapService(None, xml=response.content)
|
75
80
|
result: Dict[str, List[str]] = {}
|
76
81
|
|
77
|
-
def _fill(name, parent):
|
82
|
+
def _fill(name: str, parent: ContentMetadata) -> None:
|
78
83
|
if parent is None:
|
79
84
|
return
|
80
85
|
if parent.name not in result:
|
@@ -86,37 +91,46 @@ def wms_structure(wms_url, host, request):
|
|
86
91
|
_fill(layer.name, layer.parent)
|
87
92
|
return result
|
88
93
|
|
89
|
-
except AttributeError:
|
94
|
+
except AttributeError:
|
90
95
|
error = "WARNING! an error occurred while trying to read the mapfile and recover the themes."
|
91
|
-
error = "{
|
96
|
+
error = f"{error}\nurl: {wms_url}\nxml:\n{response.text}"
|
92
97
|
LOG.exception(error)
|
93
|
-
raise HTTPBadGateway(error)
|
98
|
+
raise HTTPBadGateway(error) # pylint: disable=raise-missing-from
|
94
99
|
|
95
|
-
except SyntaxError:
|
100
|
+
except SyntaxError:
|
96
101
|
error = "WARNING! an error occurred while trying to read the mapfile and recover the themes."
|
97
|
-
error = "{
|
102
|
+
error = f"{error}\nurl: {wms_url}\nxml:\n{response.text}"
|
98
103
|
LOG.exception(error)
|
99
|
-
raise HTTPBadGateway(error)
|
104
|
+
raise HTTPBadGateway(error) # pylint: disable=raise-missing-from
|
100
105
|
|
101
106
|
|
102
|
-
def filter_capabilities(
|
107
|
+
def filter_capabilities(
|
108
|
+
content: str, wms: bool, url: Url, headers: Dict[str, str], request: pyramid.request.Request
|
109
|
+
) -> str:
|
110
|
+
"""Filter the WMS/WFS capabilities."""
|
103
111
|
|
104
112
|
wms_structure_ = wms_structure(url, headers.get("Host"), request)
|
105
113
|
|
106
114
|
ogc_server_ids = (
|
107
115
|
get_ogc_server_wms_url_ids(request) if wms else get_ogc_server_wfs_url_ids(request)
|
108
|
-
).get(url)
|
116
|
+
).get(url.url())
|
109
117
|
gmf_private_layers = copy.copy(get_private_layers(ogc_server_ids))
|
110
118
|
for id_ in list(get_protected_layers(request, ogc_server_ids).keys()):
|
111
119
|
if id_ in gmf_private_layers:
|
112
120
|
del gmf_private_layers[id_]
|
113
121
|
|
114
122
|
private_layers = set()
|
115
|
-
for
|
116
|
-
for
|
117
|
-
private_layers.add(
|
118
|
-
if
|
119
|
-
private_layers.update(wms_structure_[
|
123
|
+
for gmf_layer in list(gmf_private_layers.values()):
|
124
|
+
for ogc_layer in gmf_layer.layer.split(","):
|
125
|
+
private_layers.add(ogc_layer)
|
126
|
+
if ogc_layer in wms_structure_:
|
127
|
+
private_layers.update(wms_structure_[ogc_layer])
|
128
|
+
|
129
|
+
LOG.debug(
|
130
|
+
"Filter capabilities of OGC server %s\nprivate_layers: %s",
|
131
|
+
", ".join([str(e) for e in ogc_server_ids]),
|
132
|
+
", ".join(private_layers),
|
133
|
+
)
|
120
134
|
|
121
135
|
parser = defusedxml.expatreader.create_parser(forbid_external=False)
|
122
136
|
# skip inclusion of DTDs
|
@@ -128,15 +142,24 @@ def filter_capabilities(content, wms, url, headers, request):
|
|
128
142
|
filter_handler = _CapabilitiesFilter(
|
129
143
|
parser, downstream_handler, "Layer" if wms else "FeatureType", layers_blacklist=private_layers
|
130
144
|
)
|
131
|
-
filter_handler.parse(StringIO(content))
|
145
|
+
filter_handler.parse(StringIO(content)) # type: ignore
|
132
146
|
return result.getvalue()
|
133
147
|
|
134
148
|
|
135
|
-
def filter_wfst_capabilities(content, wfs_url, request):
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
149
|
+
def filter_wfst_capabilities(content: str, wfs_url: Url, request: pyramid.request.Request) -> str:
|
150
|
+
"""Filter the WTS capabilities."""
|
151
|
+
|
152
|
+
writable_layers: Set[str] = set()
|
153
|
+
ogc_server_ids = get_ogc_server_wfs_url_ids(request).get(wfs_url.url())
|
154
|
+
|
155
|
+
for gmf_layer in list(get_writable_layers(request, ogc_server_ids).values()):
|
156
|
+
writable_layers |= set(gmf_layer.layer.split(","))
|
157
|
+
|
158
|
+
LOG.debug(
|
159
|
+
"Filter WFS-T capabilities of OGC server %s\nlayers: %s",
|
160
|
+
", ".join([str(e) for e in ogc_server_ids]),
|
161
|
+
", ".join(writable_layers),
|
162
|
+
)
|
140
163
|
|
141
164
|
parser = defusedxml.expatreader.create_parser(forbid_external=False)
|
142
165
|
# skip inclusion of DTDs
|
@@ -148,13 +171,13 @@ def filter_wfst_capabilities(content, wfs_url, request):
|
|
148
171
|
filter_handler = _CapabilitiesFilter(
|
149
172
|
parser, downstream_handler, "FeatureType", layers_whitelist=writable_layers
|
150
173
|
)
|
151
|
-
filter_handler.parse(StringIO(content))
|
174
|
+
filter_handler.parse(StringIO(content)) # type: ignore
|
152
175
|
return result.getvalue()
|
153
176
|
|
154
177
|
|
155
178
|
class _Layer:
|
156
|
-
def __init__(self, self_hidden=False):
|
157
|
-
self.
|
179
|
+
def __init__(self, self_hidden: bool = False):
|
180
|
+
self.accumulator: List[Callable[[], None]] = []
|
158
181
|
self.hidden = True
|
159
182
|
self.self_hidden = self_hidden
|
160
183
|
self.has_children = False
|
@@ -164,13 +187,20 @@ class _Layer:
|
|
164
187
|
class _CapabilitiesFilter(XMLFilterBase):
|
165
188
|
"""
|
166
189
|
SAX filter to show only the allowed layers in a GetCapabilities request.
|
167
|
-
|
168
|
-
|
169
|
-
is given) or is not part of the set `layers_whitelist` (when
|
190
|
+
|
191
|
+
The filter removes elements of type `tag_name` where the `name` attribute is part of the set
|
192
|
+
`layers_blacklist` (when `layers_blacklist` is given) or is not part of the set `layers_whitelist` (when
|
170
193
|
`layers_whitelist` is given).
|
171
194
|
"""
|
172
195
|
|
173
|
-
def __init__(
|
196
|
+
def __init__(
|
197
|
+
self,
|
198
|
+
upstream: XMLFilterBase,
|
199
|
+
downstream: XMLGenerator,
|
200
|
+
tag_name: str,
|
201
|
+
layers_blacklist: Optional[Set[str]] = None,
|
202
|
+
layers_whitelist: Optional[Set[str]] = None,
|
203
|
+
):
|
174
204
|
XMLFilterBase.__init__(self, upstream)
|
175
205
|
self._downstream = downstream
|
176
206
|
self._accumulator: List[str] = []
|
@@ -183,9 +213,9 @@ class _CapabilitiesFilter(XMLFilterBase):
|
|
183
213
|
), "only either layers_blacklist OR layers_whitelist can be set"
|
184
214
|
|
185
215
|
if layers_blacklist is not None:
|
186
|
-
layers_blacklist =
|
216
|
+
layers_blacklist = {layer.lower() for layer in layers_blacklist}
|
187
217
|
if layers_whitelist is not None:
|
188
|
-
layers_whitelist =
|
218
|
+
layers_whitelist = {layer.lower() for layer in layers_whitelist}
|
189
219
|
self.layers_blacklist = layers_blacklist
|
190
220
|
self.layers_whitelist = layers_whitelist
|
191
221
|
|
@@ -196,39 +226,39 @@ class _CapabilitiesFilter(XMLFilterBase):
|
|
196
226
|
|
197
227
|
def _complete_text_node(self) -> None:
|
198
228
|
if self._accumulator:
|
199
|
-
self._downstream.characters("".join(self._accumulator))
|
229
|
+
self._downstream.characters("".join(self._accumulator)) # type: ignore
|
200
230
|
self._accumulator = []
|
201
231
|
|
202
|
-
def _do(self, action):
|
232
|
+
def _do(self, action: Callable[[], Any]) -> None:
|
203
233
|
if self.layers_path:
|
204
|
-
self.layers_path[-1].
|
234
|
+
self.layers_path[-1].accumulator.append(action)
|
205
235
|
else:
|
206
236
|
self._complete_text_node()
|
207
237
|
action()
|
208
238
|
|
209
|
-
def _add_child(self, layer):
|
239
|
+
def _add_child(self, layer: _Layer) -> None:
|
210
240
|
if not layer.hidden and not (layer.has_children and layer.children_nb == 0):
|
211
|
-
for action in layer.
|
241
|
+
for action in layer.accumulator:
|
212
242
|
self._complete_text_node()
|
213
243
|
action()
|
214
|
-
layer.
|
244
|
+
layer.accumulator = []
|
215
245
|
|
216
|
-
def setDocumentLocator(self, locator): # noqa
|
217
|
-
self._downstream.setDocumentLocator(locator)
|
246
|
+
def setDocumentLocator(self, locator: str) -> None: # noqa: ignore=N802
|
247
|
+
self._downstream.setDocumentLocator(locator) # type: ignore
|
218
248
|
|
219
|
-
def startDocument(self): # noqa
|
220
|
-
self._downstream.startDocument()
|
249
|
+
def startDocument(self) -> None: # noqa: ignore=N802
|
250
|
+
self._downstream.startDocument() # type: ignore
|
221
251
|
|
222
|
-
def endDocument(self): # noqa
|
223
|
-
self._downstream.endDocument()
|
252
|
+
def endDocument(self) -> None: # noqa: ignore=N802
|
253
|
+
self._downstream.endDocument() # type: ignore
|
224
254
|
|
225
|
-
def startPrefixMapping(self, prefix, uri
|
226
|
-
self._downstream.startPrefixMapping(prefix, uri)
|
255
|
+
def startPrefixMapping(self, prefix: str, uri: str) -> None: # noqa: ignore=N802
|
256
|
+
self._downstream.startPrefixMapping(prefix, uri) # type: ignore
|
227
257
|
|
228
|
-
def endPrefixMapping(self, prefix
|
229
|
-
self._downstream.endPrefixMapping(prefix)
|
258
|
+
def endPrefixMapping(self, prefix: str) -> None: # noqa: ignore=N802
|
259
|
+
self._downstream.endPrefixMapping(prefix) # type: ignore
|
230
260
|
|
231
|
-
def startElement(self, name, attrs): # noqa
|
261
|
+
def startElement(self, name: str, attrs: xml.sax.xmlreader.AttributesImpl) -> None: # noqa: ignore=N802
|
232
262
|
if name == self.tag_name:
|
233
263
|
self.level += 1
|
234
264
|
if self.layers_path:
|
@@ -238,40 +268,40 @@ class _CapabilitiesFilter(XMLFilterBase):
|
|
238
268
|
layer = _Layer(parent_layer.self_hidden) if len(self.layers_path) > 1 else _Layer()
|
239
269
|
self.layers_path.append(layer)
|
240
270
|
|
241
|
-
parent_layer.
|
271
|
+
parent_layer.accumulator.append(lambda: self._add_child(layer))
|
242
272
|
else:
|
243
273
|
layer = _Layer()
|
244
274
|
self.layers_path.append(layer)
|
245
275
|
elif name == "Name" and self.layers_path:
|
246
276
|
self.in_name = True
|
247
277
|
|
248
|
-
self._do(lambda: self._downstream.startElement(name, attrs))
|
278
|
+
self._do(lambda: self._downstream.startElement(name, attrs)) # type: ignore
|
249
279
|
|
250
|
-
def endElement(self, name): # noqa
|
251
|
-
self._do(lambda: self._downstream.endElement(name))
|
280
|
+
def endElement(self, name: str) -> None: # noqa: ignore=N802
|
281
|
+
self._do(lambda: self._downstream.endElement(name)) # type: ignore
|
252
282
|
|
253
283
|
if name == self.tag_name:
|
254
284
|
self.level -= 1
|
255
285
|
if self.level == 0 and not self.layers_path[0].hidden:
|
256
|
-
for action in self.layers_path[0].
|
286
|
+
for action in self.layers_path[0].accumulator:
|
257
287
|
self._complete_text_node()
|
258
288
|
action()
|
259
289
|
self.layers_path.pop()
|
260
290
|
elif name == "Name":
|
261
291
|
self.in_name = False
|
262
292
|
|
263
|
-
def startElementNS(self, name, qname, attrs
|
264
|
-
self._do(lambda: self._downstream.startElementNS(name, qname, attrs))
|
293
|
+
def startElementNS(self, name: str, qname: str, attrs: Dict[str, str]) -> None: # noqa: ignore=N802
|
294
|
+
self._do(lambda: self._downstream.startElementNS(name, qname, attrs)) # type: ignore
|
265
295
|
|
266
|
-
def endElementNS(self, name, qname
|
267
|
-
self._do(lambda: self._downstream.endElementNS(name, qname))
|
296
|
+
def endElementNS(self, name: str, qname: str) -> None: # noqa: ignore=N802
|
297
|
+
self._do(lambda: self._downstream.endElementNS(name, qname)) # type: ignore
|
268
298
|
|
269
|
-
def _keep_layer(self, layer_name):
|
299
|
+
def _keep_layer(self, layer_name: str) -> bool:
|
270
300
|
return (self.layers_blacklist is not None and layer_name not in self.layers_blacklist) or (
|
271
301
|
self.layers_whitelist is not None and layer_name in self.layers_whitelist
|
272
302
|
)
|
273
303
|
|
274
|
-
def characters(self, content):
|
304
|
+
def characters(self, content: str) -> None:
|
275
305
|
if self.in_name and self.layers_path and not self.layers_path[-1].self_hidden is True:
|
276
306
|
layer_name = normalize_typename(content)
|
277
307
|
if self._keep_layer(layer_name):
|
@@ -285,19 +315,20 @@ class _CapabilitiesFilter(XMLFilterBase):
|
|
285
315
|
|
286
316
|
self._do(lambda: self._accumulator.append(content))
|
287
317
|
|
288
|
-
def ignorableWhitespace(self, chars
|
318
|
+
def ignorableWhitespace(self, chars: str) -> None: # noqa: ignore=N802
|
289
319
|
self._do(lambda: self._accumulator.append(chars))
|
290
320
|
|
291
|
-
def processingInstruction(self, target, data
|
292
|
-
self._do(lambda: self._downstream.processingInstruction(target, data))
|
321
|
+
def processingInstruction(self, target: str, data: str) -> None: # noqa: ignore=N802
|
322
|
+
self._do(lambda: self._downstream.processingInstruction(target, data)) # type: ignore
|
293
323
|
|
294
|
-
def skippedEntity(self, name
|
295
|
-
self._downstream.skippedEntity(name)
|
324
|
+
def skippedEntity(self, name: str) -> None: # noqa: ignore=N802
|
325
|
+
self._downstream.skippedEntity(name) # type: ignore
|
296
326
|
|
297
327
|
|
298
|
-
def normalize_tag(tag):
|
328
|
+
def normalize_tag(tag: str) -> str:
|
299
329
|
"""
|
300
|
-
|
330
|
+
Drop the namespace from a tag and converts to lower case.
|
331
|
+
|
301
332
|
e.g. '{https://....}TypeName' -> 'TypeName'
|
302
333
|
"""
|
303
334
|
normalized = tag
|
@@ -307,9 +338,10 @@ def normalize_tag(tag):
|
|
307
338
|
return normalized.lower()
|
308
339
|
|
309
340
|
|
310
|
-
def normalize_typename(typename):
|
341
|
+
def normalize_typename(typename: str) -> str:
|
311
342
|
"""
|
312
|
-
|
343
|
+
Drop the namespace from a type name and converts to lower case.
|
344
|
+
|
313
345
|
e.g. 'tows:parks' -> 'parks'
|
314
346
|
"""
|
315
347
|
normalized = typename
|
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2020-2021, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -28,10 +26,13 @@
|
|
28
26
|
# either expressed or implied, of the FreeBSD Project.
|
29
27
|
|
30
28
|
import re
|
29
|
+
from typing import Any, Dict
|
31
30
|
|
32
31
|
|
33
32
|
class Normalize:
|
34
|
-
|
33
|
+
"""Normalize a text for the Full text search."""
|
34
|
+
|
35
|
+
def __init__(self, config: Dict[str, Any]) -> None:
|
35
36
|
split = config.get("split_regex")
|
36
37
|
self.split_re = re.compile(split) if split is not None else None
|
37
38
|
|
@@ -39,7 +40,7 @@ class Normalize:
|
|
39
40
|
for search_regex, text in config.get("replace", {}).items():
|
40
41
|
self.word_replace.append((re.compile(search_regex), text))
|
41
42
|
|
42
|
-
def __call__(self, text):
|
43
|
+
def __call__(self, text: str) -> str:
|
43
44
|
if self.split_re is not None:
|
44
45
|
text = " ".join(self.split_re.split(text))
|
45
46
|
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
|
3
1
|
# Copyright (c) 2011-2021, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
@@ -31,6 +29,7 @@
|
|
31
29
|
import logging.config
|
32
30
|
from typing import Any, Dict, List, Set, Union, cast
|
33
31
|
|
32
|
+
import pyramid.request
|
34
33
|
from sqlalchemy.orm import joinedload
|
35
34
|
|
36
35
|
from c2cgeoportal_commons.models import main, static
|
@@ -42,13 +41,13 @@ CACHE_REGION_OBJ = get_region("obj")
|
|
42
41
|
CACHE_REGION = get_region("std")
|
43
42
|
|
44
43
|
|
45
|
-
@CACHE_REGION_OBJ.cache_on_arguments()
|
44
|
+
@CACHE_REGION_OBJ.cache_on_arguments() # type: ignore
|
46
45
|
def _get_role(name: str) -> Dict[str, Any]:
|
47
46
|
from c2cgeoportal_commons.models import DBSession # pylint: disable=import-outside-toplevel
|
48
47
|
|
49
48
|
role = (
|
50
|
-
DBSession.query(
|
51
|
-
.filter(
|
49
|
+
DBSession.query(main.Role)
|
50
|
+
.filter(main.Role.name == name)
|
52
51
|
.options(joinedload(main.Role.functionalities))
|
53
52
|
.one_or_none()
|
54
53
|
)
|
@@ -56,19 +55,23 @@ def _get_role(name: str) -> Dict[str, Any]:
|
|
56
55
|
return {"settings_functionalities": struct, "roles_functionalities": {name: struct}}
|
57
56
|
|
58
57
|
|
59
|
-
def _user_to_struct(user):
|
58
|
+
def _user_to_struct(user: static.User) -> Dict[str, Any]:
|
60
59
|
return {
|
61
60
|
"settings_functionalities": _role_to_struct(user.settings_role),
|
62
61
|
"roles_functionalities": {role.name: _role_to_struct(role) for role in user.roles},
|
63
62
|
}
|
64
63
|
|
65
64
|
|
66
|
-
def _role_to_struct(role):
|
65
|
+
def _role_to_struct(role: main.Role) -> List[Dict[str, Any]]:
|
67
66
|
return [{"name": f.name, "value": f.value} for f in role.functionalities] if role else []
|
68
67
|
|
69
68
|
|
70
69
|
def _get_db_functionality(
|
71
|
-
name
|
70
|
+
name: str,
|
71
|
+
user: Dict[str, Any],
|
72
|
+
types: Dict[str, Dict[str, Any]],
|
73
|
+
request: pyramid.request.Request,
|
74
|
+
errors: Set[str],
|
72
75
|
) -> List[Union[str, int, float, bool, List[Any], Dict[str, Any]]]:
|
73
76
|
if types.get(name, {}).get("single", False):
|
74
77
|
values = [
|
@@ -91,16 +94,17 @@ def _get_db_functionality(
|
|
91
94
|
return [r for r in values if r is not None]
|
92
95
|
|
93
96
|
|
94
|
-
@CACHE_REGION_OBJ.cache_on_arguments()
|
95
|
-
def _get_functionalities_type(request):
|
97
|
+
@CACHE_REGION_OBJ.cache_on_arguments() # type: ignore
|
98
|
+
def _get_functionalities_type(request: pyramid.request.Request) -> Dict[str, Dict[str, Any]]:
|
96
99
|
return get_types_map(
|
97
100
|
request.registry.settings.get("admin_interface", {}).get("available_functionalities", [])
|
98
101
|
)
|
99
102
|
|
100
103
|
|
101
104
|
def get_functionality(
|
102
|
-
name, request, is_intranet_
|
105
|
+
name: str, request: pyramid.request.Request, is_intranet_: bool
|
103
106
|
) -> List[Union[str, int, float, bool, List[Any], Dict[str, Any]]]:
|
107
|
+
"""Get all the functionality for the current user."""
|
104
108
|
result: List[Union[str, int, float, bool, List[Any], Dict[str, Any]]] = []
|
105
109
|
errors: Set[str] = set()
|
106
110
|
|
@@ -135,12 +139,13 @@ def get_functionality(
|
|
135
139
|
errors,
|
136
140
|
)
|
137
141
|
|
138
|
-
if errors != set():
|
142
|
+
if errors != set():
|
139
143
|
LOG.error("\n".join(errors))
|
140
144
|
return result
|
141
145
|
|
142
146
|
|
143
|
-
def get_mapserver_substitution_params(request):
|
147
|
+
def get_mapserver_substitution_params(request: pyramid.request.Request) -> Dict[str, str]:
|
148
|
+
"""Get the parameters used by the mapserver substitution."""
|
144
149
|
params: Dict[str, str] = {}
|
145
150
|
mss = get_functionality("mapserver_substitution", request, is_intranet(request))
|
146
151
|
if mss:
|
@@ -149,13 +154,11 @@ def get_mapserver_substitution_params(request):
|
|
149
154
|
index = s.find("=")
|
150
155
|
if index > 0:
|
151
156
|
attribute = "s_" + s[:index]
|
152
|
-
|
153
|
-
value = s[index + 1:]
|
154
|
-
# fmt: on
|
157
|
+
value = s[index + 1 :]
|
155
158
|
if attribute in params:
|
156
159
|
params[attribute] += "," + value
|
157
160
|
else:
|
158
161
|
params[attribute] = value
|
159
162
|
else:
|
160
|
-
LOG.warning("Mapserver Substitution '%s' does not
|
163
|
+
LOG.warning("Mapserver Substitution '%s' does not respect pattern: <attribute>=<value>", s)
|
161
164
|
return params
|
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2013-2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2013-2021, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -29,16 +27,27 @@
|
|
29
27
|
|
30
28
|
|
31
29
|
import re
|
30
|
+
from typing import Callable
|
31
|
+
|
32
|
+
import pyramid.registry
|
33
|
+
import pyramid.request
|
34
|
+
import pyramid.response
|
32
35
|
|
33
36
|
|
34
37
|
class HeadersTween:
|
35
|
-
|
38
|
+
"""Add the header on all the application."""
|
39
|
+
|
40
|
+
def __init__(
|
41
|
+
self,
|
42
|
+
handler: Callable[[pyramid.request.Request], pyramid.response.Response],
|
43
|
+
registry: pyramid.registry.Registry,
|
44
|
+
) -> None:
|
36
45
|
self.handler = handler
|
37
46
|
self.settings = [
|
38
47
|
(re.compile(e["pattern"]), e["headers"]) for e in registry.settings["global_headers"]
|
39
48
|
]
|
40
49
|
|
41
|
-
def __call__(self, request):
|
50
|
+
def __call__(self, request: pyramid.request.Request) -> pyramid.response.Response:
|
42
51
|
response = self.handler(request)
|
43
52
|
|
44
53
|
for pattern, headers in self.settings:
|
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2020-2021, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -29,11 +27,13 @@
|
|
29
27
|
|
30
28
|
|
31
29
|
import os
|
30
|
+
from typing import List
|
32
31
|
|
33
32
|
LOCALE_PATH = "/etc/geomapfish/locale/"
|
34
33
|
|
35
34
|
|
36
|
-
def available_locale_names(path=LOCALE_PATH):
|
35
|
+
def available_locale_names(path: str = LOCALE_PATH) -> List[str]:
|
36
|
+
"""Get the available locales."""
|
37
37
|
if not os.path.exists(path):
|
38
38
|
return []
|
39
39
|
return [d for d in os.listdir(path) if os.path.isdir(os.path.join(path, d))]
|