c2cgeoportal-geoportal 2.7.1.157__py2.py3-none-any.whl → 2.8.1.87__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 +23 -14
- c2cgeoportal_geoportal/lib/__init__.py +3 -5
- c2cgeoportal_geoportal/lib/authentication.py +10 -14
- c2cgeoportal_geoportal/lib/caching.py +8 -6
- c2cgeoportal_geoportal/lib/checker.py +10 -6
- c2cgeoportal_geoportal/lib/common_headers.py +2 -2
- c2cgeoportal_geoportal/lib/dbreflection.py +8 -8
- c2cgeoportal_geoportal/lib/filter_capabilities.py +8 -6
- c2cgeoportal_geoportal/lib/lingua_extractor.py +11 -12
- c2cgeoportal_geoportal/lib/loader.py +1 -1
- c2cgeoportal_geoportal/lib/oauth2.py +217 -100
- c2cgeoportal_geoportal/lib/wmstparsing.py +8 -12
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/Dockerfile +9 -11
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/development.ini +1 -1
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/gunicorn.conf.py +3 -3
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/requirements.txt +1 -1
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.api.js +6 -4
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.apps.js +1 -3
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.commons.js +1 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/__init__.py +1 -6
- c2cgeoportal_geoportal/scaffolds/advance_update/{{cookiecutter.project}}/geoportal/CONST_Makefile +0 -20
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/main.yaml +21 -7
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/rebuild.yaml +1 -1
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/update_l10n.yaml +2 -1
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Dockerfile +22 -22
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Makefile +58 -2
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/build +49 -29
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/config.yaml +2 -5
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/docker-compose-check +25 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/requirements.txt +1 -1
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-db.yaml +26 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-lib.yaml +35 -26
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-qgis.yaml +23 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.override.sample.yaml +0 -2
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.yaml +3 -3
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.default +21 -2
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.project +9 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/vars.yaml +38 -14
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/data/Readme.txt +2 -2
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/mapserver.conf +15 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/mapserver.map.tmpl +2 -3
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A3_Landscape.jrxml +5 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A3_Portrait.jrxml +5 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A4_Landscape.jrxml +5 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A4_Portrait.jrxml +5 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/config.yaml.tmpl +6 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/pyproject.toml +4 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/run_alembic.sh +3 -5
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-backup +5 -8
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-restore +5 -8
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/spell-ignore-words.txt +2 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tests/__init__.py +0 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tests/test_app.py +38 -0
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/.upgrade.yaml +2 -132
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_CHANGELOG.txt +200 -1105
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_create_template/tests/test_testapp.py +48 -0
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/geoportal/CONST_config-schema.yaml +17 -15
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/geoportal/CONST_vars.yaml +48 -2
- c2cgeoportal_geoportal/scripts/__init__.py +3 -5
- c2cgeoportal_geoportal/scripts/c2cupgrade.py +1 -2
- c2cgeoportal_geoportal/scripts/pcreate.py +8 -10
- c2cgeoportal_geoportal/scripts/theme2fts.py +58 -3
- c2cgeoportal_geoportal/scripts/urllogin.py +2 -2
- c2cgeoportal_geoportal/views/__init__.py +1 -3
- c2cgeoportal_geoportal/views/dynamic.py +2 -3
- c2cgeoportal_geoportal/views/entry.py +2 -10
- c2cgeoportal_geoportal/views/fulltextsearch.py +1 -1
- c2cgeoportal_geoportal/views/geometry_processing.py +3 -3
- c2cgeoportal_geoportal/views/layers.py +10 -11
- c2cgeoportal_geoportal/views/login.py +63 -8
- c2cgeoportal_geoportal/views/mapserverproxy.py +3 -4
- c2cgeoportal_geoportal/views/ogcproxy.py +6 -2
- c2cgeoportal_geoportal/views/pdfreport.py +1 -1
- c2cgeoportal_geoportal/views/printproxy.py +6 -8
- c2cgeoportal_geoportal/views/profile.py +1 -1
- c2cgeoportal_geoportal/views/proxy.py +6 -9
- c2cgeoportal_geoportal/views/raster.py +2 -2
- c2cgeoportal_geoportal/views/resourceproxy.py +1 -1
- c2cgeoportal_geoportal/views/shortener.py +1 -2
- c2cgeoportal_geoportal/views/theme.py +97 -61
- c2cgeoportal_geoportal/views/tinyowsproxy.py +3 -12
- c2cgeoportal_geoportal/views/vector_tiles.py +1 -1
- {c2cgeoportal_geoportal-2.7.1.157.dist-info → c2cgeoportal_geoportal-2.8.1.87.dist-info}/METADATA +20 -15
- {c2cgeoportal_geoportal-2.7.1.157.dist-info → c2cgeoportal_geoportal-2.8.1.87.dist-info}/RECORD +100 -94
- {c2cgeoportal_geoportal-2.7.1.157.dist-info → c2cgeoportal_geoportal-2.8.1.87.dist-info}/entry_points.txt +1 -0
- tests/__init__.py +3 -2
- tests/test_cachebuster.py +3 -3
- tests/test_caching.py +1 -1
- tests/test_checker.py +1 -1
- tests/test_decimaljson.py +1 -1
- tests/test_headerstween.py +1 -1
- tests/test_i18n.py +1 -1
- tests/test_init.py +14 -15
- tests/test_locale_negociator.py +4 -4
- tests/test_mapserverproxy_route_predicate.py +1 -2
- tests/test_raster.py +15 -15
- tests/test_wmstparsing.py +10 -10
- tests/xmlstr.py +1 -3
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/tools/extract-messages.js +0 -41
- {c2cgeoportal_geoportal-2.7.1.157.dist-info → c2cgeoportal_geoportal-2.8.1.87.dist-info}/WHEEL +0 -0
- {c2cgeoportal_geoportal-2.7.1.157.dist-info → c2cgeoportal_geoportal-2.8.1.87.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2012-
|
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
|
@@ -34,6 +34,7 @@ from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional, Set, Tup
|
|
34
34
|
import geojson.geometry
|
35
35
|
import pyramid.request
|
36
36
|
import pyramid.response
|
37
|
+
import shapely.geometry
|
37
38
|
import sqlalchemy.ext.declarative
|
38
39
|
from geoalchemy2 import Geometry
|
39
40
|
from geoalchemy2 import func as ga_func
|
@@ -49,8 +50,7 @@ from pyramid.httpexceptions import (
|
|
49
50
|
HTTPNotFound,
|
50
51
|
)
|
51
52
|
from pyramid.view import view_config
|
52
|
-
from shapely.
|
53
|
-
from shapely.geos import TopologicalError
|
53
|
+
from shapely.errors import TopologicalError
|
54
54
|
from shapely.ops import cascaded_union
|
55
55
|
from sqlalchemy import Enum, Numeric, String, Text, Unicode, UnicodeText, exc, func
|
56
56
|
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
|
@@ -190,7 +190,7 @@ class Layers:
|
|
190
190
|
|
191
191
|
feature = proto.read(self.request, filter=filter_)
|
192
192
|
if isinstance(feature, HTTPException):
|
193
|
-
raise feature
|
193
|
+
raise feature
|
194
194
|
return feature
|
195
195
|
|
196
196
|
@view_config(route_name="layers_read_many", renderer="geojson") # type: ignore
|
@@ -228,7 +228,7 @@ class Layers:
|
|
228
228
|
geom = feature.geometry
|
229
229
|
if not geom or isinstance(geom, geojson.geometry.Default):
|
230
230
|
return feature
|
231
|
-
shape =
|
231
|
+
shape = shapely.geometry.shape(geom)
|
232
232
|
srid = self._get_geom_col_info(layer)[1]
|
233
233
|
spatial_elt = from_shape(shape, srid=srid)
|
234
234
|
allowed = models.DBSession.query(func.count(RestrictionArea.id))
|
@@ -275,7 +275,7 @@ class Layers:
|
|
275
275
|
del obj # unused
|
276
276
|
geom = feature.geometry
|
277
277
|
if geom and not isinstance(geom, geojson.geometry.Default):
|
278
|
-
shape =
|
278
|
+
shape = shapely.geometry.shape(geom)
|
279
279
|
srid = self._get_geom_col_info(layer)[1]
|
280
280
|
spatial_elt = from_shape(shape, srid=srid)
|
281
281
|
allowed = models.DBSession.query(func.count(RestrictionArea.id))
|
@@ -298,7 +298,7 @@ class Layers:
|
|
298
298
|
try:
|
299
299
|
features = protocol.create(self.request)
|
300
300
|
if isinstance(features, HTTPException):
|
301
|
-
raise features
|
301
|
+
raise features
|
302
302
|
if features is not None:
|
303
303
|
for feature in features.features: # pylint: disable=no-member
|
304
304
|
self._log_last_update(layer, feature)
|
@@ -346,7 +346,7 @@ class Layers:
|
|
346
346
|
)
|
347
347
|
spatial_elt = None
|
348
348
|
if geom and not isinstance(geom, geojson.geometry.Default):
|
349
|
-
shape =
|
349
|
+
shape = shapely.geometry.shape(geom)
|
350
350
|
spatial_elt = from_shape(shape, srid=srid)
|
351
351
|
allowed = allowed.filter(
|
352
352
|
or_(RestrictionArea.area.is_(None), RestrictionArea.area.ST_Contains(spatial_elt))
|
@@ -439,7 +439,7 @@ class Layers:
|
|
439
439
|
protocol = self._get_protocol_for_layer(layer, before_delete=security_cb)
|
440
440
|
response = protocol.delete(self.request, feature_id)
|
441
441
|
if isinstance(response, HTTPException):
|
442
|
-
raise response
|
442
|
+
raise response
|
443
443
|
set_common_headers(self.request, "layers", Cache.PRIVATE_NO, response=response)
|
444
444
|
return response
|
445
445
|
|
@@ -506,7 +506,7 @@ def get_layer_class(
|
|
506
506
|
"""
|
507
507
|
Get the SQLAlchemy class to edit a GeoMapFish layer.
|
508
508
|
|
509
|
-
Arguments:
|
509
|
+
Keyword Arguments:
|
510
510
|
|
511
511
|
layer: The GeoMapFish layer
|
512
512
|
with_last_update_columns: False to just have a class to access to the table and be able to
|
@@ -584,7 +584,6 @@ def get_layer_metadata(layer: "main.Layer") -> List[ColumnProperties]:
|
|
584
584
|
|
585
585
|
for column_property in class_mapper(cls).iterate_properties:
|
586
586
|
if isinstance(column_property, ColumnProperty):
|
587
|
-
|
588
587
|
if len(column_property.columns) != 1:
|
589
588
|
raise NotImplementedError
|
590
589
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2011-
|
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
|
@@ -28,9 +28,9 @@
|
|
28
28
|
|
29
29
|
import json
|
30
30
|
import logging
|
31
|
-
import secrets
|
32
31
|
import sys
|
33
32
|
import urllib.parse
|
33
|
+
from random import Random
|
34
34
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
35
35
|
|
36
36
|
import pyotp
|
@@ -88,7 +88,7 @@ class Login:
|
|
88
88
|
if not hasattr(self.request, "is_valid_referer"):
|
89
89
|
self.request.is_valid_referer = is_valid_referrer(self.request)
|
90
90
|
if not self.request.is_valid_referer:
|
91
|
-
LOG.info("Invalid
|
91
|
+
LOG.info("Invalid referrer for %s: %s", self.request.path_qs, repr(self.request.referrer))
|
92
92
|
|
93
93
|
@forbidden_view_config(renderer="login.html") # type: ignore
|
94
94
|
def loginform403(self) -> Union[Dict[str, Any], pyramid.response.Response]:
|
@@ -341,11 +341,12 @@ class Login:
|
|
341
341
|
|
342
342
|
@staticmethod
|
343
343
|
def generate_password() -> str:
|
344
|
-
|
344
|
+
allchars = "123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
345
|
+
rand = Random() # nosec
|
345
346
|
|
346
347
|
password = "" # nosec
|
347
348
|
for _ in range(8):
|
348
|
-
password +=
|
349
|
+
password += rand.choice(allchars)
|
349
350
|
|
350
351
|
return password
|
351
352
|
|
@@ -397,6 +398,36 @@ class Login:
|
|
397
398
|
|
398
399
|
return {"success": True}
|
399
400
|
|
401
|
+
@view_config(route_name="oauth2introspect") # type: ignore
|
402
|
+
def oauth2introspect(self) -> pyramid.response.Response:
|
403
|
+
LOG.debug(
|
404
|
+
"Call OAuth create_introspect_response with:\nurl: %s\nmethod: %s\nbody:\n%s",
|
405
|
+
self.request.current_route_url(_query=self.request.GET),
|
406
|
+
self.request.method,
|
407
|
+
self.request.body,
|
408
|
+
)
|
409
|
+
headers, body, status = oauth2.get_oauth_client(
|
410
|
+
self.request.registry.settings
|
411
|
+
).create_introspect_response(
|
412
|
+
self.request.current_route_url(_query=self.request.GET),
|
413
|
+
self.request.method,
|
414
|
+
self.request.body,
|
415
|
+
self.request.headers,
|
416
|
+
)
|
417
|
+
LOG.debug("OAuth create_introspect_response return status: %s", status)
|
418
|
+
|
419
|
+
# All requests to /token will return a json response, no redirection.
|
420
|
+
if status != 200:
|
421
|
+
if body:
|
422
|
+
raise exception_response(status, detail=body)
|
423
|
+
raise exception_response(status)
|
424
|
+
return set_common_headers(
|
425
|
+
self.request,
|
426
|
+
"login",
|
427
|
+
Cache.PRIVATE_NO,
|
428
|
+
response=Response(body, headers=headers.items()),
|
429
|
+
)
|
430
|
+
|
400
431
|
@view_config(route_name="oauth2token") # type: ignore
|
401
432
|
def oauth2token(self) -> pyramid.response.Response:
|
402
433
|
LOG.debug(
|
@@ -414,9 +445,6 @@ class Login:
|
|
414
445
|
)
|
415
446
|
LOG.debug("OAuth create_token_response return status: %s", status)
|
416
447
|
|
417
|
-
if hasattr(self.request, "tm"):
|
418
|
-
self.request.tm.commit()
|
419
|
-
|
420
448
|
# All requests to /token will return a json response, no redirection.
|
421
449
|
if status != 200:
|
422
450
|
if body:
|
@@ -429,6 +457,33 @@ class Login:
|
|
429
457
|
response=Response(body, headers=headers.items()),
|
430
458
|
)
|
431
459
|
|
460
|
+
@view_config(route_name="oauth2revoke_token") # type: ignore
|
461
|
+
def oauth2revoke_token(self) -> pyramid.response.Response:
|
462
|
+
LOG.debug(
|
463
|
+
"Call OAuth create_revocation_response with:\nurl: %s\nmethod: %s\nbody:\n%s",
|
464
|
+
self.request.create_revocation_response(_query=self.request.GET),
|
465
|
+
self.request.method,
|
466
|
+
self.request.body,
|
467
|
+
)
|
468
|
+
headers, body, status = oauth2.get_oauth_client(
|
469
|
+
self.request.registry.settings
|
470
|
+
).create_authorize_response(
|
471
|
+
self.request.current_route_url(_query=self.request.GET),
|
472
|
+
self.request.method,
|
473
|
+
self.request.body,
|
474
|
+
self.request.headers,
|
475
|
+
)
|
476
|
+
if status != 200:
|
477
|
+
if body:
|
478
|
+
raise exception_response(status, detail=body)
|
479
|
+
raise exception_response(status)
|
480
|
+
return set_common_headers(
|
481
|
+
self.request,
|
482
|
+
"login",
|
483
|
+
Cache.PRIVATE_NO,
|
484
|
+
response=Response(body, headers=headers.items()),
|
485
|
+
)
|
486
|
+
|
432
487
|
@view_config(route_name="oauth2loginform", renderer="login.html") # type: ignore
|
433
488
|
def oauth2loginform(self) -> Dict[str, Any]:
|
434
489
|
set_common_headers(self.request, "login", Cache.PUBLIC)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2011-
|
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
|
@@ -29,7 +29,7 @@
|
|
29
29
|
import logging
|
30
30
|
from typing import Any, Dict, Set
|
31
31
|
|
32
|
-
from pyramid.httpexceptions import HTTPFound, HTTPInternalServerError, HTTPUnauthorized
|
32
|
+
from pyramid.httpexceptions import HTTPForbidden, HTTPFound, HTTPInternalServerError, HTTPUnauthorized
|
33
33
|
from pyramid.request import Request
|
34
34
|
from pyramid.response import Response
|
35
35
|
from pyramid.view import view_config
|
@@ -67,7 +67,7 @@ class MapservProxy(OGCProxy):
|
|
67
67
|
raise HTTPUnauthorized(
|
68
68
|
headers={"WWW-Authenticate": 'Basic realm="Access to restricted layers"'}
|
69
69
|
)
|
70
|
-
raise
|
70
|
+
raise HTTPForbidden("Basic auth is not enabled")
|
71
71
|
|
72
72
|
# We have a user logged in. We need to set group_id and possible layer_name in the params. We set
|
73
73
|
# layer_name when either QUERY_PARAMS or LAYERS is set in the WMS params, i.e. for GetMap and
|
@@ -108,7 +108,6 @@ class MapservProxy(OGCProxy):
|
|
108
108
|
self.params = {}
|
109
109
|
else:
|
110
110
|
if self.ogc_server.type != main.OGCSERVER_TYPE_QGISSERVER or "user_id" not in self.params:
|
111
|
-
|
112
111
|
use_cache = self.lower_params["request"] in ("getlegendgraphic",)
|
113
112
|
|
114
113
|
# no user_id and role_id or cached queries
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2011-
|
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
|
@@ -60,6 +60,8 @@ class OGCProxy(Proxy):
|
|
60
60
|
if "user_id" in self.params:
|
61
61
|
del self.params["user_id"]
|
62
62
|
|
63
|
+
main_ogc_server = self.request.registry.settings.get("main_ogc_server")
|
64
|
+
|
63
65
|
self.lower_params = self._get_lower_params(self.params)
|
64
66
|
|
65
67
|
# We need original case for OGCSERVER parameter value
|
@@ -69,11 +71,13 @@ class OGCProxy(Proxy):
|
|
69
71
|
self.ogc_server = self._get_ogcserver_byname(request.matchdict["ogcserver"])
|
70
72
|
elif "ogcserver" in self.lower_key_params:
|
71
73
|
self.ogc_server = self._get_ogcserver_byname(self.lower_key_params["ogcserver"])
|
74
|
+
elif main_ogc_server is not None:
|
75
|
+
self.ogc_server = self._get_ogcserver_byname(main_ogc_server)
|
72
76
|
elif not has_default_ogc_server:
|
73
77
|
raise HTTPBadRequest("The querystring argument 'ogcserver' is required")
|
74
78
|
|
75
79
|
@CACHE_REGION.cache_on_arguments() # type: ignore
|
76
|
-
def _get_ogcserver_byname(self, name: str) -> main.OGCServer:
|
80
|
+
def _get_ogcserver_byname(self, name: str) -> main.OGCServer:
|
77
81
|
try:
|
78
82
|
result = DBSession.query(main.OGCServer).filter(main.OGCServer.name == name).one()
|
79
83
|
DBSession.expunge(result)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2011-
|
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
|
@@ -64,24 +64,22 @@ class PrintProxy(Proxy):
|
|
64
64
|
query_string = urllib.parse.urlencode(params)
|
65
65
|
|
66
66
|
resp, content = self._capabilities(
|
67
|
-
templates, query_string, self.request.method, self.request.referrer
|
67
|
+
templates, query_string, self.request.method, self.request.referrer
|
68
68
|
)
|
69
69
|
|
70
70
|
response = self._build_response(resp, content, Cache.PRIVATE, "print")
|
71
|
-
# Mapfish print will check the
|
72
|
-
response.vary += ("Referer"
|
71
|
+
# Mapfish print will check the referrer header to return the capabilities.
|
72
|
+
response.vary += ("Referrer", "Referer")
|
73
73
|
return response
|
74
74
|
|
75
75
|
@CACHE_REGION.cache_on_arguments() # type: ignore
|
76
76
|
def _capabilities(
|
77
|
-
self, templates: List[str], query_string: Dict[str, str], method: str, referrer: str
|
77
|
+
self, templates: List[str], query_string: Dict[str, str], method: str, referrer: str
|
78
78
|
) -> Tuple[requests.Response, str]:
|
79
79
|
del query_string # Just for caching
|
80
80
|
del method # Just for caching
|
81
81
|
del referrer # Just for caching
|
82
|
-
|
83
|
-
|
84
|
-
# Get URL
|
82
|
+
# get URL
|
85
83
|
_url = self.request.get_organization_print_url() + "/capabilities.json"
|
86
84
|
|
87
85
|
response = self._proxy(Url(_url))
|
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2011-2024, Camptocamp SA
|
1
|
+
# Copyright (c) 2011-2023, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -47,7 +45,7 @@ CACHE_REGION = get_region("std")
|
|
47
45
|
|
48
46
|
|
49
47
|
class Proxy:
|
50
|
-
"""Some
|
48
|
+
"""Some methods used by all the proxy."""
|
51
49
|
|
52
50
|
def __init__(self, request: pyramid.request.Request):
|
53
51
|
self.request = request
|
@@ -175,10 +173,9 @@ class Proxy:
|
|
175
173
|
return response
|
176
174
|
|
177
175
|
@CACHE_REGION.cache_on_arguments() # type: ignore
|
178
|
-
def _proxy_cache(self,
|
176
|
+
def _proxy_cache(self, method: str, *args: Any, **kwargs: Any) -> pyramid.response.Response:
|
179
177
|
# Method is only for the cache
|
180
|
-
del
|
181
|
-
|
178
|
+
del method
|
182
179
|
kwargs["cache"] = True
|
183
180
|
return self._proxy(*args, **kwargs)
|
184
181
|
|
@@ -194,7 +191,7 @@ class Proxy:
|
|
194
191
|
headers_update = {}
|
195
192
|
cache = kwargs.get("cache", False)
|
196
193
|
if cache is True:
|
197
|
-
response = self._proxy_cache(url, self.request.
|
194
|
+
response = self._proxy_cache(url, self.request.method, **kwargs)
|
198
195
|
else:
|
199
196
|
response = self._proxy(url, **kwargs)
|
200
197
|
|
@@ -252,7 +249,7 @@ class Proxy:
|
|
252
249
|
|
253
250
|
@staticmethod
|
254
251
|
def _get_lower_params(params: Dict[str, str]) -> Dict[str, str]:
|
255
|
-
return
|
252
|
+
return {k.lower(): str(v).lower() for k, v in params.items()}
|
256
253
|
|
257
254
|
def get_headers(self) -> Dict[str, str]:
|
258
255
|
headers: Dict[str, str] = self.request.headers
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2012-
|
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
|
@@ -167,7 +167,7 @@ class Raster:
|
|
167
167
|
result = None if result == layer.get("nodata", dataset.nodata) else result
|
168
168
|
else:
|
169
169
|
LOG.debug(
|
170
|
-
"Out of index for layer: %s (%s),
|
170
|
+
"Out of index for layer: %s (%s), lon/lat: %dx%d, index: %dx%d, shape: %dx%d.",
|
171
171
|
name,
|
172
172
|
layer["file"],
|
173
173
|
lon,
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2013-
|
1
|
+
# Copyright (c) 2013-2023, Camptocamp SA
|
2
2
|
# All rights reserved.
|
3
3
|
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -71,7 +71,6 @@ class Shortener:
|
|
71
71
|
|
72
72
|
@view_config(route_name="shortener_create", renderer="json") # type: ignore
|
73
73
|
def create(self) -> Dict[str, str]:
|
74
|
-
|
75
74
|
if "url" not in self.request.params:
|
76
75
|
raise HTTPBadRequest("The parameter url is required")
|
77
76
|
|