c2cgeoportal-geoportal 2.5.0.100__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 +261 -130
- c2cgeoportal_geoportal/lib/__init__.py +74 -120
- c2cgeoportal_geoportal/lib/authentication.py +170 -21
- c2cgeoportal_geoportal/lib/bashcolor.py +17 -13
- c2cgeoportal_geoportal/lib/cacheversion.py +19 -11
- c2cgeoportal_geoportal/lib/caching.py +66 -160
- c2cgeoportal_geoportal/lib/check_collector.py +17 -10
- c2cgeoportal_geoportal/lib/checker.py +62 -64
- c2cgeoportal_geoportal/lib/common_headers.py +170 -0
- c2cgeoportal_geoportal/lib/dbreflection.py +70 -31
- c2cgeoportal_geoportal/lib/filter_capabilities.py +127 -97
- c2cgeoportal_geoportal/lib/fulltextsearch.py +50 -0
- c2cgeoportal_geoportal/lib/functionality.py +36 -21
- c2cgeoportal_geoportal/lib/headers.py +14 -5
- c2cgeoportal_geoportal/lib/i18n.py +39 -0
- c2cgeoportal_geoportal/lib/layers.py +29 -10
- c2cgeoportal_geoportal/lib/lingua_extractor.py +408 -211
- c2cgeoportal_geoportal/lib/loader.py +18 -16
- c2cgeoportal_geoportal/lib/metrics.py +29 -18
- c2cgeoportal_geoportal/lib/oauth2.py +1036 -0
- c2cgeoportal_geoportal/lib/wmstparsing.py +115 -90
- c2cgeoportal_geoportal/lib/xsd.py +29 -19
- 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/+dot+prospector.yaml → advance_create/{{cookiecutter.project}}/geoportal/.prospector.yaml} +8 -4
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/Dockerfile_tmpl → advance_create/{{cookiecutter.project}}/geoportal/Dockerfile} +24 -15
- c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/alembic.ini +1 -0
- 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/advance_create/{{cookiecutter.project}}/geoportal/setup.py +25 -0
- 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 +4 -4
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/__init__.py +47 -0
- 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/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static-ngeo/api/index.js +12 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static-ngeo/js/{{cookiecutter.package}}module.js +25 -0
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal/subscribers.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/subscribers.py} +3 -6
- c2cgeoportal_geoportal/scaffolds/advance_update/cookiecutter.json +18 -0
- c2cgeoportal_geoportal/scaffolds/{update/geoportal/CONST_Makefile_tmpl → advance_update/{{cookiecutter.project}}/geoportal/CONST_Makefile} +32 -20
- 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} +4 -8
- 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} +34 -24
- 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/{{cookiecutter.project}}/ci/config.yaml +25 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/requirements.txt +1 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-lib.yaml +474 -0
- 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} +43 -18
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.default +82 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.project +60 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/vars.yaml +396 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/mobile.css +0 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/images/markers/marker-blue.png +0 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/images/markers/marker-gold.png +0 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/images/markers/marker-green.png +0 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/images/markers/marker.png +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 +17 -9
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A3_Portrait.jrxml +17 -9
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A4_Landscape.jrxml +17 -9
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A4_Portrait.jrxml +17 -9
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/config.yaml.tmpl +30 -27
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/legend.jrxml +109 -0
- 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/{{cookiecutter.project}}/pyproject.toml +3 -0
- 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/{{cookiecutter.project}}/setup.cfg +7 -0
- 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/{{cookiecutter.project}}/.upgrade.yaml +191 -0
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_CHANGELOG.txt +1160 -0
- c2cgeoportal_geoportal/scaffolds/update/{geoportal → {{cookiecutter.project}}/geoportal}/CONST_config-schema.yaml +99 -47
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/geoportal/CONST_vars.yaml +1410 -0
- c2cgeoportal_geoportal/scripts/__init__.py +18 -32
- c2cgeoportal_geoportal/scripts/c2cupgrade.py +295 -200
- c2cgeoportal_geoportal/scripts/create_demo_theme.py +5 -6
- c2cgeoportal_geoportal/scripts/manage_users.py +34 -37
- c2cgeoportal_geoportal/scripts/pcreate.py +312 -0
- c2cgeoportal_geoportal/scripts/theme2fts.py +92 -25
- c2cgeoportal_geoportal/scripts/urllogin.py +23 -17
- c2cgeoportal_geoportal/templates/login.html +88 -84
- c2cgeoportal_geoportal/templates/notlogin.html +62 -0
- 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 +71 -40
- c2cgeoportal_geoportal/views/entry.py +93 -24
- c2cgeoportal_geoportal/views/fulltextsearch.py +36 -29
- c2cgeoportal_geoportal/views/geometry_processing.py +15 -7
- c2cgeoportal_geoportal/views/i18n.py +91 -9
- c2cgeoportal_geoportal/views/layers.py +173 -134
- c2cgeoportal_geoportal/views/login.py +206 -87
- c2cgeoportal_geoportal/views/mapserverproxy.py +59 -35
- c2cgeoportal_geoportal/views/memory.py +13 -13
- c2cgeoportal_geoportal/views/ogcproxy.py +48 -30
- c2cgeoportal_geoportal/views/pdfreport.py +31 -27
- c2cgeoportal_geoportal/views/printproxy.py +70 -54
- c2cgeoportal_geoportal/views/profile.py +25 -24
- c2cgeoportal_geoportal/views/proxy.py +100 -70
- c2cgeoportal_geoportal/views/raster.py +47 -29
- c2cgeoportal_geoportal/views/resourceproxy.py +13 -11
- c2cgeoportal_geoportal/views/shortener.py +31 -24
- c2cgeoportal_geoportal/views/theme.py +475 -365
- c2cgeoportal_geoportal/views/tinyowsproxy.py +46 -39
- c2cgeoportal_geoportal/views/vector_tiles.py +80 -0
- {c2cgeoportal_geoportal-2.5.0.100.dist-info → c2cgeoportal_geoportal-2.7.1.156.dist-info}/METADATA +17 -11
- c2cgeoportal_geoportal-2.7.1.156.dist-info/RECORD +185 -0
- {c2cgeoportal_geoportal-2.5.0.100.dist-info → c2cgeoportal_geoportal-2.7.1.156.dist-info}/WHEEL +1 -1
- {c2cgeoportal_geoportal-2.5.0.100.dist-info → c2cgeoportal_geoportal-2.7.1.156.dist-info}/entry_points.txt +3 -1
- tests/__init__.py +24 -3
- tests/test_cachebuster.py +1 -3
- tests/test_caching.py +19 -26
- tests/test_checker.py +2 -3
- tests/test_decimaljson.py +4 -4
- tests/test_headerstween.py +0 -3
- tests/test_i18n.py +31 -0
- tests/test_init.py +12 -27
- tests/test_locale_negociator.py +6 -6
- tests/test_mapserverproxy_route_predicate.py +0 -2
- tests/test_raster.py +18 -5
- tests/test_wmstparsing.py +7 -8
- c2cgeoportal_geoportal/scaffolds/__init__.py +0 -226
- c2cgeoportal_geoportal/scaffolds/create/+dot+dockerignore_tmpl +0 -11
- c2cgeoportal_geoportal/scaffolds/create/+dot+github/workflows/ci.yaml_tmpl +0 -56
- c2cgeoportal_geoportal/scaffolds/create/+dot+gitignore_tmpl +0 -12
- c2cgeoportal_geoportal/scaffolds/create/build_tmpl +0 -144
- c2cgeoportal_geoportal/scaffolds/create/docker-compose-lib.yaml_tmpl +0 -302
- c2cgeoportal_geoportal/scaffolds/create/docker-compose.override.sample.yaml_tmpl +0 -54
- c2cgeoportal_geoportal/scaffolds/create/env.default_tmpl +0 -49
- c2cgeoportal_geoportal/scaffolds/create/env.project_tmpl +0 -39
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+dot+dockerignore_tmpl +0 -5
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+dot+eslintrc_tmpl +0 -19
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/__init__.py_tmpl +0 -48
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/models.py_tmpl +0 -10
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/static/images/favicon.ico +0 -0
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/static/robot.txt +0 -3
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/static-ngeo/api/index.js_tmpl +0 -37
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/static-ngeo/js/+package+module.js_tmpl +0 -22
- c2cgeoportal_geoportal/scaffolds/create/geoportal/production.ini_tmpl +0 -106
- c2cgeoportal_geoportal/scaffolds/create/geoportal/requirements.txt +0 -2
- c2cgeoportal_geoportal/scaffolds/create/geoportal/setup.py_tmpl +0 -18
- c2cgeoportal_geoportal/scaffolds/create/geoportal/tsconfig.json_tmpl +0 -9
- c2cgeoportal_geoportal/scaffolds/create/geoportal/vars.yaml_tmpl +0 -224
- c2cgeoportal_geoportal/scaffolds/create/geoportal/webpack.api.js_tmpl +0 -71
- 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 -166
- c2cgeoportal_geoportal/scaffolds/create/print/print-apps/+package+/legend.jrxml +0 -27
- c2cgeoportal_geoportal/scaffolds/create/qgisserver/geomapfish.yaml.tmpl_tmpl +0 -29
- c2cgeoportal_geoportal/scaffolds/create/scripts/publish-docker +0 -124
- c2cgeoportal_geoportal/scaffolds/create/setup.cfg_tmpl +0 -3
- c2cgeoportal_geoportal/scaffolds/create/spell-ignore-words.txt +0 -1
- c2cgeoportal_geoportal/scaffolds/create/tilegeneration/config.yaml.tmpl_tmpl +0 -169
- c2cgeoportal_geoportal/scaffolds/create/yamllint.yaml +0 -11
- c2cgeoportal_geoportal/scaffolds/update/+dot+upgrade.yaml_tmpl +0 -171
- c2cgeoportal_geoportal/scaffolds/update/CONST_CHANGELOG.txt_tmpl +0 -64
- c2cgeoportal_geoportal/scaffolds/update/geoportal/CONST_vars.yaml_tmpl +0 -783
- c2cgeoportal_geoportal/templates/dynamic.js +0 -21
- c2cgeoportal_geoportal-2.5.0.100.dist-info/RECORD +0 -162
- tests/test_get_url.py +0 -96
- tests/test_lib.py +0 -77
- /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/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/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}}}/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/{run_alembic.sh → {{cookiecutter.project}}/run_alembic.sh} +0 -0
- {c2cgeoportal_geoportal-2.5.0.100.dist-info → c2cgeoportal_geoportal-2.7.1.156.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2011-2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2011-2021, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -27,46 +25,53 @@
|
|
27
25
|
# of the authors and should not be interpreted as representing official policies,
|
28
26
|
# either expressed or implied, of the FreeBSD Project.
|
29
27
|
|
30
|
-
import binascii
|
31
28
|
import importlib
|
32
|
-
import json
|
33
29
|
import logging
|
34
30
|
import os
|
35
|
-
import
|
36
|
-
import
|
31
|
+
from functools import partial
|
32
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, cast
|
37
33
|
from urllib.parse import urlsplit
|
38
34
|
|
39
|
-
from Crypto.Cipher import AES # nosec
|
40
35
|
import c2cgeoform
|
41
|
-
from c2cgeoform import Form, translator
|
42
36
|
import c2cwsgiutils
|
43
37
|
import c2cwsgiutils.db
|
44
|
-
from c2cwsgiutils.health_check import HealthCheck
|
45
38
|
import c2cwsgiutils.index
|
39
|
+
import pyramid.config
|
40
|
+
import pyramid.renderers
|
41
|
+
import pyramid.request
|
42
|
+
import pyramid.response
|
43
|
+
import pyramid.security
|
44
|
+
import zope.event.classhandler
|
45
|
+
from c2cgeoform import Form, translator
|
46
|
+
from c2cwsgiutils.broadcast import decorator
|
47
|
+
from c2cwsgiutils.health_check import HealthCheck
|
46
48
|
from c2cwsgiutils.metrics import MemoryMapProvider, add_provider
|
47
49
|
from dogpile.cache import register_backend
|
48
50
|
from papyrus.renderers import GeoJSON
|
49
51
|
from pyramid.config import Configurator
|
50
52
|
from pyramid.httpexceptions import HTTPException
|
51
53
|
from pyramid.path import AssetResolver
|
52
|
-
import pyramid.security
|
53
54
|
from pyramid_mako import add_mako_renderer
|
54
|
-
from sqlalchemy.orm import Session
|
55
|
-
import zope.event.classhandler
|
55
|
+
from sqlalchemy.orm import Session, joinedload
|
56
56
|
|
57
57
|
import c2cgeoportal_commons.models
|
58
|
+
import c2cgeoportal_geoportal.views
|
58
59
|
from c2cgeoportal_commons.models import InvalidateCacheEvent
|
59
60
|
from c2cgeoportal_geoportal.lib import C2CPregenerator, caching, check_collector, checker
|
60
61
|
from c2cgeoportal_geoportal.lib.cacheversion import version_cache_buster
|
61
|
-
from c2cgeoportal_geoportal.lib.
|
62
|
+
from c2cgeoportal_geoportal.lib.common_headers import Cache, set_common_headers
|
63
|
+
from c2cgeoportal_geoportal.lib.i18n import available_locale_names
|
62
64
|
from c2cgeoportal_geoportal.lib.metrics import (
|
63
65
|
MemoryCacheSizeProvider,
|
64
66
|
RasterDataSizeProvider,
|
65
67
|
TotalPythonObjectMemoryProvider,
|
66
68
|
)
|
67
69
|
from c2cgeoportal_geoportal.lib.xsd import XSD
|
68
|
-
|
69
|
-
|
70
|
+
from c2cgeoportal_geoportal.views.entry import Entry, canvas_view
|
71
|
+
|
72
|
+
if TYPE_CHECKING:
|
73
|
+
from c2cgeoportal_commons.models import static # pylint: disable=ungrouped-imports,useless-suppression
|
74
|
+
|
70
75
|
|
71
76
|
LOG = logging.getLogger(__name__)
|
72
77
|
|
@@ -76,64 +81,145 @@ GEOJSON_CONTENT_TYPE = r"Content-Type:application/geo\+json"
|
|
76
81
|
|
77
82
|
|
78
83
|
class AssetRendererFactory:
|
79
|
-
|
84
|
+
"""Get a renderer for the assets."""
|
85
|
+
|
86
|
+
def __init__(self, info: Any):
|
80
87
|
del info # unused
|
81
88
|
self.resolver = AssetResolver("c2cgeoportal_geoportal")
|
82
89
|
|
83
|
-
def __call__(self, value, system):
|
90
|
+
def __call__(self, value: Any, system: Dict[str, str]) -> bytes:
|
91
|
+
del value
|
84
92
|
asset = self.resolver.resolve(system["renderer_name"])
|
85
|
-
return asset.stream().read()
|
93
|
+
return cast(bytes, asset.stream().read())
|
86
94
|
|
87
95
|
|
88
96
|
INTERFACE_TYPE_NGEO = "ngeo"
|
97
|
+
INTERFACE_TYPE_CANVAS = "canvas"
|
89
98
|
|
90
99
|
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
del interface_type # unused
|
95
|
-
route = "/" if default else "/{}".format(interface_name)
|
96
|
-
add_interface_ngeo(
|
100
|
+
def add_interface_config(config: pyramid.config.Configurator, interface_config: Dict[str, Any]) -> None:
|
101
|
+
"""Add the interface (desktop, mobile, ...) views and routes with only the config."""
|
102
|
+
add_interface(
|
97
103
|
config,
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
104
|
+
interface_config["name"],
|
105
|
+
interface_config.get("type", INTERFACE_TYPE_NGEO),
|
106
|
+
interface_config,
|
107
|
+
default=interface_config.get("default", False),
|
102
108
|
)
|
103
109
|
|
104
110
|
|
105
|
-
def
|
111
|
+
def add_interface(
|
112
|
+
config: pyramid.config.Configurator,
|
113
|
+
interface_name: str = "desktop",
|
114
|
+
interface_type: str = INTERFACE_TYPE_NGEO,
|
115
|
+
interface_config: Optional[Dict[str, Any]] = None,
|
116
|
+
default: bool = False,
|
117
|
+
**kwargs: Any,
|
118
|
+
) -> None:
|
119
|
+
"""Add the interface (desktop, mobile, ...) views and routes."""
|
120
|
+
route = "/" if default else f"/{interface_name}"
|
121
|
+
if interface_type == INTERFACE_TYPE_NGEO:
|
122
|
+
add_interface_ngeo(
|
123
|
+
config,
|
124
|
+
route_name=interface_name,
|
125
|
+
route=route,
|
126
|
+
renderer=f"/etc/static-ngeo/{interface_name}.html",
|
127
|
+
**kwargs,
|
128
|
+
)
|
129
|
+
elif interface_type == INTERFACE_TYPE_CANVAS:
|
130
|
+
assert interface_config is not None
|
131
|
+
add_interface_canvas(
|
132
|
+
config,
|
133
|
+
route_name=interface_name,
|
134
|
+
route=route,
|
135
|
+
interface_config=interface_config,
|
136
|
+
**kwargs,
|
137
|
+
)
|
138
|
+
else:
|
139
|
+
LOG.error(
|
140
|
+
"Unknown interface type '%s', should be '%s' or '%s'.",
|
141
|
+
interface_type,
|
142
|
+
INTERFACE_TYPE_NGEO,
|
143
|
+
INTERFACE_TYPE_CANVAS,
|
144
|
+
)
|
145
|
+
|
146
|
+
|
147
|
+
def add_interface_ngeo(
|
148
|
+
config: pyramid.config.Configurator,
|
149
|
+
route_name: str,
|
150
|
+
route: str,
|
151
|
+
renderer: Optional[str] = None,
|
152
|
+
permission: Optional[str] = None,
|
153
|
+
) -> None:
|
154
|
+
"""Add the ngeo interfaces views and routes."""
|
106
155
|
|
107
156
|
config.add_route(route_name, route, request_method="GET")
|
108
|
-
config.add_view(
|
109
|
-
Entry, attr="get_ngeo_index_vars", route_name=route_name, renderer=renderer, permission=permission
|
110
|
-
)
|
111
157
|
# Permalink theme: recover the theme for generating custom viewer.js url
|
112
158
|
config.add_route(
|
113
|
-
"{}theme"
|
114
|
-
"{}{
|
159
|
+
f"{route_name}theme",
|
160
|
+
f"{route}{'' if route[-1] == '/' else '/'}theme/{{themes}}",
|
115
161
|
request_method="GET",
|
116
162
|
)
|
163
|
+
config.add_view(
|
164
|
+
Entry, attr="get_ngeo_index_vars", route_name=route_name, renderer=renderer, permission=permission
|
165
|
+
)
|
117
166
|
config.add_view(
|
118
167
|
Entry,
|
119
168
|
attr="get_ngeo_index_vars",
|
120
|
-
route_name="{}theme"
|
169
|
+
route_name=f"{route_name}theme",
|
170
|
+
renderer=renderer,
|
171
|
+
permission=permission,
|
172
|
+
)
|
173
|
+
|
174
|
+
|
175
|
+
def add_interface_canvas(
|
176
|
+
config: pyramid.config.Configurator,
|
177
|
+
route_name: str,
|
178
|
+
route: str,
|
179
|
+
interface_config: Dict[str, Any],
|
180
|
+
permission: Optional[str] = None,
|
181
|
+
) -> None:
|
182
|
+
"""Add the ngeo interfaces views and routes."""
|
183
|
+
|
184
|
+
renderer = f"/etc/geomapfish/interfaces/{route_name}.html.mako"
|
185
|
+
config.add_route(route_name, route, request_method="GET")
|
186
|
+
# Permalink theme: recover the theme for generating custom viewer.js URL
|
187
|
+
config.add_route(
|
188
|
+
f"{route_name}theme",
|
189
|
+
f"{route}{'' if route[-1] == '/' else '/'}theme/{{themes}}",
|
190
|
+
request_method="GET",
|
191
|
+
)
|
192
|
+
view = partial(canvas_view, interface_config=interface_config)
|
193
|
+
view.__module__ = canvas_view.__module__
|
194
|
+
config.add_view(
|
195
|
+
view,
|
196
|
+
route_name=route_name,
|
197
|
+
renderer=renderer,
|
198
|
+
permission=permission,
|
199
|
+
)
|
200
|
+
config.add_view(
|
201
|
+
view,
|
202
|
+
route_name=f"{route_name}theme",
|
121
203
|
renderer=renderer,
|
122
204
|
permission=permission,
|
123
205
|
)
|
124
206
|
|
125
207
|
|
126
|
-
def add_admin_interface(config):
|
208
|
+
def add_admin_interface(config: pyramid.config.Configurator) -> None:
|
209
|
+
"""Add the administration interface views and routes."""
|
127
210
|
if config.get_settings().get("enable_admin_interface", False):
|
128
211
|
config.add_request_method(
|
129
|
-
lambda request: c2cgeoportal_commons.models.DBSession(),
|
212
|
+
lambda request: c2cgeoportal_commons.models.DBSession(),
|
213
|
+
"dbsession",
|
214
|
+
reify=True,
|
130
215
|
)
|
131
216
|
config.add_view(c2cgeoportal_geoportal.views.add_ending_slash, route_name="admin_add_ending_slash")
|
132
217
|
config.add_route("admin_add_ending_slash", "/admin", request_method="GET")
|
133
218
|
config.include("c2cgeoportal_admin")
|
134
219
|
|
135
220
|
|
136
|
-
def add_getitfixed(config):
|
221
|
+
def add_getitfixed(config: pyramid.config.Configurator) -> None:
|
222
|
+
"""Add the get it fixed views and routes."""
|
137
223
|
if config.get_settings()["getitfixed"].get("enabled", False):
|
138
224
|
for route_name, pattern in (
|
139
225
|
("getitfixed_add_ending_slash", "/getitfixed"),
|
@@ -146,8 +232,9 @@ def add_getitfixed(config):
|
|
146
232
|
Form.set_zpt_renderer(c2cgeoform.default_search_paths, translator=translator)
|
147
233
|
|
148
234
|
|
149
|
-
def locale_negotiator(request):
|
150
|
-
|
235
|
+
def locale_negotiator(request: pyramid.request.Request) -> str:
|
236
|
+
"""Get the current language."""
|
237
|
+
lang: str = request.params.get("lang")
|
151
238
|
if lang is None:
|
152
239
|
lang = request.cookies.get("_LOCALE_")
|
153
240
|
else:
|
@@ -161,30 +248,34 @@ def locale_negotiator(request):
|
|
161
248
|
return lang
|
162
249
|
|
163
250
|
|
164
|
-
def _match_url_start(reference, value):
|
165
|
-
"""
|
166
|
-
Checks that the val URL starts like the ref URL.
|
167
|
-
"""
|
251
|
+
def _match_url_start(reference: str, value: List[str]) -> bool:
|
252
|
+
"""Check that the val URL starts like the ref URL."""
|
168
253
|
reference_parts = reference.rstrip("/").split("/")
|
169
|
-
|
170
|
-
value_parts = value[0:len(reference_parts)]
|
171
|
-
# fmt: on
|
254
|
+
value_parts = value[0 : len(reference_parts)]
|
172
255
|
return reference_parts == value_parts
|
173
256
|
|
174
257
|
|
175
|
-
def
|
258
|
+
def is_valid_referrer(request: pyramid.request.Request, settings: Optional[Dict[str, Any]] = None) -> bool:
|
259
|
+
"""Check if the referrer is valid."""
|
176
260
|
if request.referer is not None:
|
177
|
-
|
261
|
+
referrer = urlsplit(request.referer)._replace(query="", fragment="").geturl().rstrip("/").split("/")
|
178
262
|
if settings is None:
|
179
263
|
settings = request.registry.settings
|
180
264
|
list_ = settings.get("authorized_referers", [])
|
181
|
-
return any(_match_url_start(e,
|
265
|
+
return any(_match_url_start(e, referrer) for e in list_)
|
182
266
|
return True
|
183
267
|
|
184
268
|
|
185
|
-
def create_get_user_from_request(
|
186
|
-
|
187
|
-
|
269
|
+
def create_get_user_from_request(
|
270
|
+
settings: Dict[str, Any]
|
271
|
+
) -> Callable[[pyramid.request.Request, Optional[str]], Optional["static.User"]]:
|
272
|
+
"""Get the get_user_from_request function."""
|
273
|
+
|
274
|
+
def get_user_from_request(
|
275
|
+
request: pyramid.request.Request, username: Optional[str] = None
|
276
|
+
) -> Optional["static.User"]:
|
277
|
+
"""
|
278
|
+
Return the User object for the request.
|
188
279
|
|
189
280
|
Return ``None`` if:
|
190
281
|
* user is anonymous
|
@@ -194,35 +285,8 @@ def create_get_user_from_request(settings):
|
|
194
285
|
from c2cgeoportal_commons.models import DBSession # pylint: disable=import-outside-toplevel
|
195
286
|
from c2cgeoportal_commons.models.static import User # pylint: disable=import-outside-toplevel
|
196
287
|
|
197
|
-
try:
|
198
|
-
if request.method == "GET" and "auth" in request.params:
|
199
|
-
auth_enc = request.params.get("auth")
|
200
|
-
|
201
|
-
if auth_enc is not None:
|
202
|
-
urllogin = request.registry.settings.get("urllogin", {})
|
203
|
-
aeskey = urllogin.get("aes_key")
|
204
|
-
if aeskey is None: # pragma: nocover
|
205
|
-
raise Exception("urllogin is not configured")
|
206
|
-
now = int(time.time())
|
207
|
-
data = binascii.unhexlify(auth_enc.encode("ascii"))
|
208
|
-
nonce = data[0:16]
|
209
|
-
tag = data[16:32]
|
210
|
-
ciphertext = data[32:]
|
211
|
-
cipher = AES.new(aeskey.encode("ascii"), AES.MODE_EAX, nonce)
|
212
|
-
auth = json.loads(
|
213
|
-
cipher.decrypt_and_verify(ciphertext, tag).decode("utf-8") # type: ignore
|
214
|
-
)
|
215
|
-
|
216
|
-
if "t" in auth and "u" in auth and "p" in auth:
|
217
|
-
timestamp = int(auth["t"])
|
218
|
-
if now < timestamp and request.registry.validate_user(request, auth["u"], auth["p"]):
|
219
|
-
headers = pyramid.security.remember(request, auth["u"])
|
220
|
-
request.response.headerlist.extend(headers)
|
221
|
-
except Exception as e:
|
222
|
-
LOG.error("URL login error: %s.", e, exc_info=True)
|
223
|
-
|
224
288
|
if not hasattr(request, "is_valid_referer"):
|
225
|
-
request.is_valid_referer =
|
289
|
+
request.is_valid_referer = is_valid_referrer(request, settings)
|
226
290
|
if not request.is_valid_referer:
|
227
291
|
LOG.debug("Invalid referer for %s: %s", request.path_qs, repr(request.referer))
|
228
292
|
return None
|
@@ -234,15 +298,20 @@ def create_get_user_from_request(settings):
|
|
234
298
|
if username is not None:
|
235
299
|
# We know we will need the role object of the
|
236
300
|
# user so we use joined loading
|
237
|
-
request.user_ =
|
301
|
+
request.user_ = (
|
302
|
+
DBSession.query(User).filter_by(username=username).options(joinedload("roles")).first()
|
303
|
+
)
|
238
304
|
|
239
|
-
return request.user_
|
305
|
+
return cast(User, request.user_)
|
240
306
|
|
241
307
|
return get_user_from_request
|
242
308
|
|
243
309
|
|
244
|
-
def set_user_validator(
|
245
|
-
|
310
|
+
def set_user_validator(
|
311
|
+
config: pyramid.config.Configurator, user_validator: Callable[[pyramid.request.Request, str, str], str]
|
312
|
+
) -> None:
|
313
|
+
"""
|
314
|
+
Call this function to register a user validator function.
|
246
315
|
|
247
316
|
The validator function is passed three arguments: ``request``,
|
248
317
|
``username``, and ``password``. The function should return the
|
@@ -258,11 +327,12 @@ def set_user_validator(config, user_validator):
|
|
258
327
|
config.action("user_validator", register)
|
259
328
|
|
260
329
|
|
261
|
-
def default_user_validator(request, username, password):
|
330
|
+
def default_user_validator(request: pyramid.request.Request, username: str, password: str) -> Optional[str]:
|
262
331
|
"""
|
263
|
-
Validate the username/password.
|
264
|
-
|
265
|
-
Return None if we are anonymous, the string to remember
|
332
|
+
Validate the username/password.
|
333
|
+
|
334
|
+
This is c2cgeoportal's default user validator. Return None if we are anonymous, the string to remember
|
335
|
+
otherwise.
|
266
336
|
"""
|
267
337
|
del request # unused
|
268
338
|
from c2cgeoportal_commons.models import DBSession # pylint: disable=import-outside-toplevel
|
@@ -270,7 +340,7 @@ def default_user_validator(request, username, password):
|
|
270
340
|
|
271
341
|
user = DBSession.query(User).filter_by(username=username).first()
|
272
342
|
if user is None:
|
273
|
-
LOG.info('
|
343
|
+
LOG.info('Unknown user "%s" tried to log in', username)
|
274
344
|
return None
|
275
345
|
if user.deactivated:
|
276
346
|
LOG.info('Deactivated user "%s" tried to log in', username)
|
@@ -285,49 +355,52 @@ def default_user_validator(request, username, password):
|
|
285
355
|
|
286
356
|
|
287
357
|
class MapserverproxyRoutePredicate:
|
288
|
-
"""
|
289
|
-
|
290
|
-
|
358
|
+
"""
|
359
|
+
Serve as a custom route predicate function for mapserverproxy.
|
360
|
+
|
361
|
+
If the hide_capabilities setting is set and is true then we want to return 404s on GetCapabilities
|
362
|
+
requests.
|
363
|
+
"""
|
291
364
|
|
292
|
-
def __init__(self, val, config):
|
293
|
-
|
365
|
+
def __init__(self, val: Any, config: pyramid.config.Configurator) -> None:
|
366
|
+
del val, config
|
294
367
|
|
295
|
-
def __call__(self, context, request):
|
368
|
+
def __call__(self, context: Any, request: pyramid.request.Request) -> bool:
|
369
|
+
del context
|
296
370
|
hide_capabilities = request.registry.settings.get("hide_capabilities")
|
297
371
|
if not hide_capabilities:
|
298
372
|
return True
|
299
|
-
params =
|
373
|
+
params = {k.lower(): v.lower() for k, v in request.params.items()}
|
300
374
|
return "request" not in params or params["request"] not in ("getcapabilities", "capabilities")
|
301
375
|
|
302
376
|
@staticmethod
|
303
|
-
def text():
|
377
|
+
def text() -> str:
|
304
378
|
return "mapserverproxy"
|
305
379
|
|
306
380
|
phash = text
|
307
381
|
|
308
382
|
|
309
|
-
def add_cors_route(config, pattern, service):
|
310
|
-
"""
|
311
|
-
Add the OPTIONS route and view need for services supporting CORS.
|
312
|
-
"""
|
383
|
+
def add_cors_route(config: pyramid.config.Configurator, pattern: str, service: str) -> None:
|
384
|
+
"""Add the OPTIONS route and view need for services supporting CORS."""
|
313
385
|
|
314
|
-
def view(request
|
315
|
-
return set_common_headers(request, service,
|
386
|
+
def view(request: pyramid.request.Request) -> pyramid.response.Response:
|
387
|
+
return set_common_headers(request, service, Cache.PRIVATE_NO)
|
316
388
|
|
317
389
|
name = pattern + "_options"
|
318
390
|
config.add_route(name, pattern, request_method="OPTIONS")
|
319
391
|
config.add_view(view, route_name=name)
|
320
392
|
|
321
393
|
|
322
|
-
def error_handler(
|
323
|
-
|
324
|
-
|
325
|
-
"""
|
394
|
+
def error_handler(
|
395
|
+
http_exception: HTTPException, request: pyramid.request.Request
|
396
|
+
) -> pyramid.response.Response:
|
397
|
+
"""View callable for handling all the exceptions that are not already handled."""
|
326
398
|
LOG.warning("%s returned status code %s", request.url, http_exception.status_code)
|
327
|
-
return
|
399
|
+
return set_common_headers(request, "error", Cache.PRIVATE_NO, http_exception)
|
328
400
|
|
329
401
|
|
330
|
-
def call_hook(settings, name, *args, **kwargs):
|
402
|
+
def call_hook(settings: pyramid.config.Configurator, name: str, *args: Any, **kwargs: Any) -> None:
|
403
|
+
"""Call the hook defined in the settings."""
|
331
404
|
hooks = settings.get("hooks", {})
|
332
405
|
hook = hooks.get(name)
|
333
406
|
if hook is None:
|
@@ -338,24 +411,32 @@ def call_hook(settings, name, *args, **kwargs):
|
|
338
411
|
function_(*args, **kwargs)
|
339
412
|
|
340
413
|
|
341
|
-
def includeme(config: pyramid.config.Configurator):
|
342
|
-
"""
|
343
|
-
This function returns a Pyramid WSGI application.
|
344
|
-
"""
|
345
|
-
|
414
|
+
def includeme(config: pyramid.config.Configurator) -> None:
|
415
|
+
"""Get the Pyramid WSGI application."""
|
346
416
|
settings = config.get_settings()
|
347
417
|
|
348
|
-
|
418
|
+
if "available_locale_names" not in settings:
|
419
|
+
settings["available_locale_names"] = available_locale_names()
|
349
420
|
|
350
421
|
call_hook(settings, "after_settings", settings)
|
351
422
|
|
352
423
|
get_user_from_request = create_get_user_from_request(settings)
|
353
424
|
config.add_request_method(get_user_from_request, name="user", property=True)
|
354
425
|
config.add_request_method(get_user_from_request, name="get_user")
|
426
|
+
# Be able for an organization to override the method to use alternate:
|
427
|
+
# - Organization roles name for the standard roles 'anonymous', 'registered' and 'intranet'.
|
428
|
+
config.add_request_method(lambda request, role_type: role_type, name="get_organization_role")
|
429
|
+
# - Organization print URL
|
430
|
+
config.add_request_method(
|
431
|
+
lambda request: request.registry.settings["print_url"], name="get_organization_print_url"
|
432
|
+
)
|
433
|
+
# - Organization interface name (in the config and in the admin interface)
|
434
|
+
config.add_request_method(lambda request, interface: interface, name="get_organization_interface")
|
355
435
|
|
356
436
|
# Configure 'locale' dir as the translation dir for c2cgeoportal app
|
357
437
|
config.add_translation_dirs("c2cgeoportal_geoportal:locale/")
|
358
438
|
|
439
|
+
config.include("pyramid_mako")
|
359
440
|
config.include("c2cwsgiutils.pyramid.includeme")
|
360
441
|
health_check = HealthCheck(config)
|
361
442
|
config.registry["health_check"] = health_check
|
@@ -373,28 +454,31 @@ def includeme(config: pyramid.config.Configurator):
|
|
373
454
|
add_provider(TotalPythonObjectMemoryProvider())
|
374
455
|
|
375
456
|
# Initialise DBSessions
|
376
|
-
|
457
|
+
init_db_sessions(settings, config, health_check)
|
377
458
|
|
378
459
|
checker.init(config, health_check)
|
379
460
|
check_collector.init(config, health_check)
|
380
461
|
|
381
462
|
# dogpile.cache configuration
|
382
463
|
if "cache" in settings:
|
383
|
-
register_backend("c2cgeoportal.hybrid", "c2cgeoportal_geoportal.lib.caching", "
|
464
|
+
register_backend("c2cgeoportal.hybrid", "c2cgeoportal_geoportal.lib.caching", "HybridRedisBackend")
|
465
|
+
register_backend(
|
466
|
+
"c2cgeoportal.hybridsentinel", "c2cgeoportal_geoportal.lib.caching", "HybridRedisSentinelBackend"
|
467
|
+
)
|
384
468
|
for name, cache_config in settings["cache"].items():
|
385
469
|
caching.init_region(cache_config, name)
|
386
470
|
|
387
|
-
@zope.event.classhandler.handler(InvalidateCacheEvent)
|
388
|
-
def handle(event: InvalidateCacheEvent)
|
471
|
+
@zope.event.classhandler.handler(InvalidateCacheEvent) # type: ignore
|
472
|
+
def handle(event: InvalidateCacheEvent) -> None:
|
389
473
|
del event
|
390
474
|
caching.invalidate_region()
|
391
475
|
if caching.MEMORY_CACHE_DICT:
|
392
|
-
caching.get_region("std").delete_multi(caching.MEMORY_CACHE_DICT.keys())
|
476
|
+
caching.get_region("std").delete_multi(list(caching.MEMORY_CACHE_DICT.keys()))
|
393
477
|
caching.MEMORY_CACHE_DICT.clear()
|
394
478
|
|
395
479
|
# Register a tween to get back the cache buster path.
|
396
480
|
if "cache_path" not in config.get_settings():
|
397
|
-
config.get_settings()["cache_path"] = ["static"]
|
481
|
+
config.get_settings()["cache_path"] = ["static", "static-geomapfish"]
|
398
482
|
config.add_tween("c2cgeoportal_geoportal.lib.cacheversion.CachebusterTween")
|
399
483
|
config.add_tween("c2cgeoportal_geoportal.lib.headers.HeadersTween")
|
400
484
|
|
@@ -412,6 +496,10 @@ def includeme(config: pyramid.config.Configurator):
|
|
412
496
|
config.add_directive("set_user_validator", set_user_validator)
|
413
497
|
config.set_user_validator(default_user_validator)
|
414
498
|
|
499
|
+
config.add_route("oauth2token", "/oauth/token", request_method="POST")
|
500
|
+
config.add_route("oauth2loginform", "/oauth/login", request_method="GET")
|
501
|
+
config.add_route("notlogin", "/notlogin", request_method="GET")
|
502
|
+
|
415
503
|
config.add_route("dynamic", "/dynamic.json", request_method="GET")
|
416
504
|
|
417
505
|
# Add routes to the mapserver proxy
|
@@ -430,6 +518,22 @@ def includeme(config: pyramid.config.Configurator):
|
|
430
518
|
pregenerator=C2CPregenerator(role=True),
|
431
519
|
request_method="POST",
|
432
520
|
)
|
521
|
+
# The tow next views are used to serve the application on the URL /mapserv_proxy/<ogc server name>
|
522
|
+
# instead of /mapserv_proxy?ogcserver=<ogc server name>, required for QGIS server landing page
|
523
|
+
config.add_route(
|
524
|
+
"mapserverproxy_get_path",
|
525
|
+
"/mapserv_proxy/{ogcserver}/*path",
|
526
|
+
mapserverproxy=True,
|
527
|
+
pregenerator=C2CPregenerator(role=True),
|
528
|
+
request_method="GET",
|
529
|
+
)
|
530
|
+
config.add_route(
|
531
|
+
"mapserverproxy_post_path",
|
532
|
+
"/mapserv_proxy/{ogcserver}/*path",
|
533
|
+
mapserverproxy=True,
|
534
|
+
pregenerator=C2CPregenerator(role=True),
|
535
|
+
request_method="POST",
|
536
|
+
)
|
433
537
|
add_cors_route(config, "/mapserv_proxy", "mapserver")
|
434
538
|
|
435
539
|
# Add route to the tinyows proxy
|
@@ -454,14 +558,15 @@ def includeme(config: pyramid.config.Configurator):
|
|
454
558
|
config.add_renderer(".css", AssetRendererFactory)
|
455
559
|
config.add_renderer(".ico", AssetRendererFactory)
|
456
560
|
config.add_route("localejson", "/locale.json", request_method="GET")
|
561
|
+
config.add_route("localepot", "/locale.pot", request_method="GET")
|
457
562
|
|
458
|
-
def add_static_route(name: str, attr: str, path: str, renderer: str):
|
563
|
+
def add_static_route(name: str, attr: str, path: str, renderer: str) -> None:
|
459
564
|
config.add_route(name, path, request_method="GET")
|
460
565
|
config.add_view(Entry, attr=attr, route_name=name, renderer=renderer)
|
461
566
|
|
462
567
|
add_static_route("favicon", "favicon", "/favicon.ico", "/etc/geomapfish/static/images/favicon.ico")
|
463
568
|
add_static_route("robot.txt", "robot_txt", "/robot.txt", "/etc/geomapfish/static/robot.txt")
|
464
|
-
|
569
|
+
config.add_route("apijs", "/api.js", request_method="GET")
|
465
570
|
add_static_route("apijsmap", "apijsmap", "/api.js.map", "/etc/static-ngeo/api.js.map")
|
466
571
|
add_static_route("apicss", "apicss", "/api.css", "/etc/static-ngeo/api.css")
|
467
572
|
add_static_route("apihelp", "apihelp", "/apihelp/index.html", "/etc/geomapfish/static/apihelp/index.html")
|
@@ -501,6 +606,13 @@ def includeme(config: pyramid.config.Configurator):
|
|
501
606
|
add_cors_route(config, "/profile.json", "profile")
|
502
607
|
config.add_route("profile.json", "/profile.json", request_method="POST")
|
503
608
|
|
609
|
+
# Access to vector tiles
|
610
|
+
add_cors_route(config, "/vector_tiles", "vector_tiles")
|
611
|
+
config.add_route("vector_tiles", "/vector_tiles/{layer_name}/{z}/{x}/{y}.pbf", request_method="GET")
|
612
|
+
# There is no view corresponding to that route, it is to be used from
|
613
|
+
# mako templates to get the root of the "vector_tiles" web service
|
614
|
+
config.add_route("vector_tiles_root", "/vector_tiles", request_method="HEAD")
|
615
|
+
|
504
616
|
# Shortener
|
505
617
|
add_cors_route(config, "/short/create", "shortener")
|
506
618
|
config.add_route("shortener_create", "/short/create", request_method="POST")
|
@@ -581,13 +693,29 @@ def includeme(config: pyramid.config.Configurator):
|
|
581
693
|
cache_max_age=int(config.get_settings()["default_max_age"]),
|
582
694
|
)
|
583
695
|
|
696
|
+
# Add the c2cgeoportal static view with cache buster
|
697
|
+
config.add_static_view(
|
698
|
+
name="static-geomapfish",
|
699
|
+
path="c2cgeoportal_geoportal:static",
|
700
|
+
cache_max_age=int(config.get_settings()["default_max_age"]),
|
701
|
+
)
|
702
|
+
config.add_cache_buster("c2cgeoportal_geoportal:static", version_cache_buster)
|
703
|
+
|
704
|
+
# Add the project static view without cache buster
|
705
|
+
config.add_static_view(
|
706
|
+
name="static-ngeo-dist",
|
707
|
+
path="/opt/c2cgeoportal/geoportal/node_modules/ngeo/dist",
|
708
|
+
cache_max_age=int(config.get_settings()["default_max_age"]),
|
709
|
+
)
|
710
|
+
|
584
711
|
# Handles the other HTTP errors raised by the views. Without that,
|
585
712
|
# the client receives a status=200 without content.
|
586
713
|
config.add_view(error_handler, context=HTTPException)
|
587
714
|
|
588
715
|
c2cwsgiutils.index.additional_title = (
|
589
|
-
'<div class="row"><div class="col-lg-3"><h2>GeoMapFish</h2
|
716
|
+
'<div class="row"><div class="col-lg-3"><h2>GeoMapFish</h2></div><div class="col-lg">'
|
590
717
|
)
|
718
|
+
|
591
719
|
c2cwsgiutils.index.additional_auth.extend(
|
592
720
|
[
|
593
721
|
'<a href="../tiles/admin/">TileCloud chain admin</a><br>',
|
@@ -612,10 +740,13 @@ def includeme(config: pyramid.config.Configurator):
|
|
612
740
|
c2cwsgiutils.index.additional_noauth.append("</div></div><hr>")
|
613
741
|
|
614
742
|
|
615
|
-
def
|
743
|
+
def init_db_sessions(
|
744
|
+
settings: Dict[str, Any], config: Configurator, health_check: Optional[HealthCheck] = None
|
745
|
+
) -> None:
|
746
|
+
"""Initialize the database sessions."""
|
616
747
|
db_chooser = settings.get("db_chooser", {})
|
617
|
-
master_paths = [
|
618
|
-
slave_paths = [
|
748
|
+
master_paths = [i.replace("//", "/") for i in db_chooser.get("master", [])]
|
749
|
+
slave_paths = [i.replace("//", "/") for i in db_chooser.get("slave", [])]
|
619
750
|
|
620
751
|
slave_prefix = "sqlalchemy_slave" if "sqlalchemy_slave.url" in settings else None
|
621
752
|
|
@@ -653,7 +784,7 @@ def init_dbsessions(settings: dict, config: Configurator, health_check: HealthCh
|
|
653
784
|
version_schema=settings["schema_static"],
|
654
785
|
level=1,
|
655
786
|
)
|
656
|
-
else:
|
787
|
+
else:
|
657
788
|
|
658
789
|
def check(session_: Session) -> None:
|
659
790
|
session_.execute("SELECT 1")
|