c2cgeoportal-geoportal 2.6.0__py2.py3-none-any.whl → 2.7.1.86__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. c2cgeoportal_geoportal/__init__.py +224 -84
  2. c2cgeoportal_geoportal/lib/__init__.py +64 -42
  3. c2cgeoportal_geoportal/lib/authentication.py +50 -22
  4. c2cgeoportal_geoportal/lib/bashcolor.py +17 -13
  5. c2cgeoportal_geoportal/lib/cacheversion.py +16 -8
  6. c2cgeoportal_geoportal/lib/caching.py +61 -191
  7. c2cgeoportal_geoportal/lib/check_collector.py +17 -10
  8. c2cgeoportal_geoportal/lib/checker.py +61 -63
  9. c2cgeoportal_geoportal/lib/common_headers.py +170 -0
  10. c2cgeoportal_geoportal/lib/dbreflection.py +54 -39
  11. c2cgeoportal_geoportal/lib/filter_capabilities.py +119 -87
  12. c2cgeoportal_geoportal/lib/fulltextsearch.py +6 -5
  13. c2cgeoportal_geoportal/lib/functionality.py +20 -17
  14. c2cgeoportal_geoportal/lib/headers.py +14 -5
  15. c2cgeoportal_geoportal/lib/i18n.py +4 -4
  16. c2cgeoportal_geoportal/lib/layers.py +30 -11
  17. c2cgeoportal_geoportal/lib/lingua_extractor.py +361 -237
  18. c2cgeoportal_geoportal/lib/loader.py +10 -15
  19. c2cgeoportal_geoportal/lib/metrics.py +28 -17
  20. c2cgeoportal_geoportal/lib/oauth2.py +214 -145
  21. c2cgeoportal_geoportal/lib/wmstparsing.py +115 -90
  22. c2cgeoportal_geoportal/lib/xsd.py +26 -16
  23. c2cgeoportal_geoportal/resources.py +15 -9
  24. c2cgeoportal_geoportal/scaffolds/advance_create/ci/config.yaml +26 -0
  25. c2cgeoportal_geoportal/scaffolds/advance_create/cookiecutter.json +18 -0
  26. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/.dockerignore +6 -0
  27. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/.eslintrc.yaml +19 -0
  28. c2cgeoportal_geoportal/scaffolds/{create/geoportal/+dot+prospector.yaml → advance_create/{{cookiecutter.project}}/geoportal/.prospector.yaml} +8 -2
  29. c2cgeoportal_geoportal/scaffolds/{create/geoportal/Dockerfile_tmpl → advance_create/{{cookiecutter.project}}/geoportal/Dockerfile} +18 -9
  30. c2cgeoportal_geoportal/scaffolds/{create/geoportal/alembic.yaml_tmpl → advance_create/{{cookiecutter.project}}/geoportal/alembic.yaml} +1 -1
  31. c2cgeoportal_geoportal/scaffolds/{create/geoportal/development.ini_tmpl → advance_create/{{cookiecutter.project}}/geoportal/development.ini} +34 -15
  32. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/gunicorn.conf.py +104 -0
  33. c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/lingua-client.cfg +1 -0
  34. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/production.ini +38 -0
  35. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/requirements.txt +2 -0
  36. c2cgeoportal_geoportal/scaffolds/{create/geoportal/setup.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/setup.py} +6 -7
  37. c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/tools/extract-messages.js +8 -6
  38. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/tsconfig.json +8 -0
  39. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.api.js +75 -0
  40. c2cgeoportal_geoportal/scaffolds/{create/geoportal/webpack.apps.js_tmpl → advance_create/{{cookiecutter.project}}/geoportal/webpack.apps.js} +31 -28
  41. c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/webpack.commons.js +3 -7
  42. c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/webpack.config.js +1 -1
  43. c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal/__init__.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/__init__.py} +11 -22
  44. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/authentication.py +10 -0
  45. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/dev.py +14 -0
  46. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/models.py +8 -0
  47. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/multi_organization.py +7 -0
  48. c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/resources.py +4 -3
  49. 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
  50. 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
  51. c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal/subscribers.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/subscribers.py} +1 -3
  52. c2cgeoportal_geoportal/scaffolds/advance_update/cookiecutter.json +18 -0
  53. c2cgeoportal_geoportal/scaffolds/{update/geoportal/CONST_Makefile_tmpl → advance_update/{{cookiecutter.project}}/geoportal/CONST_Makefile} +3 -7
  54. c2cgeoportal_geoportal/scaffolds/create/cookiecutter.json +18 -0
  55. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.dockerignore +14 -0
  56. c2cgeoportal_geoportal/scaffolds/create/{+dot+editorconfig → {{cookiecutter.project}}/.editorconfig} +2 -5
  57. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/main.yaml +43 -0
  58. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/rebuild.yaml +46 -0
  59. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/update_l10n.yaml +65 -0
  60. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.gitignore +16 -0
  61. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.prettierignore +1 -0
  62. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.prettierrc.yaml +2 -0
  63. c2cgeoportal_geoportal/scaffolds/create/{Dockerfile_tmpl → {{cookiecutter.project}}/Dockerfile} +20 -11
  64. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Makefile +14 -0
  65. c2cgeoportal_geoportal/scaffolds/create/{README.rst_tmpl → {{cookiecutter.project}}/README.rst} +4 -4
  66. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/build +158 -0
  67. c2cgeoportal_geoportal/scaffolds/create/{ci/config.yaml_tmpl → {{cookiecutter.project}}/ci/config.yaml} +7 -5
  68. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/requirements.txt +1 -0
  69. c2cgeoportal_geoportal/scaffolds/create/{docker-compose-lib.yaml → {{cookiecutter.project}}/docker-compose-lib.yaml} +133 -17
  70. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.override.sample.yaml +66 -0
  71. c2cgeoportal_geoportal/scaffolds/create/{docker-compose.yaml → {{cookiecutter.project}}/docker-compose.yaml} +17 -12
  72. c2cgeoportal_geoportal/scaffolds/create/{env.default_tmpl → {{cookiecutter.project}}/env.default} +29 -14
  73. c2cgeoportal_geoportal/scaffolds/create/{env.project_tmpl → {{cookiecutter.project}}/env.project} +16 -4
  74. c2cgeoportal_geoportal/scaffolds/create/{geoportal/vars.yaml_tmpl → {{cookiecutter.project}}/geoportal/vars.yaml} +93 -27
  75. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/mobile.css +0 -0
  76. c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/data/Readme.txt +1 -1
  77. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/demo.map.tmpl +224 -0
  78. c2cgeoportal_geoportal/scaffolds/create/{mapserver/mapserver.map.tmpl_tmpl → {{cookiecutter.project}}/mapserver/mapserver.map.tmpl} +7 -15
  79. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A3_Landscape.jrxml +8 -8
  80. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A3_Portrait.jrxml +8 -8
  81. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A4_Landscape.jrxml +8 -8
  82. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A4_Portrait.jrxml +8 -8
  83. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/config.yaml.tmpl +5 -4
  84. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/localisation.properties +4 -0
  85. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/localisation_fr.properties +4 -0
  86. c2cgeoportal_geoportal/scaffolds/create/{project.yaml_tmpl → {{cookiecutter.project}}/project.yaml} +6 -6
  87. c2cgeoportal_geoportal/scaffolds/create/{qgisserver/pg_service.conf.tmpl_tmpl → {{cookiecutter.project}}/qgisserver/pg_service.conf.tmpl} +2 -2
  88. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-backup +107 -0
  89. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-restore +111 -0
  90. c2cgeoportal_geoportal/scaffolds/create/{setup.cfg_tmpl → {{cookiecutter.project}}/setup.cfg} +1 -1
  91. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/spell-ignore-words.txt +3 -0
  92. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tilegeneration/config.yaml.tmpl +195 -0
  93. c2cgeoportal_geoportal/scaffolds/update/cookiecutter.json +18 -0
  94. c2cgeoportal_geoportal/scaffolds/update/{+dot+upgrade.yaml_tmpl → {{cookiecutter.project}}/.upgrade.yaml} +49 -39
  95. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_CHANGELOG.txt +1153 -0
  96. c2cgeoportal_geoportal/scaffolds/update/{geoportal → {{cookiecutter.project}}/geoportal}/CONST_config-schema.yaml +47 -2
  97. c2cgeoportal_geoportal/scaffolds/update/{geoportal/CONST_vars.yaml_tmpl → {{cookiecutter.project}}/geoportal/CONST_vars.yaml} +350 -15
  98. c2cgeoportal_geoportal/scripts/__init__.py +15 -31
  99. c2cgeoportal_geoportal/scripts/c2cupgrade.py +271 -232
  100. c2cgeoportal_geoportal/scripts/create_demo_theme.py +3 -6
  101. c2cgeoportal_geoportal/scripts/manage_users.py +34 -39
  102. c2cgeoportal_geoportal/scripts/pcreate.py +312 -0
  103. c2cgeoportal_geoportal/scripts/theme2fts.py +72 -23
  104. c2cgeoportal_geoportal/scripts/urllogin.py +17 -9
  105. c2cgeoportal_geoportal/templates/login.html +88 -84
  106. c2cgeoportal_geoportal/templates/notlogin.html +59 -59
  107. c2cgeoportal_geoportal/templates/testi18n.html +6 -8
  108. c2cgeoportal_geoportal/views/__init__.py +23 -4
  109. c2cgeoportal_geoportal/views/dev.py +9 -7
  110. c2cgeoportal_geoportal/views/dynamic.py +54 -18
  111. c2cgeoportal_geoportal/views/entry.py +93 -24
  112. c2cgeoportal_geoportal/views/fulltextsearch.py +28 -22
  113. c2cgeoportal_geoportal/views/geometry_processing.py +15 -7
  114. c2cgeoportal_geoportal/views/i18n.py +91 -9
  115. c2cgeoportal_geoportal/views/layers.py +160 -126
  116. c2cgeoportal_geoportal/views/login.py +106 -93
  117. c2cgeoportal_geoportal/views/mapserverproxy.py +45 -28
  118. c2cgeoportal_geoportal/views/memory.py +12 -12
  119. c2cgeoportal_geoportal/views/ogcproxy.py +48 -30
  120. c2cgeoportal_geoportal/views/pdfreport.py +26 -22
  121. c2cgeoportal_geoportal/views/printproxy.py +56 -50
  122. c2cgeoportal_geoportal/views/profile.py +24 -23
  123. c2cgeoportal_geoportal/views/proxy.py +84 -67
  124. c2cgeoportal_geoportal/views/raster.py +35 -24
  125. c2cgeoportal_geoportal/views/resourceproxy.py +13 -11
  126. c2cgeoportal_geoportal/views/shortener.py +27 -24
  127. c2cgeoportal_geoportal/views/theme.py +427 -321
  128. c2cgeoportal_geoportal/views/tinyowsproxy.py +46 -39
  129. c2cgeoportal_geoportal/views/vector_tiles.py +80 -0
  130. {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.86.dist-info}/METADATA +24 -20
  131. c2cgeoportal_geoportal-2.7.1.86.dist-info/RECORD +185 -0
  132. {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.86.dist-info}/WHEEL +1 -1
  133. {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.86.dist-info}/entry_points.txt +3 -1
  134. tests/__init__.py +7 -3
  135. tests/test_cachebuster.py +0 -2
  136. tests/test_caching.py +17 -25
  137. tests/test_checker.py +0 -2
  138. tests/test_decimaljson.py +4 -4
  139. tests/test_headerstween.py +0 -2
  140. tests/test_i18n.py +1 -1
  141. tests/test_init.py +4 -7
  142. tests/test_locale_negociator.py +0 -2
  143. tests/test_mapserverproxy_route_predicate.py +0 -2
  144. tests/test_raster.py +0 -2
  145. tests/test_wmstparsing.py +0 -2
  146. c2cgeoportal_geoportal/scaffolds/__init__.py +0 -227
  147. c2cgeoportal_geoportal/scaffolds/create/+dot+dockerignore_tmpl +0 -12
  148. c2cgeoportal_geoportal/scaffolds/create/+dot+github/workflows/main.yaml_tmpl +0 -89
  149. c2cgeoportal_geoportal/scaffolds/create/+dot+github/workflows/rebuild.yaml_tmpl +0 -78
  150. c2cgeoportal_geoportal/scaffolds/create/+dot+gitignore_tmpl +0 -16
  151. c2cgeoportal_geoportal/scaffolds/create/Makefile +0 -3
  152. c2cgeoportal_geoportal/scaffolds/create/build_tmpl +0 -167
  153. c2cgeoportal_geoportal/scaffolds/create/ci/requirements.txt +0 -1
  154. c2cgeoportal_geoportal/scaffolds/create/ci/trigger +0 -68
  155. c2cgeoportal_geoportal/scaffolds/create/docker-compose.override.sample.yaml +0 -54
  156. c2cgeoportal_geoportal/scaffolds/create/geoportal/+dot+dockerignore_tmpl +0 -6
  157. c2cgeoportal_geoportal/scaffolds/create/geoportal/+dot+eslintrc_tmpl +0 -15
  158. c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/models.py_tmpl +0 -10
  159. c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/static/robot.txt +0 -3
  160. c2cgeoportal_geoportal/scaffolds/create/geoportal/production.ini_tmpl +0 -106
  161. c2cgeoportal_geoportal/scaffolds/create/geoportal/requirements.txt +0 -2
  162. c2cgeoportal_geoportal/scaffolds/create/geoportal/tsconfig.json_tmpl +0 -9
  163. c2cgeoportal_geoportal/scaffolds/create/geoportal/webpack.api.js_tmpl +0 -72
  164. c2cgeoportal_geoportal/scaffolds/create/mapserver/demo.map.tmpl_tmpl +0 -262
  165. c2cgeoportal_geoportal/scaffolds/create/mapserver/tinyows.xml +0 -36
  166. c2cgeoportal_geoportal/scaffolds/create/print/print-apps/+package+/config.yaml +0 -168
  167. c2cgeoportal_geoportal/scaffolds/create/qgisserver/geomapfish.yaml.tmpl_tmpl +0 -16
  168. c2cgeoportal_geoportal/scaffolds/create/spell-ignore-words.txt +0 -1
  169. c2cgeoportal_geoportal/scaffolds/create/tilegeneration/config.yaml.tmpl_tmpl +0 -185
  170. c2cgeoportal_geoportal/scaffolds/create/yamllint.yaml +0 -11
  171. c2cgeoportal_geoportal/scaffolds/update/CONST_CHANGELOG.txt_tmpl +0 -454
  172. c2cgeoportal_geoportal/templates/dynamic.js +0 -21
  173. c2cgeoportal_geoportal-2.6.0.dist-info/RECORD +0 -173
  174. /c2cgeoportal_geoportal/{scaffolds/create/geoportal/+package+_geoportal/static/css/desktop.css → py.typed} +0 -0
  175. /c2cgeoportal_geoportal/scaffolds/{create/geoportal/Makefile_tmpl → advance_create/{{cookiecutter.project}}/geoportal/Makefile} +0 -0
  176. /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/alembic.ini +0 -0
  177. /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/language_mapping +0 -0
  178. /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/lingua-server.cfg +0 -0
  179. /c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/views/__init__.py +0 -0
  180. /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
  181. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal/static/css/iframe_api.css → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/desktop.css} +0 -0
  182. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal/static/css/mobile.css → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/iframe_api.css} +0 -0
  183. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/banner_left.png +0 -0
  184. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/banner_right.png +0 -0
  185. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/blank.png +0 -0
  186. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-blue.png +0 -0
  187. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-gold.png +0 -0
  188. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-green.png +0 -0
  189. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker.png +0 -0
  190. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/robot.txt.tmpl +0 -0
  191. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/data/TM_EUROPE_BORDERS-0.3.sql +0 -0
  192. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arial.ttf +0 -0
  193. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arialbd.ttf +0 -0
  194. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arialbi.ttf +0 -0
  195. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Ariali.ttf +0 -0
  196. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Bold.ttf +0 -0
  197. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-BoldItalic.ttf +0 -0
  198. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Italic.ttf +0 -0
  199. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Regular.ttf +0 -0
  200. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdana.ttf +0 -0
  201. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanab.ttf +0 -0
  202. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanai.ttf +0 -0
  203. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanaz.ttf +0 -0
  204. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts.conf +0 -0
  205. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/tinyows.xml.tmpl +0 -0
  206. /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/legend.jrxml +0 -0
  207. /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/logo.png +0 -0
  208. /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/north.svg +0 -0
  209. /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/results.jrxml +0 -0
  210. /c2cgeoportal_geoportal/scaffolds/create/{pyproject.toml → {{cookiecutter.project}}/pyproject.toml} +0 -0
  211. /c2cgeoportal_geoportal/scaffolds/create/{run_alembic.sh → {{cookiecutter.project}}/run_alembic.sh} +0 -0
  212. {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.86.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  # Copyright (c) 2012-2021, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
@@ -32,41 +30,51 @@ import binascii
32
30
  import json
33
31
  import sys
34
32
  import time
33
+ from typing import cast
35
34
 
36
35
  from Crypto.Cipher import AES # nosec
36
+ from Crypto.Cipher.ChaCha20_Poly1305 import ChaCha20Poly1305Cipher # nosec
37
37
 
38
38
  from c2cgeoportal_geoportal.scripts import fill_arguments, get_appsettings
39
39
 
40
40
 
41
- def create_token(aeskey, user, password, valid):
41
+ def create_token(aeskey: str, user: str, password: str, valid: bool) -> str:
42
+ """Create the authenticated URL token."""
42
43
  auth = {"u": user, "p": password, "t": int(time.time()) + valid * 3600 * 24}
43
44
 
44
45
  if aeskey is None:
45
46
  print("urllogin is not configured")
46
47
  sys.exit(1)
47
- cipher = AES.new(aeskey.encode("ascii"), AES.MODE_EAX)
48
+ cipher = cast(ChaCha20Poly1305Cipher, AES.new(aeskey.encode("ascii"), AES.MODE_EAX))
48
49
  data = json.dumps(auth)
49
50
  mod_len = len(data) % 16
50
51
  if mod_len != 0:
51
52
  data += "".join([" " for i in range(16 - mod_len)])
52
- ciphertext, tag = cipher.encrypt_and_digest(data.encode("utf-8")) # type: ignore
53
- return binascii.hexlify(cipher.nonce + tag + ciphertext).decode("ascii") # type: ignore
53
+ ciphertext, tag = cipher.encrypt_and_digest(data.encode("utf-8"))
54
+ return binascii.hexlify(cipher.nonce + tag + ciphertext).decode("ascii")
55
+
54
56
 
57
+ def get_argparser() -> argparse.ArgumentParser:
58
+ """Get the argument parser for this script."""
55
59
 
56
- def main():
57
60
  parser = argparse.ArgumentParser(description="Generate an auth token")
58
61
  fill_arguments(parser)
59
62
  parser.add_argument("user", help="The username")
60
63
  parser.add_argument("password", help="The password")
61
64
  parser.add_argument("valid", type=int, default=1, nargs="?", help="Is valid for, in days")
65
+ return parser
66
+
67
+
68
+ def main() -> None:
69
+ """Run the command."""
62
70
 
63
- args = parser.parse_args()
71
+ args = get_argparser().parse_args()
64
72
  settings = get_appsettings(args)
65
73
  urllogin = settings.get("urllogin", {})
66
74
  aeskey = urllogin.get("aes_key")
67
75
  auth_enc = create_token(aeskey, args.user, args.password, args.valid)
68
76
 
69
- print(("Use: auth={}".format(auth_enc)))
77
+ print(f"Use: auth={auth_enc}")
70
78
 
71
79
 
72
80
  if __name__ == "__main__":
@@ -1,86 +1,90 @@
1
- <!DOCTYPE HTML>
1
+ <!DOCTYPE html>
2
2
  <html lang="${lang}">
3
- <head>
4
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5
- <meta name="Content-Language" content="${lang}" />
6
- <title>${_('Login to Geoportal Application')}</title>
7
- <style>
8
- body {
9
- background: #444444;
10
- font-family: Helvetica, Arial, sans-serif;
11
- }
12
- * {
13
- padding: 0;
14
- margin: 0;
15
- }
16
- div#content {
17
- background: #F5F5EF;
18
- padding: 20px 30px;
19
- width: 330px;
20
- margin: 100px auto auto auto;
21
- -webkit-border-radius: 10px;
22
- border-radius: 10px;
23
- }
24
- td.field {
25
- padding-top: 20px;
26
- }
27
- td.field p {
28
- font-weight: bold;
29
- color: #444444;
30
- font-size: 80%;
31
- margin-bottom: 3px;
32
- }
33
- td.field input {
34
- -webkit-border-radius: 2px;
35
- border-radius: 2px;
36
- border: solid 1px #444444;
37
- padding: 3px 6px;
38
- font-size: 110%;
39
- width: 250px;
40
- }
41
- td.buttons {
42
- padding-top: 25px;
43
- padding-bottom: 20px;
44
- text-align: right;
45
- }
46
- td.buttons input {
47
- padding: 1px 6px;
48
- font-weight: bold;
49
- color: #444444;
50
- }
51
- </style>
52
- </head>
53
- <body>
54
- <div id="content">
55
- <form method="POST" id="loginForm" action="${request.route_url('login', _query=login_params)}">
56
- <table style="margin-left: auto; margin-right: auto;">
57
- <tbody>
58
- <tr>
59
- <td class="field"><p>
60
- <label for="email">${_('Username')}</label></p>
61
- <input id="login" name="login" type="text">
62
- </td>
63
- </tr>
64
- <tr>
65
- <td class="field"><p>
66
- <label for="password">${_('Password')}</label></p>
67
- <input id="password" name="password" type="password">
68
- </td>
69
- </tr>
70
- % if two_fa:
71
- <tr>
72
- <td class="field">
73
- <p><label for="otp">${_('Authentication code')}</label></p>
74
- <input id="otp" name="otp" type="text" autocomplete="off">
75
- </td>
76
- </tr>
77
- % endif
78
- <tr>
79
- <td class="buttons"><input tabindex="4" value="${_('Login')}" type="submit"></td>
80
- </tr>
81
- </tbody>
82
- </table>
83
- </form>
84
- </div>
85
- </body>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5
+ <meta name="Content-Language" content="${lang}" />
6
+ <title>${_('Login to Geoportal Application')}</title>
7
+ <style>
8
+ body {
9
+ background: #444444;
10
+ font-family: Helvetica, Arial, sans-serif;
11
+ }
12
+ * {
13
+ padding: 0;
14
+ margin: 0;
15
+ }
16
+ div#content {
17
+ background: #f5f5ef;
18
+ padding: 20px 30px;
19
+ width: 330px;
20
+ margin: 100px auto auto auto;
21
+ -webkit-border-radius: 10px;
22
+ border-radius: 10px;
23
+ }
24
+ td.field {
25
+ padding-top: 20px;
26
+ }
27
+ td.field p {
28
+ font-weight: bold;
29
+ color: #444444;
30
+ font-size: 80%;
31
+ margin-bottom: 3px;
32
+ }
33
+ td.field input {
34
+ -webkit-border-radius: 2px;
35
+ border-radius: 2px;
36
+ border: solid 1px #444444;
37
+ padding: 3px 6px;
38
+ font-size: 110%;
39
+ width: 250px;
40
+ }
41
+ td.buttons {
42
+ padding-top: 25px;
43
+ padding-bottom: 20px;
44
+ text-align: right;
45
+ }
46
+ td.buttons input {
47
+ padding: 1px 6px;
48
+ font-weight: bold;
49
+ color: #444444;
50
+ }
51
+ </style>
52
+ </head>
53
+ <body>
54
+ <div id="content">
55
+ <form method="POST" id="loginForm" action="${request.route_url('login', _query=login_params)}">
56
+ <table style="margin-left: auto; margin-right: auto">
57
+ <tbody>
58
+ <tr>
59
+ <td class="field">
60
+ <p>
61
+ <label for="email">${_('Username')}</label>
62
+ </p>
63
+ <input id="login" name="login" type="text" />
64
+ </td>
65
+ </tr>
66
+ <tr>
67
+ <td class="field">
68
+ <p>
69
+ <label for="password">${_('Password')}</label>
70
+ </p>
71
+ <input id="password" name="password" type="password" />
72
+ </td>
73
+ </tr>
74
+ % if two_fa:
75
+ <tr>
76
+ <td class="field">
77
+ <p><label for="otp">${_('Authentication code')}</label></p>
78
+ <input id="otp" name="otp" type="text" autocomplete="off" />
79
+ </td>
80
+ </tr>
81
+ % endif
82
+ <tr>
83
+ <td class="buttons"><input tabindex="4" value="${_('Login')}" type="submit" /></td>
84
+ </tr>
85
+ </tbody>
86
+ </table>
87
+ </form>
88
+ </div>
89
+ </body>
86
90
  </html>
@@ -1,62 +1,62 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="${lang}">
3
- <head>
4
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5
- <meta name="Content-Language" content="${lang}" />
6
- <title>${_('Login to Geoportal Application')}</title>
7
- <style>
8
- body {
9
- background: #444444;
10
- font-family: Helvetica, Arial, sans-serif;
11
- }
12
- * {
13
- padding: 0;
14
- margin: 0;
15
- }
16
- div#content {
17
- background: #f5f5ef;
18
- padding: 20px 30px;
19
- width: 330px;
20
- margin: 100px auto auto auto;
21
- -webkit-border-radius: 10px;
22
- border-radius: 10px;
23
- }
24
- td.field {
25
- padding-top: 20px;
26
- }
27
- td.field p {
28
- font-weight: bold;
29
- color: #444444;
30
- font-size: 80%;
31
- margin-bottom: 3px;
32
- }
33
- td.field input {
34
- -webkit-border-radius: 2px;
35
- border-radius: 2px;
36
- border: solid 1px #444444;
37
- padding: 3px 6px;
38
- font-size: 110%;
39
- width: 250px;
40
- }
41
- td.buttons {
42
- padding-top: 25px;
43
- padding-bottom: 20px;
44
- text-align: right;
45
- }
46
- td.buttons input {
47
- padding: 1px 6px;
48
- font-weight: bold;
49
- color: #444444;
50
- }
51
- </style>
52
- </head>
53
- <body>
54
- <div id="content">
55
- <p>
56
- ${_('The user is not correctly initialized you should login in the main application and try '
57
- 'again.')}
58
- </p>
59
- <p><a href="${request.route_url('base')}">${_('Main application')}</a></p>
60
- </div>
61
- </body>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5
+ <meta name="Content-Language" content="${lang}" />
6
+ <title>${_('Login to Geoportal Application')}</title>
7
+ <style>
8
+ body {
9
+ background: #444444;
10
+ font-family: Helvetica, Arial, sans-serif;
11
+ }
12
+ * {
13
+ padding: 0;
14
+ margin: 0;
15
+ }
16
+ div#content {
17
+ background: #f5f5ef;
18
+ padding: 20px 30px;
19
+ width: 330px;
20
+ margin: 100px auto auto auto;
21
+ -webkit-border-radius: 10px;
22
+ border-radius: 10px;
23
+ }
24
+ td.field {
25
+ padding-top: 20px;
26
+ }
27
+ td.field p {
28
+ font-weight: bold;
29
+ color: #444444;
30
+ font-size: 80%;
31
+ margin-bottom: 3px;
32
+ }
33
+ td.field input {
34
+ -webkit-border-radius: 2px;
35
+ border-radius: 2px;
36
+ border: solid 1px #444444;
37
+ padding: 3px 6px;
38
+ font-size: 110%;
39
+ width: 250px;
40
+ }
41
+ td.buttons {
42
+ padding-top: 25px;
43
+ padding-bottom: 20px;
44
+ text-align: right;
45
+ }
46
+ td.buttons input {
47
+ padding: 1px 6px;
48
+ font-weight: bold;
49
+ color: #444444;
50
+ }
51
+ </style>
52
+ </head>
53
+ <body>
54
+ <div id="content">
55
+ <p>
56
+ ${_('The user is not correctly initialized you should login in the main application and try '
57
+ 'again.')}
58
+ </p>
59
+ <p><a href="${request.route_url('base')}">${_('Main application')}</a></p>
60
+ </div>
61
+ </body>
62
62
  </html>
@@ -1,14 +1,12 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE html
3
- PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
3
  <html xmlns="http://www.w3.org/1999/xhtml">
6
- <head>
7
- <meta charset="UTF-8">
4
+ <head>
5
+ <meta charset="UTF-8" />
8
6
  <title>${title}</title>
9
- </head>
10
- <body>
7
+ </head>
8
+ <body>
11
9
  <h1>${title}</h1>
12
10
  <p>${_('my translation test')}</p>
13
- </body>
11
+ </body>
14
12
  </html>
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- # Copyright (c) 2011-2020, Camptocamp SA
3
+ # Copyright (c) 2011-2021, Camptocamp SA
4
4
  # All rights reserved.
5
5
 
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -27,17 +27,36 @@
27
27
  # of the authors and should not be interpreted as representing official policies,
28
28
  # either expressed or implied, of the FreeBSD Project.
29
29
 
30
+ from typing import Dict, List
30
31
 
32
+ import pyramid.config
33
+ import pyramid.request
31
34
  from pyramid.httpexceptions import HTTPFound
32
35
 
33
36
 
34
- def add_ending_slash(request):
37
+ def add_ending_slash(request: pyramid.request.Request) -> HTTPFound:
38
+ """Add an ending slash view."""
35
39
  return HTTPFound(location=request.path + "/")
36
40
 
37
41
 
38
- def add_redirect(config, name, from_, to):
39
- def redirect_view(request):
42
+ def add_redirect(config: pyramid.config.Configurator, name: str, from_: str, to: str) -> None:
43
+ """Add a redirect view."""
44
+
45
+ def redirect_view(request: pyramid.request.Request) -> HTTPFound:
40
46
  return HTTPFound(location=request.route_url(to))
41
47
 
42
48
  config.add_route(name, from_, request_method="GET")
43
49
  config.add_view(redirect_view, route_name=name)
50
+
51
+
52
+ def restrict_headers(headers: Dict[str, str], whitelist: List[str], blacklist: List[str]) -> Dict[str, str]:
53
+ """
54
+ Filter headers with a whitelist then a blacklist.
55
+
56
+ Some default pyramid headers will be added back by pyramid.
57
+ """
58
+ if len(whitelist) > 0:
59
+ headers = {key: value for key, value in headers.items() if key in whitelist}
60
+
61
+ headers = {key: value for key, value in headers.items() if key not in blacklist}
62
+ return headers
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
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
@@ -31,25 +29,29 @@
31
29
  import logging
32
30
  import re
33
31
 
32
+ import pyramid.request
33
+ import pyramid.response
34
34
  from pyramid.httpexceptions import HTTPFound
35
35
  from pyramid.view import view_config
36
36
 
37
+ from c2cgeoportal_commons.lib.url import Url
37
38
  from c2cgeoportal_geoportal.views.proxy import Proxy
38
39
 
39
40
  logger = logging.getLogger(__name__)
40
41
 
41
42
 
42
43
  class Dev(Proxy):
44
+ """All the development views."""
43
45
 
44
46
  THEME_RE = re.compile(r"/theme/.*$")
45
47
 
46
- def __init__(self, request):
48
+ def __init__(self, request: pyramid.request.Request):
47
49
  super().__init__(request)
48
50
  self.dev_url = self.request.registry.settings["devserver_url"]
49
51
 
50
- @view_config(route_name="dev")
51
- def dev(self):
52
+ @view_config(route_name="dev") # type: ignore
53
+ def dev(self) -> pyramid.response.Response:
52
54
  path = self.THEME_RE.sub("", self.request.path_info)
53
55
  if self.request.path.endswith("/dynamic.js"):
54
56
  return HTTPFound(location=self.request.route_url("dynamic", _query=self.request.params))
55
- return self._proxy_response("dev", "{}/{}".format(self.dev_url.rstrip("/"), path.lstrip("/")))
57
+ return self._proxy_response("dev", Url(f"{self.dev_url.rstrip('/')}/{path.lstrip('/')}"))
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  # Copyright (c) 2018-2021, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
@@ -30,8 +28,9 @@
30
28
 
31
29
  import re
32
30
  import urllib.parse
33
- from typing import Dict, List, Union
31
+ from typing import Any, Dict, List, Union, cast
34
32
 
33
+ import pyramid.request
35
34
  from pyramid.httpexceptions import HTTPNotFound
36
35
  from pyramid.view import view_config
37
36
  from sqlalchemy import func
@@ -39,22 +38,25 @@ from sqlalchemy import func
39
38
  from c2cgeoportal_commons import models
40
39
  from c2cgeoportal_commons.models import main
41
40
  from c2cgeoportal_geoportal.lib.cacheversion import get_cache_version
42
- from c2cgeoportal_geoportal.lib.caching import NO_CACHE, get_region, set_common_headers
41
+ from c2cgeoportal_geoportal.lib.caching import get_region
42
+ from c2cgeoportal_geoportal.lib.common_headers import Cache, set_common_headers
43
43
 
44
44
  CACHE_REGION = get_region("std")
45
45
 
46
46
 
47
47
  class DynamicView:
48
- def __init__(self, request):
48
+ """The dynamic vies that provide the configuration of the client application."""
49
+
50
+ def __init__(self, request: pyramid.request.Request):
49
51
  self.request = request
50
52
  self.settings = request.registry.settings
51
53
  self.interfaces_config = self.settings["interfaces_config"]
52
54
 
53
- def get(self, value, interface):
54
- return self.interfaces_config.get(interface, {}).get(value, {})
55
+ def get(self, value: Dict[str, Any], interface: str) -> Dict[str, Any]:
56
+ return cast(Dict[str, Any], self.interfaces_config.get(interface, {}).get(value, {}))
55
57
 
56
- @CACHE_REGION.cache_on_arguments()
57
- def _fulltextsearch_groups(self): # pylint: disable=no-self-use
58
+ @CACHE_REGION.cache_on_arguments() # type: ignore
59
+ def _fulltextsearch_groups(self) -> List[str]: # pylint: disable=no-self-use
58
60
  return [
59
61
  group[0]
60
62
  for group in models.DBSession.query(func.distinct(main.FullTextSearch.layer_name))
@@ -62,11 +64,30 @@ class DynamicView:
62
64
  .all()
63
65
  ]
64
66
 
65
- def _interface(self, interface_config, interface_name, dynamic):
67
+ def _interface(
68
+ self,
69
+ interface_config: Dict[str, Any],
70
+ interface_name: str,
71
+ original_interface_name: str,
72
+ dynamic: Dict[str, Any],
73
+ ) -> Dict[str, Any]:
74
+ """
75
+ Get the interface configuration.
76
+
77
+ Arguments:
78
+
79
+ interface_config: Current interface configuration
80
+ interface_name: Interface name (we use in the configuration)
81
+ original_interface_name: Original interface name (directly for the query string)
82
+ dynamic: The values that's dynamically generated
83
+ """
66
84
 
67
85
  if "extends" in interface_config:
68
86
  constants = self._interface(
69
- self.interfaces_config[interface_config["extends"]], interface_name, dynamic
87
+ self.interfaces_config[interface_config["extends"]],
88
+ interface_name,
89
+ original_interface_name,
90
+ dynamic,
70
91
  )
71
92
  else:
72
93
  constants = {}
@@ -87,7 +108,7 @@ class DynamicView:
87
108
  )
88
109
 
89
110
  for constant, config in interface_config.get("routes", {}).items():
90
- route_name = interface_name if config.get("currentInterface", False) else config["name"]
111
+ route_name = original_interface_name if config.get("currentInterface", False) else config["name"]
91
112
  params: Dict[str, str] = {}
92
113
  params.update(config.get("params", {}))
93
114
  for name, dyn in config.get("dynamic_params", {}).items():
@@ -98,14 +119,28 @@ class DynamicView:
98
119
 
99
120
  return constants
100
121
 
101
- @view_config(route_name="dynamic", renderer="json")
102
- def dynamic(self):
103
- interface_name = self.request.get_organization_interface(self.request.params.get("interface"))
122
+ @view_config(route_name="dynamic", renderer="json") # type: ignore
123
+ def dynamic(self) -> Dict[str, Any]:
124
+ original_interface_name = self.request.params.get("interface")
125
+ interface_name = self.request.get_organization_interface(original_interface_name)
104
126
 
105
127
  if interface_name not in self.interfaces_config:
106
128
  raise HTTPNotFound("Interface {} doesn't exists in the 'interfaces_config'.")
107
129
 
108
130
  interface_config = self.interfaces_config[interface_name]
131
+ lang_urls_suffix = interface_config.get("lang_urls_suffix", "")
132
+
133
+ i18next_configuration = self.settings.get("i18next", {})
134
+ i18next_configuration.setdefault("backend", {})
135
+ if "loadPath" not in i18next_configuration["backend"]:
136
+ path: List[str] = [
137
+ self.request.route_url("base").rstrip("/"),
138
+ "static-{{ns}}",
139
+ get_cache_version(),
140
+ "locales",
141
+ "{{lng}}.json",
142
+ ]
143
+ i18next_configuration["backend"]["loadPath"] = "/".join(path)
109
144
 
110
145
  dynamic = {
111
146
  "interface": interface_name,
@@ -113,14 +148,15 @@ class DynamicView:
113
148
  "two_factor": self.request.registry.settings.get("authentication", {}).get("two_factor", False),
114
149
  "lang_urls": {
115
150
  lang: self.request.static_url(
116
- "/etc/geomapfish/static/{lang}.json".format(lang=lang),
151
+ f"/etc/geomapfish/static/{lang}{lang_urls_suffix}.json",
117
152
  )
118
153
  for lang in self.request.registry.settings["available_locale_names"]
119
154
  },
155
+ "i18next_configuration": i18next_configuration,
120
156
  "fulltextsearch_groups": self._fulltextsearch_groups(),
121
157
  }
122
158
 
123
- constants = self._interface(interface_config, interface_name, dynamic)
159
+ constants = self._interface(interface_config, interface_name, original_interface_name, dynamic)
124
160
 
125
161
  do_redirect = False
126
162
  url = None
@@ -159,5 +195,5 @@ class DynamicView:
159
195
  else:
160
196
  constants["redirectUrl"] = no_redirect_url
161
197
 
162
- set_common_headers(self.request, "dynamic", NO_CACHE)
198
+ set_common_headers(self.request, "dynamic", Cache.PUBLIC_NO)
163
199
  return {"constants": constants, "doRedirect": do_redirect, "redirectUrl": url}