c2cgeoportal-geoportal 2.6.0__py2.py3-none-any.whl → 2.7.1.156__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 +67 -43
- 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 +122 -88
- 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 +102 -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 +162 -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 +67 -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 +110 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-restore +114 -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 +1160 -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 -17
- c2cgeoportal_geoportal/scripts/__init__.py +16 -30
- 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 +19 -11
- 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 +56 -19
- 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 +46 -29
- 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 +60 -52
- c2cgeoportal_geoportal/views/profile.py +24 -23
- c2cgeoportal_geoportal/views/proxy.py +87 -69
- 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.156.dist-info}/METADATA +25 -20
- c2cgeoportal_geoportal-2.7.1.156.dist-info/RECORD +185 -0
- {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.156.dist-info}/WHEEL +1 -1
- {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.156.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.156.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2014-2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2014-2024, 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,48 @@ 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
|
-
get_ogc_server_wms_url_ids(request
|
108
|
-
|
115
|
+
get_ogc_server_wms_url_ids(request, request.host)
|
116
|
+
if wms
|
117
|
+
else get_ogc_server_wfs_url_ids(request, request.host)
|
118
|
+
).get(url.url())
|
109
119
|
gmf_private_layers = copy.copy(get_private_layers(ogc_server_ids))
|
110
120
|
for id_ in list(get_protected_layers(request, ogc_server_ids).keys()):
|
111
121
|
if id_ in gmf_private_layers:
|
112
122
|
del gmf_private_layers[id_]
|
113
123
|
|
114
124
|
private_layers = set()
|
115
|
-
for
|
116
|
-
for
|
117
|
-
private_layers.add(
|
118
|
-
if
|
119
|
-
private_layers.update(wms_structure_[
|
125
|
+
for gmf_layer in list(gmf_private_layers.values()):
|
126
|
+
for ogc_layer in gmf_layer.layer.split(","):
|
127
|
+
private_layers.add(ogc_layer)
|
128
|
+
if ogc_layer in wms_structure_:
|
129
|
+
private_layers.update(wms_structure_[ogc_layer])
|
130
|
+
|
131
|
+
LOG.debug(
|
132
|
+
"Filter capabilities of OGC server %s\nprivate_layers: %s",
|
133
|
+
", ".join([str(e) for e in ogc_server_ids]),
|
134
|
+
", ".join(private_layers),
|
135
|
+
)
|
120
136
|
|
121
137
|
parser = defusedxml.expatreader.create_parser(forbid_external=False)
|
122
138
|
# skip inclusion of DTDs
|
@@ -128,15 +144,24 @@ def filter_capabilities(content, wms, url, headers, request):
|
|
128
144
|
filter_handler = _CapabilitiesFilter(
|
129
145
|
parser, downstream_handler, "Layer" if wms else "FeatureType", layers_blacklist=private_layers
|
130
146
|
)
|
131
|
-
filter_handler.parse(StringIO(content))
|
147
|
+
filter_handler.parse(StringIO(content)) # type: ignore
|
132
148
|
return result.getvalue()
|
133
149
|
|
134
150
|
|
135
|
-
def filter_wfst_capabilities(content, wfs_url, request):
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
151
|
+
def filter_wfst_capabilities(content: str, wfs_url: Url, request: pyramid.request.Request) -> str:
|
152
|
+
"""Filter the WTS capabilities."""
|
153
|
+
|
154
|
+
writable_layers: Set[str] = set()
|
155
|
+
ogc_server_ids = get_ogc_server_wfs_url_ids(request, request.host).get(wfs_url.url())
|
156
|
+
|
157
|
+
for gmf_layer in list(get_writable_layers(request, ogc_server_ids).values()):
|
158
|
+
writable_layers |= set(gmf_layer.layer.split(","))
|
159
|
+
|
160
|
+
LOG.debug(
|
161
|
+
"Filter WFS-T capabilities of OGC server %s\nlayers: %s",
|
162
|
+
", ".join([str(e) for e in ogc_server_ids]),
|
163
|
+
", ".join(writable_layers),
|
164
|
+
)
|
140
165
|
|
141
166
|
parser = defusedxml.expatreader.create_parser(forbid_external=False)
|
142
167
|
# skip inclusion of DTDs
|
@@ -148,13 +173,13 @@ def filter_wfst_capabilities(content, wfs_url, request):
|
|
148
173
|
filter_handler = _CapabilitiesFilter(
|
149
174
|
parser, downstream_handler, "FeatureType", layers_whitelist=writable_layers
|
150
175
|
)
|
151
|
-
filter_handler.parse(StringIO(content))
|
176
|
+
filter_handler.parse(StringIO(content)) # type: ignore
|
152
177
|
return result.getvalue()
|
153
178
|
|
154
179
|
|
155
180
|
class _Layer:
|
156
|
-
def __init__(self, self_hidden=False):
|
157
|
-
self.
|
181
|
+
def __init__(self, self_hidden: bool = False):
|
182
|
+
self.accumulator: List[Callable[[], None]] = []
|
158
183
|
self.hidden = True
|
159
184
|
self.self_hidden = self_hidden
|
160
185
|
self.has_children = False
|
@@ -164,13 +189,20 @@ class _Layer:
|
|
164
189
|
class _CapabilitiesFilter(XMLFilterBase):
|
165
190
|
"""
|
166
191
|
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
|
192
|
+
|
193
|
+
The filter removes elements of type `tag_name` where the `name` attribute is part of the set
|
194
|
+
`layers_blacklist` (when `layers_blacklist` is given) or is not part of the set `layers_whitelist` (when
|
170
195
|
`layers_whitelist` is given).
|
171
196
|
"""
|
172
197
|
|
173
|
-
def __init__(
|
198
|
+
def __init__(
|
199
|
+
self,
|
200
|
+
upstream: XMLFilterBase,
|
201
|
+
downstream: XMLGenerator,
|
202
|
+
tag_name: str,
|
203
|
+
layers_blacklist: Optional[Set[str]] = None,
|
204
|
+
layers_whitelist: Optional[Set[str]] = None,
|
205
|
+
):
|
174
206
|
XMLFilterBase.__init__(self, upstream)
|
175
207
|
self._downstream = downstream
|
176
208
|
self._accumulator: List[str] = []
|
@@ -183,9 +215,9 @@ class _CapabilitiesFilter(XMLFilterBase):
|
|
183
215
|
), "only either layers_blacklist OR layers_whitelist can be set"
|
184
216
|
|
185
217
|
if layers_blacklist is not None:
|
186
|
-
layers_blacklist =
|
218
|
+
layers_blacklist = {layer.lower() for layer in layers_blacklist}
|
187
219
|
if layers_whitelist is not None:
|
188
|
-
layers_whitelist =
|
220
|
+
layers_whitelist = {layer.lower() for layer in layers_whitelist}
|
189
221
|
self.layers_blacklist = layers_blacklist
|
190
222
|
self.layers_whitelist = layers_whitelist
|
191
223
|
|
@@ -196,39 +228,39 @@ class _CapabilitiesFilter(XMLFilterBase):
|
|
196
228
|
|
197
229
|
def _complete_text_node(self) -> None:
|
198
230
|
if self._accumulator:
|
199
|
-
self._downstream.characters("".join(self._accumulator))
|
231
|
+
self._downstream.characters("".join(self._accumulator)) # type: ignore
|
200
232
|
self._accumulator = []
|
201
233
|
|
202
|
-
def _do(self, action):
|
234
|
+
def _do(self, action: Callable[[], Any]) -> None:
|
203
235
|
if self.layers_path:
|
204
|
-
self.layers_path[-1].
|
236
|
+
self.layers_path[-1].accumulator.append(action)
|
205
237
|
else:
|
206
238
|
self._complete_text_node()
|
207
239
|
action()
|
208
240
|
|
209
|
-
def _add_child(self, layer):
|
241
|
+
def _add_child(self, layer: _Layer) -> None:
|
210
242
|
if not layer.hidden and not (layer.has_children and layer.children_nb == 0):
|
211
|
-
for action in layer.
|
243
|
+
for action in layer.accumulator:
|
212
244
|
self._complete_text_node()
|
213
245
|
action()
|
214
|
-
layer.
|
246
|
+
layer.accumulator = []
|
215
247
|
|
216
|
-
def setDocumentLocator(self, locator): # noqa
|
217
|
-
self._downstream.setDocumentLocator(locator)
|
248
|
+
def setDocumentLocator(self, locator: str) -> None: # noqa: ignore=N802
|
249
|
+
self._downstream.setDocumentLocator(locator) # type: ignore
|
218
250
|
|
219
|
-
def startDocument(self): # noqa
|
220
|
-
self._downstream.startDocument()
|
251
|
+
def startDocument(self) -> None: # noqa: ignore=N802
|
252
|
+
self._downstream.startDocument() # type: ignore
|
221
253
|
|
222
|
-
def endDocument(self): # noqa
|
223
|
-
self._downstream.endDocument()
|
254
|
+
def endDocument(self) -> None: # noqa: ignore=N802
|
255
|
+
self._downstream.endDocument() # type: ignore
|
224
256
|
|
225
|
-
def startPrefixMapping(self, prefix, uri
|
226
|
-
self._downstream.startPrefixMapping(prefix, uri)
|
257
|
+
def startPrefixMapping(self, prefix: str, uri: str) -> None: # noqa: ignore=N802
|
258
|
+
self._downstream.startPrefixMapping(prefix, uri) # type: ignore
|
227
259
|
|
228
|
-
def endPrefixMapping(self, prefix
|
229
|
-
self._downstream.endPrefixMapping(prefix)
|
260
|
+
def endPrefixMapping(self, prefix: str) -> None: # noqa: ignore=N802
|
261
|
+
self._downstream.endPrefixMapping(prefix) # type: ignore
|
230
262
|
|
231
|
-
def startElement(self, name, attrs): # noqa
|
263
|
+
def startElement(self, name: str, attrs: xml.sax.xmlreader.AttributesImpl) -> None: # noqa: ignore=N802
|
232
264
|
if name == self.tag_name:
|
233
265
|
self.level += 1
|
234
266
|
if self.layers_path:
|
@@ -238,40 +270,40 @@ class _CapabilitiesFilter(XMLFilterBase):
|
|
238
270
|
layer = _Layer(parent_layer.self_hidden) if len(self.layers_path) > 1 else _Layer()
|
239
271
|
self.layers_path.append(layer)
|
240
272
|
|
241
|
-
parent_layer.
|
273
|
+
parent_layer.accumulator.append(lambda: self._add_child(layer))
|
242
274
|
else:
|
243
275
|
layer = _Layer()
|
244
276
|
self.layers_path.append(layer)
|
245
277
|
elif name == "Name" and self.layers_path:
|
246
278
|
self.in_name = True
|
247
279
|
|
248
|
-
self._do(lambda: self._downstream.startElement(name, attrs))
|
280
|
+
self._do(lambda: self._downstream.startElement(name, attrs)) # type: ignore
|
249
281
|
|
250
|
-
def endElement(self, name): # noqa
|
251
|
-
self._do(lambda: self._downstream.endElement(name))
|
282
|
+
def endElement(self, name: str) -> None: # noqa: ignore=N802
|
283
|
+
self._do(lambda: self._downstream.endElement(name)) # type: ignore
|
252
284
|
|
253
285
|
if name == self.tag_name:
|
254
286
|
self.level -= 1
|
255
287
|
if self.level == 0 and not self.layers_path[0].hidden:
|
256
|
-
for action in self.layers_path[0].
|
288
|
+
for action in self.layers_path[0].accumulator:
|
257
289
|
self._complete_text_node()
|
258
290
|
action()
|
259
291
|
self.layers_path.pop()
|
260
292
|
elif name == "Name":
|
261
293
|
self.in_name = False
|
262
294
|
|
263
|
-
def startElementNS(self, name, qname, attrs
|
264
|
-
self._do(lambda: self._downstream.startElementNS(name, qname, attrs))
|
295
|
+
def startElementNS(self, name: str, qname: str, attrs: Dict[str, str]) -> None: # noqa: ignore=N802
|
296
|
+
self._do(lambda: self._downstream.startElementNS(name, qname, attrs)) # type: ignore
|
265
297
|
|
266
|
-
def endElementNS(self, name, qname
|
267
|
-
self._do(lambda: self._downstream.endElementNS(name, qname))
|
298
|
+
def endElementNS(self, name: str, qname: str) -> None: # noqa: ignore=N802
|
299
|
+
self._do(lambda: self._downstream.endElementNS(name, qname)) # type: ignore
|
268
300
|
|
269
|
-
def _keep_layer(self, layer_name):
|
301
|
+
def _keep_layer(self, layer_name: str) -> bool:
|
270
302
|
return (self.layers_blacklist is not None and layer_name not in self.layers_blacklist) or (
|
271
303
|
self.layers_whitelist is not None and layer_name in self.layers_whitelist
|
272
304
|
)
|
273
305
|
|
274
|
-
def characters(self, content):
|
306
|
+
def characters(self, content: str) -> None:
|
275
307
|
if self.in_name and self.layers_path and not self.layers_path[-1].self_hidden is True:
|
276
308
|
layer_name = normalize_typename(content)
|
277
309
|
if self._keep_layer(layer_name):
|
@@ -285,19 +317,20 @@ class _CapabilitiesFilter(XMLFilterBase):
|
|
285
317
|
|
286
318
|
self._do(lambda: self._accumulator.append(content))
|
287
319
|
|
288
|
-
def ignorableWhitespace(self, chars
|
320
|
+
def ignorableWhitespace(self, chars: str) -> None: # noqa: ignore=N802
|
289
321
|
self._do(lambda: self._accumulator.append(chars))
|
290
322
|
|
291
|
-
def processingInstruction(self, target, data
|
292
|
-
self._do(lambda: self._downstream.processingInstruction(target, data))
|
323
|
+
def processingInstruction(self, target: str, data: str) -> None: # noqa: ignore=N802
|
324
|
+
self._do(lambda: self._downstream.processingInstruction(target, data)) # type: ignore
|
293
325
|
|
294
|
-
def skippedEntity(self, name
|
295
|
-
self._downstream.skippedEntity(name)
|
326
|
+
def skippedEntity(self, name: str) -> None: # noqa: ignore=N802
|
327
|
+
self._downstream.skippedEntity(name) # type: ignore
|
296
328
|
|
297
329
|
|
298
|
-
def normalize_tag(tag):
|
330
|
+
def normalize_tag(tag: str) -> str:
|
299
331
|
"""
|
300
|
-
|
332
|
+
Drop the namespace from a tag and converts to lower case.
|
333
|
+
|
301
334
|
e.g. '{https://....}TypeName' -> 'TypeName'
|
302
335
|
"""
|
303
336
|
normalized = tag
|
@@ -307,9 +340,10 @@ def normalize_tag(tag):
|
|
307
340
|
return normalized.lower()
|
308
341
|
|
309
342
|
|
310
|
-
def normalize_typename(typename):
|
343
|
+
def normalize_typename(typename: str) -> str:
|
311
344
|
"""
|
312
|
-
|
345
|
+
Drop the namespace from a type name and converts to lower case.
|
346
|
+
|
313
347
|
e.g. 'tows:parks' -> 'parks'
|
314
348
|
"""
|
315
349
|
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))]
|