c2cgeoportal-geoportal 2.7.1.156__py2.py3-none-any.whl → 2.8.1.180__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 (97) hide show
  1. c2cgeoportal_geoportal/__init__.py +24 -14
  2. c2cgeoportal_geoportal/lib/authentication.py +10 -14
  3. c2cgeoportal_geoportal/lib/caching.py +8 -6
  4. c2cgeoportal_geoportal/lib/checker.py +10 -6
  5. c2cgeoportal_geoportal/lib/common_headers.py +5 -8
  6. c2cgeoportal_geoportal/lib/dbreflection.py +8 -8
  7. c2cgeoportal_geoportal/lib/filter_capabilities.py +5 -1
  8. c2cgeoportal_geoportal/lib/lingua_extractor.py +11 -12
  9. c2cgeoportal_geoportal/lib/loader.py +1 -1
  10. c2cgeoportal_geoportal/lib/oauth2.py +217 -100
  11. c2cgeoportal_geoportal/lib/wmstparsing.py +8 -12
  12. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/Dockerfile +9 -11
  13. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/development.ini +1 -1
  14. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/gunicorn.conf.py +0 -2
  15. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/requirements.txt +1 -1
  16. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.api.js +6 -4
  17. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.apps.js +1 -3
  18. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.commons.js +1 -0
  19. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/__init__.py +1 -6
  20. c2cgeoportal_geoportal/scaffolds/advance_update/{{cookiecutter.project}}/geoportal/CONST_Makefile +0 -20
  21. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/main.yaml +20 -6
  22. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/update_l10n.yaml +4 -3
  23. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Dockerfile +22 -22
  24. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Makefile +58 -2
  25. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/build +48 -24
  26. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/config.yaml +2 -5
  27. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/docker-compose-check +25 -0
  28. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/requirements.txt +1 -1
  29. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-db.yaml +26 -0
  30. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-lib.yaml +53 -26
  31. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-qgis.yaml +23 -0
  32. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.override.sample.yaml +0 -1
  33. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.yaml +3 -3
  34. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.default +21 -2
  35. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.project +9 -0
  36. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/vars.yaml +38 -14
  37. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/data/Readme.txt +2 -2
  38. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/mapserver.conf +15 -0
  39. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/mapserver.map.tmpl +2 -3
  40. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A3_Landscape.jrxml +5 -0
  41. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A3_Portrait.jrxml +5 -0
  42. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A4_Landscape.jrxml +5 -0
  43. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A4_Portrait.jrxml +5 -0
  44. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/config.yaml.tmpl +6 -0
  45. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/pyproject.toml +4 -0
  46. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/run_alembic.sh +3 -5
  47. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-backup +1 -1
  48. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-restore +1 -1
  49. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/spell-ignore-words.txt +2 -0
  50. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tests/__init__.py +0 -0
  51. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tests/test_app.py +38 -0
  52. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/.upgrade.yaml +2 -132
  53. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_CHANGELOG.txt +210 -1097
  54. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_create_template/tests/test_testapp.py +48 -0
  55. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/geoportal/CONST_config-schema.yaml +17 -15
  56. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/geoportal/CONST_vars.yaml +46 -2
  57. c2cgeoportal_geoportal/scripts/c2cupgrade.py +1 -2
  58. c2cgeoportal_geoportal/scripts/pcreate.py +8 -10
  59. c2cgeoportal_geoportal/scripts/theme2fts.py +58 -3
  60. c2cgeoportal_geoportal/views/__init__.py +1 -3
  61. c2cgeoportal_geoportal/views/dynamic.py +1 -1
  62. c2cgeoportal_geoportal/views/entry.py +2 -10
  63. c2cgeoportal_geoportal/views/fulltextsearch.py +1 -1
  64. c2cgeoportal_geoportal/views/geometry_processing.py +3 -3
  65. c2cgeoportal_geoportal/views/layers.py +10 -11
  66. c2cgeoportal_geoportal/views/login.py +63 -8
  67. c2cgeoportal_geoportal/views/mapserverproxy.py +2 -3
  68. c2cgeoportal_geoportal/views/ogcproxy.py +6 -2
  69. c2cgeoportal_geoportal/views/pdfreport.py +4 -4
  70. c2cgeoportal_geoportal/views/printproxy.py +2 -2
  71. c2cgeoportal_geoportal/views/profile.py +1 -1
  72. c2cgeoportal_geoportal/views/proxy.py +2 -4
  73. c2cgeoportal_geoportal/views/raster.py +2 -2
  74. c2cgeoportal_geoportal/views/resourceproxy.py +1 -1
  75. c2cgeoportal_geoportal/views/shortener.py +1 -2
  76. c2cgeoportal_geoportal/views/theme.py +97 -63
  77. c2cgeoportal_geoportal/views/tinyowsproxy.py +3 -12
  78. c2cgeoportal_geoportal/views/vector_tiles.py +1 -1
  79. {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/METADATA +21 -15
  80. {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/RECORD +96 -90
  81. {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/entry_points.txt +1 -0
  82. tests/__init__.py +3 -2
  83. tests/test_cachebuster.py +3 -3
  84. tests/test_caching.py +7 -7
  85. tests/test_checker.py +1 -1
  86. tests/test_decimaljson.py +1 -1
  87. tests/test_headerstween.py +1 -1
  88. tests/test_i18n.py +1 -1
  89. tests/test_init.py +14 -15
  90. tests/test_locale_negociator.py +4 -4
  91. tests/test_mapserverproxy_route_predicate.py +1 -2
  92. tests/test_raster.py +15 -15
  93. tests/test_wmstparsing.py +10 -10
  94. tests/xmlstr.py +1 -3
  95. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/tools/extract-messages.js +0 -41
  96. {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/WHEEL +0 -0
  97. {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011-2021, Camptocamp SA
1
+ # Copyright (c) 2011-2024, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -257,8 +257,8 @@ def _match_url_start(reference: str, value: List[str]) -> bool:
257
257
 
258
258
  def is_valid_referrer(request: pyramid.request.Request, settings: Optional[Dict[str, Any]] = None) -> bool:
259
259
  """Check if the referrer is valid."""
260
- if request.referer is not None:
261
- referrer = urlsplit(request.referer)._replace(query="", fragment="").geturl().rstrip("/").split("/")
260
+ if request.referrer is not None:
261
+ referrer = urlsplit(request.referrer)._replace(query="", fragment="").geturl().rstrip("/").split("/")
262
262
  if settings is None:
263
263
  settings = request.registry.settings
264
264
  list_ = settings.get("authorized_referers", [])
@@ -280,7 +280,8 @@ def create_get_user_from_request(
280
280
  Return ``None`` if:
281
281
  * user is anonymous
282
282
  * it does not exist in the database
283
- * the referer is invalid
283
+ * it has been deactivated
284
+ * the referrer is invalid
284
285
  """
285
286
  from c2cgeoportal_commons.models import DBSession # pylint: disable=import-outside-toplevel
286
287
  from c2cgeoportal_commons.models.static import User # pylint: disable=import-outside-toplevel
@@ -288,7 +289,7 @@ def create_get_user_from_request(
288
289
  if not hasattr(request, "is_valid_referer"):
289
290
  request.is_valid_referer = is_valid_referrer(request, settings)
290
291
  if not request.is_valid_referer:
291
- LOG.debug("Invalid referer for %s: %s", request.path_qs, repr(request.referer))
292
+ LOG.debug("Invalid referrer for %s: %s", request.path_qs, repr(request.referrer))
292
293
  return None
293
294
 
294
295
  if not hasattr(request, "user_"):
@@ -299,7 +300,10 @@ def create_get_user_from_request(
299
300
  # We know we will need the role object of the
300
301
  # user so we use joined loading
301
302
  request.user_ = (
302
- DBSession.query(User).filter_by(username=username).options(joinedload("roles")).first()
303
+ DBSession.query(User)
304
+ .filter_by(username=username, deactivated=False)
305
+ .options(joinedload("roles"))
306
+ .first()
303
307
  )
304
308
 
305
309
  return cast(User, request.user_)
@@ -453,7 +457,7 @@ def includeme(config: pyramid.config.Configurator) -> None:
453
457
  if metrics_config["total_python_object_memory"]:
454
458
  add_provider(TotalPythonObjectMemoryProvider())
455
459
 
456
- # Initialise DBSessions
460
+ # Initialize DBSessions
457
461
  init_db_sessions(settings, config, health_check)
458
462
 
459
463
  checker.init(config, health_check)
@@ -468,13 +472,15 @@ def includeme(config: pyramid.config.Configurator) -> None:
468
472
  for name, cache_config in settings["cache"].items():
469
473
  caching.init_region(cache_config, name)
470
474
 
471
- @zope.event.classhandler.handler(InvalidateCacheEvent) # type: ignore
472
- def handle(event: InvalidateCacheEvent) -> None:
473
- del event
474
- caching.invalidate_region()
475
- if caching.MEMORY_CACHE_DICT:
476
- caching.get_region("std").delete_multi(list(caching.MEMORY_CACHE_DICT.keys()))
477
- caching.MEMORY_CACHE_DICT.clear()
475
+ @zope.event.classhandler.handler(InvalidateCacheEvent) # type: ignore
476
+ def handle(event: InvalidateCacheEvent) -> None:
477
+ del event
478
+ caching.invalidate_region("ogc-server")
479
+ caching.invalidate_region("std")
480
+ caching.invalidate_region("obj")
481
+ if caching.MEMORY_CACHE_DICT:
482
+ caching.get_region("std").delete_multi(list(caching.MEMORY_CACHE_DICT.keys()))
483
+ caching.MEMORY_CACHE_DICT.clear()
478
484
 
479
485
  # Register a tween to get back the cache buster path.
480
486
  if "cache_path" not in config.get_settings():
@@ -496,8 +502,10 @@ def includeme(config: pyramid.config.Configurator) -> None:
496
502
  config.add_directive("set_user_validator", set_user_validator)
497
503
  config.set_user_validator(default_user_validator)
498
504
 
505
+ config.add_route("oauth2introspect", "/oauth/introspect", request_method="POST")
499
506
  config.add_route("oauth2token", "/oauth/token", request_method="POST")
500
507
  config.add_route("oauth2loginform", "/oauth/login", request_method="GET")
508
+ config.add_route("oauth2revoke_token", "/oauth/revoke_token", request_method="GET")
501
509
  config.add_route("notlogin", "/notlogin", request_method="GET")
502
510
 
503
511
  config.add_route("dynamic", "/dynamic.json", request_method="GET")
@@ -666,6 +674,8 @@ def includeme(config: pyramid.config.Configurator) -> None:
666
674
  # Used memory in caches
667
675
  config.add_route("memory", "/memory", request_method="GET")
668
676
 
677
+ config.add_route("ogc_server_clear_cache", "clear-ogc-server-cache/{id}", request_method="GET")
678
+
669
679
  # Scan view decorator for adding routes
670
680
  config.scan(
671
681
  ignore=[
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2014-2021, Camptocamp SA
1
+ # Copyright (c) 2014-2023, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -70,14 +70,14 @@ class UrlAuthenticationPolicy(CallbackAuthenticationPolicy): # type: ignore
70
70
  return None
71
71
  try:
72
72
  if self.aeskey is None: # pragma: nocover
73
- raise Exception("urllogin is not configured")
73
+ raise Exception("urllogin is not configured") # pylint: disable=broad-exception-raised
74
74
  now = int(time.time())
75
75
  data = binascii.unhexlify(auth_enc.encode("ascii"))
76
76
  nonce = data[0:16]
77
77
  tag = data[16:32]
78
78
  ciphertext = data[32:]
79
79
  cipher = AES.new(self.aeskey.encode("ascii"), AES.MODE_EAX, nonce)
80
- auth = json.loads(cipher.decrypt_and_verify(ciphertext, tag).decode("utf-8")) # type: ignore
80
+ auth = json.loads(cipher.decrypt_and_verify(ciphertext, tag).decode("utf-8"))
81
81
 
82
82
  if "t" in auth and "u" in auth and "p" in auth:
83
83
  timestamp = int(auth["t"])
@@ -92,14 +92,12 @@ class UrlAuthenticationPolicy(CallbackAuthenticationPolicy): # type: ignore
92
92
 
93
93
  return None
94
94
 
95
- def remember( # pylint: disable=no-self-use
96
- self, request: pyramid.request.Request, userid: str, **kw: Any
97
- ) -> List[Dict[str, str]]:
95
+ def remember(self, request: pyramid.request.Request, userid: str, **kw: Any) -> List[Dict[str, str]]:
98
96
  """Do no-op."""
99
97
  del request, userid, kw
100
98
  return []
101
99
 
102
- def forget(self, request: pyramid.request.Request) -> List[Dict[str, str]]: # pylint: disable=no-self-use
100
+ def forget(self, request: pyramid.request.Request) -> List[Dict[str, str]]:
103
101
  """Do no-op."""
104
102
  del request
105
103
  return []
@@ -134,17 +132,15 @@ class OAuth2AuthenticationPolicy(CallbackAuthenticationPolicy): # type: ignore
134
132
  if valid:
135
133
  request.user_ = oauth2_request.user
136
134
 
137
- return cast(str, request.user_.username)
135
+ return cast(str, request.user.username)
138
136
  return None
139
137
 
140
- def remember( # pylint: disable=no-self-use
141
- self, request: pyramid.request.Request, userid: str, **kw: Any
142
- ) -> List[Dict[str, str]]:
138
+ def remember(self, request: pyramid.request.Request, userid: str, **kw: Any) -> List[Dict[str, str]]:
143
139
  """Do no-op."""
144
140
  del request, userid, kw
145
141
  return []
146
142
 
147
- def forget(self, request: pyramid.request.Request) -> List[Dict[str, str]]: # pylint: disable=no-self-use
143
+ def forget(self, request: pyramid.request.Request) -> List[Dict[str, str]]:
148
144
  """Do no-op."""
149
145
  del request
150
146
  return []
@@ -177,7 +173,7 @@ def create_authentication(settings: Dict[str, Any]) -> MultiAuthenticationPolicy
177
173
  secret = settings["authtkt_secret"]
178
174
  basicauth = settings.get("basicauth", "False").lower() in ("true", "yes", "1")
179
175
  if len(secret) < 64:
180
- raise Exception(
176
+ raise Exception( # pylint: disable=broad-exception-raised
181
177
  '"authtkt_secret should be at least 64 characters.'
182
178
  "See https://docs.pylonsproject.org/projects/pyramid/en/latest/api/session.html"
183
179
  )
@@ -211,7 +207,7 @@ def create_authentication(settings: Dict[str, Any]) -> MultiAuthenticationPolicy
211
207
  if basicauth:
212
208
  if settings["authentication"].get("two_factor", False):
213
209
  LOG.warning(
214
- "Basic auth and tow factor auth should not be enable toogether, "
210
+ "Basic auth and two factor auth should not be enable together, "
215
211
  "you should use OAuth2 instead of Basic auth"
216
212
  )
217
213
 
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2012-2021, Camptocamp SA
1
+ # Copyright (c) 2012-2023, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -30,13 +30,14 @@ import inspect
30
30
  import logging
31
31
  from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional
32
32
 
33
+ import pyramid.interfaces
33
34
  import sqlalchemy.ext.declarative
35
+ import zope.interface
34
36
  from dogpile.cache.api import NO_VALUE, CacheBackend
35
37
  from dogpile.cache.backends.memory import MemoryBackend
36
38
  from dogpile.cache.backends.redis import RedisBackend, RedisSentinelBackend
37
39
  from dogpile.cache.region import CacheRegion, make_region
38
40
  from dogpile.cache.util import sha1_mangle_key
39
- from pyramid.request import Request
40
41
  from sqlalchemy.orm.util import identity_key
41
42
 
42
43
  from c2cgeoportal_commons.models import Base
@@ -82,7 +83,9 @@ def keygen_function(namespace: Any, function: Callable[..., Any]) -> Callable[..
82
83
  parts.extend(namespace)
83
84
  if ignore_first_argument:
84
85
  args = args[1:]
85
- new_args: List[str] = [arg for arg in args if not isinstance(arg, Request)]
86
+ new_args: List[str] = [
87
+ arg for arg in args if pyramid.interfaces.IRequest not in zope.interface.implementedBy(type(arg))
88
+ ]
86
89
  parts.extend(map(str, map(map_dbobject, new_args)))
87
90
  return "|".join(parts)
88
91
 
@@ -100,8 +103,7 @@ def _configure_region(conf: Dict[str, Any], cache_region: CacheRegion) -> None:
100
103
  kwargs: Dict[str, Any] = {"replace_existing_backend": True}
101
104
  backend = conf["backend"]
102
105
  kwargs.update({k: conf[k] for k in conf if k != "backend"})
103
- kwargs.setdefault("arguments", {})
104
- kwargs["arguments"]["cache_dict"] = MEMORY_CACHE_DICT
106
+ kwargs.setdefault("arguments", {}).setdefault("cache_dict", MEMORY_CACHE_DICT)
105
107
  cache_region.configure(backend, **kwargs)
106
108
 
107
109
 
@@ -124,7 +126,7 @@ def invalidate_region(region: Optional[str] = None) -> None:
124
126
  class HybridRedisBackend(CacheBackend): # type: ignore
125
127
  """A Dogpile cache backend with a memory cache backend in front of a Redis backend for performance."""
126
128
 
127
- def __init__(self, arguments: Dict[str, Any]): # pylint: disable=super-init-not-called
129
+ def __init__(self, arguments: Dict[str, Any]):
128
130
  self._use_memory_cache = not arguments.pop("disable_memory_cache", False)
129
131
  self._memory = MemoryBackend({"cache_dict": arguments.pop("cache_dict", {})})
130
132
  self._redis = RedisBackend(arguments)
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011-2021, Camptocamp SA
1
+ # Copyright (c) 2011-2023, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -122,7 +122,9 @@ def _pdf3(settings: Dict[str, Any], health_check: c2cwsgiutils.health_check.Heal
122
122
 
123
123
  status = resp.json()
124
124
  if "error" in status:
125
- raise Exception(f"Failed to do the printing: {status['error']}")
125
+ raise Exception( # pylint: disable=broad-exception-raised
126
+ f"Failed to do the printing: {status['error']}",
127
+ )
126
128
  done = status["done"]
127
129
 
128
130
  path = request.route_path("printproxy_report_get", ref=job["ref"])
@@ -204,7 +206,9 @@ def _lang_files(
204
206
  if type_ == "ngeo":
205
207
  url = f"/etc/geomapfish/static/{lang}.json"
206
208
  else:
207
- raise Exception(f"Your language type value '{type_}' is not valid, available values [ngeo]")
209
+ raise Exception( # pylint: disable=broad-exception-raised
210
+ f"Your language type value '{type_}' is not valid, available values [ngeo]",
211
+ )
208
212
 
209
213
  name = f"checker_lang_{type_}_{lang}"
210
214
 
@@ -248,7 +252,7 @@ def _phantomjs(settings: Dict[str, Any], health_check: c2cwsgiutils.health_check
248
252
  path = request.route_path(self.route["name"], _query=self.route.get("params", {}))
249
253
  url: str = cast(str, build_url("Check", path, request)["url"])
250
254
 
251
- cmd: List[str] = ["node", "/usr/bin/check-example.js", url]
255
+ cmd: List[str] = ["check-example", url]
252
256
  env = dict(os.environ)
253
257
  for name, value in self.route.get("environment", {}).items():
254
258
  if isinstance(value, (list, dict)):
@@ -260,12 +264,12 @@ def _phantomjs(settings: Dict[str, Any], health_check: c2cwsgiutils.health_check
260
264
  try:
261
265
  subprocess.check_output(cmd, env=env, timeout=70)
262
266
  except subprocess.CalledProcessError as exception:
263
- raise Exception(
267
+ raise Exception( # pylint: disable=broad-exception-raised
264
268
  f"{' '.join(exception.cmd)} exit with code: {exception.returncode}\n"
265
269
  f"{exception.output.decode('utf-8')[:10000]}"
266
270
  ) from exception
267
271
  except subprocess.TimeoutExpired as exception:
268
- raise Exception(
272
+ raise Exception( # pylint: disable=broad-exception-raised
269
273
  f"""Timeout:
270
274
  command: {' '.join(exception.cmd)}
271
275
  output:
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2012-2021, Camptocamp SA
1
+ # Copyright (c) 2012-2024, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -33,8 +33,6 @@ from typing import Any, Dict, List, Optional, cast
33
33
  import pyramid.request
34
34
  import pyramid.response
35
35
 
36
- from c2cgeoportal_geoportal.lib import is_intranet
37
-
38
36
  _LOG = logging.getLogger(__name__)
39
37
 
40
38
 
@@ -119,6 +117,8 @@ def _set_common_headers(
119
117
  ) -> pyramid.response.Response:
120
118
  """Set the common headers."""
121
119
 
120
+ del request # Unused
121
+
122
122
  response.headers.update(service_headers_settings.get("headers", {}))
123
123
 
124
124
  if cache in (Cache.PRIVATE, Cache.PRIVATE_NO):
@@ -136,12 +136,9 @@ def _set_common_headers(
136
136
  elif cache in (Cache.PUBLIC, Cache.PUBLIC_NO):
137
137
  response.cache_control.public = True
138
138
  elif cache in (Cache.PRIVATE, Cache.PRIVATE_NO):
139
- if hasattr(request, "user") and request.user is not None or is_intranet(request):
140
- response.cache_control.private = True
141
- else:
142
- response.cache_control.public = True
139
+ response.cache_control.private = True
143
140
  else:
144
- raise Exception("Invalid cache type")
141
+ raise Exception("Invalid cache type") # pylint: disable=broad-exception-raised
145
142
 
146
143
  if content_type is not None:
147
144
  response.content_type = content_type
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011-2021, Camptocamp SA
1
+ # Copyright (c) 2011-2023, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -176,16 +176,16 @@ def _create_class(
176
176
  from c2cgeoportal_commons.models import Base # pylint: disable=import-outside-toplevel
177
177
 
178
178
  exclude_properties = exclude_properties or ()
179
- attributes = dict(
180
- __table__=table,
181
- __mapper_args__={"exclude_properties": exclude_properties},
182
- __attributes_order__=attributes_order,
183
- __enumerations_config__=enumerations_config,
184
- )
179
+ attributes = {
180
+ "__table__": table,
181
+ "__mapper_args__": {"exclude_properties": exclude_properties},
182
+ "__attributes_order__": attributes_order,
183
+ "__enumerations_config__": enumerations_config,
184
+ }
185
185
  if pk_name is not None:
186
186
  attributes[pk_name] = Column(Integer, primary_key=True)
187
187
  # The randint is to fix the SAWarning: This declarative base already contains a class with the same
188
- # class name and module nam
188
+ # class name and module name
189
189
  cls = type(
190
190
  f"{table.name.capitalize()}_{random.randint(0, 9999999)}", (GeoInterface, Base), attributes # nosec
191
191
  )
@@ -34,6 +34,7 @@ from typing import Any, Callable, Dict, List, Optional, Set, Union
34
34
  from xml.sax.saxutils import XMLFilterBase, XMLGenerator # nosec
35
35
 
36
36
  import defusedxml.expatreader
37
+ import pyramid.httpexceptions
37
38
  import pyramid.request
38
39
  import requests
39
40
  from owslib.map.wms111 import ContentMetadata as ContentMetadata111
@@ -153,6 +154,9 @@ def filter_wfst_capabilities(content: str, wfs_url: Url, request: pyramid.reques
153
154
 
154
155
  writable_layers: Set[str] = set()
155
156
  ogc_server_ids = get_ogc_server_wfs_url_ids(request, request.host).get(wfs_url.url())
157
+ if ogc_server_ids is None:
158
+ LOG.error("No OGC server found for WFS URL %s", wfs_url)
159
+ raise pyramid.httpexceptions.HTTPInternalServerError("No OGC server found for WFS URL")
156
160
 
157
161
  for gmf_layer in list(get_writable_layers(request, ogc_server_ids).values()):
158
162
  writable_layers |= set(gmf_layer.layer.split(","))
@@ -260,7 +264,7 @@ class _CapabilitiesFilter(XMLFilterBase):
260
264
  def endPrefixMapping(self, prefix: str) -> None: # noqa: ignore=N802
261
265
  self._downstream.endPrefixMapping(prefix) # type: ignore
262
266
 
263
- def startElement(self, name: str, attrs: xml.sax.xmlreader.AttributesImpl) -> None: # noqa: ignore=N802
267
+ def startElement(self, name: str, attrs: Dict[str, str]) -> None: # noqa: ignore=N802
264
268
  if name == self.tag_name:
265
269
  self.level += 1
266
270
  if self.layers_path:
@@ -62,6 +62,10 @@ if TYPE_CHECKING:
62
62
  from c2cgeoportal_commons.models import main # pylint: disable=ungrouped-imports,useless-suppression
63
63
 
64
64
 
65
+ class LinguaExtractorException(Exception):
66
+ """Exception raised when an error occurs during the extraction."""
67
+
68
+
65
69
  def _get_config(key: str, default: Optional[str] = None) -> Optional[str]:
66
70
  """
67
71
  Return the config value for passed key.
@@ -170,8 +174,7 @@ class GeomapfishAngularExtractor(Extractor): # type: ignore
170
174
  empty_template = Template("") # nosec
171
175
 
172
176
  class Lookup(TemplateLookup): # type: ignore
173
- @staticmethod
174
- def get_template(uri: str) -> Template:
177
+ def get_template(self, uri: str) -> Template:
175
178
  del uri # unused
176
179
  return empty_template
177
180
 
@@ -220,10 +223,7 @@ class GeomapfishAngularExtractor(Extractor): # type: ignore
220
223
  print(traceback.format_exc())
221
224
 
222
225
  # Path in geomapfish-tools
223
- script_path = "geoportal/tools/extract-messages.js"
224
- if not os.path.isfile(script_path):
225
- # Path in geomapfish runner
226
- script_path = "/app/tools/extract-messages.js"
226
+ script_path = "/opt/c2cgeoportal/geoportal/extract-messages.js"
227
227
  message_str = subprocess.check_output(["node", script_path, int_filename]).decode("utf-8")
228
228
  if int_filename != filename:
229
229
  os.unlink(int_filename)
@@ -246,8 +246,8 @@ def init_db(settings: Dict[str, Any]) -> None:
246
246
  """
247
247
  Initialize the SQLAlchemy Session.
248
248
 
249
- First test the connection, on wen environment it should be OK, with the command line we should get
250
- an exception ind initialise the connection.
249
+ First test the connection, on when environment it should be OK, with the command line we should get
250
+ an exception ind initialize the connection.
251
251
  """
252
252
 
253
253
  try:
@@ -257,7 +257,6 @@ def init_db(settings: Dict[str, Any]) -> None:
257
257
  session = DBSession()
258
258
  session.query(Theme).count()
259
259
  except: # pylint: disable=bare-except
260
-
261
260
  # Init db sessions
262
261
 
263
262
  class R:
@@ -305,7 +304,7 @@ class GeomapfishConfigExtractor(Extractor): # type: ignore
305
304
  # For the print config
306
305
  if "templates" in gmf_config:
307
306
  return self._collect_print_config(gmf_config, filename)
308
- raise Exception("Not a known config file")
307
+ raise Exception("Not a known config file") # pylint: disable=broad-exception-raised
309
308
 
310
309
  def _collect_app_config(self, filename: str) -> List[Message]:
311
310
  config.init(filename)
@@ -797,7 +796,7 @@ class GeomapfishThemeExtractor(Extractor): # type: ignore
797
796
  )
798
797
  print(f"Response: {response.status_code} {response.reason}\n{response.text}")
799
798
  if _get_config_str("IGNORE_I18N_ERRORS", "FALSE") != "TRUE":
800
- raise Exception(response.reason)
799
+ raise LinguaExtractorException(response.reason)
801
800
  except Exception as e:
802
801
  print(colorize(str(e), Color.RED))
803
802
  rendered_headers = " ".join(
@@ -859,7 +858,7 @@ class GeomapfishThemeExtractor(Extractor): # type: ignore
859
858
  )
860
859
  if _get_config_str("IGNORE_I18N_ERRORS", "FALSE") == "TRUE":
861
860
  return [], []
862
- raise Exception("Aborted")
861
+ raise Exception("Aborted") # pylint: disable=broad-exception-raised
863
862
 
864
863
  try:
865
864
  describe = parseString(response.text)
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2019-2021, Camptocamp SA
1
+ # Copyright (c) 2019-2023, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without