From 91e68714ecf5bfd3afe9262855337e7f959f752c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 09:52:47 +0200 Subject: [PATCH 001/253] [Fixes #11100] Bump to Geoserver 2.23.1 (#11104) (#11107) * Bump to Geoserver 2.23.1 * fixed typo (cherry picked from commit a5d75529921a14bee833912c6b3c1283aed1f21d) Co-authored-by: Giovanni Allegri --- dev_config.yml | 4 ++-- docker-compose-geoserver-server.yml | 4 ++-- docker-compose-test.yml | 4 ++-- docker-compose.yml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dev_config.yml b/dev_config.yml index 3fa02cd768e..b6c89644210 100644 --- a/dev_config.yml +++ b/dev_config.yml @@ -1,6 +1,6 @@ --- -GEOSERVER_URL: "https://artifacts.geonode.org/geoserver/2.23.0/geoserver.war" -DATA_DIR_URL: "https://artifacts.geonode.org/geoserver/2.23.0/geonode-geoserver-ext-web-app-data.zip" +GEOSERVER_URL: "https://artifacts.geonode.org/geoserver/2.23.1/geoserver.war" +DATA_DIR_URL: "https://artifacts.geonode.org/geoserver/2.23.1/geonode-geoserver-ext-web-app-data.zip" JETTY_RUNNER_URL: "https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-runner/9.4.31.v20200723/jetty-runner-9.4.31.v20200723.jar" WINDOWS: py2exe: "http://downloads.sourceforge.net/project/py2exe/py2exe/0.6.9/py2exe-0.6.9.win32-py2.7.exe" diff --git a/docker-compose-geoserver-server.yml b/docker-compose-geoserver-server.yml index 10785a5794a..8dfc08b06c0 100644 --- a/docker-compose-geoserver-server.yml +++ b/docker-compose-geoserver-server.yml @@ -2,7 +2,7 @@ version: '2.2' services: data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:2.23.1 restart: on-failure container_name: gsconf4${COMPOSE_PROJECT_NAME} labels: @@ -13,7 +13,7 @@ services: - geoserver-data-dir:/geoserver_data/data geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:2.23.1 restart: unless-stopped container_name: geoserver4${COMPOSE_PROJECT_NAME} stdin_open: true diff --git a/docker-compose-test.yml b/docker-compose-test.yml index de398f099a7..9fed05cbb8d 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -89,7 +89,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:2.23.1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://127.0.0.1:8080/geoserver/ows" @@ -113,7 +113,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:2.23.1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: diff --git a/docker-compose.yml b/docker-compose.yml index a4fc63d9b88..5bf831b1ff5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -89,7 +89,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:2.23.1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://127.0.0.1:8080/geoserver/ows" @@ -113,7 +113,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:2.23.1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: From 91c4a3ceacdd90912ce6e493a591a022c5bda851 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 09:53:06 +0200 Subject: [PATCH 002/253] Add geotiff to supported raster type (#11106) (#11108) (cherry picked from commit 82ca860929d209e690b781d0cdc0bdd6fb19e1a7) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/settings.py b/geonode/settings.py index 1854dc875ea..d408093575b 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -2226,7 +2226,7 @@ def get_geonode_catalogue_service(): "id": "tiff", "label": "GeoTIFF", "format": "raster", - "ext": ["tiff", "tif"], + "ext": ["tiff", "tif", "geotiff", "geotif"], "mimeType": ["image/tiff"], "optional": ["xml", "sld"], }, From 49d7db28fdad9e6ddc10b4c0dcf09efacf71ee24 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 10:24:19 +0200 Subject: [PATCH 003/253] Bump requests from 2.30.0 to 2.31.0 (#11099) (#11109) * Bump requests from 2.30.0 to 2.31.0 Bumps [requests](https://github.com/psf/requests) from 2.30.0 to 2.31.0. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.30.0...v2.31.0) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production ... Signed-off-by: dependabot[bot] * [Dependencies] Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani (cherry picked from commit 100a46e6a23a121edf54096c8c3c9a321c2c35b0) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index f7098bfac67..c5aca3b8542 100644 --- a/requirements.txt +++ b/requirements.txt @@ -127,7 +127,7 @@ jdcal==1.4.1 mock<6.0.0 python-dateutil==2.8.2 pytz==2023.3 -requests==2.30.0 +requests==2.31.0 timeout-decorator==0.5.0 pylibmc==1.6.3 sherlock==0.4.1 diff --git a/setup.cfg b/setup.cfg index a4fb936d3fe..bccde3e9be0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -152,7 +152,7 @@ install_requires = mock<6.0.0 python-dateutil==2.8.2 pytz==2023.3 - requests==2.30.0 + requests==2.31.0 timeout-decorator==0.5.0 pylibmc==1.6.3 sherlock==0.4.1 From 2f2232b79d9eec58988afac1a433bb842fa8599b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 10:34:04 +0200 Subject: [PATCH 004/253] Bump owslib from 0.29.1 to 0.29.2 (#11092) (#11111) * Bump owslib from 0.29.1 to 0.29.2 Bumps [owslib](https://github.com/geopython/OWSLib) from 0.29.1 to 0.29.2. - [Release notes](https://github.com/geopython/OWSLib/releases) - [Commits](https://github.com/geopython/OWSLib/compare/0.29.1...0.29.2) --- updated-dependencies: - dependency-name: owslib dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * [Dependencies] Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani (cherry picked from commit 65e580cfd877d9ccd810003e6fa221e1f667a2dc) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index c5aca3b8542..ed73e7c97cd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -54,7 +54,7 @@ pyjwt==2.7.0 # geopython dependencies pyproj<3.6.0 -OWSLib==0.29.1 +OWSLib==0.29.2 pycsw==2.6.1 SQLAlchemy==2.0.13 # required by PyCSW Shapely==1.8.5.post1 diff --git a/setup.cfg b/setup.cfg index bccde3e9be0..c30639fac5a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -80,7 +80,7 @@ install_requires = # geopython dependencies pyproj<3.6.0 - OWSLib==0.29.1 + OWSLib==0.29.2 pycsw==2.6.1 SQLAlchemy==2.0.13 # required by PyCSW Shapely==1.8.5.post1 From 7985d3114bc3276b91a0d8ac7e5550310879b306 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 10:34:26 +0200 Subject: [PATCH 005/253] Bump geoserver-restconfig from 2.0.8 to 2.0.9 (#11087) (#11110) * Bump geoserver-restconfig from 2.0.8 to 2.0.9 Bumps [geoserver-restconfig](https://github.com/GeoNode/geoserver-restconfig) from 2.0.8 to 2.0.9. - [Release notes](https://github.com/GeoNode/geoserver-restconfig/releases) - [Changelog](https://github.com/GeoNode/geoserver-restconfig/blob/master/CHANGELOG.md) - [Commits](https://github.com/GeoNode/geoserver-restconfig/commits) --- updated-dependencies: - dependency-name: geoserver-restconfig dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * [Dependencies] Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani (cherry picked from commit 83703e8f5b442802fa18091319d1601be6fdb64f) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index ed73e7c97cd..d88f97b7f8f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -97,7 +97,7 @@ geonode-user-messages==2.0.2 geonode-announcements==2.0.2 geonode-django-activity-stream==0.10.0 gn-arcrest==10.5.5 -geoserver-restconfig==2.0.8 +geoserver-restconfig==2.0.9 gn-gsimporter==2.0.4 gisdata==0.5.4 diff --git a/setup.cfg b/setup.cfg index c30639fac5a..23a9956d24c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -122,7 +122,7 @@ install_requires = geonode-announcements==2.0.2 geonode-django-activity-stream==0.10.0 gn-arcrest==10.5.5 - geoserver-restconfig==2.0.8 + geoserver-restconfig==2.0.9 gn-gsimporter==2.0.4 gisdata==0.5.4 From b4b9f9fb65b4f3c7678e7bb1fcf06ee5916e6b8a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 10:35:53 +0200 Subject: [PATCH 006/253] Bump invoke from 2.1.1 to 2.1.2 (#11089) (#11112) * Bump invoke from 2.1.1 to 2.1.2 Bumps [invoke](https://github.com/pyinvoke/invoke) from 2.1.1 to 2.1.2. - [Commits](https://github.com/pyinvoke/invoke/compare/2.1.1...2.1.2) --- updated-dependencies: - dependency-name: invoke dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * [Dependencies] Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani (cherry picked from commit f3ddb105417c2f2d9fc5492a3f5fe63ce09ee183) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index d88f97b7f8f..163298b53d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -147,7 +147,7 @@ uWSGI==2.0.21 gunicorn==20.1.0 ipython==8.13.2 docker==6.1.2 -invoke==2.1.1 +invoke==2.1.2 # tests coverage==7.2.5 diff --git a/setup.cfg b/setup.cfg index 23a9956d24c..ad6bc2d61f6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -172,7 +172,7 @@ install_requires = gunicorn==20.1.0 ipython==8.13.2 docker==6.1.2 - invoke==2.1.1 + invoke==2.1.2 # tests coverage==7.2.5 From fcaf74af5c3429872cb5234c123f28ce8c49378c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 10:37:01 +0200 Subject: [PATCH 007/253] Update setuptools requirement from <67.8.0,>=59.1.1 to >=59.1.1,<67.9.0 (#11091) (#11113) * Update setuptools requirement from <67.8.0,>=59.1.1 to >=59.1.1,<67.9.0 Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v65.5.1...v67.8.0) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:production ... Signed-off-by: dependabot[bot] * [Dependencies] Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani (cherry picked from commit 6d8fe4337ce78bcee53a0c39bf7e70fefb50e1e0) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 163298b53d9..f6e9025df4d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -159,7 +159,7 @@ pytest-bdd==6.1.1 splinter==0.19.0 pytest-splinter==3.3.2 pytest-django==4.5.2 -setuptools>=59.1.1,<67.8.0 +setuptools>=59.1.1,<67.9.0 pip==23.1.2 Twisted==22.10.0 pixelmatch==0.3.0 diff --git a/setup.cfg b/setup.cfg index ad6bc2d61f6..f0c8c5aaef5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -184,7 +184,7 @@ install_requires = splinter==0.19.0 pytest-splinter==3.3.2 pytest-django==4.5.2 - setuptools>=59.1.1,<67.8.0 + setuptools>=59.1.1,<67.9.0 pip==23.1.2 Twisted==22.10.0 pixelmatch==0.3.0 From ac26ed5287e0d96d64585757de3bbecb3b708ac7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 10:49:55 +0200 Subject: [PATCH 008/253] Bump wandb from 0.15.2 to 0.15.3 (#11090) (#11114) * Bump wandb from 0.15.2 to 0.15.3 Bumps [wandb](https://github.com/wandb/wandb) from 0.15.2 to 0.15.3. - [Release notes](https://github.com/wandb/wandb/releases) - [Changelog](https://github.com/wandb/wandb/blob/main/CHANGELOG.md) - [Commits](https://github.com/wandb/wandb/compare/v0.15.2...v0.15.3) --- updated-dependencies: - dependency-name: wandb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * [Dependencies] Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani (cherry picked from commit 32cda5beff8ce65716fa2be71a60e857f2a78ae6) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index f6e9025df4d..3f22f1e269c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -171,7 +171,7 @@ webdriver_manager==3.8.6 # Security and audit mistune==2.0.5 -wandb==0.15.2 +wandb==0.15.3 protobuf==3.20.3 mako==1.2.4 certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability diff --git a/setup.cfg b/setup.cfg index f0c8c5aaef5..bf8979de6be 100644 --- a/setup.cfg +++ b/setup.cfg @@ -196,7 +196,7 @@ install_requires = # Security and audit mistune==2.0.5 - wandb==0.15.2 + wandb==0.15.3 protobuf==3.20.3 mako==1.2.4 certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability From 7629dbf657c83eb1aa38a927f820ac7eee7bf7c4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 10:52:19 +0200 Subject: [PATCH 009/253] Bump sqlalchemy from 2.0.13 to 2.0.15 (#11088) (#11116) * Bump sqlalchemy from 2.0.13 to 2.0.15 Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.13 to 2.0.15. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * [Dependencies] Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani (cherry picked from commit 3fbdad0e340763b131123225d1a6d5e9c7cf8e68) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 3f22f1e269c..02604b59665 100644 --- a/requirements.txt +++ b/requirements.txt @@ -56,7 +56,7 @@ pyjwt==2.7.0 pyproj<3.6.0 OWSLib==0.29.2 pycsw==2.6.1 -SQLAlchemy==2.0.13 # required by PyCSW +SQLAlchemy==2.0.15 # required by PyCSW Shapely==1.8.5.post1 mercantile==1.2.1 geoip2==4.7.0 diff --git a/setup.cfg b/setup.cfg index bf8979de6be..20d84ec1a40 100644 --- a/setup.cfg +++ b/setup.cfg @@ -82,7 +82,7 @@ install_requires = pyproj<3.6.0 OWSLib==0.29.2 pycsw==2.6.1 - SQLAlchemy==2.0.13 # required by PyCSW + SQLAlchemy==2.0.15 # required by PyCSW Shapely==1.8.5.post1 mercantile==1.2.1 geoip2==4.7.0 From e480261493adc06b93d1d0315f6f6880e9cd4518 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 10:54:07 +0200 Subject: [PATCH 010/253] Bump boto3 from 1.26.133 to 1.26.137 (#11086) (#11115) * Bump boto3 from 1.26.133 to 1.26.137 Bumps [boto3](https://github.com/boto/boto3) from 1.26.133 to 1.26.137. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.133...1.26.137) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * [Dependencies] Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani (cherry picked from commit 1fa0e2ddde190f490e67ddb45c16f7bddac2a033) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 02604b59665..a911b3db9e2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -113,7 +113,7 @@ django-storages==1.13.2 dropbox==11.36.0 google-cloud-storage==2.9.0 google-cloud-core==2.3.2 -boto3==1.26.133 +boto3==1.26.137 # Django Caches python-memcached<=1.59 diff --git a/setup.cfg b/setup.cfg index 20d84ec1a40..cbd06ed72ea 100644 --- a/setup.cfg +++ b/setup.cfg @@ -138,7 +138,7 @@ install_requires = dropbox==11.36.0 google-cloud-storage==2.9.0 google-cloud-core==2.3.2 - boto3==1.26.133 + boto3==1.26.137 # Django Caches python-memcached<=1.59 From a5deddd6927eafe1cc99f1efbe09b5ac6e5086b5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 17:07:05 +0200 Subject: [PATCH 011/253] Remove doc_file and file_path from document serializer (#11117) (#11119) (cherry picked from commit 927a302bb4494a3d7dce5c829d7c6a646247704c) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/documents/api/serializers.py | 7 +++++++ geonode/documents/api/tests.py | 15 ++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/geonode/documents/api/serializers.py b/geonode/documents/api/serializers.py index 7fdeb0ad990..dc11cb201f5 100644 --- a/geonode/documents/api/serializers.py +++ b/geonode/documents/api/serializers.py @@ -61,3 +61,10 @@ class Meta: "doc_url", "metadata", ) + + def to_representation(self, obj): + _doc = super(DocumentSerializer, self).to_representation(obj) + # better to hide internal server file path + _doc.pop("file_path") + _doc.pop("doc_file") + return _doc diff --git a/geonode/documents/api/tests.py b/geonode/documents/api/tests.py index e480cdfd3be..dbb3b13588b 100644 --- a/geonode/documents/api/tests.py +++ b/geonode/documents/api/tests.py @@ -16,7 +16,6 @@ # along with this program. If not, see . # ######################################################################### -import os import logging from django.contrib.auth import get_user_model @@ -139,14 +138,20 @@ def test_creation_should_create_the_doc(self): } actual = self.client.post(self.url, data=payload, format="json") self.assertEqual(201, actual.status_code) - cloned_path = actual.json().get("document", {}).get("file_path", "")[0] extension = actual.json().get("document", {}).get("extension", "") - self.assertTrue(os.path.exists(cloned_path)) self.assertEqual("xml", extension) self.assertTrue(Document.objects.filter(title="New document for testing").exists()) - if cloned_path: - os.remove(cloned_path) + def test_file_path_and_doc_path_are_not_returned(self): + """ + If file_path and doc_path should not be visible + from the GET payload + """ + actual = self.client.get(self.url) + self.assertEqual(200, actual.status_code) + _doc_payload = actual.json().get("document", {}) + self.assertFalse("file_path" in _doc_payload) + self.assertFalse("doc_path" in _doc_payload) def test_creation_from_url_should_create_the_doc(self): """ From d85c69c18f81b05c9f8c3be5b6c05c7777c8321d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 26 May 2023 09:22:52 +0200 Subject: [PATCH 012/253] fix: scripts/docker/nginx/Dockerfile to reduce vulnerabilities (#11122) (#11123) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-ALPINE317-CURL-3320725 - https://snyk.io/vuln/SNYK-ALPINE317-CURL-3320725 - https://snyk.io/vuln/SNYK-ALPINE317-CURL-3364764 - https://snyk.io/vuln/SNYK-ALPINE317-CURL-3364764 - https://snyk.io/vuln/SNYK-ALPINE317-TIFF-3368766 Co-authored-by: snyk-bot (cherry picked from commit a66bef9bb776f5b1a6e6ae6b9c7ff90af27c0d3a) Co-authored-by: Alessio Fabiani --- scripts/docker/nginx/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docker/nginx/Dockerfile b/scripts/docker/nginx/Dockerfile index 3f8c8027c20..92652f376c6 100644 --- a/scripts/docker/nginx/Dockerfile +++ b/scripts/docker/nginx/Dockerfile @@ -1,4 +1,4 @@ -FROM nginx:1.23.3-alpine +FROM nginx:1-alpine RUN apk add --no-cache openssl inotify-tools From bf134671a8a5a217f1aac8ee005d0ea9b4debfc6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 May 2023 09:59:50 +0200 Subject: [PATCH 013/253] [Fixes #11129] GWC REST path incorrectly renamed to datasets (#11130) (#11132) (cherry picked from commit 4bf0d8a699c2f2fceb35ae5ff67cd289d7aa1a30) Co-authored-by: Emanuele Tajariol --- geonode/geoserver/management/commands/set_default_gridsets.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geonode/geoserver/management/commands/set_default_gridsets.py b/geonode/geoserver/management/commands/set_default_gridsets.py index 0fcfb51b499..0826b744e57 100644 --- a/geonode/geoserver/management/commands/set_default_gridsets.py +++ b/geonode/geoserver/management/commands/set_default_gridsets.py @@ -78,11 +78,11 @@ def handle(self, **options): """ curl -v -u admin:geoserver -XPOST \ -H "Content-type: text/xml" -d @poi.xml \ - "http://localhost:8080/geoserver/gwc/rest/datasets/tiger:poi.xml" + "http://localhost:8080/geoserver/gwc/rest/layers/tiger:poi.xml" """ headers = {'Content-type': 'text/xml'} payload = ET.tostring(tree) - r = requests.post(f'{url}gwc/rest/datasets/{layer.typename}.xml', + r = requests.post(f'{url}gwc/rest/layers/{layer.typename}.xml', headers=headers, data=payload, auth=HTTPBasicAuth(user, passwd)) From 10f44e02915b31b998f866d3f85cac156525bce9 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 1 Jun 2023 15:04:31 +0200 Subject: [PATCH 014/253] Revert "[Fixes #11100] Bump to Geoserver 2.23.1 (#11104) (#11107)" (#11136) This reverts commit 91e68714ecf5bfd3afe9262855337e7f959f752c. --- dev_config.yml | 4 ++-- docker-compose-geoserver-server.yml | 4 ++-- docker-compose-test.yml | 4 ++-- docker-compose.yml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dev_config.yml b/dev_config.yml index b6c89644210..3fa02cd768e 100644 --- a/dev_config.yml +++ b/dev_config.yml @@ -1,6 +1,6 @@ --- -GEOSERVER_URL: "https://artifacts.geonode.org/geoserver/2.23.1/geoserver.war" -DATA_DIR_URL: "https://artifacts.geonode.org/geoserver/2.23.1/geonode-geoserver-ext-web-app-data.zip" +GEOSERVER_URL: "https://artifacts.geonode.org/geoserver/2.23.0/geoserver.war" +DATA_DIR_URL: "https://artifacts.geonode.org/geoserver/2.23.0/geonode-geoserver-ext-web-app-data.zip" JETTY_RUNNER_URL: "https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-runner/9.4.31.v20200723/jetty-runner-9.4.31.v20200723.jar" WINDOWS: py2exe: "http://downloads.sourceforge.net/project/py2exe/py2exe/0.6.9/py2exe-0.6.9.win32-py2.7.exe" diff --git a/docker-compose-geoserver-server.yml b/docker-compose-geoserver-server.yml index 8dfc08b06c0..10785a5794a 100644 --- a/docker-compose-geoserver-server.yml +++ b/docker-compose-geoserver-server.yml @@ -2,7 +2,7 @@ version: '2.2' services: data-dir-conf: - image: geonode/geoserver_data:2.23.1 + image: geonode/geoserver_data:2.23.0 restart: on-failure container_name: gsconf4${COMPOSE_PROJECT_NAME} labels: @@ -13,7 +13,7 @@ services: - geoserver-data-dir:/geoserver_data/data geoserver: - image: geonode/geoserver:2.23.1 + image: geonode/geoserver:2.23.0 restart: unless-stopped container_name: geoserver4${COMPOSE_PROJECT_NAME} stdin_open: true diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 9fed05cbb8d..de398f099a7 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -89,7 +89,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.1 + image: geonode/geoserver:2.23.0 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://127.0.0.1:8080/geoserver/ows" @@ -113,7 +113,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.1 + image: geonode/geoserver_data:2.23.0 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: diff --git a/docker-compose.yml b/docker-compose.yml index 5bf831b1ff5..a4fc63d9b88 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -89,7 +89,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.1 + image: geonode/geoserver:2.23.0 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://127.0.0.1:8080/geoserver/ows" @@ -113,7 +113,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.1 + image: geonode/geoserver_data:2.23.0 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: From b045b0fbdc9f800b4aa344cb78c7360302125724 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 1 Jun 2023 15:16:12 +0200 Subject: [PATCH 015/253] Bump client and importer version (#11133) --- requirements.txt | 5 ++--- setup.cfg | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/requirements.txt b/requirements.txt index a911b3db9e2..47b97aae7e0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,9 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -# django-geonode-mapstore-client==4.0.5 --e git+https://github.com/GeoNode/geonode-mapstore-client.git@master#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.1.0 +geonode-importer==1.0.3 geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index cbd06ed72ea..23ffef28b5b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.0.5,<5.0.0 - geonode-importer>=1.0.0 + django-geonode-mapstore-client==4.1.0 + geonode-importer==1.0.3 geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 81cdb013ade41487029d88336e356312f7bfcec8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 15:54:05 +0200 Subject: [PATCH 016/253] [Fixes #11147] Strip port from visitor_ip_address (#11148) (#11150) * strip port from visitor_ip_address * gix PEP (cherry picked from commit 6887596c9672b2e5b6575e6e40c07b37951f4b8e) Co-authored-by: Giovanni Allegri --- geonode/base/auth.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/geonode/base/auth.py b/geonode/base/auth.py index cfef16bd820..e56d03edb01 100644 --- a/geonode/base/auth.py +++ b/geonode/base/auth.py @@ -259,6 +259,8 @@ def visitor_ip_address(request): ip = x_forwarded_for.split(",")[0] else: ip = request.META.get("REMOTE_ADDR") + if ip: + ip = re.match(r"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", ip)[0] return ip From a4f4a4cdce6387e74b1494ce13b4fa0b8e43b92f Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 7 Jun 2023 15:35:01 +0200 Subject: [PATCH 017/253] updated changelog --- CHANGELOG.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee54d4a6d2e..799dbb6035c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,50 @@ # Change Log +## [4.1.0](https://github.com/GeoNode/geonode/tree/4.1.0) (2023-06-05) +### New upload engine +GeoNode integrates a brand new importer module based on [GDAL/OGR](https://gdal.org/), which offers increased robustness and reliability to the upload UI and API services. GeoPackage (vector), GeoJSON, KML/KMZ formats and a new CSV handler have been implemented. + +### Thesaurus faceting and date filtering +If thesaurus and thesaurus keywords are configured and assigned to resources, they will be available inside the filters panel, along with the number of associated resources. +Date filtering (from/top) has also been added. + +### Time series configurable after the upload +The configuration of (potential) time series at upload time was confusing for users, and not very robust. +With the new importer, the optional configuration of vector time series can be done afterward, through the Settings tab inside the Metadata editing page +Only vector fomats that provide date(time) fields natively are supported. Conversion from string fields is not implemented. + +### Related resources +This restore a functionality available in previous versions of GeoNode. +A tab inside the info panel has been added where relationships between datasets, maps and documents are reported. + +### Vector dataset attributes +A tab inside the info panel has been added showing the attributes of vector datasets + +### Remote documents +The API has been extended to permit the creation of document resources referencing remote URLs + +### ISO-19115 XML upload via API +The API now supports the upload of a metadata XML file along with the resource data + +### Software upgrades + + - [Geoserver 2.23.0](https://geoserver.org/announcements/2023/04/05/geoserver-2-23-0-released.html) is now the reference version. This version includes Geofence WPS rules which are employed by GeoNode to strengthen the security of the OGC/WPS processes. +- [MapStore 2022.02.xx](https://github.com/geosolutions-it/MapStore2/tree/2022.02.xx) +- [Django 3.2.19](https://docs.djangoproject.com/en/4.2/releases/3.2.19/) +- PostgreSQL 13 and PostGIS 3.3.3 + + +## Security and Bug Fixes +- [CVE-2023-26043](https://github.com/GeoNode/geonode/security/advisories/GHSA-mcmc-c59m-pqq8) +Fixed a vulnerability to XML External Entity (XXE) injection +- [CVE-2023-28442](https://github.com/GeoNode/geonode/security/advisories/GHSA-87mh-vw7c-5v6w) +Fixed information leak + +You can see the **full list of closed issues [here](https://github.com/GeoNode/geonode/compare/4.1.0...4.0.3)**. + +## System requirements +Python >3.9 is required to run GeoNode 4.1.0, since many of its dependencies have dropped support for older versions. + ## [4.0.2](https://github.com/GeoNode/geonode/tree/4.0.2) (2022-12-20) ### Breaking Changes From a10f0cbf555f869d8526a8d9d42672f166716d6c Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 7 Jun 2023 17:02:52 +0200 Subject: [PATCH 018/253] Track client and importer development packages (#11151) --- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 47b97aae7e0..be7ab302224 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -django-geonode-mapstore-client==4.1.0 -geonode-importer==1.0.3 +-e git+https://github.com/GeoNode/geonode-mapstore-client.git@master#egg=django_geonode_mapstore_client +-e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 23ffef28b5b..2fbfb5af065 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client==4.1.0 - geonode-importer==1.0.3 + django-geonode-mapstore-client>=4.1.0 + geonode-importer>=1.0.3 geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 7b50d0a336215ae9cb03c13f4e4c8b99609e5e9e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 22 Jun 2023 17:12:22 +0200 Subject: [PATCH 019/253] Fix region intersection test (#11167) (#11168) (cherry picked from commit 5ae4e1818d7544acc6cd9c899dc1e270cb979784) Co-authored-by: Giovanni Allegri --- geonode/base/fixtures/regions.json | 17 ----------------- geonode/resource/utils.py | 2 +- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/geonode/base/fixtures/regions.json b/geonode/base/fixtures/regions.json index 9aee734f63f..98e93362e0f 100644 --- a/geonode/base/fixtures/regions.json +++ b/geonode/base/fixtures/regions.json @@ -4334,23 +4334,6 @@ "bbox_y1": 27.454559 } }, - { - "pk": 256, - "model": "base.region", - "fields": { - "rght": 515, - "code": "PAC", - "name": "Pacific", - "parent": null, - "level": 1, - "lft": 464, - "tree_id": 90, - "bbox_x0": 139.572356, - "bbox_x1": -74.531208, - "bbox_y0": -56.267241, - "bbox_y1": 62.0215969 - } - }, { "pk": 257, "model": "base.region", diff --git a/geonode/resource/utils.py b/geonode/resource/utils.py index 83dc56290de..70dda53f921 100644 --- a/geonode/resource/utils.py +++ b/geonode/resource/utils.py @@ -489,7 +489,7 @@ def metadata_post_save(instance, *args, **kwargs): poly2 = GEOSGeometry(wkt2, srid=int(srid2[0])) poly2.transform(4326) - if poly2.intersection(poly1): + if not poly2.intersection(poly1).empty: regions_to_add.append(region) if region.level == 0 and region.parent is None: global_regions.append(region) From 140d6f158cf91973cf5b3b85cdbd12d8e14ad69c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 22 Jun 2023 17:36:11 +0200 Subject: [PATCH 020/253] [Fixes #11188] Make keywords optional when editing a resource with the Django Admin (#11189) (#11190) (cherry picked from commit c34e4924414c30c15b14ed6ca7627d457a72a5d6) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/base/admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/base/admin.py b/geonode/base/admin.py index 7b5cbaba581..0f6c4ee859c 100755 --- a/geonode/base/admin.py +++ b/geonode/base/admin.py @@ -338,7 +338,7 @@ def keyword_id(self, obj): class ResourceBaseAdminForm(autocomplete.FutureModelForm): - keywords = TagField(widget=TaggitSelect2Custom("autocomplete_hierachical_keyword")) + keywords = TagField(widget=TaggitSelect2Custom("autocomplete_hierachical_keyword"), required=False) def delete_queryset(self, request, queryset): """ From 87cde26410f76640dd2255cc2da27959dea8142a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 26 Jun 2023 15:24:09 +0200 Subject: [PATCH 021/253] Direct download on preview on dataset list is not working #11156 (#11165) (#11201) * FIx download_url for WFS url * FIx download_url for WFS url * FIx download_url for WFS url, change settings * FIx download_url for WFS url, change settings * Fix tests * [Fixes #11156] Approach change and code rollback * [Fixes #11156] Approach change and code rollback * [Fixes #11156] Approach change and code rollback * [Fixes #11156] Change delete query for original links --------- Co-authored-by: Giovanni Allegri (cherry picked from commit e103d06a391f250218cfbdc35bf6311a2b6e5204) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/layers/tests.py | 1 - geonode/utils.py | 14 +++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/geonode/layers/tests.py b/geonode/layers/tests.py index a24fb52ee01..fbe14c340ba 100644 --- a/geonode/layers/tests.py +++ b/geonode/layers/tests.py @@ -373,7 +373,6 @@ def test_dataset_links(self): links = Link.objects.filter(resource=lyr.resourcebase_ptr, link_type="image") self.assertIsNotNone(links) - # get and update original link to external Link.objects.filter(resource=lyr.resourcebase_ptr, link_type="original").update( url="http://google.com/test" ) diff --git a/geonode/utils.py b/geonode/utils.py index b7f82fbeaa0..8dc2443e884 100755 --- a/geonode/utils.py +++ b/geonode/utils.py @@ -1377,6 +1377,8 @@ def set_resource_default_links(instance, layer, prune=False, **kwargs): from geonode.base.models import Link from django.urls import reverse from django.utils.translation import ugettext + from geonode.layers.models import Dataset + from geonode.documents.models import Document # Prune old links if prune: @@ -1446,9 +1448,15 @@ def set_resource_default_links(instance, layer, prune=False, **kwargs): # Create Raw Data download link if settings.DISPLAY_ORIGINAL_DATASET_LINK: logger.debug(" -- Resource Links[Create Raw Data download link]...") - download_url = urljoin(settings.SITEURL, reverse("download", args=[instance.id])) - while Link.objects.filter(resource=instance.resourcebase_ptr, url=download_url).count() > 1: - Link.objects.filter(resource=instance.resourcebase_ptr, url=download_url).first().delete() + if isinstance(instance, Dataset): + download_url = build_absolute_uri(reverse("dataset_download", args=(instance.alternate,))) + elif isinstance(instance, Document): + download_url = build_absolute_uri(reverse("document_download", args=(instance.id,))) + else: + download_url = None + + while Link.objects.filter(resource=instance.resourcebase_ptr, link_type="original").exists(): + Link.objects.filter(resource=instance.resourcebase_ptr, link_type="original").delete() Link.objects.update_or_create( resource=instance.resourcebase_ptr, url=download_url, From db34729dc968a52c13c540ee7a93b6a626afb0c8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Jul 2023 10:38:49 +0200 Subject: [PATCH 022/253] Fix #11154 - Wrong login URL in notification (#11155) (#11214) * Fix #11154 - Wrong login URL in notification * fix single quote (cherry picked from commit ad68f2ed7c697345fd0fda644d0e77f49af158f0) Co-authored-by: Francisco Vicent --- geonode/people/models.py | 1 + .../notifications/account_active/account_active_message.txt | 2 +- geonode/templates/pinax/notifications/account_active/full.txt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/geonode/people/models.py b/geonode/people/models.py index 37d4c21631c..c07b6f5e81f 100644 --- a/geonode/people/models.py +++ b/geonode/people/models.py @@ -246,6 +246,7 @@ def _notify_account_activated(self): "site_name": current_site.name, "email": self.email, "inviter": self, + "LOGIN_URL": settings.LOGIN_URL, } email_template = "pinax/notifications/account_active/account_active" diff --git a/geonode/templates/pinax/notifications/account_active/account_active_message.txt b/geonode/templates/pinax/notifications/account_active/account_active_message.txt index 02237b540e6..f9ddbc0c091 100644 --- a/geonode/templates/pinax/notifications/account_active/account_active_message.txt +++ b/geonode/templates/pinax/notifications/account_active/account_active_message.txt @@ -1,3 +1,3 @@ {% load i18n %} {% trans "Your account has been approved and is now active." %} ({{ username }})
-{% trans "You can use the login form at" %}: http://{{ current_site.name }} +{% trans "You can use the login form at" %}: {{ LOGIN_URL }} diff --git a/geonode/templates/pinax/notifications/account_active/full.txt b/geonode/templates/pinax/notifications/account_active/full.txt index aac4b9cc507..8344ed13d4b 100644 --- a/geonode/templates/pinax/notifications/account_active/full.txt +++ b/geonode/templates/pinax/notifications/account_active/full.txt @@ -1,3 +1,3 @@ {% load i18n %} {% trans "Your account has been approved and is now active." %}
-{% trans "You can use the login form at" %}: http://{{ current_site }} +{% trans "You can use the login form at" %}: {{ LOGIN_URL }} From be3b86410d39ff6204c9af41b3785a7aa983ee9c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Jul 2023 16:11:00 +0200 Subject: [PATCH 023/253] Bump django from 3.2.19 to 3.2.20 (#11216) (#11217) * Bump django from 3.2.19 to 3.2.20 Bumps [django](https://github.com/django/django) from 3.2.19 to 3.2.20. - [Commits](https://github.com/django/django/compare/3.2.19...3.2.20) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * - Align "setup.cfg" to "requirements.txt" --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani (cherry picked from commit de59bced4d56479eae55febb2c527132a7a4e2c6) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index be7ab302224..cd578ba7ce7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ Pillow==9.5.0 lxml==4.9.2 psycopg2==2.9.6 -Django==3.2.19 +Django==3.2.20 # Other amqp==5.1.1 diff --git a/setup.cfg b/setup.cfg index 2fbfb5af065..95bf6ac165d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,7 +28,7 @@ install_requires = Pillow==9.5.0 lxml==4.9.2 psycopg2==2.9.6 - Django==3.2.19 + Django==3.2.20 # Other amqp==5.1.1 From 3169cc0533aca2cfcc74a0413289b515faf62fcb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 5 Jul 2023 09:57:07 +0200 Subject: [PATCH 024/253] fix: Dockerfile to reduce vulnerabilities (#11223) (#11224) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-UBUNTU2204-BASH-3098342 - https://snyk.io/vuln/SNYK-UBUNTU2204-COREUTILS-2801226 - https://snyk.io/vuln/SNYK-UBUNTU2204-GLIBC-2801292 - https://snyk.io/vuln/SNYK-UBUNTU2204-LIBCAP2-5538282 - https://snyk.io/vuln/SNYK-UBUNTU2204-LIBCAP2-5538296 Co-authored-by: snyk-bot (cherry picked from commit 543d751d8c5d98184008b175d06d97b4b8131db2) Co-authored-by: Alessio Fabiani --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6c62736737b..5d76bb6f25d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04 +FROM ubuntu:22.10 LABEL GeoNode development team RUN mkdir -p /usr/src/geonode From 385ff006a86a590f42d6a060fdff386bf404aa55 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 12 Jul 2023 17:30:35 +0200 Subject: [PATCH 025/253] [Fixes #11256] Assign regions based on contains and overlaps (#11257) (#11261) * Assign regions based on contains and overlaps * tests * fix E501 --- geonode/base/models.py | 17 +++++++++++++++- geonode/base/tests.py | 41 ++++++++++++++++++++++++++++++++++++++- geonode/resource/utils.py | 10 ++-------- 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/geonode/base/models.py b/geonode/base/models.py index 6da70b6994c..1efe7288b0d 100644 --- a/geonode/base/models.py +++ b/geonode/base/models.py @@ -41,7 +41,7 @@ from django.contrib.auth import get_user_model from django.db.models.fields.json import JSONField from django.utils.functional import cached_property, classproperty -from django.contrib.gis.geos import Polygon, Point +from django.contrib.gis.geos import GEOSGeometry, Polygon, Point from django.contrib.gis.db.models import PolygonField from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ @@ -204,6 +204,21 @@ def geographic_bounding_box(self): """BBOX is in the format: [x0,x1,y0,y1].""" return bbox_to_wkt(self.bbox_x0, self.bbox_x1, self.bbox_y0, self.bbox_y1, srid=self.srid) + @property + def geom(self): + srid, wkt = self.geographic_bounding_box.split(";") + srid = re.findall(r"\d+", srid) + geom = GEOSGeometry(wkt, srid=int(srid[0])) + geom.transform(4326) + return geom + + def is_assignable_to_geom(self, extent_geom: GEOSGeometry): + region_geom = self.geom + + if region_geom.contains(extent_geom) or region_geom.overlaps(extent_geom): + return True + return False + class Meta: ordering = ("name",) verbose_name_plural = "Metadata Regions" diff --git a/geonode/base/tests.py b/geonode/base/tests.py index 7ee9a49b557..3c6cfb9b4f2 100644 --- a/geonode/base/tests.py +++ b/geonode/base/tests.py @@ -48,13 +48,14 @@ Menu, MenuItem, Configuration, + Region, TopicCategory, Thesaurus, ThesaurusKeyword, generate_thesaurus_reference, ) from django.conf import settings -from django.contrib.gis.geos import Polygon +from django.contrib.gis.geos import Polygon, GEOSGeometry from django.template import Template, Context from django.contrib.auth import get_user_model from geonode.storage.manager import storage_manager @@ -1124,3 +1125,41 @@ def test_keyword_raise_db_error(self, add_root_mocked): "Error during the keyword creation for keyword: keyword2", [x.message for x in _log.records], ) + + +class TestRegions(GeoNodeBaseTestSupport): + def setUp(self): + self.dataset_inside_region = GEOSGeometry( + "POLYGON ((-4.01799226543944599 57.18451093931114571, 8.89409253052255622 56.91828238681708285, \ + 9.29343535926363984 47.73339732577194638, -3.75176371294537603 48.13274015451304422, \ + -4.01799226543944599 57.18451093931114571))", + srid=4326, + ) + + self.dataset_overlapping_region = GEOSGeometry( + "POLYGON ((15.28357779038003628 33.6232840435866791, 28.19566258634203848 33.35705549109261625, \ + 28.5950054150831221 24.17217043004747978, 15.54980634287410624 24.57151325878857762, \ + 15.28357779038003628 33.6232840435866791))", + srid=4326, + ) + + self.dataset_outside_region = GEOSGeometry( + "POLYGON ((-3.75176371294537603 23.10725622007123548, 9.16032108301662618 22.84102766757717262, \ + 9.5596639117577098 13.65614260653203615, -3.48553516045130607 14.05548543527313399, \ + -3.75176371294537603 23.10725622007123548))", + srid=4326, + ) + + def test_region_assignment_for_extent(self): + region = Region.objects.get(code="EUR") + + self.assertTrue( + region.is_assignable_to_geom(self.dataset_inside_region), "Extent inside a region shouldn't be assigned" + ) + self.assertTrue( + region.is_assignable_to_geom(self.dataset_overlapping_region), + "Extent overlapping a region should be assigned", + ) + self.assertFalse( + region.is_assignable_to_geom(self.dataset_outside_region), "Extent outside a region should be assigned" + ) diff --git a/geonode/resource/utils.py b/geonode/resource/utils.py index 70dda53f921..ca7175c799b 100644 --- a/geonode/resource/utils.py +++ b/geonode/resource/utils.py @@ -483,13 +483,7 @@ def metadata_post_save(instance, *args, **kwargs): regions_to_add = [] for region in queryset: try: - srid2, wkt2 = region.geographic_bounding_box.split(";") - srid2 = re.findall(r"\d+", srid2) - - poly2 = GEOSGeometry(wkt2, srid=int(srid2[0])) - poly2.transform(4326) - - if not poly2.intersection(poly1).empty: + if region.is_assignable_to_geom(poly1): regions_to_add.append(region) if region.level == 0 and region.parent is None: global_regions.append(region) @@ -498,7 +492,7 @@ def metadata_post_save(instance, *args, **kwargs): if tb: logger.debug(tb) if regions_to_add or global_regions: - if regions_to_add and len(regions_to_add) > 0 and len(regions_to_add) <= 30: + if regions_to_add: instance.regions.add(*regions_to_add) else: instance.regions.add(*global_regions) From aaee1496f45e9862023eaa0091eb71ba035f7902 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 21 Jul 2023 16:57:30 +0200 Subject: [PATCH 026/253] [Fixes #11225] Italian translations aren't built with the latest fixes [Fixes #11264] Fix the italian translation for Position (#11284) (cherry picked from commit 2bdd2422ae20a389cd2a2910bb6afc121ce27656) Co-authored-by: etj --- geonode/locale/it/LC_MESSAGES/django.mo | Bin 155297 -> 161119 bytes geonode/locale/it/LC_MESSAGES/django.po | 2510 ++++++++++------------- 2 files changed, 1052 insertions(+), 1458 deletions(-) diff --git a/geonode/locale/it/LC_MESSAGES/django.mo b/geonode/locale/it/LC_MESSAGES/django.mo index a093d7f2986572518ff6c3196a2195cdfea49d9e..0a9e88e7f7d43b2150075b76272bf4703f194b8f 100644 GIT binary patch delta 38086 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 o-ILL_X&?9PXMD@M_5-$;`*Dudbom$ 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 delta 33511 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 b*7Ybc*jKo^w`O4YrkdVSzM-|e*F*jfhks># diff --git a/geonode/locale/it/LC_MESSAGES/django.po b/geonode/locale/it/LC_MESSAGES/django.po index 154a9219bfc..f698c7205b5 100644 --- a/geonode/locale/it/LC_MESSAGES/django.po +++ b/geonode/locale/it/LC_MESSAGES/django.po @@ -39,16 +39,15 @@ msgstr "" "Project-Id-Version: GeoNode\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-07-08 09:02+0300\n" -"PO-Revision-Date: 2021-04-29 13:43+0200\n" +"PO-Revision-Date: 2023-07-20 11:35+0200\n" "Last-Translator: Julien Collaer \n" -"Language-Team: Italian (http://www.transifex.com/geonode/geonode/language/" -"it/)\n" +"Language-Team: Italian (http://www.transifex.com/geonode/geonode/language/it/)\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 2.4.2\n" +"X-Generator: Poedit 3.0.1\n" msgid "Request to download a resource" msgstr "Richiedi di scaricare la risorsa" @@ -60,8 +59,7 @@ msgid "Request resource change" msgstr "Richiedi di modificare la risorsa" msgid "Owner has requested permissions to modify a resource" -msgstr "" -"Il proprietario ha richiesto le autorizzazioni per modificare la risorsa" +msgstr "Il proprietario ha richiesto le autorizzazioni per modificare la risorsa" msgid "series" msgstr "serie" @@ -199,11 +197,10 @@ msgid "Free-text Keywords" msgstr "Free-text Keywords" msgid "" -"A space or comma-separated list of keywords. Use the widget to select from " -"Hierarchical tree." +"A space or comma-separated list of keywords. Use the widget to select from Hierarchical tree." msgstr "" -"Uno spazio o un elenco delimitato da virgole di parole chiave. Utilizzare il " -"widget per selezionare dalla struttura ad albero gerarchica." +"Uno spazio o un elenco delimitato da virgole di parole chiave. Utilizzare il widget per " +"selezionare dalla struttura ad albero gerarchica." msgid "Regions" msgstr "Regioni" @@ -220,11 +217,9 @@ msgstr "Licenza" msgid "Language" msgstr "Lingua" -#, fuzzy -#| msgid "Users" msgid "User" msgid_plural "Users" -msgstr[0] "Utenti" +msgstr[0] "Utente" msgstr[1] "Utenti" msgid "Permission Type" @@ -258,41 +253,37 @@ msgid "version of the cited resource" msgstr "versione della risorsa citata" msgid "" -"authority or function assigned, as to a ruler, legislative assembly, " -"delegate, or the like." +"authority or function assigned, as to a ruler, legislative assembly, delegate, or the like." msgstr "" -"autorità o funzione assegnata, ad esempio un regolatore, un'assemblea " -"legislativa, un delegato o simili." +"autorità o funzione assegnata, ad esempio un regolatore, un'assemblea legislativa, un " +"delegato o simili." msgid "a DOI will be added by Admin before publication." msgstr "un DOI verrà aggiunto dall'amministratore prima della pubblicazione." msgid "summary of the intentions with which the resource(s) was developed" -msgstr "" -"sintesi delle intenzioni con cui la risorsa (o le risorse) sono state " -"sviluppate" +msgstr "sintesi delle intenzioni con cui la risorsa (o le risorse) sono state sviluppate" msgid "" -"frequency with which modifications and deletions are made to the data after " -"it is first produced" +"frequency with which modifications and deletions are made to the data after it is first " +"produced" msgstr "" -"frequenza con cui le modifiche e le cancellazioni sui dati vengono eseguite " -"dopo essere stati prodotti la prima volta" +"frequenza con cui le modifiche e le cancellazioni sui dati vengono eseguite dopo essere " +"stati prodotti la prima volta" msgid "" -"commonly used word(s) or formalised word(s) or phrase(s) used to describe " -"the subject (space or comma-separated)" +"commonly used word(s) or formalised word(s) or phrase(s) used to describe the subject (space " +"or comma-separated)" msgstr "" -"parola (o parole) comunemente usate o parola (o parole) e frase (o frasi) " -"formalizzate usate per descrivere il soggetto (separando attraverso spazio o " -"virgola" +"parola (o parole) comunemente usate o parola (o parole) e frase (o frasi) formalizzate usate " +"per descrivere il soggetto (separando attraverso spazio o virgola" msgid "" -"formalised word(s) or phrase(s) from a fixed thesaurus used to describe the " -"subject (space or comma-separated)" +"formalised word(s) or phrase(s) from a fixed thesaurus used to describe the subject (space " +"or comma-separated)" msgstr "" -"parola(e) o frase(i) formalizzate da un thesaurus fisso utilizzato per " -"descrivere l'oggetto (spazio o delimitato da virgole)" +"parola(e) o frase(i) formalizzate da un thesaurus fisso utilizzato per descrivere l'oggetto " +"(spazio o delimitato da virgole)" msgid "keyword identifies a location" msgstr "parola chiave che identifica una posizione" @@ -301,11 +292,9 @@ msgid "limitation(s) placed upon the access or use of the data." msgstr "limitazione(i) sull'accesso o l'uso dei dati." msgid "" -"other restrictions and legal prerequisites for accessing and using the " -"resource or metadata" +"other restrictions and legal prerequisites for accessing and using the resource or metadata" msgstr "" -"altre restrizioni e requisiti legali per l'accesso e l'uso della risorsa o " -"dei metadati" +"altre restrizioni e requisiti legali per l'accesso e l'uso della risorsa o dei metadati" msgid "license of the dataset" msgstr "licenza del dataset" @@ -314,11 +303,11 @@ msgid "language used within the dataset" msgstr "lingua usata all'interno del dataset" msgid "" -"high-level geographic data thematic classification to assist in the grouping " -"and search of available geographic data sets." +"high-level geographic data thematic classification to assist in the grouping and search of " +"available geographic data sets." msgstr "" -"classificazione tematica di dati geografici di alto livello per facilitare " -"il raggruppamento e la ricerca di set di dati geografici disponibili." +"classificazione tematica di dati geografici di alto livello per facilitare il raggruppamento " +"e la ricerca di set di dati geografici disponibili." msgid "method used to represent geographic information in the dataset." msgstr "metodo di rappresentazione spaziale del dataset." @@ -329,12 +318,10 @@ msgstr "periodo di tempo coperto dal contenuto del dataset (inizio)" msgid "time period covered by the content of the dataset (end)" msgstr "periodo di tempo coperto dal contenuto del dataset (fine)" -msgid "" -"general explanation of the data producer's knowledge about the lineage of a " -"dataset" +msgid "general explanation of the data producer's knowledge about the lineage of a dataset" msgstr "" -"spiegazione generale della conoscenza del produttore dei dati riguardo il " -"lignaggio di un dataset" +"spiegazione generale della conoscenza del produttore dei dati riguardo il lignaggio di un " +"dataset" msgid "title" msgstr "titolo" @@ -438,10 +425,8 @@ msgstr "Questa risorsa è stata convalidata da un editore o un curatore?" msgid "Thumbnail url" msgstr "Url della miniatura" -#, fuzzy -#| msgid "Dirty State" msgid "State" -msgstr "Non ancora aggiornato" +msgstr "Stato" msgid "Hold the resource processing state." msgstr "" @@ -621,25 +606,17 @@ msgid "Reason for the request" msgstr "Motivo della richiesta" msgid "" -"To allow the change, set the resource to not \"Approved\" under the metadata " -"settingsand write message to the owner to notify him" +"To allow the change, set the resource to not \"Approved\" under the metadata settingsand " +"write message to the owner to notify him" msgstr "" -"Per consentire la modifica, impostare la risorsa su non \"Approvato\" nelle " -"impostazioni dei metadati e scrivere un messaggio al proprietario per " -"notificarlo" +"Per consentire la modifica, impostare la risorsa su non \"Approvato\" nelle impostazioni dei " +"metadati e scrivere un messaggio al proprietario per notificarlo" -#, fuzzy -#| msgid "Service rescanned successfully" msgid "Resource Cloned Successfully!" -msgstr "Il servizio è stato analizzato di nuovo correttamente" +msgstr "La risorsa è stata clonata con successo!" -#, fuzzy, python-brace-format -#| msgid "" -#| "Some error occurred while trying to access the uploaded schema: {str(e)}" msgid "Error Occurred while Cloning the Resource: {e}" -msgstr "" -"Si è verificato un errore durante il tentativo di accesso allo schema " -"caricato: {str(e)}" +msgstr "Si è verificato un errore durante la clonazione della risorsa: {e}" msgid "Resource Metadata" msgstr "Metadati delle risorse" @@ -675,237 +652,219 @@ msgid "GeoNode Client Library" msgstr "Libreria client di GeoNode" msgid "" -"Flora and/or fauna in natural environment. Examples: wildlife, vegetation, " -"biological sciences, ecology, wilderness, sealife, wetlands, habitat." +"Flora and/or fauna in natural environment. Examples: wildlife, vegetation, biological " +"sciences, ecology, wilderness, sealife, wetlands, habitat." msgstr "" -"Flora e/o fauna in ambiente naturale. Esempi: fauna selvatica, vegetazione, " -"scienze biologiche, ecologia, natura selvaggia, vita marina, zone umide, " -"habitat." +"Flora e/o fauna in ambiente naturale. Esempi: fauna selvatica, vegetazione, scienze " +"biologiche, ecologia, natura selvaggia, vita marina, zone umide, habitat." msgid "Biota" msgstr "Biota" -msgid "" -"Legal land descriptions. Examples: political and administrative boundaries." -msgstr "" -"Descrizioni legali dei terreni. Esempi: confini politici e amministrativi." +msgid "Legal land descriptions. Examples: political and administrative boundaries." +msgstr "Descrizioni legali dei terreni. Esempi: confini politici e amministrativi." msgid "Boundaries" msgstr "Confini" msgid "" -"Processes and phenomena of the atmosphere. Examples: cloud cover, weather, " -"climate, atmospheric conditions, climate change, precipitation." +"Processes and phenomena of the atmosphere. Examples: cloud cover, weather, climate, " +"atmospheric conditions, climate change, precipitation." msgstr "" -"Processi e fenomeni dell'atmosfera. Esempi: copertura nuvolosa, meteo, " -"clima, condizioni atmosferiche, cambiamenti climatici, precipitazioni." +"Processi e fenomeni dell'atmosfera. Esempi: copertura nuvolosa, meteo, clima, condizioni " +"atmosferiche, cambiamenti climatici, precipitazioni." msgid "Climatology Meteorology Atmosphere" msgstr "Climatologia Meteorologia Atmosfera" msgid "" -"Economic activities, conditions and employment. Examples: production, " -"labour, revenue, commerce, industry, tourism and ecotourism, forestry, " -"fisheries, commercial or subsistence hunting, exploration and exploitation " -"of resources such as minerals, oil and gas." +"Economic activities, conditions and employment. Examples: production, labour, revenue, " +"commerce, industry, tourism and ecotourism, forestry, fisheries, commercial or subsistence " +"hunting, exploration and exploitation of resources such as minerals, oil and gas." msgstr "" -"Attività economiche, condizioni e occupazione. Esempi: produzione, lavoro, " -"entrate, commercio, industria, turismo ed ecoturismo, silvicoltura, pesca, " -"caccia commerciale o di sussistenza, esplorazione e sfruttamento di risorse " -"quali minerali, petrolio e gas." +"Attività economiche, condizioni e occupazione. Esempi: produzione, lavoro, entrate, " +"commercio, industria, turismo ed ecoturismo, silvicoltura, pesca, caccia commerciale o di " +"sussistenza, esplorazione e sfruttamento di risorse quali minerali, petrolio e gas." msgid "Economy" msgstr "Economia" msgid "" -"Height above or below sea level. Examples: altitude, bathymetry, digital " -"elevation models, slope, derived products." +"Height above or below sea level. Examples: altitude, bathymetry, digital elevation models, " +"slope, derived products." msgstr "" -"Altezza sopra o sotto il livello del mare. Esempi: altitudine, batimetria, " -"modelli digitali di elevazione, pendenza, prodotti derivati." +"Altezza sopra o sotto il livello del mare. Esempi: altitudine, batimetria, modelli digitali " +"di elevazione, pendenza, prodotti derivati." msgid "Elevation" msgstr "Elevazione" msgid "" -"Environmental resources, protection and conservation. Examples: " -"environmental pollution, waste storage and treatment, environmental impact " -"assessment, monitoring environmental risk, nature reserves, landscape." +"Environmental resources, protection and conservation. Examples: environmental pollution, " +"waste storage and treatment, environmental impact assessment, monitoring environmental risk, " +"nature reserves, landscape." msgstr "" -"Risorse ambientali, protezione e conservazione. Esempi: inquinamento " -"ambientale, stoccaggio e trattamento dei rifiuti, valutazione dell'impatto " -"ambientale, monitoraggio del rischio ambientale, riserve naturali, paesaggio." +"Risorse ambientali, protezione e conservazione. Esempi: inquinamento ambientale, stoccaggio " +"e trattamento dei rifiuti, valutazione dell'impatto ambientale, monitoraggio del rischio " +"ambientale, riserve naturali, paesaggio." msgid "Environment" msgstr "Ambiente" msgid "" -"Rearing of animals and/or cultivation of plants. Examples: agriculture, " -"irrigation, aquaculture, plantations, herding, pests and diseases affecting " -"crops and livestock." +"Rearing of animals and/or cultivation of plants. Examples: agriculture, irrigation, " +"aquaculture, plantations, herding, pests and diseases affecting crops and livestock." msgstr "" -"Allevamento di animali e/o coltivazione di piante. Esempi: agricoltura, " -"irrigazione, acquacoltura, piantagioni, mandrie, parassiti e malattie che " -"colpiscono le colture e il bestiame." +"Allevamento di animali e/o coltivazione di piante. Esempi: agricoltura, irrigazione, " +"acquacoltura, piantagioni, mandrie, parassiti e malattie che colpiscono le colture e il " +"bestiame." msgid "Farming" msgstr "Agricoltura" msgid "" -"Information pertaining to earth sciences. Examples: geophysical features and " -"processes, geology, minerals, sciences dealing with the composition, " -"structure and origin of the earth s rocks, risks of earthquakes, volcanic " -"activity, landslides, gravity information, soils, permafrost, hydrogeology, " -"erosion." +"Information pertaining to earth sciences. Examples: geophysical features and processes, " +"geology, minerals, sciences dealing with the composition, structure and origin of the earth " +"s rocks, risks of earthquakes, volcanic activity, landslides, gravity information, soils, " +"permafrost, hydrogeology, erosion." msgstr "" -"Informazioni relative alle scienze della terra. Esempi: caratteristiche e " -"processi geofisici, geologia, minerali, scienze che si occupano della " -"composizione, struttura e origine delle rocce terrestri, rischi di " -"terremoti, attività vulcanica, frane, informazioni sulla gravità, suoli, " -"permafrost, idrogeologia, erosione." +"Informazioni relative alle scienze della terra. Esempi: caratteristiche e processi " +"geofisici, geologia, minerali, scienze che si occupano della composizione, struttura e " +"origine delle rocce terrestri, rischi di terremoti, attività vulcanica, frane, informazioni " +"sulla gravità, suoli, permafrost, idrogeologia, erosione." msgid "Geoscientific Information" msgstr "Informazioni geoscientifiche" msgid "" -"Health, health services, human ecology, and safety. Examples: disease and " -"illness, factors affecting health, hygiene, substance abuse, mental and " -"physical health, health services." +"Health, health services, human ecology, and safety. Examples: disease and illness, factors " +"affecting health, hygiene, substance abuse, mental and physical health, health services." msgstr "" -"Salute, servizi sanitari, ecologia umana e sicurezza. Esempi: malattia e " -"malattia, fattori che influenzano la salute, l'igiene, l'abuso di sostanze, " -"la salute mentale e fisica, i servizi sanitari." +"Salute, servizi sanitari, ecologia umana e sicurezza. Esempi: malattia e malattia, fattori " +"che influenzano la salute, l'igiene, l'abuso di sostanze, la salute mentale e fisica, i " +"servizi sanitari." msgid "Health" msgstr "Salute" msgid "" -"Base maps. Examples: land cover, topographic maps, imagery, unclassified " -"images, annotations." +"Base maps. Examples: land cover, topographic maps, imagery, unclassified images, annotations." msgstr "" -"Mappe di base. Esempi: copertura del terreno, mappe topografiche, immagini, " -"immagini non classificate, annotazioni." +"Mappe di base. Esempi: copertura del terreno, mappe topografiche, immagini, immagini non " +"classificate, annotazioni." msgid "Imagery Base Maps Earth Cover" msgstr "Mappe Immagini di Base Copertina della Terra" msgid "" -"Inland water features, drainage systems and their characteristics. Examples: " -"rivers and glaciers, salt lakes, water utilization plans, dams, currents, " -"floods, water quality, hydrographic charts." +"Inland water features, drainage systems and their characteristics. Examples: rivers and " +"glaciers, salt lakes, water utilization plans, dams, currents, floods, water quality, " +"hydrographic charts." msgstr "" -"Caratteristiche dell'acqua dell'entroterra, sistemi di drenaggio e loro " -"caratteristiche. Esempi: fiumi e ghiacciai, laghi salati, piani di utilizzo " -"dell'acqua, dighe, correnti, inondazioni, qualità dell'acqua, grafici " -"idrografici." +"Caratteristiche dell'acqua dell'entroterra, sistemi di drenaggio e loro caratteristiche. " +"Esempi: fiumi e ghiacciai, laghi salati, piani di utilizzo dell'acqua, dighe, correnti, " +"inondazioni, qualità dell'acqua, grafici idrografici." msgid "Inland Waters" msgstr "Acque interne" msgid "" -"Military bases, structures, activities. Examples: barracks, training " -"grounds, military transportation, information collection." +"Military bases, structures, activities. Examples: barracks, training grounds, military " +"transportation, information collection." msgstr "" -"Basi militari, strutture, attività. Esempi: caserme, campi di addestramento, " -"trasporto militare, raccolta di informazioni." +"Basi militari, strutture, attività. Esempi: caserme, campi di addestramento, trasporto " +"militare, raccolta di informazioni." msgid "Intelligence Military" msgstr "Intelligence militare" msgid "" -"Positional information and services. Examples: addresses, geodetic networks, " -"control points, postal zones and services, place names." +"Positional information and services. Examples: addresses, geodetic networks, control points, " +"postal zones and services, place names." msgstr "" -"Informazioni e servizi di localizzazione. Esempi: indirizzi, reti " -"geodetiche, punti di controllo, zone postali e servizi, nomi di luoghi." +"Informazioni e servizi di localizzazione. Esempi: indirizzi, reti geodetiche, punti di " +"controllo, zone postali e servizi, nomi di luoghi." msgid "Location" msgstr "Posizione" msgid "" -"Features and characteristics of salt water bodies (excluding inland waters). " -"Examples: tides, tidal waves, coastal information, reefs." +"Features and characteristics of salt water bodies (excluding inland waters). Examples: " +"tides, tidal waves, coastal information, reefs." msgstr "" -"Caratteristiche e caratteristiche dei corpi idrici dell'acqua salata " -"(escluse le acque interne). Esempi: maree, onde di marea, informazioni " -"costiere, barriere coralline." +"Caratteristiche e caratteristiche dei corpi idrici dell'acqua salata (escluse le acque " +"interne). Esempi: maree, onde di marea, informazioni costiere, barriere coralline." msgid "Oceans" msgstr "Oceani" msgid "" -"Information used for appropriate actions for future use of the land. " -"Examples: land use maps, zoning maps, cadastral surveys, land ownership." +"Information used for appropriate actions for future use of the land. Examples: land use " +"maps, zoning maps, cadastral surveys, land ownership." msgstr "" -"Informazioni utilizzate per azioni appropriate per un uso futuro del " -"terreno. Esempi: mappe dell'uso del suolo, mappe di zonzing, indagini " -"cadastrali, proprietà del terreno." +"Informazioni utilizzate per azioni appropriate per un uso futuro del terreno. Esempi: mappe " +"dell'uso del suolo, mappe di zonzing, indagini cadastrali, proprietà del terreno." msgid "Planning Cadastre" msgstr "Pianificazione catasto" msgid "" -"Settlements, anthropology, archaeology, education, traditional beliefs, " -"manners and customs, demographic data, recreational areas and activities, " -"social impact assessments, crime and justice, census information. Economic " -"activities, conditions and employment." +"Settlements, anthropology, archaeology, education, traditional beliefs, manners and customs, " +"demographic data, recreational areas and activities, social impact assessments, crime and " +"justice, census information. Economic activities, conditions and employment." msgstr "" -"Insediamenti, antropologia, archeologia, educazione, credenze tradizionali, " -"modi e costumi, dati demografici, aree e attività ricreative, valutazioni di " -"impatto sociale, criminalità e giustizia, informazioni sul censimento. " -"Attività economiche, condizioni e occupazione." +"Insediamenti, antropologia, archeologia, educazione, credenze tradizionali, modi e costumi, " +"dati demografici, aree e attività ricreative, valutazioni di impatto sociale, criminalità e " +"giustizia, informazioni sul censimento. Attività economiche, condizioni e occupazione." msgid "Population" msgstr "Popolazione" msgid "" -"Characteristics of society and cultures. Examples: settlements, " -"anthropology, archaeology, education, traditional beliefs, manners and " -"customs, demographic data, recreational areas and activities, social impact " -"assessments, crime and justice, census information." +"Characteristics of society and cultures. Examples: settlements, anthropology, archaeology, " +"education, traditional beliefs, manners and customs, demographic data, recreational areas " +"and activities, social impact assessments, crime and justice, census information." msgstr "" -"Caratteristiche della società e delle culture. Esempi: insediamenti, " -"antropologia, archeologia, istruzione, credenze tradizionali, modi e " -"costumi, dati demografici, aree ricreative e attività, valutazioni " -"dell'impatto sociale, criminalità e giustizia, informazioni sul censimento." +"Caratteristiche della società e delle culture. Esempi: insediamenti, antropologia, " +"archeologia, istruzione, credenze tradizionali, modi e costumi, dati demografici, aree " +"ricreative e attività, valutazioni dell'impatto sociale, criminalità e giustizia, " +"informazioni sul censimento." msgid "Society" msgstr "Società" msgid "" -"Man-made construction. Examples: buildings, museums, churches, factories, " -"housing, monuments, shops, towers." +"Man-made construction. Examples: buildings, museums, churches, factories, housing, " +"monuments, shops, towers." msgstr "" -"Costruzione artificiale. Esempi: edifici, musei, chiese, fabbriche, " -"abitazioni, monumenti, negozi, torri." +"Costruzione artificiale. Esempi: edifici, musei, chiese, fabbriche, abitazioni, monumenti, " +"negozi, torri." msgid "Structure" msgstr "Strutture" msgid "" -"Means and aids for conveying persons and/or goods. Examples: roads, airports/" -"airstrips, shipping routes, tunnels, nautical charts, vehicle or vessel " -"location, aeronautical charts, railways." +"Means and aids for conveying persons and/or goods. Examples: roads, airports/airstrips, " +"shipping routes, tunnels, nautical charts, vehicle or vessel location, aeronautical charts, " +"railways." msgstr "" -"Mezzi e aiuti per il trasporto di persone e/o merci. Esempi: strade, " -"aeroporti/sciviole, rotte marittime, gallerie, carte nautiche, posizione di " -"veicoli o navi, carte aeronautiche, ferrovie." +"Mezzi e aiuti per il trasporto di persone e/o merci. Esempi: strade, aeroporti/sciviole, " +"rotte marittime, gallerie, carte nautiche, posizione di veicoli o navi, carte aeronautiche, " +"ferrovie." msgid "Transportation" msgstr "Trasporti" msgid "" -"Energy, water and waste systems and communications infrastructure and " -"services. Examples: hydroelectricity, geothermal, solar and nuclear sources " -"of energy, water purification and distribution, sewage collection and " -"disposal, electricity and gas distribution, data communication, " -"telecommunication, radio, communication networks." +"Energy, water and waste systems and communications infrastructure and services. Examples: " +"hydroelectricity, geothermal, solar and nuclear sources of energy, water purification and " +"distribution, sewage collection and disposal, electricity and gas distribution, data " +"communication, telecommunication, radio, communication networks." msgstr "" -"Sistemi energetici, idrici e dei rifiuti, infrastrutture e servizi di " -"comunicazione. Esempi: fonti idroelettriche, geotermiche, solari e nucleari " -"di energia, depurazione e distribuzione dell'acqua, raccolta e smaltimento " -"delle acque reflue, distribuzione di elettricità e gas, comunicazione dei " -"dati, telecomunicazioni, radio, reti di comunicazione." +"Sistemi energetici, idrici e dei rifiuti, infrastrutture e servizi di comunicazione. Esempi: " +"fonti idroelettriche, geotermiche, solari e nucleari di energia, depurazione e distribuzione " +"dell'acqua, raccolta e smaltimento delle acque reflue, distribuzione di elettricità e gas, " +"comunicazione dei dati, telecomunicazioni, radio, reti di comunicazione." msgid "Utilities Communication" msgstr "Servizi Comunicazioni" @@ -1051,15 +1010,13 @@ msgstr "Procedura guidata" msgid "Advanced Edit" msgstr "Modifica avanzata" -#, fuzzy -#| msgid "Document" msgid "Document" msgid_plural "Documents" msgstr[0] "Documento" -msgstr[1] "Documento" +msgstr[1] "Documenti" msgid "Clone" -msgstr "" +msgstr "Clona" msgid "Replace" msgstr "Sostituisci" @@ -1098,8 +1055,7 @@ msgid "Permissions" msgstr "Permessi" msgid "Click the button below to change the permissions of this document." -msgstr "" -"Clicca il pulsante qui sotto per modificare i permessi di questo documento." +msgstr "Clicca il pulsante qui sotto per modificare i permessi di questo documento." msgid "Change Document Permissions" msgstr "Cambia i permessi del Documento" @@ -1124,9 +1080,7 @@ msgid "Check Schema mandatory fields" msgstr "Controllare i campi obbligatori dello schema" msgid "Error updating metadata. Please check the following fields: " -msgstr "" -"Errore nell'aggiornamento dei metadati. Per favore controlla i seguenti " -"campi: " +msgstr "Errore nell'aggiornamento dei metadati. Per favore controlla i seguenti campi: " msgid "Done" msgstr "Fatto" @@ -1156,7 +1110,7 @@ msgid "Return to Document" msgstr "Ritorna al documento" msgid "Deleting" -msgstr "Sto cancellando" +msgstr "Sto eliminando" msgid "Remove Document" msgstr "Rimuovi documento" @@ -1164,13 +1118,13 @@ msgstr "Rimuovi documento" #, python-format msgid "" "\n" -" Are you sure you want to remove %(document_title)s?\n" +" Are you sure you want to remove %(document_title)s?\n" " " msgstr "" "\n" -" Sei sicuro di voler rimuovere %(document_title)s?\n" +" Sei sicuro di voler rimuovere %(document_title)s?\n" " " msgid "Yes, I am sure" @@ -1300,7 +1254,7 @@ msgid "Log in to add/delete Favorites." msgstr "Accedi per aggiungere/eliminare preferiti." msgid "Delete from Favorites" -msgstr "Cancella dai preferiti" +msgstr "Elimina dai preferiti" msgid "Favorites" msgstr "Preferiti" @@ -1400,12 +1354,11 @@ msgid "Embed Iframe" msgstr "Incorpora Iframe" msgid "" -"To embed this map, add the following code snippet and customize its " -"properties (scrolling, width, height) based on your needs to your site" +"To embed this map, add the following code snippet and customize its properties (scrolling, " +"width, height) based on your needs to your site" msgstr "" -"Per incorporare questa mappa, aggiungere il frammento di codice seguente e " -"personalizzarne le proprietà (scorrimento, larghezza, altezza) in base alle " -"proprie esigenze nel sito" +"Per incorporare questa mappa, aggiungere il frammento di codice seguente e personalizzarne " +"le proprietà (scorrimento, larghezza, altezza) in base alle proprie esigenze nel sito" msgid "Download" msgstr "Scarica" @@ -1425,22 +1378,19 @@ msgid "for %(map_title)s" msgstr "per %(map_title)s" msgid "" -"Note: this geoapp's orginal metadata was populated by importing a metadata " -"XML file.\n" -" GeoNode's metadata import supports a subset of ISO, FGDC, and Dublin " -"Core metadata elements.\n" +"Note: this geoapp's orginal metadata was populated by importing a metadata XML file.\n" +" GeoNode's metadata import supports a subset of ISO, FGDC, and Dublin Core metadata " +"elements.\n" " Some of your original metadata may have been lost." msgstr "" -"Nota: i metadati orginali di questa geoapp sono stati popolati importando un " -"file XML di metadati.\n" -" L'importazione dei metadati di GeoNode supporta un sottoinsieme di " -"elementi di metadati ISO, FGDC e Dublin Core.\n" +"Nota: i metadati orginali di questa geoapp sono stati popolati importando un file XML di " +"metadati.\n" +" L'importazione dei metadati di GeoNode supporta un sottoinsieme di elementi di " +"metadati ISO, FGDC e Dublin Core.\n" " Alcuni dei metadati originali potrebbero essere stati persi." -#, fuzzy -#| msgid "Explore Maps" msgid "Explore Apps" -msgstr "Esplora mappe" +msgstr "Esplora apps" #, python-format msgid "" @@ -1452,10 +1402,8 @@ msgstr "" " Modifica dei dettagli per il %(map_title)s\n" " " -#, fuzzy -#| msgid "Return to Map" msgid "Return to GeoApp" -msgstr "Ritorna alla mappa" +msgstr "Ritorna alla GeoApp" msgid "New Map" msgstr "Nuova mappa" @@ -1463,13 +1411,13 @@ msgstr "Nuova mappa" #, python-format msgid "" "\n" -" Are you sure you want to remove %(resource_title)s?\n" +" Are you sure you want to remove %(resource_title)s?\n" " " msgstr "" "\n" -" Siete sicuri di voler rimuovere %(resource_title)s?\n" +" Siete sicuri di voler rimuovere %(resource_title)s?\n" " " msgid "Other Settings" @@ -1523,39 +1471,29 @@ msgstr "Linee" msgid "Polygons" msgstr "Poligoni" -#, fuzzy -#| msgid "dataset" msgid "Dataset name" -msgstr "dataset" +msgstr "Nome del dataset" -#, fuzzy -#| msgid "Dataset Attributes" msgid "Dataset title" -msgstr "Attributi del dataset" +msgstr "Titolo del dataset" msgid "Geometry type" msgstr "Tipo di geometria" -#, fuzzy -#| msgid "Featured Datasets" msgid "Create Dataset" -msgstr "Dataset in primo piano" +msgstr "Crea Dataset" -#, fuzzy -#| msgid "Explore Layers" msgid "Explore Datasets" -msgstr "Esplora livelli" +msgstr "Esplora dataset" -#, fuzzy -#| msgid "Create an empty layer" msgid "Create an empty dataset" -msgstr "Creare un livello vuoto" +msgstr "Crea un dataset vuoto" msgid "Add Attribute" -msgstr "Aggiungere attributo" +msgstr "Aggiungi attributo" msgid "Create" -msgstr "Creare" +msgstr "Crea" msgid "String" msgstr "Stringa" @@ -1616,18 +1554,16 @@ msgstr "PNG" msgid "You don't have permissions to change style for this layer" msgstr "" -"Non si dispone delle autorizzazioni necessarie per modificare lo stile di " -"questo livello" +"Non si dispone delle autorizzazioni necessarie per modificare lo stile di questo livello" msgid "Bad HTTP Authorization Credentials." msgstr "Credenziali di autorizzazione HTTP errate." msgid "" -"a short version of the name consisting only of letters, numbers, underscores " -"and hyphens." +"a short version of the name consisting only of letters, numbers, underscores and hyphens." msgstr "" -"una versione abbreviata del nome consiste solo di lettere, numeri, caratteri " -"di sottolineatura e trattini." +"una versione abbreviata del nome consiste solo di lettere, numeri, caratteri di " +"sottolineatura e trattini." msgid "A group already exists with that slug." msgstr "Un gruppo esiste già con questo slug." @@ -1642,10 +1578,8 @@ msgid "Assign manager role" msgstr "Assegnare il ruolo di manager" #, python-format -msgid "" -"The following are not valid usernames: %(errors)s; not added to the group" -msgstr "" -"I seguenti non sono nomi utente validi: %(errors)s; non aggiunto al gruppo" +msgid "The following are not valid usernames: %(errors)s; not added to the group" +msgstr "I seguenti non sono nomi utente validi: %(errors)s; non aggiunto al gruppo" msgid "Group Categories" msgstr "Categorie gruppo" @@ -1660,24 +1594,23 @@ msgid "Private" msgstr "Privato" msgid "" -"Public: Any registered user can view and join a public group.
Public " -"(invite-only):Any registered user can view the group. Only invited users " -"can join.
Private: Registered users cannot see any details about the " -"group, including membership. Only invited users can join." +"Public: Any registered user can view and join a public group.
Public (invite-only):Any " +"registered user can view the group. Only invited users can join.
Private: Registered " +"users cannot see any details about the group, including membership. Only invited users can " +"join." msgstr "" -"Pubblico: Qualsiasi utente registrato può visualizzare e unirsi a un gruppo " -"pubblico.
(Solo su invito) Pubblico: Qualsiasi utente registrato può " -"visualizzare il gruppo. Solo gli utenti invitati possono partecipare.
" -"Per uso privato: Gli utenti registrati non possono vedere tutti i dettagli " -"sul gruppo, compresa l'appartenenza. Solo gli utenti invitati possono " -"partecipare." +"Pubblico: Qualsiasi utente registrato può visualizzare e unirsi a un gruppo pubblico.
" +"(Solo su invito) Pubblico: Qualsiasi utente registrato può visualizzare il gruppo. Solo gli " +"utenti invitati possono partecipare.
Per uso privato: Gli utenti registrati non possono " +"vedere tutti i dettagli sul gruppo, compresa l'appartenenza. Solo gli utenti invitati " +"possono partecipare." msgid "" -"Email used to contact one or all group members, such as a mailing list, " -"shared email, or exchange group." +"Email used to contact one or all group members, such as a mailing list, shared email, or " +"exchange group." msgstr "" -"E-mail utilizzato per contattare gli utenti di uno o di tutti i gruppi, come " -"ad esempio una mailing list, e-mail condivisa, o un gruppo di scambio." +"E-mail utilizzato per contattare gli utenti di uno o di tutti i gruppi, come ad esempio una " +"mailing list, e-mail condivisa, o un gruppo di scambio." msgid "Logo" msgstr "Logo" @@ -1777,9 +1710,7 @@ msgid "Join Group" msgstr "Iscriviti al gruppo" msgid "Anyone may view this group but membership is by invitation only." -msgstr "" -"Chiunque può visualizzare questo gruppo, ma l'iscrizione è possibile solo su " -"invito." +msgstr "Chiunque può visualizzare questo gruppo, ma l'iscrizione è possibile solo su invito." msgid "Membership is by invitation only." msgstr "L'iscrizione è possibile solo su invito." @@ -1862,30 +1793,25 @@ msgstr "Inserimento risorse..." msgid "checking-availability" msgstr "" -#, fuzzy -#| msgid "Harvested" msgid "Harvester name" -msgstr "Raccolte" +msgstr "Nome dell'harvester" msgid "Base URL of the remote service that is to be harvested" msgstr "" msgid "" -"Whether to periodically schedule this harvester to look for resources on the " -"remote service" +"Whether to periodically schedule this harvester to look for resources on the remote service" msgstr "" msgid "" -"How often (in minutes) should new harvesting sessions be automatically " -"scheduled? Setting this value to zero has the same effect as setting " -"`scheduling_enabled` to False " +"How often (in minutes) should new harvesting sessions be automatically scheduled? Setting " +"this value to zero has the same effect as setting `scheduling_enabled` to False " msgstr "" msgid "Whether the remote service is known to be available or not" msgstr "" -msgid "" -"How often (in minutes) should the remote service be checked for availability?" +msgid "How often (in minutes) should the remote service be checked for availability?" msgstr "" msgid "Last time the remote server was checked for availability" @@ -1894,26 +1820,20 @@ msgstr "" msgid "Last time the remote server was checked for harvestable resources" msgstr "" -#, fuzzy -#| msgid "version of the cited resource" msgid "Default owner of harvested resources" -msgstr "versione della risorsa citata" +msgstr "Proprietario di default della risorsa harvestata" -#, fuzzy -#| msgid "Set permissions on selected resources" msgid "Default access permissions of harvested resources" -msgstr "Impostare le autorizzazioni per le risorse selezionate" +msgstr "Autorizzazioni di default per le risorse harvestate" -msgid "" -"Should new resources be harvested automatically without explicit selection?" +msgid "Should new resources be harvested automatically without explicit selection?" msgstr "" msgid "" -"Orphan resources are those that have previously been created by means of a " -"harvesting operation but that GeoNode can no longer find on the remote " -"service being harvested. Should these resources be deleted from GeoNode " -"automatically? This also applies to when a harvester configuration is " -"deleted, in which case all of the resources that originated from that " +"Orphan resources are those that have previously been created by means of a harvesting " +"operation but that GeoNode can no longer find on the remote service being harvested. Should " +"these resources be deleted from GeoNode automatically? This also applies to when a harvester " +"configuration is deleted, in which case all of the resources that originated from that " "harvester are now considered to be orphan." msgstr "" @@ -1921,14 +1841,14 @@ msgid "Date of last update to the harvester configuration." msgstr "" msgid "" -"Harvester class used to perform harvesting sessions. New harvester types can " -"be added by an admin by changing the main GeoNode `settings.py` file" +"Harvester class used to perform harvesting sessions. New harvester types can be added by an " +"admin by changing the main GeoNode `settings.py` file" msgstr "" msgid "" -"Configuration specific to each harvester type. Please consult GeoNode " -"documentation on harvesting for more info. This field is mandatory, so at " -"the very least an empty object (i.e. {}) must be supplied." +"Configuration specific to each harvester type. Please consult GeoNode documentation on " +"harvesting for more info. This field is mandatory, so at the very least an empty object (i." +"e. {}) must be supplied." msgstr "" msgid "Periodic task used to configure harvest scheduling" @@ -1950,17 +1870,15 @@ msgid "harvesting-resource" msgstr "Inserimento risorse..." msgid "" -"Identifier that allows referencing the resource on its remote service in a " -"unique fashion. This is usually automatically filled by the harvester " -"worker. The harvester worker needs to know how to either read or generate " -"this from each remote resource in order to be able to compare the " -"availability of resources between consecutive harvesting sessions." +"Identifier that allows referencing the resource on its remote service in a unique fashion. " +"This is usually automatically filled by the harvester worker. The harvester worker needs to " +"know how to either read or generate this from each remote resource in order to be able to " +"compare the availability of resources between consecutive harvesting sessions." msgstr "" msgid "" -"Type of the resource in the remote service. Each harvester worker knows how " -"to fill this field, in accordance with the resources for which harvesting is " -"supported" +"Type of the resource in the remote service. Each harvester worker knows how to fill this " +"field, in accordance with the resources for which harvesting is supported" msgstr "" #, python-brace-format @@ -1973,9 +1891,7 @@ msgstr "L'indirizzo e-mail '{email}' ha già accettato un invito." #, python-brace-format msgid "An active user is already using the e-mail address '{email}'" -msgstr "" -"Un utente attivo sta già utilizzando l'indirizzo di posta elettronica " -"'{email}'" +msgstr "Un utente attivo sta già utilizzando l'indirizzo di posta elettronica '{email}'" msgid "E-mail" msgstr "E-mail" @@ -1986,11 +1902,11 @@ msgstr "Inviti mandati con successo a '%(email)s'" #, python-format msgid "" -"Sorry, it was not possible to invite '%(email)s' due to the following isse: " -"%(error)s (%(type)s)" +"Sorry, it was not possible to invite '%(email)s' due to the following isse: %(error)s " +"(%(type)s)" msgstr "" -"Spiacenti, non è stato possibile invitare '%(email)s' a causa di quanto " -"segue: %(error)s (%(type)s)" +"Spiacenti, non è stato possibile invitare '%(email)s' a causa di quanto segue: %(error)s " +"(%(type)s)" msgid "Layer Created" msgstr "Livello creato" @@ -2074,8 +1990,7 @@ msgid "use featureinfo custom template?" msgstr "utilizzare il modello personalizzato featureinfo?" msgid "specifies wether or not use a custom GetFeatureInfo template." -msgstr "" -"specifica se si utilizza o meno un modello GetFeatureInfo personalizzato." +msgstr "specifica se si utilizza o meno un modello GetFeatureInfo personalizzato." msgid "featureinfo custom template" msgstr "featureinfo modello personalizzato" @@ -2119,11 +2034,8 @@ msgstr "specifica se l'attributo deve essere visualizzato nei risultati" msgid "display order" msgstr "mostra ordine" -msgid "" -"specifies the order in which attribute should be displayed in identify " -"results" -msgstr "" -"specifica l'ordine con cui l'attributo deve essere visualizzato nei risultati" +msgid "specifies the order in which attribute should be displayed in identify results" +msgstr "specifica l'ordine con cui l'attributo deve essere visualizzato nei risultati" msgid "Label" msgstr "Etichetta" @@ -2159,11 +2071,10 @@ msgid "featureinfo type" msgstr "tipo featureinfo" msgid "" -"specifies if the attribute should be rendered with an HTML widget on " -"GetFeatureInfo template." +"specifies if the attribute should be rendered with an HTML widget on GetFeatureInfo template." msgstr "" -"specifica se il rendering dell'attributo deve essere eseguito con un widget " -"HTML nel modello GetFeatureInfo." +"specifica se il rendering dell'attributo deve essere eseguito con un widget HTML nel modello " +"GetFeatureInfo." msgid "count" msgstr "conta" @@ -2216,15 +2127,11 @@ msgstr "ultimo modificato" msgid "date when attribute statistics were last updated" msgstr "data in cui le statistiche degli attributi sono stati aggiornati" -#, fuzzy -#| msgid "Append Data" msgid "Append to Dataset" -msgstr "Accoda dati" +msgstr "Aggiungi al dataset" -#, fuzzy -#| msgid "Return to Layer" msgid "Return to Dataset" -msgstr "Torna al livello" +msgstr "Torna al dataset" msgid "Preserve Metadata XML" msgstr "Preserva metadati XML" @@ -2241,10 +2148,8 @@ msgstr "Modifica contatto" msgid "Assign a new point of contact to the layers below:" msgstr "Assegna un nuovo contatto ai layer sottostanti:" -#, fuzzy -#| msgid "Layer WMS GetCapabilities document" msgid "Dataset WMS GetCapabilities document" -msgstr "Documento WMS GetCapabilities del livello" +msgstr "Documento WMS GetCapabilities del dataset" msgid "Filter Granules" msgstr "Filtra granuli" @@ -2300,18 +2205,14 @@ msgstr "Mediana" msgid "Standard Deviation" msgstr "Deviazione standard" -#, fuzzy -#| msgid "Rate this layer" msgid "Rate this dataset" -msgstr "Giudica questo livello" +msgstr "Valuta questo dataset" msgid "Analyze with" msgstr "Analizza con" -#, fuzzy -#| msgid "Download the" msgid "Download Dataset" -msgstr "Scarica il" +msgstr "Scarica dataset" msgid "Images" msgstr "Immagini" @@ -2356,11 +2257,10 @@ msgid "Pick your download format:" msgstr "Seleziona formato da scaricare:" msgid "" -"No data available for this resource. Please contact a system administrator " -"or a manager." +"No data available for this resource. Please contact a system administrator or a manager." msgstr "" -"Nessun dato disponibile per questa risorsa. Contattare un amministratore di " -"sistema o un responsabile." +"Nessun dato disponibile per questa risorsa. Contattare un amministratore di sistema o un " +"responsabile." msgid "Warning" msgstr "Attenzione" @@ -2377,11 +2277,9 @@ msgstr "Stili" msgid "Manage" msgstr "Gestisci" -#, fuzzy -#| msgid "Layers" msgid "Layer" msgid_plural "Layers" -msgstr[0] "Livelli" +msgstr[0] "Livello" msgstr[1] "Livelli" msgid "Append Data" @@ -2390,10 +2288,8 @@ msgstr "Accoda dati" msgid "Edit data" msgstr "Modifica dati" -#, fuzzy -#| msgid "View Metadata" msgid "View Dataset" -msgstr "Metadati" +msgstr "Vedi Dataset" msgid "Attribute Information" msgstr "Informazioni sugli attributi" @@ -2404,44 +2300,26 @@ msgstr "ISO Feature Catalogue" msgid "Legend" msgstr "Legenda" -#, fuzzy -#| msgid "Maps using this layer" msgid "Maps using this dataset" -msgstr "Mappe che usano questo livello" +msgstr "Mappe che usano questo dataset" -#, fuzzy -#| msgid "List of maps using this layer:" msgid "List of maps using this dataset:" -msgstr "Elenco di mappe che usano questo livello:" +msgstr "Elenco delle mappe che usano questo dataset:" -#, fuzzy -#| msgid "This layer is not currently used in any maps." msgid "This dataset is not currently used in any maps." -msgstr "Questo livello non è al momento utilizzato da alcuna mappa." +msgstr "Questo dataset non è al momento utilizzato da alcuna mappa." -#, fuzzy -#| msgid "Create a map using this layer" msgid "Create a map using this dataset" -msgstr "Crea una mappa usando questo livello" +msgstr "Crea una mappa usando questo dataset" -#, fuzzy -#| msgid "Click the button below to generate a new map based on this layer." msgid "Click the button below to generate a new map based on this dataset." -msgstr "" -"Clicca il pulsante qui sotto per generare una nuova mappa basata su questo " -"livello." +msgstr "Clicca il pulsante qui sotto per generare una nuova mappa basata su questo dataset." -#, fuzzy -#| msgid "Add the layer to an existing map" msgid "Add the dataset to an existing map" -msgstr "Aggiungi il livello ad una mappa esistente" +msgstr "Aggiungi il dataset ad una mappa esistente" -#, fuzzy -#| msgid "Click the button below to add the layer to the selected map." msgid "Click the button below to add the dataset to the selected map." -msgstr "" -"Fare clic sul pulsante sottostante per aggiungere il livello alla mappa " -"selezionata." +msgstr "Fare clic sul pulsante sottostante per aggiungere il dataset alla mappa selezionata." msgid "Add to Map" msgstr "Aggiungi alla mappa" @@ -2453,11 +2331,11 @@ msgid "List of documents related to this layer:" msgstr "Elenco di documenti correlati a questo livello:" msgid "" -"The following styles are associated with this layer. Choose a style to view " -"it in the preview map." +"The following styles are associated with this layer. Choose a style to view it in the " +"preview map." msgstr "" -"I seguenti stili sono associati a questo livello. Scegli uno stile da " -"visualizzare nell'anteprima della mappa." +"I seguenti stili sono associati a questo livello. Scegli uno stile da visualizzare " +"nell'anteprima della mappa." msgid "(default style)" msgstr "(stile predefinito)" @@ -2476,17 +2354,17 @@ msgstr "Aggiorna attributi e statistiche di questo livello" #, fuzzy #| msgid "" -#| "Click the button below to allow GeoNode refreshing the list of available " -#| "Layer Attributes. If the option 'WPS_ENABLED' has been also set on the " -#| "backend, it will recalculate their statistics too." +#| "Click the button below to allow GeoNode refreshing the list of available Layer " +#| "Attributes. If the option 'WPS_ENABLED' has been also set on the backend, it will " +#| "recalculate their statistics too." msgid "" -"Click the button below to allow GeoNode refreshing the list of available " -"Dataset Attributes. If the option 'WPS_ENABLED' has been also set on the " -"backend, it will recalculate their statistics too." +"Click the button below to allow GeoNode refreshing the list of available Dataset Attributes. " +"If the option 'WPS_ENABLED' has been also set on the backend, it will recalculate their " +"statistics too." msgstr "" -"Clicca il pulsante sotto per permettere a GeoNode di aggiornare la lista " -"degli attributi del livello. Se l'opzione 'WPS_ENABLED' è stata settata sul " -"backend, verranno anche ricalcolate le statistiche del livello." +"Clicca il pulsante sotto per permettere a GeoNode di aggiornare la lista degli attributi del " +"livello. Se l'opzione 'WPS_ENABLED' è stata settata sul backend, verranno anche ricalcolate " +"le statistiche del livello." msgid "Refresh Attributes and Statistics" msgstr "Aggiorna attributi e statistiche" @@ -2495,8 +2373,7 @@ msgid "Clear the Server Cache of this layer" msgstr "Pulisci la Cache Server di questo livello" msgid "Click the button below to wipe the tile-cache of this layer." -msgstr "" -"Clicca il pulsante qui sotto per eliminare la tile-cache di questo livello." +msgstr "Clicca il pulsante qui sotto per eliminare la tile-cache di questo livello." #, fuzzy #| msgid "Empty Tiled-Layer Cache" @@ -2504,13 +2381,10 @@ msgid "Empty Tiled-Dataset Cache" msgstr "Svuota la tile-cache del livello" msgid "Click the button below to change the permissions of this layer." -msgstr "" -"Clicca il pulsante qui sotto per modificare i permessi di questo livello." +msgstr "Clicca il pulsante qui sotto per modificare i permessi di questo livello." -#, fuzzy -#| msgid "Change Layer Permissions" msgid "Change Dataset Permissions" -msgstr "Cambia i permessi del livello" +msgstr "Cambia i permessi del dataset" msgid "Remove Mosaic Granules" msgstr "Rimuovere i granuli del mosaico" @@ -2518,13 +2392,13 @@ msgstr "Rimuovere i granuli del mosaico" #, python-format msgid "" "\n" -" Are you sure you want to remove Granule %(granule_id)s of the " -"Mosaic %(layer_title)s?\n" +" Are you sure you want to remove Granule %(granule_id)s of the Mosaic %(layer_title)s?\n" " " msgstr "" "\n" -" Si è sicuri di voler rimuovere il granulo %(granule_id)s del " -"mosaico %(layer_title)s?\n" +" Si è sicuri di voler rimuovere il granulo %(granule_id)s del mosaico %(layer_title)s?\n" " " msgid "This action affects the following maps:" @@ -2533,35 +2407,32 @@ msgstr "Questa azione avrà effetto sulle seguenti mappe:" msgid "No maps are using this layer" msgstr "Nessuna mappa utilizza questo livello" -#, fuzzy -#| msgid "Upload status" msgid "Upload Datasets" -msgstr "Stato caricamento" +msgstr "Carica dataset" #, python-format msgid "for %(layer_title)s" msgstr "per %(layer_title)s" msgid "" -"Note: this layer's orginal metadata was populated and preserved by importing " -"a metadata XML file.\n" +"Note: this layer's orginal metadata was populated and preserved by importing a metadata XML " +"file.\n" " This metadata cannot be edited." msgstr "" -"Nota: i metadati originali di questo livello sono stati popolati e " -"conservati importando un file XML di metadati.\n" +"Nota: i metadati originali di questo livello sono stati popolati e conservati importando un " +"file XML di metadati.\n" " Questi metadati non possono essere modificati." msgid "" -"Note: this layer's orginal metadata was populated by importing a metadata " -"XML file.\n" -" GeoNode's metadata import supports a subset of ISO, FGDC, and " -"Dublin Core metadata elements.\n" +"Note: this layer's orginal metadata was populated by importing a metadata XML file.\n" +" GeoNode's metadata import supports a subset of ISO, FGDC, and Dublin Core metadata " +"elements.\n" " Some of your original metadata may have been lost." msgstr "" -"Note: I metadati originali di questo livello sono stati popolati importando " -"un file di metadati XML.\n" -" L'import dei metadati di GeoNode supporta un sottinsieme di elementi " -"di metadata Dublin Core, ISO e FGDC.\n" +"Note: I metadati originali di questo livello sono stati popolati importando un file di " +"metadati XML.\n" +" L'import dei metadati di GeoNode supporta un sottinsieme di elementi di metadata " +"Dublin Core, ISO e FGDC.\n" " Alcuni dei tuoi metadati originali potrebbero essere andati persi." #, python-format @@ -2608,13 +2479,13 @@ msgstr "Rimuovi i livelli" #, python-format msgid "" "\n" -" Are you sure you want to remove %(layer_title)s?\n" +" Are you sure you want to remove %(layer_title)s?\n" " " msgstr "" "\n" -" Sei sicuro di voler eliminare %(layer_title)s?\n" +" Sei sicuro di voler eliminare %(layer_title)s?\n" " " #, fuzzy @@ -2628,29 +2499,25 @@ msgstr "Gestisci stili" #, python-format msgid "" "\n" -" Manage Available Styles for " -"%(layer_title)s\n" +" Manage Available Styles for %(layer_title)s\n" " " msgstr "" "\n" -" Gestisci gli stili disponibili per " -"%(layer_title)s\n" +" Gestisci gli stili disponibili per %(layer_title)s\n" " " -#, fuzzy -#| msgid "Layer Default Style" msgid "Dataset Default Style" -msgstr "Stile predefinito del livello" +msgstr "Stile predefinito del dataset" msgid "Available styles" msgstr "Stili disponibili" msgid "" -"Click on an available style in the upper box to assign it to this layer. " -"Selected styles appear in the lower box." +"Click on an available style in the upper box to assign it to this layer. Selected styles " +"appear in the lower box." msgstr "" -"Fare clic su uno stile disponibile nella casella in alto per assegnare a " -"questo livello. Stili selezionati vengono visualizzati nel riquadro in basso." +"Fare clic su uno stile disponibile nella casella in alto per assegnare a questo livello. " +"Stili selezionati vengono visualizzati nel riquadro in basso." msgid "Update Available Styles" msgstr "Aggiorna gli stili disponibili" @@ -2658,10 +2525,8 @@ msgstr "Aggiorna gli stili disponibili" msgid "Return to Layer" msgstr "Torna al livello" -#, fuzzy -#| msgid "Upload Layer Style" msgid "Upload Dataset Style" -msgstr "Carica stile del livello" +msgstr "Carica stile del dataset" msgid "(SLD - Style Layer Descriptor 1.0, 1.1)" msgstr "(SLD - Descrittore di stile del livello 1.0, 1.1)" @@ -2670,8 +2535,7 @@ msgid "WARNING" msgstr "ATTENZIONE" msgid "This will most probably overwrite the current default style!" -msgstr "" -"Questo molto probabilmente sovrascriverà lo stile predefinito corrente!" +msgstr "Questo molto probabilmente sovrascriverà lo stile predefinito corrente!" msgid "Preview" msgstr "Anteprima" @@ -2679,34 +2543,29 @@ msgstr "Anteprima" msgid "Dataset Attributes" msgstr "Attributi del dataset" -#, fuzzy -#| msgid "Upload status" msgid "Upload Dataset" -msgstr "Stato caricamento" +msgstr "Carica dataset" msgid "Upload status" msgstr "Stato caricamento" msgid "" -"This file needs additional configuration to complete the upload process. " -"Please click on the button to fill the required configuration" +"This file needs additional configuration to complete the upload process. Please click on the " +"button to fill the required configuration" msgstr "" -"Questo file necessita di una configurazione aggiuntiva per completare il " -"processo di caricamento. Clicca sul pulsante per riempire la configurazione " -"richiesta" +"Questo file necessita di una configurazione aggiuntiva per completare il processo di " +"caricamento. Clicca sul pulsante per riempire la configurazione richiesta" msgid "Delete" -msgstr "Cancella" +msgstr "Elimina" msgid "Upload process completed" msgstr "Processo di caricamento completato" -msgid "" -"The upload process cannot be completed because the original file is no more " -"available" +msgid "The upload process cannot be completed because the original file is no more available" msgstr "" -"Impossibile completare il processo di caricamento perché il file originale " -"non è più disponibile" +"Impossibile completare il processo di caricamento perché il file originale non è più " +"disponibile" msgid "Created" msgstr "Creato" @@ -2726,10 +2585,8 @@ msgstr "Eliminare caricamenti incompleti" msgid "Are you sure you want to remove this incomplete upload?" msgstr "Rimuovere questo caricamento incompleto?" -#, fuzzy -#| msgid "Upload Layer Step: Set SRS" msgid "Upload Dataset Step: Set SRS" -msgstr "Carica livello, passo: Imposta SRS" +msgstr "Carica dataset, passo: Imposta SRS" msgid "Provide CRS for " msgstr "Fornire CRS per " @@ -2740,34 +2597,28 @@ msgstr "Sistema di riferimento delle coordinate" #, fuzzy #| msgid "" #| "\n" -#| " A coordinate reference system for this layer could not be " -#| "determined.\n" -#| " Locate or enter the appropriate ESPG code for this layer " -#| "below.\n" +#| " A coordinate reference system for this layer could not be determined.\n" +#| " Locate or enter the appropriate ESPG code for this layer below.\n" #| " One way to do this is do visit:\n" -#| " prj2epsg\n" +#| " prj2epsg\n" #| " and enter the following:\n" #| " " msgid "" "\n" -" A coordinate reference system for this dataset could not be " -"determined.\n" -" Locate or enter the appropriate ESPG code for this dataset " -"below.\n" +" A coordinate reference system for this dataset could not be determined.\n" +" Locate or enter the appropriate ESPG code for this dataset below.\n" " One way to do this is do visit:\n" -" prj2epsg\n" +" prj2epsg\n" " and enter the following:\n" " " msgstr "" "\n" -" Un sistema di riferimento di coordinate per questo strato " -"non poteva essere determinata.\n" -" Individuare o immettere il codice ESPG appropriato per " -"questo livello sottostante.\n" -" Un modo per farlo è fare visitare: prj2epsg\n" +" Un sistema di riferimento di coordinate per questo strato non poteva essere " +"determinata.\n" +" Individuare o immettere il codice ESPG appropriato per questo livello " +"sottostante.\n" +" Un modo per farlo è fare visitare: prj2epsg\n" " e immettere il seguente:\n" " " @@ -2784,27 +2635,24 @@ msgid "Select a Source SRS" msgstr "Seleziona un SRS di origine" msgid "" -"Source SRS EPSG Code is mandatory and represents the native data Spatial " -"Reference System.\n" +"Source SRS EPSG Code is mandatory and represents the native data Spatial Reference System.\n" "

\n" -" This must be coherent with the Geometry values (lon/lat " -"coordinates as an instance) stored on the geospatial dataset.\n" +" This must be coherent with the Geometry values (lon/lat coordinates as " +"an instance) stored on the geospatial dataset.\n" "

\n" -" If not specified on the geospatial data itself, it must " -"be manually declared by the operator.\n" +" If not specified on the geospatial data itself, it must be manually " +"declared by the operator.\n" "

\n" -" More information is provided at the bottom of the page " -"in the \"Additional Help\" sections.\n" +" More information is provided at the bottom of the page in the " +"\"Additional Help\" sections.\n" " " msgstr "" -"Source SRS EPSG Code è obbligatorio e rappresenta il sistema di riferimento " -"spaziale dei dati nativi.

Deve essere coerente " -"con i valori Geometry (coordinate lon/lat come istanza) archiviati nel set " -"di dati geospaziali.

Se non specificato nei dati " -"geospaziali stessi, deve essere dichiarato manualmente " -"dall'operatore.

Ulteriori informazioni sono " -"disponibili nella parte inferiore della pagina nelle sezioni \"Guida " -"aggiuntiva\". " +"Source SRS EPSG Code è obbligatorio e rappresenta il sistema di riferimento spaziale dei " +"dati nativi.

Deve essere coerente con i valori Geometry " +"(coordinate lon/lat come istanza) archiviati nel set di dati geospaziali. " +"

Se non specificato nei dati geospaziali stessi, deve essere dichiarato manualmente " +"dall'operatore.

Ulteriori informazioni sono disponibili nella " +"parte inferiore della pagina nelle sezioni \"Guida aggiuntiva\". " msgid "Next" msgstr "Prossimo" @@ -2831,140 +2679,130 @@ msgid "Spatial Reference System" msgstr "Sistema di riferimento spaziale" msgid "" -"A spatial reference system (SRS) or coordinate reference system (CRS) is a " -"coordinate-based local,\n" -" regional or global system used to locate " -"geographical entities. A spatial reference system defines a specific map\n" -" projection, as well as transformations between " -"different spatial reference systems. Spatial reference systems are\n" -" defined by the OGC's Simple feature access using " -"well-known text, and support has been implemented by several\n" -" standards-based geographic information systems. " -"Spatial reference systems can be referred to using a SRID integer,\n" -" including EPSG codes defined by the " -"International Association of Oil and Gas Producers.\n" -" It is specified in ISO 19111:2007 Geographic " -"information—Spatial referencing by coordinates, also published as\n" -" OGC Abstract Specification, Topic 2: Spatial " -"referencing by coordinate." -msgstr "" -"Un sistema di riferimento spaziale (SRS) o un sistema di riferimento delle " -"coordinate (CRS) è un sistema di riferimento\n" -" sistema regionale o globale utilizzato per " -"individuare le entità geografiche. Un sistema di riferimento spaziale " -"definisce una mappa specifica\n" -" proiezioni, nonché trasformazioni tra diversi " -"sistemi di riferimento spaziale. I sistemi di riferimento spaziali sono\n" -" definito dall'accesso alle funzionalità semplice " -"dell'OGC utilizzando testo noto, e il supporto è stato implementato da " -"diversi\n" -" sistemi di informazione geografica basati su " -"standard. I sistemi di riferimento spaziale possono essere indicati " -"utilizzando un numero intero SRID,\n" -" compresi i codici EPSG definiti " -"dall'Associazione internazionale dei produttori di petrolio e gas.\n" -" È specificato in ISO 19111:2007 Informazioni " -"geografiche: riferimento spaziale in base alle coordinate, pubblicato anche " -"come\n" -" Specifica astratta OGC, Argomento 2: Riferimento " -"spaziale per coordinata." +"A spatial reference system (SRS) or coordinate reference system (CRS) is a coordinate-based " +"local,\n" +" regional or global system used to locate geographical entities. " +"A spatial reference system defines a specific map\n" +" projection, as well as transformations between different spatial " +"reference systems. Spatial reference systems are\n" +" defined by the OGC's Simple feature access using well-known " +"text, and support has been implemented by several\n" +" standards-based geographic information systems. Spatial " +"reference systems can be referred to using a SRID integer,\n" +" including EPSG codes defined by the International Association of " +"Oil and Gas Producers.\n" +" It is specified in ISO 19111:2007 Geographic information—Spatial " +"referencing by coordinates, also published as\n" +" OGC Abstract Specification, Topic 2: Spatial referencing by " +"coordinate." +msgstr "" +"Un sistema di riferimento spaziale (SRS) o un sistema di riferimento delle coordinate (CRS) " +"è un sistema di riferimento\n" +" sistema regionale o globale utilizzato per individuare le entità " +"geografiche. Un sistema di riferimento spaziale definisce una mappa specifica\n" +" proiezioni, nonché trasformazioni tra diversi sistemi di " +"riferimento spaziale. I sistemi di riferimento spaziali sono\n" +" definito dall'accesso alle funzionalità semplice dell'OGC " +"utilizzando testo noto, e il supporto è stato implementato da diversi\n" +" sistemi di informazione geografica basati su standard. I sistemi " +"di riferimento spaziale possono essere indicati utilizzando un numero intero SRID,\n" +" compresi i codici EPSG definiti dall'Associazione internazionale " +"dei produttori di petrolio e gas.\n" +" È specificato in ISO 19111:2007 Informazioni geografiche: " +"riferimento spaziale in base alle coordinate, pubblicato anche come\n" +" Specifica astratta OGC, Argomento 2: Riferimento spaziale per " +"coordinata." msgid "Identifiers" msgstr "Identificatori" msgid "" "\n" -" A Spatial Reference System Identifier (SRID) is a " -"unique value used to unambiguously identify projected, unprojected,\n" -" and local spatial coordinate system definitions. " -"These coordinate systems form the heart of all GIS applications.\n" +" A Spatial Reference System Identifier (SRID) is a unique value used " +"to unambiguously identify projected, unprojected,\n" +" and local spatial coordinate system definitions. These coordinate " +"systems form the heart of all GIS applications.\n" "\n" -" Virtually all major spatial vendors have created " -"their own SRID implementation or refer to those of an authority,\n" +" Virtually all major spatial vendors have created their own SRID " +"implementation or refer to those of an authority,\n" " such as the European Petroleum Survey Group (EPSG).\n" " " msgstr "" "\n" -"Un identificatore SRID (Spatial Reference System Identifier) è un valore " -"univoco utilizzato per identificare in modo inequivocabile\n" -" e le definizioni del sistema di coordinate spaziali " -"locali. Questi sistemi di coordinate costituiscono il cuore di tutte le " -"applicazioni GIS.\n" +"Un identificatore SRID (Spatial Reference System Identifier) è un valore univoco utilizzato " +"per identificare in modo inequivocabile\n" +" e le definizioni del sistema di coordinate spaziali locali. Questi " +"sistemi di coordinate costituiscono il cuore di tutte le applicazioni GIS.\n" "\n" -"Praticamente tutti i principali fornitori spaziali hanno creato la propria " -"implementazione SRID o si riferiscono a quelli di un'autorità,\n" +"Praticamente tutti i principali fornitori spaziali hanno creato la propria implementazione " +"SRID o si riferiscono a quelli di un'autorità,\n" " come l'European Petroleum Survey Group (EPSG).\n" " " msgid "" -"NOTE: As of 2005 the EPSG SRID values are now maintained by the " -"International\n" -" Association of Oil & Gas Producers (OGP) " -"Surveying & Positioning Committee" +"NOTE: As of 2005 the EPSG SRID values are now maintained by the International\n" +" Association of Oil & Gas Producers (OGP) Surveying & Positioning " +"Committee" msgstr "" -"NOTA: a partire dal 2005 i valori EPSG SRID sono ora mantenuti " -"dall'International\n" -" Comitato di rilevamento e posizionamento " -"dell'Associazione dei produttori di petrolio e gas (OGP)" +"NOTA: a partire dal 2005 i valori EPSG SRID sono ora mantenuti dall'International\n" +" Comitato di rilevamento e posizionamento dell'Associazione dei " +"produttori di petrolio e gas (OGP)" msgid "" "\n" -" SRIDs are the primary key for the Open Geospatial " -"Consortium (OGC) spatial_ref_sys metadata table for the Simple\n" -" Features for SQL Specification, Versions 1.1 and " -"1.2, which is defined as follows:\n" +" SRIDs are the primary key for the Open Geospatial Consortium (OGC) " +"spatial_ref_sys metadata table for the Simple\n" +" Features for SQL Specification, Versions 1.1 and 1.2, which is " +"defined as follows:\n" " " msgstr "" "\n" -"Gli S SRID sono la chiave primaria per l'Open Geospatial Consortium (OGC) " -"spatial_ref_sys di metadati per il\n" -" Funzionalità per la specifica SQL, le versioni 1.1 e " -"1.2, definite come segue:\n" +"Gli S SRID sono la chiave primaria per l'Open Geospatial Consortium (OGC) spatial_ref_sys di " +"metadati per il\n" +" Funzionalità per la specifica SQL, le versioni 1.1 e 1.2, definite " +"come segue:\n" " " msgid "" "\n" -" In spatially enabled databases (such as IBM DB2, IBM " -"Informix, Microsoft SQL Server, MySQL, Oracle RDBMS, Teradata, PostGIS and\n" -" SQL Anywhere), SRIDs are used to uniquely identify " -"the coordinate systems used to define columns of spatial data or individual\n" -" spatial objects in a spatial column (depending on " -"the spatial implementation). SRIDs are typically associated with a well " -"known\n" -" text (WKT) string definition of the coordinate " -"system (SRTEXT, above). From the Well Known Text Wikipedia page\n" +" In spatially enabled databases (such as IBM DB2, IBM Informix, " +"Microsoft SQL Server, MySQL, Oracle RDBMS, Teradata, PostGIS and\n" +" SQL Anywhere), SRIDs are used to uniquely identify the coordinate " +"systems used to define columns of spatial data or individual\n" +" spatial objects in a spatial column (depending on the spatial " +"implementation). SRIDs are typically associated with a well known\n" +" text (WKT) string definition of the coordinate system (SRTEXT, " +"above). From the Well Known Text Wikipedia page\n" " " msgstr "" "\n" -"Nei database abilitati per l'ambiente (come IBM DB2, IBM Informix, Microsoft " -"SQL Server, MySQL, Oracle RDBMS, Teradata, PostGIS e\n" -" SQL Anywhere), gli SED vengono utilizzati per " -"identificare in modo univoco i sistemi di coordinate utilizzati per definire " -"colonne di dati spaziali o singoli\n" +"Nei database abilitati per l'ambiente (come IBM DB2, IBM Informix, Microsoft SQL Server, " +"MySQL, Oracle RDBMS, Teradata, PostGIS e\n" +" SQL Anywhere), gli SED vengono utilizzati per identificare in modo " +"univoco i sistemi di coordinate utilizzati per definire colonne di dati spaziali o singoli\n" " oggetti spaziali in una colonna spaziale (a seconda " "dell'implementazione spaziale). I SED sono in genere associati a un\n" -" text (WKT) definizione di stringa del sistema di " -"coordinate (SRTEXT, sopra). Dalla pagina Wikipedia di Ben Known Text\n" +" text (WKT) definizione di stringa del sistema di coordinate (SRTEXT, " +"sopra). Dalla pagina Wikipedia di Ben Known Text\n" " " msgid "" -"“A WKT string for a spatial reference system describes the datum, geoid, " -"coordinate system,\n" +"“A WKT string for a spatial reference system describes the datum, geoid, coordinate system,\n" " and map projection of the spatial objects”." msgstr "" -"\"Una stringa WKT per un sistema di riferimento spaziale descrive il sistema " -"di coordinate di riferimento, geoide,\n" +"\"Una stringa WKT per un sistema di riferimento spaziale descrive il sistema di coordinate " +"di riferimento, geoide,\n" " e la proiezione mappa degli oggetti spaziali\"." msgid "" "\n" -" Here are two common coordinate systems with their " -"EPSG SRID value followed by their well known text:\n" +" Here are two common coordinate systems with their EPSG SRID value " +"followed by their well known text:\n" " " msgstr "" "\n" -" Qui ci sono due sistemi di coordinate comuni con il " -"loro valore di EPSG SRID seguita dal loro WKT:\n" +" Qui ci sono due sistemi di coordinate comuni con il loro valore di " +"EPSG SRID seguita dal loro WKT:\n" " " msgid "" @@ -2987,87 +2825,76 @@ msgstr "" msgid "" "\n" -" SRID values associated with spatial data can be used " -"to constrain spatial operations — for instance, spatial operations cannot be " -"performed\n" -" between spatial objects with differing SRIDs in some " -"systems, or trigger coordinate system transformations between spatial " -"objects in others.\n" +" SRID values associated with spatial data can be used to constrain " +"spatial operations — for instance, spatial operations cannot be performed\n" +" between spatial objects with differing SRIDs in some systems, or " +"trigger coordinate system transformations between spatial objects in others.\n" " " msgstr "" "\n" -"I valori SRID associati ai dati spaziali possono essere utilizzati per " -"vincolare le operazioni spaziali, ad esempio le operazioni spaziali non " -"possono essere eseguite\n" -" tra oggetti spaziali con SRID diversi in alcuni " -"sistemi o attivare trasformazioni del sistema di coordinate tra oggetti " -"spaziali in altri.\n" +"I valori SRID associati ai dati spaziali possono essere utilizzati per vincolare le " +"operazioni spaziali, ad esempio le operazioni spaziali non possono essere eseguite\n" +" tra oggetti spaziali con SRID diversi in alcuni sistemi o attivare " +"trasformazioni del sistema di coordinate tra oggetti spaziali in altri.\n" " " msgid "" -"Source SRS EPSG Code is mandatory and represents the native data Spatial " -"Reference System. This must be coherent with the\n" -" Geometry values (lon/lat coordinates as an " -"instance) stored on the geospatial dataset. If not specified on the " -"geospatial data itself, it\n" +"Source SRS EPSG Code is mandatory and represents the native data Spatial Reference System. " +"This must be coherent with the\n" +" Geometry values (lon/lat coordinates as an instance) stored on " +"the geospatial dataset. If not specified on the geospatial data itself, it\n" " must be manually declared by the operator." msgstr "" -"Source SRS EPSG Code è obbligatorio e rappresenta il sistema di riferimento " -"spaziale dei dati nativi. Questo deve essere coerente con il\n" -" Valori geometrici (coordinate lon/lat come " -"istanza) archiviati nel set di dati geospaziali. Se non viene specificato " -"sui dati geospaziali stessi,\n" -" deve essere dichiarato manualmente " -"dall'operatore." +"Source SRS EPSG Code è obbligatorio e rappresenta il sistema di riferimento spaziale dei " +"dati nativi. Questo deve essere coerente con il\n" +" Valori geometrici (coordinate lon/lat come istanza) archiviati " +"nel set di dati geospaziali. Se non viene specificato sui dati geospaziali stessi,\n" +" deve essere dichiarato manualmente dall'operatore." msgid "" -"Target SRS EPSG Code is optional. This must be used only if we need to re-" -"project the coordinates from Source SRS to another one.\n" +"Target SRS EPSG Code is optional. This must be used only if we need to re-project the " +"coordinates from Source SRS to another one.\n" " " msgstr "" -"Target SRS EPSG Code è facoltativo. Questo deve essere utilizzato solo se è " -"necessario ri-proiettare le coordinate da Source SRS ad un altro.\n" +"Target SRS EPSG Code è facoltativo. Questo deve essere utilizzato solo se è necessario ri-" +"proiettare le coordinate da Source SRS ad un altro.\n" " " #, fuzzy #| msgid "Upload Layer Step: CSV Field Mapping" msgid "Upload Dataset Step: CSV Field Mapping" -msgstr "Upload Layer Step: CSV Field Mapping" +msgstr "Carica dataset, passo: campi CSV" msgid "Geospatial Data" msgstr "Dati geospaziali" msgid "" -"Please indicate which attributes contain the latitude and longitude " -"coordinates in the CSV data." +"Please indicate which attributes contain the latitude and longitude coordinates in the CSV " +"data." msgstr "" -"Si prega di indicare quali attributi contengono le coordinate di latitudine " -"e longitudine nei dati CSV." +"Si prega di indicare quali attributi contengono le coordinate di latitudine e longitudine " +"nei dati CSV." msgid "" "With this data, GeoNode was able to guess which attributes contain the\n" -" latitude and longitude coordinates, but please confirm that " -"the correct\n" +" latitude and longitude coordinates, but please confirm that the correct\n" " attributes are selected below." msgstr "" -"Con questi dati, GeoNode è stato in grado di capire quali attributi " -"contengono\n" -" latitudine e longitudine, ma si prega di verificare che le " -"coordinate siano corrette\n" +"Con questi dati, GeoNode è stato in grado di capire quali attributi contengono\n" +" latitudine e longitudine, ma si prega di verificare che le coordinate siano " +"corrette\n" " per gli attributi sono selezionati di seguito." msgid "Select an attribute" msgstr "Seleziona un attributo" msgid "" -"We did not detect columns that could be used for the latitude and " -"longitude.\n" -" Please verify that you have two columns in your csv file that can be " -"used for\n" +"We did not detect columns that could be used for the latitude and longitude.\n" +" Please verify that you have two columns in your csv file that can be used for\n" " the latitude and longitude." msgstr "" -"Non abbiamo rilevato colonne che potessero essere utilizzate per latitudine " -"e la longitudine.\n" +"Non abbiamo rilevato colonne che potessero essere utilizzate per latitudine e la " +"longitudine.\n" " Verificare di avere due colonne nel file csv che possono essere\n" " latitudine e la longitudine." @@ -3080,10 +2907,8 @@ msgstr "Torna a" msgid "Upload Form" msgstr "Carica Form" -#, fuzzy -#| msgid "Upload Layer Step: Time" msgid "Upload Dataset Step: Time" -msgstr "Caricamento livello: Dimensione temporale" +msgstr "Caricamento dataset: Dimensione temporale" msgid "Inspect data for " msgstr "Esamina dati per " @@ -3092,26 +2917,25 @@ msgid "Configure as Time-Series" msgstr "Configura come serie temporale" msgid "" -"Toggling this selector allows you to configure (or not) this data as a time " -"series; in this case you will also have to select an attribute\n" +"Toggling this selector allows you to configure (or not) this data as a time series; in this " +"case you will also have to select an attribute\n" " to drive the time dimension.\n" "

\n" -" If GeoNode is not able to parse any of the values for " -"the selected attribute red markers will appear to highlight the problems.\n" +" If GeoNode is not able to parse any of the values for the selected " +"attribute red markers will appear to highlight the problems.\n" "

\n" -" More information is provided at the bottom of the page " -"in the \"Additional Help\" sections.\n" +" More information is provided at the bottom of the page in the " +"\"Additional Help\" sections.\n" " " msgstr "" -"L'attivazione/attivazione/attivazione/configurazione di questo selettore " -"consente di configurare (o meno) questi dati come serie di tempo; in questo " -"caso si dovrà anche selezionare un attributo\n" -" per guidare la dimensione " -"temporale.

Se GeoNode non è in grado di " -"analizzare nessuno dei valori per l'attributo selezionato, gli indicatori " -"rossi verranno visualizzati per evidenziare i problemi. " -"

Ulteriori informazioni sono disponibili nella parte inferiore della " -"pagina nelle sezioni \"Guida aggiuntiva\". " +"L'attivazione/attivazione/attivazione/configurazione di questo selettore consente di " +"configurare (o meno) questi dati come serie di tempo; in questo caso si dovrà anche " +"selezionare un attributo\n" +" per guidare la dimensione temporale.

Se " +"GeoNode non è in grado di analizzare nessuno dei valori per l'attributo selezionato, gli " +"indicatori rossi verranno visualizzati per evidenziare i problemi. " +"

Ulteriori informazioni sono disponibili nella parte inferiore della pagina nelle " +"sezioni \"Guida aggiuntiva\". " msgid "No" msgstr "No" @@ -3122,12 +2946,9 @@ msgstr "Utilizzare un attributo timestamp esistente nei dati" msgid "Yes: with an existing Time-Attribute" msgstr "Sì: con un attributo Time esistente" -msgid "" -"Yes: by converting data to a timestamp using standard date/time " -"representation" +msgid "Yes: by converting data to a timestamp using standard date/time representation" msgstr "" -"Sì: convertendo i dati in un timestamp utilizzando la rappresentazione " -"standard di data/ora" +"Sì: convertendo i dati in un timestamp utilizzando la rappresentazione standard di data/ora" msgid "Convert a number field into a year" msgstr "Convertire un campo numerico in un anno" @@ -3135,12 +2956,10 @@ msgstr "Convertire un campo numerico in un anno" msgid "Yes: by converting a number as Year" msgstr "Sì: convertendo un numero come Anno" -msgid "" -"Convert data to a timestamp using standard date/time representation or a " -"custom format" +msgid "Convert data to a timestamp using standard date/time representation or a custom format" msgstr "" -"Convertire i dati in un timestamp utilizzando la rappresentazione di data/" -"ora standard o un formato personalizzato" +"Convertire i dati in un timestamp utilizzando la rappresentazione di data/ora standard o un " +"formato personalizzato" msgid "Start Importer" msgstr "Avvia importazione" @@ -3187,12 +3006,10 @@ msgstr "definito dalla risoluzione" msgid "Continuous Intervals" msgstr "Intervalli continui" -msgid "" -"for data that is frequently updated, resolution describes the frequency of " -"updates" +msgid "for data that is frequently updated, resolution describes the frequency of updates" msgstr "" -"per i dati che viene aggiornato di frequente, risoluzione descrive la " -"frequenza degli aggiornamenti" +"per i dati che viene aggiornato di frequente, risoluzione descrive la frequenza degli " +"aggiornamenti" msgid "Resolution of time attribute" msgstr "Risoluzione di un attributo tempo" @@ -3200,31 +3017,20 @@ msgstr "Risoluzione di un attributo tempo" msgid "Enabling Time" msgstr "Tempo di attivazione" -#, fuzzy -#| msgid "" -#| "A layer can support one or two time attributes. If a single\n" -#| " attribute is used, the layer is considered to " -#| "contain data that is valid at single points in time. If two\n" -#| " attributes are used, the second attribute " -#| "represents the end of a valid period hence the layer is considered\n" -#| " to contain data that is valid at certain periods " -#| "in time." msgid "" "A dataset can support one or two time attributes. If a single\n" -" attribute is used, the dataset is considered to " -"contain data that is valid at single points in time. If two\n" -" attributes are used, the second attribute represents " -"the end of a valid period hence the dataset is considered\n" -" to contain data that is valid at certain periods in " -"time." -msgstr "" -"Un layer può supportare uno o due attributi temporali. Se un singolo\n" -" attributo viene utilizzato, il layer è considerato " -"contenere dati validi in singoli punti nel tempo. Se due\n" -" attributi, il secondo attributo rappresenta la fine " -"di un periodo valido, quindi il layer è considerato\n" -" per contenere dati validi in determinati periodi di " -"tempo." +" attribute is used, the dataset is considered to contain data that is " +"valid at single points in time. If two\n" +" attributes are used, the second attribute represents the end of a " +"valid period hence the dataset is considered\n" +" to contain data that is valid at certain periods in time." +msgstr "" +"Un dataset può supportare uno o due attributi temporali. Se un singolo\n" +" attributo viene utilizzato, il layer è considerato contenere dati " +"validi in singoli punti nel tempo. Se due\n" +" attributi, il secondo attributo rappresenta la fine di un periodo " +"valido, quindi il layer è considerato\n" +" per contenere dati validi in determinati periodi di tempo." msgid "Selecting an Attribute" msgstr "Seleziona un attributo" @@ -3243,30 +3049,24 @@ msgstr "Un numero che rappresenta l'anno" msgid "" "\n" -" For text attributes, one can specify a custom format " -"(as part of the \"Advanced Options\") or use the 'best guess' approach which " -"will try to\n" -" automatically translate well-known recognized " -"patterns into valid times.\n" +" For text attributes, one can specify a custom format (as part of the " +"\"Advanced Options\") or use the 'best guess' approach which will try to\n" +" automatically translate well-known recognized patterns into valid " +"times.\n" " " msgstr "" "\n" -" Per gli attributi di testo, è possibile specificare " -"un formato personalizzato (come parte delle \"Opzioni avanzate\") o " -"utilizzare l'approccio \"best guess\" che cercherà di\n" -" convertire automaticamente i patterns riconosciuti " -"in date valide.\n" +" Per gli attributi di testo, è possibile specificare un formato " +"personalizzato (come parte delle \"Opzioni avanzate\") o utilizzare l'approccio \"best " +"guess\" che cercherà di\n" +" convertire automaticamente i patterns riconosciuti in date valide.\n" " " msgid "The 'best guess' will handle date and optional time variants of" -msgstr "" -"L''ipotesi migliore' in grado di gestire le varianti di data e ora opzionale " -"di" +msgstr "L''ipotesi migliore' in grado di gestire le varianti di data e ora opzionale di" msgid "In terms of the formatting flags noted above, these are" -msgstr "" -"Per quanto riguarda le bandiere di formattazione osservato in precedenza, si " -"tratta di" +msgstr "Per quanto riguarda le bandiere di formattazione osservato in precedenza, si tratta di" msgid "Modal Header" msgstr "Intestazione modale" @@ -3295,11 +3095,9 @@ msgstr "Scelta sbagliata" msgid "Please, select one Time Attribute to test!" msgstr "Si prega di selezionare un Attributo Temporale!" -msgid "" -"Returning to the upload starting page in 5seconds " +msgid "Returning to the upload starting page in 5seconds " msgstr "" -"Sarai rediretto alla pagina iniziale di caricamento entro 5 secondi " +"Sarai rediretto alla pagina iniziale di caricamento entro 5 secondi " msgid " Or just go " msgstr " O semplicemente andare " @@ -3318,21 +3116,13 @@ msgid "You are attempting to {action_type} a raster dataset with a vector." msgstr "Si sta tentando di {action_type} un livello raster con un vettore." #, fuzzy, python-brace-format -#| msgid "" -#| "You are attempting to {action_type} a vector layer with an unknown format." -msgid "" -"You are attempting to {action_type} a vector dataset with an unknown format." -msgstr "" -"Si sta tentando di {action_type} un livello vettoriale con un formato " -"sconosciuto." +#| msgid "You are attempting to {action_type} a vector layer with an unknown format." +msgid "You are attempting to {action_type} a vector dataset with an unknown format." +msgstr "Si sta tentando di {action_type} un livello vettoriale con un formato sconosciuto." #, python-brace-format -msgid "" -"Please ensure the name is consistent with the file you are trying to " -"{action_type}." -msgstr "" -"Assicurarsi che il nome sia coerente con il file che si sta tentando di " -"{action_type}." +msgid "Please ensure the name is consistent with the file you are trying to {action_type}." +msgstr "Assicurarsi che il nome sia coerente con il file che si sta tentando di {action_type}." #, fuzzy #| msgid "Local GeoNode layer has no geometry type." @@ -3341,83 +3131,55 @@ msgstr "Il livello GeoNode locale non ha alcun tipo di geometria." #, python-brace-format msgid "" -"Please ensure there is at least one geometry " -"type that is consistent with the file you are " -"trying to {action_type}." +"Please ensure there is at least one geometry type that is " +"consistent with the file you are trying to {action_type}." msgstr "" -"Assicurarsi che sia disponibile almeno un tipo di geometria coerente con il " -"file che si sta tentando di {action_type}." +"Assicurarsi che sia disponibile almeno un tipo di geometria coerente con il file che si sta " +"tentando di {action_type}." -#, fuzzy -#| msgid "The selected Layer does not exists in the catalog." msgid "The selected Dataset does not exists in the catalog." -msgstr "Il livello selezionato non esiste nel catalogo." +msgstr "Il dataset selezionato non esiste nel catalogo." -#, fuzzy -#| msgid "Please ensure that the layer structure is consistent " msgid "Please ensure that the dataset structure is consistent " -msgstr "Assicurarsi che la struttura del livello sia coerente " +msgstr "Assicurarsi che la struttura del dataset sia coerente " -msgid "" -"Some error occurred while trying to access the uploaded schema: {str(e)}" +msgid "Some error occurred while trying to access the uploaded schema: {str(e)}" msgstr "" -"Si è verificato un errore durante il tentativo di accesso allo schema " -"caricato: {str(e)}" +"Si è verificato un errore durante il tentativo di accesso allo schema caricato: {str(e)}" msgid "" -"There was an error while attempting to upload your data. Please try again, " -"or contact and administrator if the problem continues." +"There was an error while attempting to upload your data. Please try again, or contact and " +"administrator if the problem continues." msgstr "" -"E' occorso un errore durante l'invio dei tuoi dati. Riprova o contatta un " -"amministratore se il problema persiste." +"E' occorso un errore durante l'invio dei tuoi dati. Riprova o contatta un amministratore se " +"il problema persiste." -#, fuzzy -#| msgid "" -#| "Note: this layer's orginal metadata was populated and preserved by " -#| "importing a metadata XML file. This metadata cannot be edited." msgid "" -"Note: this dataset's orginal metadata was populated and preserved by " -"importing a metadata XML file. This metadata cannot be edited." +"Note: this dataset's orginal metadata was populated and preserved by importing a metadata " +"XML file. This metadata cannot be edited." msgstr "" -"Nota: i metadati originali di questo livello sono stati popolati e " -"conservati importando un file XML di metadati. Questi metadati non possono " -"essere modificati." +"Nota: i metadati originali di questo dataset sono stati popolati e conservati importando un " +"file XML di metadati. Questi metadati non possono essere modificati." -#, fuzzy -#| msgid "You are not permitted to delete this layer" msgid "You are not permitted to delete this dataset" -msgstr "Non hai il permesso di eliminare questo livello" +msgstr "Non hai il permesso di eliminare questo dataset" -#, fuzzy -#| msgid "You do not have permissions for this layer." msgid "You do not have permissions for this dataset." -msgstr "Non hai i permessi per questo livello." +msgstr "Non hai i permessi per questo dataset." -#, fuzzy -#| msgid "You are not permitted to modify this layer" msgid "You are not permitted to modify this dataset" -msgstr "Non hai i permessi per modificare questo livello" +msgstr "Non hai i permessi per modificare questo dataset" -#, fuzzy -#| msgid "You are not permitted to modify this layer's metadata" msgid "You are not permitted to modify this dataset's metadata" -msgstr "Non hai il permesso di modificare i metadati di questo livello" +msgstr "Non hai il permesso di modificare i metadati di questo dataset" -#, fuzzy -#| msgid "You are not permitted to view this layer" msgid "You are not permitted to view this dataset" -msgstr "Non hai il permesso di visualizzare questo livello" +msgstr "Non hai il permesso di visualizzare questo dataset" -#, fuzzy -#| msgid "" -#| "This layer is a member of a layer group, you must remove the layer from " -#| "the group before deleting." msgid "" -"This dataset is a member of a layer group, you must remove the dataset from " -"the group before deleting." -msgstr "" -"Questo livello è membro di un gruppo, devi rimuoverlo dal gruppo prima di " -"eliminarlo." +"This dataset is a member of a layer group, you must remove the dataset from the group before " +"deleting." +msgstr "Questo dataset è membro di un gruppo, devi rimuoverlo dal gruppo prima di eliminarlo." #, python-format msgid "couldn't generate thumbnail: %s" @@ -3516,11 +3278,9 @@ msgstr "Valuta questa mappa" msgid "Download Map" msgstr "Scarica la mappa" -#, fuzzy -#| msgid "Maps" msgid "Map" msgid_plural "Maps" -msgstr[0] "Mappe" +msgstr[0] "Mappa" msgstr[1] "Mappe" msgid "Map Layers" @@ -3560,25 +3320,23 @@ msgstr "" msgid "" "\n" -"

Could not find downloadable layers " -"for this map. You can go back to \n" +"
Could not find downloadable layers for this map. " +"You can go back to \n" " " msgstr "" "\n" -"
Impossibile trovare livelli " -"scaricabili per questa mappa. Si può tornare a \n" +"
Impossibile trovare livelli scaricabili per questa " +"mappa. Si può tornare a \n" " " msgid "" "\n" -" Additionally, the map contains these layers which will not be " -"downloaded\n" +" Additionally, the map contains these layers which will not be downloaded\n" " due to security restrictions:\n" " " msgstr "" "\n" -" Inoltre, la mappa contiene questi livelli che non possono essere " -"scaricati\n" +" Inoltre, la mappa contiene questi livelli che non possono essere scaricati\n" " per vincoli di sicurezza:\n" " " @@ -3589,8 +3347,7 @@ msgid "" " " msgstr "" "\n" -" Infine, la mappa contiene questi livelli che non possono essere " -"scaricati\n" +" Infine, la mappa contiene questi livelli che non possono essere scaricati\n" " perchè non sono disponibili direttamente da questo GeoNode:\n" " " @@ -3616,16 +3373,14 @@ msgid "Explore Maps" msgstr "Esplora mappe" msgid "" -"Note: this map's orginal metadata was populated by importing a metadata XML " -"file.\n" -" GeoNode's metadata import supports a subset of ISO, FGDC, and Dublin " -"Core metadata elements.\n" +"Note: this map's orginal metadata was populated by importing a metadata XML file.\n" +" GeoNode's metadata import supports a subset of ISO, FGDC, and Dublin Core metadata " +"elements.\n" " Some of your original metadata may have been lost." msgstr "" -"Nota: i metadati originale di questa mappa era popolato importando un file " -"XML di metadati. Metadati importazione di GeoNode supporta un sottoinsieme " -"di elementi di metadati ISO, FGDC, e Dublin Core. Alcuni dei i metadati " -"originale Potrebbero essere state compromesse." +"Nota: i metadati originale di questa mappa era popolato importando un file XML di metadati. " +"Metadati importazione di GeoNode supporta un sottoinsieme di elementi di metadati ISO, FGDC, " +"e Dublin Core. Alcuni dei i metadati originale Potrebbero essere state compromesse." msgid "Return to Map" msgstr "Ritorna alla mappa" @@ -3636,13 +3391,13 @@ msgstr "Rimuovi mappa" #, python-format msgid "" "\n" -" Are you sure you want to remove %(map_title)s?\n" +" Are you sure you want to remove %(map_title)s?\n" " " msgstr "" "\n" -" Sei sicuro di voler rimuovere " -"%(map_title)s?\n" +" Sei sicuro di voler rimuovere %(map_title)s?\n" " " msgid "You are not permitted to delete this map." @@ -3688,18 +3443,18 @@ msgid "Show list of services" msgstr "Elenco dei servizi" msgid "" -"Process data since specific timestamp (YYYY-MM-DD HH:MM:SS format). If not " -"provided, last sync will be used." +"Process data since specific timestamp (YYYY-MM-DD HH:MM:SS format). If not provided, last " +"sync will be used." msgstr "" -"Elaborare i dati dal timestamp specifico (formato AAAA-MM-GG HH:MM:SS). Se " -"non viene specificato, verrà utilizzata l'ultima sincronizzazione." +"Elaborare i dati dal timestamp specifico (formato AAAA-MM-GG HH:MM:SS). Se non viene " +"specificato, verrà utilizzata l'ultima sincronizzazione." msgid "" -"Process data until specific timestamp (YYYY-MM-DD HH:MM:SS format). If not " -"provided, now will be used." +"Process data until specific timestamp (YYYY-MM-DD HH:MM:SS format). If not provided, now " +"will be used." msgstr "" -"Elaborare i dati fino al timestamp specifico (formato AAAA-MM-GG HH:MM:SS). " -"Se non specificato, verrà utilizzata l'ora attuale." +"Elaborare i dati fino al timestamp specifico (formato AAAA-MM-GG HH:MM:SS). Se non " +"specificato, verrà utilizzata l'ora attuale." msgid "Force check" msgstr "Controllo forzato" @@ -3708,11 +3463,11 @@ msgid "Format of audit log (xml, json)" msgstr "Formato del log di audit (xml, json)" msgid "" -"Should old data be preserved (default: no, data older than settings." -"MONITORING_DATA_TTL will be removed)" +"Should old data be preserved (default: no, data older than settings.MONITORING_DATA_TTL will " +"be removed)" msgstr "" -"Conservare i dati precedenti (impostazione predefinita: no, i dati più " -"vecchi di settings.MONITORING_DATA_TTL verranno rimossi)" +"Conservare i dati precedenti (impostazione predefinita: no, i dati più vecchi di settings." +"MONITORING_DATA_TTL verranno rimossi)" msgid "Should stop on first error occured (default: no)" msgstr "Interruzione al primo errore (impostazione predefinita: no)" @@ -3739,8 +3494,7 @@ msgid "Metric name" msgstr "Nome metrica" msgid "Show data for specific resource in resource_type=resource_name format" -msgstr "" -"Mostra i dati per una risorsa specifica nel formato tipo_risorsa-nome_risorsa" +msgstr "Mostra i dati per una risorsa specifica nel formato tipo_risorsa-nome_risorsa" msgid "Show data for specific resource" msgstr "Mostra dati per risorsa specifica" @@ -3752,12 +3506,10 @@ msgstr "Mostra dati per un'etichetta specifica" msgid "Write result to file, default GEOIP_PATH: {settings.GEOIP_PATH}" msgstr "Scritto risultato su file, default GEOIP_PATH: {settings.GEOIP_PATH}" -msgid "" -"Fetch database from specific url. If nothing provided, default {} will be " -"used" +msgid "Fetch database from specific url. If nothing provided, default {} will be used" msgstr "" -"Recuperare il database da un URL specifico. Se non viene fornito nulla, " -"verrà utilizzato il valore predefinito {}" +"Recuperare il database da un URL specifico. Se non viene fornito nulla, verrà utilizzato il " +"valore predefinito {}" msgid "Overwrite file if exists" msgstr "Sovrascrivi file se esiste già" @@ -3908,8 +3660,7 @@ msgid "Last update must not be older than" msgstr "L'ultimo aggiornamento non deve essere più vecchio di" msgid "Max timeout for given metric before error should be raised" -msgstr "" -"Timeout massimo per la metrica specificata prima che venga generato l'errore" +msgstr "Timeout massimo per la metrica specificata prima che venga generato l'errore" msgid "Monitoring & Analytics" msgstr "Monitoraggio & Analytics" @@ -3972,29 +3723,22 @@ msgstr "Cambia password: %s" msgid "party who authored the resource" msgstr "gruppo che ha creato la risorsa" -msgid "" -"party who has processed the data in a manner such that the resource has been " -"modified" -msgstr "" -"gruppo che ha elaborato i dati in modo tale che la risorsa sia stata " -"modificata" +msgid "party who has processed the data in a manner such that the resource has been modified" +msgstr "gruppo che ha elaborato i dati in modo tale che la risorsa sia stata modificata" msgid "party who published the resource" msgstr "gruppo che ha pubblicato la risorsa" msgid "" -"party that accepts accountability and responsibility for the data and " -"ensures appropriate care and maintenance of the resource" +"party that accepts accountability and responsibility for the data and ensures " +"appropriate care and maintenance of the resource" msgstr "" -"partito che accetta la responsabilità e la responsabilità per i dati e " -"garantisce la cura e la manutenzione appropriata della risorsa" +"partito che accetta la responsabilità e la responsabilità per i dati e garantisce la cura e " +"la manutenzione appropriata della risorsa" -msgid "" -"party who can be contacted for acquiring knowledge about or acquisition of " -"the resource" +msgid "party who can be contacted for acquiring knowledge about or acquisition of the resource" msgstr "" -"parte che può essere contattata per l'acquisizione di conoscenza o " -"acquisizione della risorsa" +"parte che può essere contattata per l'acquisizione di conoscenza o acquisizione della risorsa" msgid "party who distributes the resource" msgstr "parte che distribuisce la risorsa" @@ -4013,8 +3757,7 @@ msgstr "parte che possiede la risorsa" msgid "key party responsible for gathering information and conducting research" msgstr "" -"parte chiave responsabile della raccolta di informazioni e della conduzione " -"della ricerca" +"parte chiave responsabile della raccolta di informazioni e della conduzione della ricerca" msgid "Email Address" msgstr "Indirizzo email" @@ -4041,30 +3784,23 @@ msgid "Voice" msgstr "Voce" msgid "" -"telephone number by which individuals can speak to the responsible " -"organization or individual" +"telephone number by which individuals can speak to the responsible organization or individual" msgstr "" -"numero di telefono con cui le persone possono parlare con l'organizzazione o " -"l'individuo responsabile" +"numero di telefono con cui le persone possono parlare con l'organizzazione o l'individuo " +"responsabile" msgid "Facsimile" msgstr "Fax" -msgid "" -"telephone number of a facsimile machine for the responsible organization or " -"individual" -msgstr "" -"numero di telefono o fax per l'organizzazione o l'individuo responsabile" +msgid "telephone number of a facsimile machine for the responsible organization or individual" +msgstr "numero di telefono o fax per l'organizzazione o l'individuo responsabile" msgid "Delivery Point" msgstr "Informazioni di contatto" -msgid "" -"physical and email address at which the organization or individual may be " -"contacted" +msgid "physical and email address at which the organization or individual may be contacted" msgstr "" -"indirizzo fisico e email ai quali l'organizzazione o l'individuo possono " -"essere contattati" +"indirizzo fisico e email ai quali l'organizzazione o l'individuo possono essere contattati" msgid "City" msgstr "Città" @@ -4091,11 +3827,11 @@ msgid "country of the physical address" msgstr "paese dell'indirizzo fisico" msgid "" -"commonly used word(s) or formalised word(s) or phrase(s) used to describe " -"the subject (space or comma-separated" +"commonly used word(s) or formalised word(s) or phrase(s) used to describe the " +"subject (space or comma-separated" msgstr "" -"parola di uso comune (s) o una parola formalizzata (s) o la frase (s) " -"utilizzati per descrivere il soggetto (spazio o separato da virgole" +"parola di uso comune (s) o una parola formalizzata (s) o la frase (s) utilizzati per " +"descrivere il soggetto (spazio o separato da virgole" msgid "Timezone" msgstr "Fuso orario" @@ -4113,11 +3849,11 @@ msgid "Forgot Username" msgstr "Username dimenticato" msgid "" -"Enter your email address and click the submit button.
Your username " -"will be sent to you." +"Enter your email address and click the submit button.
Your username will be sent to " +"you." msgstr "" -"Inserisci il tuo indirizzo email e clicca il bottone submit.
Il tuo " -"username sarà spedito all'indirizzo specificato." +"Inserisci il tuo indirizzo email e clicca il bottone submit.
Il tuo username sarà " +"spedito all'indirizzo specificato." msgid "Create Profile" msgstr "Crea profilo" @@ -4129,7 +3865,7 @@ msgid "Not provided." msgstr "Non fornito." msgid "Position" -msgstr "Posizione" +msgstr "Incarico" msgid "Organization" msgstr "Organizzazione" @@ -4219,12 +3955,8 @@ msgstr "Non è consentito salvare o modificare questa risorsa." msgid "You are not authorized to download this resource." msgstr "Non è consentito scaricare questa risorsa." -msgid "" -"No files have been found for this resource. Please, contact a system " -"administrator." -msgstr "" -"Nessun file trovato per questa risorsa. Contattare un amministratore di " -"sistema." +msgid "No files have been found for this resource. Please, contact a system administrator." +msgstr "Nessun file trovato per questa risorsa. Contattare un amministratore di sistema." msgid "No files found." msgstr "Nessun file trovato." @@ -4232,10 +3964,8 @@ msgstr "Nessun file trovato." msgid "Not Authorized" msgstr "Non autorizzato" -#, fuzzy -#| msgid "GeoNode Themes Library" msgid "GeoNode Resource Processing Library" -msgstr "Libreria dei temi GeoNode" +msgstr "Libreria dei processamenti GeoNode" msgid "Disabling this Task will make the Processing Workflow to skip it." msgstr "" @@ -4253,11 +3983,11 @@ msgid "Error updating permissions :(" msgstr "Errore durante l'aggiornamento delle autorizzazioni :(" msgid "" -"User {username} has download permissions but cannot access the resource. " -"Please update permission consistently!" +"User {username} has download permissions but cannot access the resource. Please update " +"permission consistently!" msgstr "" -"L'utente {username} ha le autorizzazioni di scaricamento ma non può " -"visualizzare la risorsa. Controllare che le autorizzazioni siano consistenti." +"L'utente {username} ha le autorizzazioni di scaricamento ma non può visualizzare la risorsa. " +"Controllare che le autorizzazioni siano consistenti." msgid "You are not allowed to change permissions for this resource" msgstr "Non ti è consentito modificare le autorizzazioni per questa risorsa" @@ -4480,10 +4210,8 @@ msgstr "La Risorsa {resource_id} è in fase di elaborazione" msgid "Service rescanned successfully" msgstr "Il servizio è stato analizzato di nuovo correttamente" -#, fuzzy -#| msgid "You are not permitted to save or edit this resource." msgid "You dont have enougth rigths to see the resource detail" -msgstr "Non è consentito salvare o modificare questa risorsa." +msgstr "Non hai i privilegi necessari per vedere i dettagli di questa risorsa" msgid "You are not permitted to change this service." msgstr "Non è consentito modificare questo servizio." @@ -4545,13 +4273,12 @@ msgstr "Pagina non trovata" msgid "" "\n" -" The page you requested does not exist. Perhaps you are using an " -"outdated bookmark?\n" +" The page you requested does not exist. Perhaps you are using an outdated " +"bookmark?\n" " " msgstr "" "\n" -" La pagina richiesta non esiste. Forse si utilizza un segnalibro " -"obsoleto?\n" +" La pagina richiesta non esiste. Forse si utilizza un segnalibro obsoleto?\n" " " msgid "Toggle navigation" @@ -4578,31 +4305,28 @@ msgid "You are using an outdated browser that is not supported by GeoNode." msgstr "Stai usando un browser obsoleto che non è supportato da GeoNode." msgid "" -"Please use a modern browser like Mozilla Firefox, Google " -"Chrome or Safari." +"Please use a modern browser like Mozilla Firefox, Google Chrome or Safari." msgstr "" -"Utilizza un browser moderno come Mozilla Firefox, Google " -"Chrome o Safari." +"Utilizza un browser moderno come Mozilla Firefox, Google Chrome o Safari." msgid "There was a problem loading this page" msgstr "C'è stato un problema nel caricare la pagina" msgid "" "\n" -" Please contact your GeoNode administrator (they may have " -"received an email automatically if they configured it properly).\n" -" If you are the site administrator, enable debug mode to see the " -"actual error and fix it or file an issue in
GeoNode's issue tracker\n" +" Please contact your GeoNode administrator (they may have received an email " +"automatically if they configured it properly).\n" +" If you are the site administrator, enable debug mode to see the actual error and " +"fix it or file an issue in GeoNode's " +"issue tracker\n" " " msgstr "" "\n" -" Si prega di contattare l'amministratore di GeoNode (può aver " -"ricevuto un'e-mail automaticamente se ha configurato correttamente).\n" -" Se sei l'amministratore del sito, attivare la modalità di debug " -"visualizzare l'errore effettivo e risolvere il problema o un problema del " -"file nel tracciatore di " -"problemi di GeoNode\n" +" Si prega di contattare l'amministratore di GeoNode (può aver ricevuto un'e-mail " +"automaticamente se ha configurato correttamente).\n" +" Se sei l'amministratore del sito, attivare la modalità di debug visualizzare " +"l'errore effettivo e risolvere il problema o un problema del file nel tracciatore di problemi di GeoNode\n" " " #, fuzzy @@ -4703,21 +4427,16 @@ msgstr "Chi può scaricarlo?" msgid "Who can change metadata for it?" msgstr "Chi può modificare i metadati per questo?" -#, fuzzy -#| msgid "Who can edit data for this layer?" msgid "Who can edit data for this dataset?" -msgstr "Chi può modificare i dati di questo livello?" +msgstr "Chi può modificare i dati di questo dataset?" -#, fuzzy -#| msgid "Who can edit styles for this layer?" msgid "Who can edit styles for this dataset?" -msgstr "Chi può modificare gli stili di questo livello?" +msgstr "Chi può modificare gli stili di questo dataset?" -msgid "" -"Who can manage it? (update, delete, change permissions, publish/unpublish it)" +msgid "Who can manage it? (update, delete, change permissions, publish/unpublish it)" msgstr "" -"Chi può gestirlo? (Aggiornare, cancellare, modificare le autorizzazioni, " -"pubblicare / annullare la pubblicazione di esso)" +"Chi può gestirlo? (Aggiornare, eliminare, modificare le autorizzazioni, pubblicare / " +"annullare la pubblicazione di esso)" msgid "Set permissions for this resource" msgstr "Impostare le autorizzazioni per questa risorsa" @@ -4753,12 +4472,11 @@ msgid "Mandatory files : SHP , DBF" msgstr "File obbligatori: .shp, .dbf" msgid "" -"Upload a ZIP file containing an ESRI Shapefile. If the ZIP provides also a ." -"prj file, you don't have to specify the EPSG SRID" +"Upload a ZIP file containing an ESRI Shapefile. If the ZIP provides also a .prj file, you " +"don't have to specify the EPSG SRID" msgstr "" -"Carica uo file ZIP contenente uno Shapegile ESRI. Se lo ZIP fornisceanche un " -"file .prj non è necessario specificare il Sistema di Riferimento (Codice " -"EPSG)" +"Carica uo file ZIP contenente uno Shapegile ESRI. Se lo ZIP fornisceanche un file .prj non è " +"necessario specificare il Sistema di Riferimento (Codice EPSG)" msgid "Choose" msgstr "Seleziona" @@ -4782,32 +4500,31 @@ msgid "Load SHP-ZIP" msgstr "Carica uno Shapefile .zip" msgid "" -"

This will remove the Geo Limits currently drawn on the map.

In " -"order to store the Geo Limits you will need to save them " -"anyway.

Do you want to proceed?

" +"

This will remove the Geo Limits currently drawn on the map.

In order to store the " +"Geo Limits you will need to save them anyway.

Do you want to proceed?" +"

" msgstr "" -"

Questa azione rimuoverà i limiti spaziali attualmente disegnati " -"sullamappa.

Vuoi procedere?

" +"

Questa azione rimuoverà i limiti spaziali attualmente disegnati sullamappa.

Vuoi " +"procedere?

" msgid "" -"

This will override the current stored Geo Limits on the DB.

To " -"apply them you will need to click on Apply Changes button " -"anyway.

WARNING: This operation cannot be reverted!

Do you want to proceed?

" +"

This will override the current stored Geo Limits on the DB.

To apply them you will " +"need to click on Apply Changes button anyway.

WARNING: This operation cannot be reverted!

Do you want to proceed?

" msgstr "" -"

Questa azione sovrascriverà i limiti spaziali attualmente salvantinel DB." -"

Per procedere clicca su Esegui.

ATTENZIONE: Questa azione è irreversibile!

" +"

Questa azione sovrascriverà i limiti spaziali attualmente salvantinel DB.

Per " +"procedere clicca su Esegui.

ATTENZIONE: Questa " +"azione è irreversibile!

" msgid "Save Geo Limit" msgstr "Salve limiti spaziali" msgid "" -"

Geometry successfully saved!

To apply them you " -"will need to click on Apply Changes button.

" +"

Geometry successfully saved!

To apply them you will need to click " +"on Apply Changes button.

" msgstr "" -"

Geometria salvata con successo!

Per applicarli è " -"necessario fare clic sul pulsante Applica modifiche.

" +"

Geometria salvata con successo!

Per applicarli è necessario fare " +"clic sul pulsante Applica modifiche.

" msgid "

Error while trying to save the Geometry!

" msgstr "

Errore nel salvataggio della geometria!

" @@ -4822,13 +4539,13 @@ msgid "

No Geometry found!

" msgstr "

Nessuna geometria trovata!

" msgid "" -"

This will permanently remove the Geo Limits from the DB." -"

To apply them you will need to click on Apply Changes button.

Do you want to proceed?

" +"

This will permanently remove the Geo Limits from the DB.

To apply " +"them you will need to click on Apply Changes button.

Do you want to " +"proceed?

" msgstr "" -"

In questo modo i limiti geografici verranno rimossi " -"definitivamente dal database.

Per applicarli è necessario fare clic " -"sul pulsante Applica modifiche.

Vuoi procedere?

" +"

In questo modo i limiti geografici verranno rimossi definitivamente dal " +"database.

Per applicarli è necessario fare clic sul pulsante Applica modifiche." +"

Vuoi procedere?

" msgid "Delete Geo Limit" msgstr "Elimina limite geografico" @@ -4836,11 +4553,9 @@ msgstr "Elimina limite geografico" msgid "

Geo Limitsy successfully deleted!

" msgstr "

Geo Limite eliminato con successo!

" -msgid "" -"

Error occurred while trying to delete Geo Limits:

" +msgid "

Error occurred while trying to delete Geo Limits:

" msgstr "" -"

Errore durante il tentativo di eliminazione dei limiti " -"geografici:

" +"

Errore durante il tentativo di eliminazione dei limiti geografici:

" msgid "Choose users..." msgstr "Scegli gli utenti ..." @@ -4858,43 +4573,37 @@ msgid "About GeoNode" msgstr "A proposito di GeoNode" msgid "" -"GeoNode is a geospatial content management system, a platform for the " -"management and publication of geospatial data. It brings together mature and " -"stable open-source software projects under a consistent and easy-to-use " -"interface allowing non-specialized users to share data and create " -"interactive maps." +"GeoNode is a geospatial content management system, a platform for the management and " +"publication of geospatial data. It brings together mature and stable open-source software " +"projects under a consistent and easy-to-use interface allowing non-specialized users to " +"share data and create interactive maps." msgstr "" -"GeoNode è un sistema di gestione dei contenuti geospaziali, una piattaforma " -"per la gestione e la pubblicazione di dati geospaziali. Riunisce progetti " -"software open source maturi e stabili sotto un'interfaccia coerente e facile " -"da usare che consente agli utenti non specializzati di condividere dati e " -"creare mappe interattive." +"GeoNode è un sistema di gestione dei contenuti geospaziali, una piattaforma per la gestione " +"e la pubblicazione di dati geospaziali. Riunisce progetti software open source maturi e " +"stabili sotto un'interfaccia coerente e facile da usare che consente agli utenti non " +"specializzati di condividere dati e creare mappe interattive." msgid "" -"Data management tools built into GeoNode allow for integrated creation of " -"data, metadata, and map visualizations. Each dataset in the system can be " -"shared publicly or restricted to allow access to only specific users. Social " -"features like user profiles and commenting and rating systems allow for the " -"development of communities around each platform to facilitate the use, " -"management, and quality control of the data the GeoNode instance contains." +"Data management tools built into GeoNode allow for integrated creation of data, metadata, " +"and map visualizations. Each dataset in the system can be shared publicly or restricted to " +"allow access to only specific users. Social features like user profiles and commenting and " +"rating systems allow for the development of communities around each platform to facilitate " +"the use, management, and quality control of the data the GeoNode instance contains." msgstr "" -"Gli strumenti di gestione dei dati integrati in GeoNode consentono la " -"creazione integrata di dati, metadati e visualizzazioni mappa. Ogni set di " -"dati nel sistema può essere condiviso pubblicamente o limitato per " -"consentire l'accesso solo a utenti specifici. Le funzionalità di social " -"networking come i profili utente e i sistemi di commenti e classificazione " -"consentono lo sviluppo di comunità intorno a ogni piattaforma per facilitare " -"l'utilizzo, la gestione e il controllo qualità dei dati contenuti " -"nell'istanza GeoNode." +"Gli strumenti di gestione dei dati integrati in GeoNode consentono la creazione integrata di " +"dati, metadati e visualizzazioni mappa. Ogni set di dati nel sistema può essere condiviso " +"pubblicamente o limitato per consentire l'accesso solo a utenti specifici. Le funzionalità " +"di social networking come i profili utente e i sistemi di commenti e classificazione " +"consentono lo sviluppo di comunità intorno a ogni piattaforma per facilitare l'utilizzo, la " +"gestione e il controllo qualità dei dati contenuti nell'istanza GeoNode." msgid "" -"It is also designed to be a flexible platform that software developers can " -"extend, modify or integrate against to meet requirements in their own " -"applications." +"It is also designed to be a flexible platform that software developers can extend, modify or " +"integrate against to meet requirements in their own applications." msgstr "" -"È inoltre progettato per essere una piattaforma flessibile che gli " -"sviluppatori di software possono estendere, modificare o integrare per " -"soddisfare i requisiti nelle proprie applicazioni." +"È inoltre progettato per essere una piattaforma flessibile che gli sviluppatori di software " +"possono estendere, modificare o integrare per soddisfare i requisiti nelle proprie " +"applicazioni." msgid "Account Inactive" msgstr "Account non attivo" @@ -4907,13 +4616,11 @@ msgstr "Account in attesa di approvazione" #, python-format msgid "" -"We have sent the administrators a notice to approve your account associated " -"with %(email)s. If the account is approved, you will receive a " -"confirmation notice." +"We have sent the administrators a notice to approve your account associated with " +"%(email)s. If the account is approved, you will receive a confirmation notice." msgstr "" -"Abbiamo inviato agli amministratori un avviso per approvare il tuo account " -"associato a %(email)s. Se l'account viene approvato, riceverai un " -"avviso di conferma." +"Abbiamo inviato agli amministratori un avviso per approvare il tuo account associato a " +"%(email)s. Se l'account viene approvato, riceverai un avviso di conferma." msgid "Account" msgstr "Account" @@ -4943,12 +4650,12 @@ msgid "Warning:" msgstr "Avviso:" msgid "" -"You currently do not have any e-mail address set up. You should really add " -"an e-mail address so you can receive notifications, reset your password, etc." +"You currently do not have any e-mail address set up. You should really add an e-mail address " +"so you can receive notifications, reset your password, etc." msgstr "" -"Al momento non è stato impostato alcun indirizzo di posta elettronica. Si " -"dovrebbe davvero aggiungere un indirizzo e-mail in modo da poter ricevere " -"notifiche, reimpostare la password, ecc." +"Al momento non è stato impostato alcun indirizzo di posta elettronica. Si dovrebbe davvero " +"aggiungere un indirizzo e-mail in modo da poter ricevere notifiche, reimpostare la password, " +"ecc." msgid "Add E-mail Address" msgstr "Aggiungi indirizzo e-mail" @@ -4963,15 +4670,15 @@ msgstr "Vuoi davvero rimuovere l'indirizzo e-mail selezionato?" msgid "" "Hello from %(site_name)s!\n" "\n" -"You're receiving this e-mail because user %(user_display)s has given yours " -"as an e-mail address to connect their account.\n" +"You're receiving this e-mail because user %(user_display)s has given yours as an e-mail " +"address to connect their account.\n" "\n" "To confirm this is correct, go to %(activate_url)s\n" msgstr "" "Ciao da %(site_name)s!\n" "\n" -"Ricevi questa e-mail perché utente %(user_display)s ha dato la tua come un " -"indirizzo di posta elettronica per collegare il proprio account.\n" +"Ricevi questa e-mail perché utente %(user_display)s ha dato la tua come un indirizzo di " +"posta elettronica per collegare il proprio account.\n" "\n" "Per confermare che questo è corretto, andare al s %(activate_url)s\n" @@ -4995,8 +4702,7 @@ msgstr "Sei stato invitato a registrarti all'indirizzo %(site_name)s." msgid "Create an account on %(site_name)s" msgstr "Creare un account su %(site_name)s" -msgid "" -"This is the email notification to confirm your password has been changed on" +msgid "This is the email notification to confirm your password has been changed on" msgstr "Questa è la notifica e-mail per confermare che la password è stata" msgid "Change password email notification" @@ -5006,17 +4712,17 @@ msgstr "Modifica password" msgid "" "Hello from %(site_name)s!\n" "\n" -"You're receiving this e-mail because you or someone else has requested a " -"password for your user account.\n" -"It can be safely ignored if you did not request a password reset. Click the " -"link below to reset your password." +"You're receiving this e-mail because you or someone else has requested a password for your " +"user account.\n" +"It can be safely ignored if you did not request a password reset. Click the link below to " +"reset your password." msgstr "" "Ciao da %(site_name)s!\n" "\n" -"Ricevi questa e-mail perché tu o qualcun altro ha richiesto una password per " -"l'account utente.\n" -"Può essere tranquillamente ignorato se non hai richiesto la reimpostazione " -"della password. Clicca sul link qui sotto per reimpostare la password." +"Ricevi questa e-mail perché tu o qualcun altro ha richiesto una password per l'account " +"utente.\n" +"Può essere tranquillamente ignorato se non hai richiesto la reimpostazione della password. " +"Clicca sul link qui sotto per reimpostare la password." #, python-format msgid "In case you forgot, your username is %(username)s." @@ -5039,23 +4745,22 @@ msgstr "Confermare Indirizzo e-Mail" #, python-format msgid "" -"Please confirm that %(email)s is an e-mail " -"address for user %(user_display)s." +"Please confirm that %(email)s is an e-mail address for user " +"%(user_display)s." msgstr "" -"Verificare che %(email)s sia un indirizzo " -"di posta elettronica per l'utente %(user_display)s." +"Verificare che %(email)s sia un indirizzo di posta " +"elettronica per l'utente %(user_display)s." msgid "Confirm" msgstr "Conferma" #, python-format msgid "" -"This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request." +"This e-mail confirmation link expired or is invalid. Please issue " +"a new e-mail confirmation request." msgstr "" -"Questo link di conferma e-mail è scaduto o non è valido. Si prega di " -"emettere una nuova richiesta di conferma e-mail." +"Questo link di conferma e-mail è scaduto o non è valido. Si prega di emettere una nuova " +"richiesta di conferma e-mail." msgid "Log in" msgstr "Entra" @@ -5066,13 +4771,12 @@ msgstr "Effettua il login con un account esistente" #, python-format msgid "" "Please sign in with one\n" -" of your existing third party accounts. Or, sign up\n" +" of your existing third party accounts. Or, sign up\n" " for a %(site_name)s account and sign in below:" msgstr "" "Si prega di accedere con uno\n" -" degli account di terze parti esistenti. In alternativa, iscriviti\n" +" degli account di terze parti esistenti. In alternativa, iscriviti\n" " per un account %(site_name)s e accedere di seguito:" msgid "or" @@ -5116,32 +4820,27 @@ msgstr "Reimposta password" msgid "Forgotten your password?" msgstr "Hai dimenticato la password?" -msgid "" -"Enter your email address below, and we'll send you an email allowing you to " -"reset it." +msgid "Enter your email address below, and we'll send you an email allowing you to reset it." msgstr "" -"Inserisci sotto il tuo indirizzo email e ti spediremo un'email per " -"permetterti di cambiare la password." +"Inserisci sotto il tuo indirizzo email e ti spediremo un'email per permetterti di cambiare " +"la password." msgid "Reset my password" msgstr "Reimposta la mia password" #, python-format msgid "" -"If you have any trouble resetting your password, contact us at %(THEME_ACCOUNT_CONTACT_EMAIL)s." +"If you have any trouble resetting your password, contact us at %(THEME_ACCOUNT_CONTACT_EMAIL)s." msgstr "" -"Se hai dei problemi nel reimpostare la password, contattaci a %(THEME_ACCOUNT_CONTACT_EMAIL)s." +"Se hai dei problemi nel reimpostare la password, contattaci a %(THEME_ACCOUNT_CONTACT_EMAIL)s." msgid "" -"We have sent you an e-mail. Please contact us if you do not receive it " -"within a few minutes." +"We have sent you an e-mail. Please contact us if you do not receive it within a few minutes." msgstr "" -"Vi abbiamo inviato un'e-mail. Vi preghiamo di contattarci se non lo ricevete " -"entro pochi minuti." +"Vi abbiamo inviato un'e-mail. Vi preghiamo di contattarci se non lo ricevete entro pochi " +"minuti." msgid "Change Password" msgstr "Cambia Password" @@ -5151,13 +4850,12 @@ msgstr "Token non valido" #, python-format msgid "" -"The password reset link was invalid, possibly because it has already been " -"used. Please request a new password reset." +"The password reset link was invalid, possibly because it has already been used. Please " +"request a new password reset." msgstr "" -"Il collegamento per la reimpostazione della password non è valido, " -"probabilmente perché è già stato utilizzato. Si prega di richiedere una nuova reimpostazione della password." +"Il collegamento per la reimpostazione della password non è valido, probabilmente perché è " +"già stato utilizzato. Si prega di richiedere una nuova " +"reimpostazione della password." msgid "change password" msgstr "modifica password" @@ -5208,13 +4906,11 @@ msgstr "Verificare l'indirizzo di posta elettronica" msgid "" "We have sent an email to you for verification. Follow the\n" -" link provided to finalize the signup process. Please contact us if you " -"do\n" +" link provided to finalize the signup process. Please contact us if you do\n" " not receive it within a few minutes" msgstr "" "We have sent an email to you for verification. Follow the\n" -" link provided to finalize the signup process. Please contact us if you " -"do\n" +" link provided to finalize the signup process. Please contact us if you do\n" " not receive it within a few minutes" msgid "Verify Your E-mail Address" @@ -5235,17 +4931,16 @@ msgid "" "contact us if you do not receive it within a few minutes." msgstr "" "Vi abbiamo inviato un'e-mail per\n" -"verifica. Si prega di fare clic sul link all'interno di questa e-mail. per " -"favore\n" +"verifica. Si prega di fare clic sul link all'interno di questa e-mail. per favore\n" "contattarci se non lo ricevi entro pochi minuti." #, python-format msgid "" -"Note: you can still change your e-" -"mail address." +"Note: you can still change your e-mail address." msgstr "" -"Nota: è comunque possibile modificare l'indirizzo e-mail." +"Nota: è comunque possibile modificare l'indirizzo " +"e-mail." msgid "My Activity feed" msgstr "Il mio feed attività" @@ -5292,13 +4987,11 @@ msgstr "Pubblicato da" #, python-format msgid "" "\n" -" Published from %(publish_start)s to %(publish_end)s.\n" +" Published from %(publish_start)s to %(publish_end)s.\n" " " msgstr "" "\n" -" Pubblicato da %(publish_start)s per %(publish_end)s.\n" +" Pubblicato da %(publish_start)s per %(publish_end)s.\n" " " #, python-format @@ -5328,14 +5021,13 @@ msgstr "Si prega di selezionare gli avatar che si desidera eliminare." #, python-format msgid "" -"You have no avatars to delete. Please upload one now." +"You have no avatars to delete. Please upload one now." msgstr "" -"Non ci sono gli avatar da eliminare. Si prega di caricare un ora." +"Non ci sono gli avatar da eliminare. Si prega di caricare " +"un ora." msgid "Delete These" -msgstr "Cancella questi" +msgstr "Elimina questi" msgid "GeoNode Search" msgstr "Ricerca GeoNode" @@ -5361,10 +5053,8 @@ msgstr "Aggiornamento Miniatura..." msgid "Message. Do you want to proceed?" msgstr "Sei sicuro di voler procedere?" -#, fuzzy -#| msgid "Harvesting resources..." msgid "Processing Resource..." -msgstr "Inserimento risorse..." +msgstr "Processamento risorse..." msgid "Information for Developers" msgstr "Informazioni per gli sviluppatori" @@ -5375,160 +5065,141 @@ msgstr "Informazioni utili per gli sviluppatori interessati a GeoNode." #, fuzzy, python-format #| msgid "" #| "\n" -#| "

GeoNode is an open service " -#| "built on open source software. We encourage you to build new applications " -#| "using the components and resources it provides. This page is a starting " -#| "point for developers interesting in taking full advantage of GeoNode. It " -#| "also includes links to the project's source code so anyone can build and " -#| "customize their own GeoNode.

\n" +#| "

GeoNode is an open service built on open " +#| "source software. We encourage you to build new applications using the components and " +#| "resources it provides. This page is a starting point for developers interesting in taking " +#| "full advantage of GeoNode. It also includes links to the project's source code so anyone " +#| "can build and customize their own GeoNode.

\n" #| "\n" #| "

GeoNode Software

\n" #| "\n" -#| "

All the code that runs GeoNode is open source. The code is " -#| "available at http://github." -#| "com/GeoNode/geonode/. The issue tracker for the project is at http://github.com/GeoNode/" -#| "geonode/issues.

\n" +#| "

All the code that runs GeoNode is open source. The code is available at http://github.com/GeoNode/geonode/. The " +#| "issue tracker for the project is at http://github.com/GeoNode/geonode/issues.

\n" #| "\n" -#| "

GeoNode is built using several open source projects, each with its " -#| "own community. If you are interested in contributing new features to the " -#| "GeoNode, we encourage you to do so by contributing to one of the projects " -#| "on which it is built:

\n" +#| "

GeoNode is built using several open source projects, each with its own community. " +#| "If you are interested in contributing new features to the GeoNode, we encourage you to do " +#| "so by contributing to one of the projects on which it is built:

\n" #| "
    \n" -#| "
  • GeoServer - Standards " -#| "based server for geospatial information
  • \n" -#| "
  • GeoWebCache - Cache " -#| "engine for WMS Tiles
  • OpenLayers - Pure JavaScript library powering the maps of GeoExt\n" -#| "
  • pycsw - CSW, OpenSearch and " -#| "OAI-PMH metadata catalogue server
  • \n" +#| "
  • GeoServer - Standards based server for " +#| "geospatial information
  • \n" +#| "
  • GeoWebCache - Cache engine for WMS " +#| "Tiles
  • OpenLayers - Pure JavaScript library " +#| "powering the maps of GeoExt
  • \n" +#| "
  • pycsw - CSW, OpenSearch and OAI-PMH metadata " +#| "catalogue server
  • \n" #| "
\n" #| "\n" #| "

What are OGC Services?

\n" -#| "

The data in this application is served using open standards " -#| "endorsed by ISO and the Open " -#| "Geospatial Consortium; in particular, WMS (Web Map Service) is used " -#| "for accessing maps, WFS (Web Feature Service) is used for accessing " -#| "vector data, and WCS (Web Coverage Service) is used for accessing raster " -#| "data. WMC (Web Map Context Documents) is used for sharing maps. You can " -#| "use these services in your own applications using libraries such as " -#| "OpenLayers, GeoTools, and OGR (all of which are open-source software and " -#| "available at zero cost). Additionally, CSW (Catalog Service for the Web) " -#| "supports access to collections of descriptive information (metadata) " -#| "about data and services.

\n" +#| "

The data in this application is served using open standards endorsed by ISO and " +#| "the Open Geospatial Consortium; in particular, " +#| "WMS (Web Map Service) is used for accessing maps, WFS (Web Feature Service) is used for " +#| "accessing vector data, and WCS (Web Coverage Service) is used for accessing raster data. " +#| "WMC (Web Map Context Documents) is used for sharing maps. You can use these services in " +#| "your own applications using libraries such as OpenLayers, GeoTools, and OGR (all of which " +#| "are open-source software and available at zero cost). Additionally, CSW (Catalog Service " +#| "for the Web) supports access to collections of descriptive information (metadata) about " +#| "data and services.

\n" #| "\n" #| "

What is GeoWebCache?

\n" -#| "

GeoWebCache provides mapping tiles that are compatible with a " -#| "number of mapping engines, including Google Maps, Bing Maps and " -#| "OpenLayers. All the data hosted by GeoNode is also available through " -#| "GeoWebCache. GeoWebCache improves on WMS by caching data and providing " -#| "more responsive maps.

\n" +#| "

GeoWebCache provides mapping tiles that are compatible with a number of mapping " +#| "engines, including Google Maps, Bing Maps and OpenLayers. All the data hosted by GeoNode " +#| "is also available through GeoWebCache. GeoWebCache improves on WMS by caching data and " +#| "providing more responsive maps.

\n" #| "\n" #| "

CSW Example Code

\n" -#| "

To interact with GeoNode's CSW you can use any CSW client (QGIS " -#| "MetaSearch, GRASS, etc.). The following example illustrates a simple " -#| "invocation using the OWSLib Python package:

\n" +#| "

To interact with GeoNode's CSW you can use any CSW client (QGIS MetaSearch, GRASS, " +#| "etc.). The following example illustrates a simple invocation using the OWSLib Python " +#| "package:

\n" #| "

from owslib.csw import CatalogueServiceWeb

\n" #| "

from owslib.fes import PropertyIsLike

\n" -#| "

csw = CatalogueServiceWeb('%(CATALOGUE_BASE_URL)s')\n" -#| "

anytext = PropertyIsLike('csw:AnyText', 'birds')')\n" +#| "

csw = CatalogueServiceWeb('%(CATALOGUE_BASE_URL)s')

\n" +#| "

anytext = PropertyIsLike('csw:AnyText', 'birds')')

\n" #| "

csw.getrecords2(constraints=[anytext])

\n" #| "

print csw.results

\n" #| "

print csw.records

\n" #| "\n" #| "

OpenLayers Example Code

\n" #| "\n" -#| "

To include a GeoNode map layer in an OpenLayers map, first find " -#| "the name for that layer. This is found in the layer's name " -#| "field (not title) of the layer list. For this example, we " -#| "will use the Nicaraguan political boundaries background layer, whose name " -#| "is risk:nicaragua_admin. Then, create an instance of " -#| "OpenLayers.Layer.WMS:

\n" -#| "

var geonodeLayer = new OpenLayers.Layer.WMS(\"GeoNode Risk " -#| "Data\", \"http://demo.geonode.org/geoserver/wms\",{ layers: \"risk:" -#| "nicaragua_admin\" });

\n" +#| "

To include a GeoNode map layer in an OpenLayers map, first find the name for that " +#| "layer. This is found in the layer's name field (not title) of " +#| "the layer list. For this example, we will use the Nicaraguan political boundaries " +#| "background layer, whose name is risk:nicaragua_admin. Then, create an " +#| "instance of OpenLayers.Layer.WMS:

\n" +#| "

var geonodeLayer = new OpenLayers.Layer.WMS(\"GeoNode Risk Data\", \"http://" +#| "demo.geonode.org/geoserver/wms\",{ layers: \"risk:nicaragua_admin\" });

\n" #| "\n" #| "

Google Maps Example Code

\n" -#| "

To include a GeoNode map layer in a Google Map, include the layer " -#| "namein the URL template.

\n" -#| "

var tilelayer = new GTileLayer(null, null, null, " -#| "{tileUrlTemplate: 'http://demo.geonode.org/geoserver/gwc/service/gmaps?" -#| "layers=risk:nicaragua_admin&zoom={Z}&x={X}&y={Y}', isPng:" -#| "true, opacity:0.5 } );

\n" +#| "

To include a GeoNode map layer in a Google Map, include the layer namein the URL " +#| "template.

\n" +#| "

var tilelayer = new GTileLayer(null, null, null, {tileUrlTemplate: 'http://" +#| "demo.geonode.org/geoserver/gwc/service/gmaps?layers=risk:nicaragua_admin&zoom={Z}&" +#| "x={X}&y={Y}', isPng:true, opacity:0.5 } );

\n" #| "\n" #| "

Shapefile/GeoJSON/GML Output

\n" -#| "

To get data from the GeoNode web services use the WFS protocol. " -#| "For example, to get the full Nicaraguan admin boundaries use:

\n" -#| "

http://demo.geonode.org/geoserver/wfs?request=GetFeature&" -#| "typeName=risk:nicaragua_admin&outputformat=SHAPE-ZIP

\n" -#| "

Changing output format to json, GML2, " -#| "GML3, or csv will get data in those formats. " -#| "The WFS protocol also can handle more precise queries, specifying a " -#| "bounding box or various spatial and non-spatial filters based on the " -#| "attributes of the data.

\n" +#| "

To get data from the GeoNode web services use the WFS protocol. For example, to " +#| "get the full Nicaraguan admin boundaries use:

\n" +#| "

http://demo.geonode.org/geoserver/wfs?request=GetFeature&typeName=risk:" +#| "nicaragua_admin&outputformat=SHAPE-ZIP

\n" +#| "

Changing output format to json, GML2, GML3, " +#| "or csv will get data in those formats. The WFS protocol also can handle more " +#| "precise queries, specifying a bounding box or various spatial and non-spatial filters " +#| "based on the attributes of the data.

\n" #| "\n" #| "

GeoTools Example Code

\n" -#| "

Create a DataStore and extract a FeatureType from it, then run a " -#| "Query. It is all documented on the wiki at http://geotools.org/.

\n" +#| "

Create a DataStore and extract a FeatureType from it, then run a Query. It is all " +#| "documented on the wiki at http://geotools.org/.

\n" #| " " msgid "" "\n" -"

GeoNode is an open service built " -"on open source software. We encourage you to build new applications using " -"the components and resources it provides. This page is a starting point for " -"developers interesting in taking full advantage of GeoNode. It also includes " -"links to the project's source code so anyone can build and customize their " -"own GeoNode.

\n" +"

GeoNode is an open service built on open source " +"software. We encourage you to build new applications using the components and resources it " +"provides. This page is a starting point for developers interesting in taking full advantage " +"of GeoNode. It also includes links to the project's source code so anyone can build and " +"customize their own GeoNode.

\n" "\n" "

GeoNode Software

\n" "\n" -"

All the code that runs GeoNode is open source. The code is available " -"at http://github.com/GeoNode/" -"geonode/. The issue tracker for the project is at http://github.com/GeoNode/geonode/" -"issues.

\n" +"

All the code that runs GeoNode is open source. The code is available at http://github.com/GeoNode/geonode/. The issue " +"tracker for the project is at http://" +"github.com/GeoNode/geonode/issues.

\n" "\n" -"

GeoNode is built using several open source projects, each with its " -"own community. If you are interested in contributing new features to the " -"GeoNode, we encourage you to do so by contributing to one of the projects on " -"which it is built:

\n" +"

GeoNode is built using several open source projects, each with its own community. If " +"you are interested in contributing new features to the GeoNode, we encourage you to do so by " +"contributing to one of the projects on which it is built:

\n" "
    \n" -"
  • GeoServer - Standards based " -"server for geospatial information
  • \n" -"
  • GeoWebCache - Cache engine " -"for WMS Tiles
  • OpenLayers - " -"Pure JavaScript library powering the maps of GeoExt
  • \n" -"
  • pycsw - CSW, OpenSearch and OAI-" -"PMH metadata catalogue server
  • \n" +"
  • GeoServer - Standards based server for " +"geospatial information
  • \n" +"
  • GeoWebCache - Cache engine for WMS Tiles
  • OpenLayers - Pure JavaScript library powering " +"the maps of GeoExt
  • \n" +"
  • pycsw - CSW, OpenSearch and OAI-PMH metadata " +"catalogue server
  • \n" "
\n" "\n" "

What are OGC Services?

\n" -"

The data in this application is served using open standards endorsed " -"by ISO and the Open Geospatial " -"Consortium; in particular, WMS (Web Map Service) is used for accessing " -"maps, WFS (Web Feature Service) is used for accessing vector data, and WCS " -"(Web Coverage Service) is used for accessing raster data. WMC (Web Map " -"Context Documents) is used for sharing maps. You can use these services in " -"your own applications using libraries such as OpenLayers, GeoTools, and OGR " -"(all of which are open-source software and available at zero cost). " -"Additionally, CSW (Catalog Service for the Web) supports access to " -"collections of descriptive information (metadata) about data and services.\n" +"

The data in this application is served using open standards endorsed by ISO and the " +"Open Geospatial Consortium; in particular, WMS " +"(Web Map Service) is used for accessing maps, WFS (Web Feature Service) is used for " +"accessing vector data, and WCS (Web Coverage Service) is used for accessing raster data. " +"WMC (Web Map Context Documents) is used for sharing maps. You can use these services in your " +"own applications using libraries such as OpenLayers, GeoTools, and OGR (all of which are " +"open-source software and available at zero cost). Additionally, CSW (Catalog Service for the " +"Web) supports access to collections of descriptive information (metadata) about data and " +"services.

\n" "\n" "

What is GeoWebCache?

\n" -"

GeoWebCache provides mapping tiles that are compatible with a number " -"of mapping engines, including Google Maps, Bing Maps and OpenLayers. All the " -"data hosted by GeoNode is also available through GeoWebCache. GeoWebCache " -"improves on WMS by caching data and providing more responsive maps.

\n" +"

GeoWebCache provides mapping tiles that are compatible with a number of mapping " +"engines, including Google Maps, Bing Maps and OpenLayers. All the data hosted by GeoNode is " +"also available through GeoWebCache. GeoWebCache improves on WMS by caching data and " +"providing more responsive maps.

\n" "\n" "

CSW Example Code

\n" -"

To interact with GeoNode's CSW you can use any CSW client (QGIS " -"MetaSearch, GRASS, etc.). The following example illustrates a simple " -"invocation using the OWSLib Python package:

\n" +"

To interact with GeoNode's CSW you can use any CSW client (QGIS MetaSearch, GRASS, " +"etc.). The following example illustrates a simple invocation using the OWSLib Python " +"package:

\n" "

from owslib.csw import CatalogueServiceWeb

\n" "

from owslib.fes import PropertyIsLike

\n" "

csw = CatalogueServiceWeb('%(CATALOGUE_BASE_URL)s')

\n" @@ -5539,95 +5210,84 @@ msgid "" "\n" "

OpenLayers Example Code

\n" "\n" -"

To include a GeoNode map layer in an OpenLayers map, first find the " -"name for that layer. This is found in the layer's name field " -"(not title) of the layer list. For this example, we will use " -"the Nicaraguan political boundaries background layer, whose name is " -"risk:nicaragua_admin. Then, create an instance of OpenLayers." -"Layer.WMS:

\n" -"

var geonodeLayer = new OpenLayers.Layer.WMS(\"GeoNode Risk Data" -"\", \"http://demo.geonode.org/geoserver/wms\",{ layers: \"risk:" -"nicaragua_admin\" });

\n" +"

To include a GeoNode map layer in an OpenLayers map, first find the name for that " +"layer. This is found in the layer's name field (not title) of the " +"layer list. For this example, we will use the Nicaraguan political boundaries background " +"layer, whose name is risk:nicaragua_admin. Then, create an instance of " +"OpenLayers.Layer.WMS:

\n" +"

var geonodeLayer = new OpenLayers.Layer.WMS(\"GeoNode Risk Data\", \"http://" +"demo.geonode.org/geoserver/wms\",{ layers: \"risk:nicaragua_admin\" });

\n" "\n" "

Google Maps Example Code

\n" -"

To include a GeoNode map layer in a Google Map, include the dataset " -"name in the URL template.

\n" -"

var tilelayer = new GTileLayer(null, null, null, " -"{tileUrlTemplate: 'http://demo.geonode.org/geoserver/gwc/service/gmaps?" -"layers=risk:nicaragua_admin&zoom={Z}&x={X}&y={Y}', isPng:true, " -"opacity:0.5 } );

\n" +"

To include a GeoNode map layer in a Google Map, include the dataset name in the URL " +"template.

\n" +"

var tilelayer = new GTileLayer(null, null, null, {tileUrlTemplate: 'http://" +"demo.geonode.org/geoserver/gwc/service/gmaps?layers=risk:nicaragua_admin&zoom={Z}&" +"x={X}&y={Y}', isPng:true, opacity:0.5 } );

\n" "\n" "

Shapefile/GeoJSON/GML Output

\n" -"

To get data from the GeoNode web services use the WFS protocol. For " -"example, to get the full Nicaraguan admin boundaries use:

\n" -"

http://demo.geonode.org/geoserver/wfs?request=GetFeature&" -"typeName=risk:nicaragua_admin&outputformat=SHAPE-ZIP

\n" -"

Changing output format to json, GML2, " -"GML3, or csv will get data in those formats. The " -"WFS protocol also can handle more precise queries, specifying a bounding box " -"or various spatial and non-spatial filters based on the attributes of the " -"data.

\n" +"

To get data from the GeoNode web services use the WFS protocol. For example, to get " +"the full Nicaraguan admin boundaries use:

\n" +"

http://demo.geonode.org/geoserver/wfs?request=GetFeature&typeName=risk:" +"nicaragua_admin&outputformat=SHAPE-ZIP

\n" +"

Changing output format to json, GML2, GML3, or " +"csv will get data in those formats. The WFS protocol also can handle more " +"precise queries, specifying a bounding box or various spatial and non-spatial filters based " +"on the attributes of the data.

\n" "\n" "

GeoTools Example Code

\n" -"

Create a DataStore and extract a FeatureType from it, then run a " -"Query. It is all documented on the wiki at http://geotools.org/." -"

\n" +"

Create a DataStore and extract a FeatureType from it, then run a Query. It is all " +"documented on the wiki at http://geotools.org/.

\n" " " msgstr "" "\n" -"

GeoNode è un servizio aperto " -"costruito su software open source. Vi incoraggiamo a costruire nuove " -"applicazioni utilizzando i componenti e le risorse che fornisce. Questa " -"pagina è un punto di partenza per gli sviluppatori interessati a trarre il " -"massimo vantaggio da GeoNode. Include anche link al codice sorgente del " -"progetto in modo che chiunque possa costruire e personalizzare il proprio " -"GeoNode.

\n" +"

GeoNode è un servizio aperto costruito su " +"software open source. Vi incoraggiamo a costruire nuove applicazioni utilizzando i " +"componenti e le risorse che fornisce. Questa pagina è un punto di partenza per gli " +"sviluppatori interessati a trarre il massimo vantaggio da GeoNode. Include anche link al " +"codice sorgente del progetto in modo che chiunque possa costruire e personalizzare il " +"proprio GeoNode.

\n" "\n" "

GeoNode Software

\n" "\n" -"

Tutto il codice che esegue GeoNode è open source. Il codice è " -"disponibile all'indirizzo http://github.com/GeoNode/geonode/. Il issue tracker per il progetto " -"è disponibile all'indirizzo http://github.com/GeoNode/geonode/issues.

\n" -"

GeoNode è costruito utilizzando diversi progetti open source, ognuno " -"con la propria comunità. Se siete interessati a contribuire con nuove " -"funzionalità al GeoNode, vi invitiamo a farlo contribuendo ad uno dei " -"progetti su cui è costruito:

\n" +"

Tutto il codice che esegue GeoNode è open source. Il codice è disponibile " +"all'indirizzo http://github.com/GeoNode/" +"geonode/. Il issue tracker per il progetto è disponibile all'indirizzo http://github.com/GeoNode/geonode/issues.

\n" +"

GeoNode è costruito utilizzando diversi progetti open source, ognuno con la propria " +"comunità. Se siete interessati a contribuire con nuove funzionalità al GeoNode, vi invitiamo " +"a farlo contribuendo ad uno dei progetti su cui è costruito:

\n" "
    \n" -"
  • GeoServer - Server basato su " -"standard per informazioni geospaziali
  • \n" -"
  • GeoWebCache - Motore di " -"cache per WMS Tiles
  • OpenLayers " -"- Pura libreria JavaScript che alimenta le mappe di GeoExt
  • \n" -"
  • pycsw - CSW, OpenSearch e OAI-PMH " -"metadata catalogue server
  • \n" +"
  • GeoServer - Server basato su standard per " +"informazioni geospaziali
  • \n" +"
  • GeoWebCache - Motore di cache per WMS " +"Tiles
  • OpenLayers - Pura libreria JavaScript " +"che alimenta le mappe di GeoExt
  • \n" +"
  • pycsw - CSW, OpenSearch e OAI-PMH metadata " +"catalogue server
  • \n" "
\n" "\n" "

Che cosa sono i servizi OGC?

\n" -"

I dati in questa applicazione sono serviti utilizzando standard " -"aperti approvati dall'ISO e dal Open " -"Geospatial Consortium; in particolare, il WMS (Web Map Service) è " -"utilizzato per l'accesso alle mappe, il WFS (Web Feature Service) è " -"utilizzato per l'accesso ai dati vettoriali, e il WCS (Web Coverage Service) " -"è utilizzato per l'accesso ai dati raster. Il WMC (Web Map Context " -"Documents) viene utilizzato per la condivisione delle mappe. Questi servizi " -"possono essere utilizzati nelle proprie applicazioni utilizzando librerie " -"come OpenLayers, GeoTools e OGR (tutti software open-source e disponibili a " -"costo zero). Inoltre, CSW (Catalog Service for the Web) supporta l'accesso a " -"raccolte di informazioni descrittive (metadati) su dati e servizi.

\n" +"

I dati in questa applicazione sono serviti utilizzando standard aperti approvati " +"dall'ISO e dal Open Geospatial Consortium; in " +"particolare, il WMS (Web Map Service) è utilizzato per l'accesso alle mappe, il WFS (Web " +"Feature Service) è utilizzato per l'accesso ai dati vettoriali, e il WCS (Web Coverage " +"Service) è utilizzato per l'accesso ai dati raster. Il WMC (Web Map Context Documents) " +"viene utilizzato per la condivisione delle mappe. Questi servizi possono essere utilizzati " +"nelle proprie applicazioni utilizzando librerie come OpenLayers, GeoTools e OGR (tutti " +"software open-source e disponibili a costo zero). Inoltre, CSW (Catalog Service for the Web) " +"supporta l'accesso a raccolte di informazioni descrittive (metadati) su dati e servizi.

\n" "\n" "

Che cos'è GeoWebCache?

\n" -"

GeoWebCache fornisce tiles di mappatura compatibili con una serie di " -"motori di mappatura, tra cui Google Maps, Bing Maps e OpenLayers. Tutti i " -"dati ospitati da GeoNode sono disponibili anche attraverso GeoWebCache. " -"GeoWebCache migliora il WMS mettendo in cache i dati e fornendo mappe più " -"reattive.

\n" +"

GeoWebCache fornisce tiles di mappatura compatibili con una serie di motori di " +"mappatura, tra cui Google Maps, Bing Maps e OpenLayers. Tutti i dati ospitati da GeoNode " +"sono disponibili anche attraverso GeoWebCache. GeoWebCache migliora il WMS mettendo in cache " +"i dati e fornendo mappe più reattive.

\n" "\n" "

CSW Codice d'esempio

\n" -"

Per interagire con il CSW di GeoNode è possibile utilizzare qualsiasi " -"client CSW (QGIS MetaSearch, GRASS, ecc.). Il seguente esempio illustra una " -"semplice invocazione utilizzando il pacchetto Python di OWSLib:

\n" +"

Per interagire con il CSW di GeoNode è possibile utilizzare qualsiasi client CSW " +"(QGIS MetaSearch, GRASS, ecc.). Il seguente esempio illustra una semplice invocazione " +"utilizzando il pacchetto Python di OWSLib:

\n" "

from owslib.csw import CatalogueServiceWeb

\n" "

from owslib.fes import PropertyIsLike

\n" "

csw = CatalogueServiceWeb('%(CATALOGUE_BASE_URL)s')

\n" @@ -5638,39 +5298,33 @@ msgstr "" "\n" "

Codice d'esempio OpenLayers

\n" "\n" -"

Per includere un livello di mappa GeoNode in una mappa OpenLayers, " -"trovare prima il nome di quel livello. Questo si trova nel campo nome del livello (non titolo) della lista dei livelli. Per " -"questo esempio, useremo il livello di sfondo dei confini politici del " -"Nicaragua, il cui nome è risk:nicaragua_admin. Quindi, creare " -"un'istanza di OpenLayers.Layer.WMS:

\n" -"

var geonodeLayer = new OpenLayers.Layer.WMS(\"GeoNode Risk Data" -"\", \"http://demo.geonode.org/geoserver/wms\",{ strati: \"risk:" -"nicaragua_admin\" });

\n" +"

Per includere un livello di mappa GeoNode in una mappa OpenLayers, trovare prima il " +"nome di quel livello. Questo si trova nel campo nome del livello (non " +"titolo) della lista dei livelli. Per questo esempio, useremo il livello di " +"sfondo dei confini politici del Nicaragua, il cui nome è risk:nicaragua_admin. " +"Quindi, creare un'istanza di OpenLayers.Layer.WMS:

\n" +"

var geonodeLayer = new OpenLayers.Layer.WMS(\"GeoNode Risk Data\", \"http://" +"demo.geonode.org/geoserver/wms\",{ strati: \"risk:nicaragua_admin\" });

\n" "\n" "

Codice di esempio di Google Maps

\n" -"

Per includere un livello di mappa GeoNode in una Google Map, " -"includere il nome del livello nel modello URL.

\n" -"

var tilelayer = new GTileLayer(null, null, null, null, " -"{tileUrlTemplate: 'http://demo.geonode.org/geoserver/gwc/service/gmaps?" -"layers=risk:nicaragua_admin&zoom={Z}&x={X}&y={Y}', isPng:true, " -"opacity:0.5 }', isPng:true, opacity:0.5 }. );

\n" +"

Per includere un livello di mappa GeoNode in una Google Map, includere il nome del " +"livello nel modello URL.

\n" +"

var tilelayer = new GTileLayer(null, null, null, null, {tileUrlTemplate: " +"'http://demo.geonode.org/geoserver/gwc/service/gmaps?layers=risk:nicaragua_admin&zoom={Z}" +"&x={X}&y={Y}', isPng:true, opacity:0.5 }', isPng:true, opacity:0.5 }. );

\n" "\n" "

Formafile/GeoJSON/GML Output

\n" -"

Per ottenere dati dai servizi web GeoNode utilizzare il protocollo " -"WFS. Per esempio, per ottenere i confini amministrativi completi del " -"Nicaragua usare:

\n" -"

http://demo.geonode.org/geoserver/wfs?request=GetFeature&" -"typeName=rischio:nicaragua_admin&outputformat=SHAPE-ZIP

\n" -"

Cambiando il formato di uscita in json, GML2, GML3, o csv si ottengono dati in questi " -"formati. Il protocollo WFS può anche gestire query più precise, specificando " -"un bounding box o vari filtri spaziali e non spaziali in base agli attributi " -"dei dati.

\n" +"

Per ottenere dati dai servizi web GeoNode utilizzare il protocollo WFS. Per esempio, " +"per ottenere i confini amministrativi completi del Nicaragua usare:

\n" +"

http://demo.geonode.org/geoserver/wfs?request=GetFeature&typeName=rischio:" +"nicaragua_admin&outputformat=SHAPE-ZIP

\n" +"

Cambiando il formato di uscita in json, GML2, GML3, o csv si ottengono dati in questi formati. Il protocollo WFS può anche " +"gestire query più precise, specificando un bounding box o vari filtri spaziali e non " +"spaziali in base agli attributi dei dati.

\n" "

Codice d'esempio di GeoTools

\n" -"

Creare un DataStore ed estrarre un FeatureType da esso, quindi " -"eseguire una query. È tutto documentato sul wiki all'indirizzo http://" -"geotools.org/.

\n" +"

Creare un DataStore ed estrarre un FeatureType da esso, quindi eseguire una query. È " +"tutto documentato sul wiki all'indirizzo http://geotools.org/.

\n" " " msgid "GeoNode's Web Services" @@ -5707,86 +5361,79 @@ msgid "GeoNode Help" msgstr "Aiuto su GeoNode" msgid "" -"This page provides helpful information about how to use the GeoNode. You can " -"use the sidebar links to navigate to what you want to know." +"This page provides helpful information about how to use the GeoNode. You can use the sidebar " +"links to navigate to what you want to know." msgstr "" -"Questa pagina fornisce informazioni di aiuto sull'utilizzo di GeoNode. Puoi " -"utilizzare i collegamenti nella barra laterale per ricercare quello che ti " -"interessa." +"Questa pagina fornisce informazioni di aiuto sull'utilizzo di GeoNode. Puoi utilizzare i " +"collegamenti nella barra laterale per ricercare quello che ti interessa." msgid "" "\n" -"

The GeoNode provides access to data sets and a map editing " -"application allows users to browse existing maps and contribute their own.\n" +"

The GeoNode provides access to data sets and a map editing application allows users " +"to browse existing maps and contribute their own.

\n" "\n" "

Browsing Layers

\n" "

The Layers tab allows you to browse data " "uploaded to this GeoNode.

\n" -"

All data can be downloaded in a variety of formats, for use in other " -"applications.

\n" +"

All data can be downloaded in a variety of formats, for use in other applications.\n" "\n" "

Developer Access

\n" -"

The Developer page is the place for " -"developers to get started building applications against the GeoNode. It " -"includes instructions on using the web services, links to the source code of " -"the GeoNode, and information about the open source projects used to create " -"it.

\n" +"

The Developer page is the place for developers " +"to get started building applications against the GeoNode. It includes instructions on using " +"the web services, links to the source code of the GeoNode, and information about the open " +"source projects used to create it.

\n" "\n" "

Browsing Maps

\n" -"

The GeoNode allows users to create and share maps with one another.\n" +"

The GeoNode allows users to create and share maps with one another.

\n" "

The Maps tab is a gateway to map exploration on " -"GeoNode. From here you can search for a map or " -"create a map, which will open the Map " -"Composer.

\n" +"GeoNode. From here you can search for a map or create a map, which will open the Map Composer.

\n" "
Google Earth Mode
\n" -"

Any map viewed in the interactive map editor can be seen in 3D mode " -"with the Google Earth plugin. To switch to 3D mode select the Google Earth " -"globe logo, the rightmost button on top toolbar. If you do not have the " -"Google Earth plugin installed you will be prompted to install it.

\n" +"

Any map viewed in the interactive map editor can be seen in 3D mode with the Google " +"Earth plugin. To switch to 3D mode select the Google Earth globe logo, the rightmost button " +"on top toolbar. If you do not have the Google Earth plugin installed you will be prompted to " +"install it.

\n" "\n" "

Creating a Map

\n" "

To create a new map go to the Contributed Maps " "tab and click the create your own map link.

\n" -"

This will take you to the Map Composer with " -"a base layer loaded.

\n" -"

To add data layers from the GeoNode click on the green plus button " -"located below the layers tab on the left hand side of the screen. This will " -"open a dialog listing all the layers available on the GeoNode.

\n" -"

To add layers to your map select them and hit the Add Layers button. When finished you may hit Done to close the " -"dialog and go back to the map.

\n" +"

This will take you to the Map Composer with a base " +"layer loaded.

\n" +"

To add data layers from the GeoNode click on the green plus button located below the " +"layers tab on the left hand side of the screen. This will open a dialog listing all the " +"layers available on the GeoNode.

\n" +"

To add layers to your map select them and hit the Add Layers button. " +"When finished you may hit Done to close the dialog and go back to the map.\n" "\n" "

Reordering and Removing Layers
\n" -"

Change the display order of the layers listed in the data tab by " -"simply dragging and dropping their names. The order in the map will be " -"updated to reflect that. To turn a layer's visibility off simply uncheck it, " -"and to remove it entirely select it and hit the red minus button.

\n" +"

Change the display order of the layers listed in the data tab by simply dragging and " +"dropping their names. The order in the map will be updated to reflect that. To turn a " +"layer's visibility off simply uncheck it, and to remove it entirely select it and hit the " +"red minus button.

\n" "\n" "
Saving your map
\n" -"

Once a suitable set of layers and zoom level has been found it's time " -"to save it so others can see it. Click the Save button--the left most icon " -"on the top toolbar, an image of a map with a disk--on the top menu and fill " -"out the title and abstract of the map.

\n" +"

Once a suitable set of layers and zoom level has been found it's time to save it so " +"others can see it. Click the Save button--the left most icon on the top toolbar, an image " +"of a map with a disk--on the top menu and fill out the title and abstract of the map.

\n" "\n" "

Publishing a Map

\n" -"

Any map from the GeoNode can be embedded for use in another site or " -"blog. To publish a map:

\n" +"

Any map from the GeoNode can be embedded for use in another site or blog. To publish " +"a map:

\n" "
    \n" -"
  1. Select the from the list of maps on the community or map page and " -"then hit the 'Publish map' button.
  2. \n" -"
  3. Choose your desired height and width for the widget in the wizard." -"
  4. \n" -"
  5. Copy the HTML snippet provided in the wizard to any HTML page or " -"iFrame-supporting blog post.
  6. \n" +"
  7. Select the from the list of maps on the community or map page and then hit the " +"'Publish map' button.
  8. \n" +"
  9. Choose your desired height and width for the widget in the wizard.
  10. \n" +"
  11. Copy the HTML snippet provided in the wizard to any HTML page or iFrame-supporting " +"blog post.
  12. \n" "
\n" -"

This will put an interactive widget showing you map in your web page " -"or blog post.

\n" -"

Note that the Map Composer also has a " -"button to publish the map. Just be sure to save the map before publishing if " -"there are changes that you want others to see. It publishes the last saved " -"version, not the last viewed version.

\n" +"

This will put an interactive widget showing you map in your web page or blog post.\n" +"

Note that the Map Composer also has a button to " +"publish the map. Just be sure to save the map before publishing if there are changes that " +"you want others to see. It publishes the last saved version, not the last viewed version.\n" "\n" "

Remixing a Map

\n" "

Any map available can serve as a starting point for a new map.

\n" @@ -5794,86 +5441,80 @@ msgid "" "
  • Open the map in the Map Composer.
  • \n" "
  • Add and remove layers as you like.
  • \n" "
  • Pan and zoom to highlight the area of interest.
  • \n" -"
  • IMPORTANT: Update the title, abstract, contact " -"info and tags to reflect the new map.
  • \n" +"
  • IMPORTANT: Update the title, abstract, contact info and tags to " +"reflect the new map.
  • \n" "
  • Save the map.
  • \n" " \n" -"

    You will be able to see your new map when you search for it from the " -"Maps tab.

    \n" +"

    You will be able to see your new map when you search for it from the Maps tab.

    \n" " " msgstr "" "\n" -"

    The GeoNode provides access to data sets and a map editing " -"application allows users to browse existing maps and contribute their own.\n" +"

    The GeoNode provides access to data sets and a map editing application allows users " +"to browse existing maps and contribute their own.

    \n" "\n" "

    Browsing Layers

    \n" "

    The Layers tab allows you to browse data " "uploaded to this GeoNode.

    \n" -"

    All data can be downloaded in a variety of formats, for use in other " -"applications.

    \n" +"

    All data can be downloaded in a variety of formats, for use in other applications.\n" "\n" "

    Developer Access

    \n" -"

    The Developer page is the place for " -"developers to get started building applications against the GeoNode. It " -"includes instructions on using the web services, links to the source code of " -"the GeoNode, and information about the open source projects used to create " -"it.

    \n" +"

    The Developer page is the place for developers " +"to get started building applications against the GeoNode. It includes instructions on using " +"the web services, links to the source code of the GeoNode, and information about the open " +"source projects used to create it.

    \n" "\n" "

    Browsing Maps

    \n" -"

    The GeoNode allows users to create and share maps with one another.\n" +"

    The GeoNode allows users to create and share maps with one another.

    \n" "

    The Maps tab is a gateway to map exploration on " -"GeoNode. From here you can search for a map or " -"create a map, which will open the Map " -"Composer.

    \n" +"GeoNode. From here you can search for a map or create a map, which will open the Map Composer.

    \n" "
    Google Earth Mode
    \n" -"

    Any map viewed in the interactive map editor can be seen in 3D mode " -"with the Google Earth plugin. To switch to 3D mode select the Google Earth " -"globe logo, the rightmost button on top toolbar. If you do not have the " -"Google Earth plugin installed you will be prompted to install it.

    \n" +"

    Any map viewed in the interactive map editor can be seen in 3D mode with the Google " +"Earth plugin. To switch to 3D mode select the Google Earth globe logo, the rightmost button " +"on top toolbar. If you do not have the Google Earth plugin installed you will be prompted to " +"install it.

    \n" "\n" "

    Creating a Map

    \n" "

    To create a new map go to the Contributed Maps " "tab and click the create your own map link.

    \n" -"

    This will take you to the Map Composer with " -"a base layer loaded.

    \n" -"

    To add data layers from the GeoNode click on the green plus button " -"located below the layers tab on the left hand side of the screen. This will " -"open a dialog listing all the layers available on the GeoNode.

    \n" -"

    To add layers to your map select them and hit the Add Layers button. When finished you may hit Done to close the " -"dialog and go back to the map.

    \n" +"

    This will take you to the Map Composer with a base " +"layer loaded.

    \n" +"

    To add data layers from the GeoNode click on the green plus button located below the " +"layers tab on the left hand side of the screen. This will open a dialog listing all the " +"layers available on the GeoNode.

    \n" +"

    To add layers to your map select them and hit the Add Layers button. " +"When finished you may hit Done to close the dialog and go back to the map.\n" "\n" "

    Reordering and Removing Layers
    \n" -"

    Change the display order of the layers listed in the data tab by " -"simply dragging and dropping their names. The order in the map will be " -"updated to reflect that. To turn a layer's visibility off simply uncheck it, " -"and to remove it entirely select it and hit the red minus button.

    \n" +"

    Change the display order of the layers listed in the data tab by simply dragging and " +"dropping their names. The order in the map will be updated to reflect that. To turn a " +"layer's visibility off simply uncheck it, and to remove it entirely select it and hit the " +"red minus button.

    \n" "\n" "
    Saving your map
    \n" -"

    Once a suitable set of layers and zoom level has been found it's time " -"to save it so others can see it. Click the Save button--the left most icon " -"on the top toolbar, an image of a map with a disk--on the top menu and fill " -"out the title and abstract of the map.

    \n" +"

    Once a suitable set of layers and zoom level has been found it's time to save it so " +"others can see it. Click the Save button--the left most icon on the top toolbar, an image " +"of a map with a disk--on the top menu and fill out the title and abstract of the map.

    \n" "\n" "

    Publishing a Map

    \n" -"

    Any map from the GeoNode can be embedded for use in another site or " -"blog. To publish a map:

    \n" +"

    Any map from the GeoNode can be embedded for use in another site or blog. To publish " +"a map:

    \n" "
      \n" -"
    1. Select the from the list of maps on the community or map page and " -"then hit the 'Publish map' button.
    2. \n" -"
    3. Choose your desired height and width for the widget in the wizard." -"
    4. \n" -"
    5. Copy the HTML snippet provided in the wizard to any HTML page or " -"iFrame-supporting blog post.
    6. \n" +"
    7. Select the from the list of maps on the community or map page and then hit the " +"'Publish map' button.
    8. \n" +"
    9. Choose your desired height and width for the widget in the wizard.
    10. \n" +"
    11. Copy the HTML snippet provided in the wizard to any HTML page or iFrame-supporting " +"blog post.
    12. \n" "
    \n" -"

    This will put an interactive widget showing you map in your web page " -"or blog post.

    \n" -"

    Note that the Map Composer also has a " -"button to publish the map. Just be sure to save the map before publishing if " -"there are changes that you want others to see. It publishes the last saved " -"version, not the last viewed version.

    \n" +"

    This will put an interactive widget showing you map in your web page or blog post.\n" +"

    Note that the Map Composer also has a button to " +"publish the map. Just be sure to save the map before publishing if there are changes that " +"you want others to see. It publishes the last saved version, not the last viewed version.\n" "\n" "

    Remixing a Map

    \n" "

    Any map available can serve as a starting point for a new map.

    \n" @@ -5881,12 +5522,12 @@ msgstr "" "
  • Open the map in the Map Composer.
  • \n" "
  • Add and remove layers as you like.
  • \n" "
  • Pan and zoom to highlight the area of interest.
  • \n" -"
  • IMPORTANT: Update the title, abstract, contact " -"info and tags to reflect the new map.
  • \n" +"
  • IMPORTANT: Update the title, abstract, contact info and tags to " +"reflect the new map.
  • \n" "
  • Save the map.
  • \n" " \n" -"

    You will be able to see your new map when you search for it from the " -"Maps tab.

    \n" +"

    You will be able to see your new map when you search for it from the Maps tab.

    \n" " " msgid "Sections" @@ -5923,30 +5564,25 @@ msgid "Advanced Search" msgstr "Ricerca Avanzata" msgid "" -"Click to search for geospatial data published by other users, organizations " -"and public sources. Download data in standard formats." +"Click to search for geospatial data published by other users, organizations and public " +"sources. Download data in standard formats." msgstr "" -"Clicca per la ricerca di dati geospaziali pubblicati da altri utenti, " -"organizzazioni e fonti pubbliche. Scaricare i dati in formati standard." +"Clicca per la ricerca di dati geospaziali pubblicati da altri utenti, organizzazioni e fonti " +"pubbliche. Scaricare i dati in formati standard." -#, fuzzy -#| msgid "dataset" msgid "Add datasets" -msgstr "dataset" +msgstr "Aggiungi dataset" -#, fuzzy -#| msgid "Explore Layers" msgid "Explore datasetss" -msgstr "Esplora livelli" +msgstr "Esplora i dataset" msgid "" -"Data is available for browsing, aggregating and styling to generate maps " -"which can be saved, downloaded, shared publicly or restricted to specify " -"users only." +"Data is available for browsing, aggregating and styling to generate maps which can be saved, " +"downloaded, shared publicly or restricted to specify users only." msgstr "" -"I dati sono disponibili per la navigazione, l'aggregazione e lo styling per " -"generare mappe che possono essere salvate, scaricate, condivise " -"pubblicamente o limitate per specificare solo gli utenti." +"I dati sono disponibili per la navigazione, l'aggregazione e lo styling per generare mappe " +"che possono essere salvate, scaricate, condivise pubblicamente o limitate per specificare " +"solo gli utenti." msgid "Create maps" msgstr "Creare mappe" @@ -5955,11 +5591,11 @@ msgid "Explore maps" msgstr "Esplora mappe" msgid "" -"As for the layers and maps GeoNode allows to publish tabular and text data, " -"manage their metadata and associated documents." +"As for the layers and maps GeoNode allows to publish tabular and text data, manage their " +"metadata and associated documents." msgstr "" -"Per quanto riguarda i livelli e le mappe, GeoNode consente di pubblicare " -"dati tabulari e di testo, gestirne i metadati e i documenti associati." +"Per quanto riguarda i livelli e le mappe, GeoNode consente di pubblicare dati tabulari e di " +"testo, gestirne i metadati e i documenti associati." msgid "Add documents" msgstr "Aggiungi documenti" @@ -5968,11 +5604,11 @@ msgid "Explore documents" msgstr "Esplora documenti" msgid "" -"Geonode allows registered users to easily upload geospatial data and various " -"documents in several formats." +"Geonode allows registered users to easily upload geospatial data and various documents in " +"several formats." msgstr "" -"GeoNode permette agli utenti registrati di caricare facilmente i dati " -"geospaziali e vari documenti in diversi formati." +"GeoNode permette agli utenti registrati di caricare facilmente i dati geospaziali e vari " +"documenti in diversi formati." msgid "See users" msgstr "Vedi utenti" @@ -5997,19 +5633,13 @@ msgid "is inviting you to join (%(site_name)s)." msgstr "ti sta invitando a registrati su (%(site_name)s)." #, python-format -msgid "" -"To do so, please register at %(site_name)s " -"Registration." +msgid "To do so, please register at %(site_name)s Registration." msgstr "" -"A tale scopo, registrarsi all'indirizzo " -"%(site_name)s Registrazione." +"A tale scopo, registrarsi all'indirizzo %(site_name)s " +"Registrazione." -msgid "" -"Once you receive the confirmation that your account is activated, you can " -"notify" -msgstr "" -"Una volta ricevuta la conferma dell'attivazione dell'account, è possibile " -"notificare" +msgid "Once you receive the confirmation that your account is activated, you can notify" +msgstr "Una volta ricevuta la conferma dell'attivazione dell'account, è possibile notificare" msgid "that you wish to join her/his group(s) through" msgstr "che si desidera unirsi al suo gruppo/i attraverso" @@ -6018,8 +5648,7 @@ msgid "this link" msgstr "questo link" #, python-format -msgid "" -"%(inviter_name)s is a member of the following group(s):" +msgid "%(inviter_name)s is a member of the following group(s):" msgstr "%(inviter_name)s è un membro dei seguenti gruppi:" msgid "We look forward to seeing you on the platform," @@ -6136,11 +5765,9 @@ msgstr "Il tuo account è ora attivo" msgid "has requested access to the site." msgstr "ha richiesto l'accesso a questo sito." -msgid "" -"You can enable access by setting the user as active on the admin section" +msgid "You can enable access by setting the user as active on the admin section" msgstr "" -"Puoi abilitare l'accesso all'utente impostandolo come attivo nella sezione " -"di Amministrazione" +"Puoi abilitare l'accesso all'utente impostandolo come attivo nella sezione di Amministrazione" msgid "A user has requested access to the site" msgstr "Un utente ha richiesto l'accesso al sito" @@ -6176,10 +5803,10 @@ msgid "A document has been uploaded" msgstr "Un documento è stato caricato" msgid "The following document was deleted" -msgstr "Il seguente documento è stato cancellato" +msgstr "Il seguente documento è stato eliminato" msgid "A document has been deleted" -msgstr "Un documento è stato cancellato" +msgstr "Un documento è stato eliminato" msgid "The following document was published" msgstr "Il seguente documento è stato pubblicato" @@ -6314,17 +5941,16 @@ msgid "" "\n" "

    \n" " Note:\n" -" You do not have a verified email address to which notices can be " -"sent. Add one now.\n" +" You do not have a verified email address to which notices can be sent. Add one now.\n" "

    \n" " " msgstr "" "\n" "

    \n" " Nota:\n" -" Non si dispone di un indirizzo e-mail verificato a cui gli " -"avvisi possono essere inviati. Aggiungerne uno " -"now.\n" +" Non si dispone di un indirizzo e-mail verificato a cui gli avvisi possono essere " +"inviati. Aggiungerne uno now.\n" "

    \n" " " @@ -6334,11 +5960,9 @@ msgstr "Tipo di notifica" msgid "requested you to download this resource" msgstr "ti ha richiesto di scaricare questa risorsa" -msgid "" -"Please go to resource page and assign the download permissions if you wish" +msgid "Please go to resource page and assign the download permissions if you wish" msgstr "" -"Per favore vai alla pagina delle risorse ed assegna i permessi di " -"scaricamento se desideri" +"Per favore vai alla pagina delle risorse ed assegna i permessi di scaricamento se desideri" msgid "A resource's download has been requested" msgstr "Richiesto lo scaricamento di una risorsa" @@ -6419,16 +6043,13 @@ msgstr "Selezione" msgid "No list items selected. Use the selection fields to add." msgstr "" -"Nessun elemento selezionato. Usare i pulsanti di selezione per aggiungere " -"gli elementi." +"Nessun elemento selezionato. Usare i pulsanti di selezione per aggiungere gli elementi." msgid "Filters" msgstr "Filtri" -#, fuzzy -#| msgid "Layers found" msgid "Datasets found" -msgstr "Livelli trovati" +msgstr "Dataset trovati" msgid "Maps found" msgstr "Mappe trovate" @@ -6466,10 +6087,8 @@ msgstr "Più popolari" msgid "Text" msgstr "Testo" -#, fuzzy -#| msgid "Share This" msgid "Share This Dataset" -msgstr "Condividi" +msgstr "Condividi questo dataset" msgid "Share This" msgstr "Condividi" @@ -6477,11 +6096,10 @@ msgstr "Condividi" msgid "Social Network Login Failure" msgstr "Errore di accesso al social network" -msgid "" -"An error occurred while attempting to login via your social network account." +msgid "An error occurred while attempting to login via your social network account." msgstr "" -"Si è verificato un errore durante il tentativo di accesso tramite l'account " -"del social network." +"Si è verificato un errore durante il tentativo di accesso tramite l'account del social " +"network." msgid "Code" msgstr "Codice" @@ -6493,16 +6111,14 @@ msgid "Account Connections" msgstr "Connessioni account" msgid "" -"You can sign in to your account using any of the following already connected " -"third party accounts:" +"You can sign in to your account using any of the following already connected third party " +"accounts:" msgstr "" -"Puoi accedere al tuo account utilizzando uno dei seguenti account di terze " -"parti già connessi:" +"Puoi accedere al tuo account utilizzando uno dei seguenti account di terze parti già " +"connessi:" -msgid "" -"You currently have no social network accounts connected to this account." -msgstr "" -"Al momento non hai account di social network connessi a questo account." +msgid "You currently have no social network accounts connected to this account." +msgstr "Al momento non hai account di social network connessi a questo account." msgid "Add a 3rd Party Account" msgstr "Aggiungere un account di terze parti" @@ -6512,13 +6128,12 @@ msgstr "Accesso annullato" #, python-format msgid "" -"You decided to cancel logging in to our site using one of your existing " -"accounts. If this was a mistake, please proceed to sign in." +"You decided to cancel logging in to our site using one of your existing accounts. If this " +"was a mistake, please proceed to sign in." msgstr "" -"Hai deciso di annullare l'accesso al nostro sito utilizzando uno dei tuoi " -"account esistenti. Se questo è stato un errore, si prega di procedere per accedere." +"Hai deciso di annullare l'accesso al nostro sito utilizzando uno dei tuoi account esistenti. " +"Se questo è stato un errore, si prega di procedere per accedere." msgid "Signup" msgstr "Registrati" @@ -6598,9 +6213,7 @@ msgid "Check this if the jumbotron background image already contains text" msgstr "Verificare se l'immagine di sfondo jumbotron contiene già testo" msgid "Disabling this slide will hide it from the slide show" -msgstr "" -"Se si disattiva questa diapositiva, questa verrà nascondeta dalla " -"presentazione" +msgstr "Se si disattiva questa diapositiva, questa verrà nascondeta dalla presentazione" msgid "Choose between using jumbotron background and slide show" msgstr "Scegliere tra l'utilizzo dello sfondo jumbotron e della presentazione" @@ -6611,19 +6224,11 @@ msgstr "Contenuto" msgid "Could not access to uploaded data." msgstr "Impossibile accedere ai dati caricati." -msgid "" -"One or more XML files was provided, but no matching files were found for " -"them." -msgstr "" -"È stato fornito uno o più file XML, ma non sono stati trovati file " -"corrispondenti." +msgid "One or more XML files was provided, but no matching files were found for them." +msgstr "È stato fornito uno o più file XML, ma non sono stati trovati file corrispondenti." -msgid "" -"One or more SLD files was provided, but no matching files were found for " -"them." -msgstr "" -"È stato fornito uno o più file SLD, ma non sono stati trovati file " -"corrispondenti." +msgid "One or more SLD files was provided, but no matching files were found for them." +msgstr "È stato fornito uno o più file SLD, ma non sono stati trovati file corrispondenti." msgid "Layer already exists" msgstr "Il livello esiste già" @@ -6644,8 +6249,7 @@ msgstr "Previsto per trovare il livello denominato '{name}' nel geoserver" msgid "Exception occurred while parsing the provided Metadata file." msgstr "Eccezione durante l'analisi del file di metadati fornito." -msgid "" -"The UUID identifier from the XML Metadata is already in use in this system." +msgid "The UUID identifier from the XML Metadata is already in use in this system." msgstr "L'identificatore UUID dei metadati XML è già in uso in questo sistema." msgid "Error configuring Layer" @@ -6655,9 +6259,7 @@ msgid "Invalid zip file detected" msgstr "Rilevato file zip non valido" msgid "Could not find any valid spatial file inside the uploaded zip" -msgstr "" -"Impossibile trovare alcun file spaziale valido all'interno del file zip " -"caricato" +msgstr "Impossibile trovare alcun file spaziale valido all'interno del file zip caricato" msgid "Invalid kmz file detected" msgstr "Rilevato file kmz non valido" @@ -6680,12 +6282,8 @@ msgstr "È consentito un solo file kml per file zip" msgid "Only one kml file per kmz is allowed" msgstr "È consentito un solo file kml per kmz" -msgid "" -"You are trying to upload multiple GeoTIFFs without a valid 'indexer." -"properties' file." -msgstr "" -"Si sta tentando di caricare più GeoTIFF senza un file 'indexer.properties' " -"valido." +msgid "You are trying to upload multiple GeoTIFFs without a valid 'indexer.properties' file." +msgstr "Si sta tentando di caricare più GeoTIFF senza un file 'indexer.properties' valido." msgid "Only one raster file per ZIP is allowed" msgstr "È consentito un solo file raster per file zip" @@ -6693,11 +6291,9 @@ msgstr "È consentito un solo file raster per file zip" msgid "No multiple rasters allowed" msgstr "Non sono consentiti più raster" -msgid "" -"To support the time step, you must enable the OGC_SERVER DATASTORE option" +msgid "To support the time step, you must enable the OGC_SERVER DATASTORE option" msgstr "" -"Per supportare il passaggio temporale, è necessario attivare l'opzione " -"OGC_SERVER DATASTORE" +"Per supportare il passaggio temporale, è necessario attivare l'opzione OGC_SERVER DATASTORE" #, python-brace-format msgid "Unsupported file type: {e.message}" @@ -6757,9 +6353,7 @@ msgstr "Permesso negato" #~ msgstr "Carica livello" #~ msgid "You are attempting to replace a vector layer with an unknown format." -#~ msgstr "" -#~ "Stai tentando di sostituire un livello vettoriale con un formato " -#~ "sconosiuto." +#~ msgstr "Stai tentando di sostituire un livello vettoriale con un formato sconosiuto." #~ msgid "Failed to upload the layer" #~ msgstr "Impossibile caricare il livello" From 2cad44ef748fbde2ef464ea09bd64965bbf0d2a7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 13:17:49 +0200 Subject: [PATCH 027/253] [Fixes #11312] Expose dataset ows url (#11313) (#11314) * expose dataser ows url * Formatting (cherry picked from commit 3c5729e24fef14c8da0dc4d9575d91a8946d2c21) Co-authored-by: Giovanni Allegri --- geonode/geoserver/helpers.py | 16 ++++++++++++++++ geonode/geoserver/tests/test_helpers.py | 12 ++++++++++++ geonode/layers/api/serializers.py | 1 + geonode/layers/models.py | 6 ++++++ 4 files changed, 35 insertions(+) diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index d04fb3e12ff..e46179532c1 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -2296,6 +2296,22 @@ def get_dataset_capabilities_url(layer, version="1.3.0", access_token=None): return wms_url +def get_layer_ows_url(layer, access_token=None): + """ + Generate the layer-specific GetCapabilities URL + """ + workspace_layername = layer.alternate.split(":") if ":" in layer.alternate else ("", layer.alternate) + ows_url = settings.GEOSERVER_PUBLIC_LOCATION + if not layer.remote_service: + ows_url = f"{ows_url}{'/'.join(workspace_layername)}/ows" # noqa + if access_token: + ows_url += f"?access_token={access_token}" + else: + ows_url = f"{layer.remote_service.service_url}" + + return ows_url + + def wps_format_is_supported(_format, dataset_type): return (_format, dataset_type) in WPS_ACCEPTABLE_FORMATS diff --git a/geonode/geoserver/tests/test_helpers.py b/geonode/geoserver/tests/test_helpers.py index 80a0823bf32..581547cf73e 100644 --- a/geonode/geoserver/tests/test_helpers.py +++ b/geonode/geoserver/tests/test_helpers.py @@ -40,6 +40,7 @@ get_dataset_storetype, extract_name_from_sld, get_dataset_capabilities_url, + get_layer_ows_url, ) from geonode.geoserver.ows import _wcs_link, _wfs_link, _wms_link @@ -295,3 +296,14 @@ def test_dataset_capabilties_url(self): expected_url = f"{ows_url}geonode/CA/wms?service=wms&version=1.3.0&request=GetCapabilities" capabilities_url = get_dataset_capabilities_url(dataset) self.assertEqual(capabilities_url, expected_url, capabilities_url) + + @on_ogc_backend(geoserver.BACKEND_PACKAGE) + def test_layer_ows_url(self): + from geonode.layers.models import Dataset + + ows_url = settings.GEOSERVER_PUBLIC_LOCATION + identifier = "geonode:CA" + dataset = Dataset.objects.get(alternate=identifier) + expected_url = f"{ows_url}geonode/CA/ows" + capabilities_url = get_layer_ows_url(dataset) + self.assertEqual(capabilities_url, expected_url, capabilities_url) diff --git a/geonode/layers/api/serializers.py b/geonode/layers/api/serializers.py index fd8736fc4eb..270c469aa82 100644 --- a/geonode/layers/api/serializers.py +++ b/geonode/layers/api/serializers.py @@ -173,6 +173,7 @@ class Meta: "featureinfo_custom_template", "ows_url", "capabilities_url", + "dataset_ows_url", "workspace", "default_style", "styles", diff --git a/geonode/layers/models.py b/geonode/layers/models.py index 11612ed8f09..0d6c425e8e0 100644 --- a/geonode/layers/models.py +++ b/geonode/layers/models.py @@ -261,6 +261,12 @@ def capabilities_url(self): return get_dataset_capabilities_url(self) + @property + def dataset_ows_url(self): + from geonode.geoserver.helpers import get_layer_ows_url + + return get_layer_ows_url(self) + @property def embed_url(self): try: From 2bcf394fe1b043fb0c11636caf483e7f34af7dbf Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Tue, 1 Aug 2023 19:14:30 +0200 Subject: [PATCH 028/253] [Fixes #11080] Unable to add ArcGIS REST ImageServer as Remote Service (#11309) (#11315) Co-authored-by: Alessio Fabiani --- geonode/harvesting/harvesters/arcgis.py | 8 ++++---- requirements.txt | 2 +- setup.cfg | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/geonode/harvesting/harvesters/arcgis.py b/geonode/harvesting/harvesters/arcgis.py index c57202cc404..f64934f5b78 100644 --- a/geonode/harvesting/harvesters/arcgis.py +++ b/geonode/harvesting/harvesters/arcgis.py @@ -205,8 +205,8 @@ def _get_resource_descriptor( epsg_code, spatial_extent = _parse_spatial_extent(layer_representation["extent"]) ows_url = harvestable_resource.unique_identifier.rpartition("/")[0] store = slugify(ows_url) - name = layer_representation["id"] - title = layer_representation["name"] + name = layer_representation.get("id", layer_representation.get("name", "Undefined")) + title = layer_representation.get("name", layer_representation.get("title", "Undefined")) workspace = "remoteWorkspace" alternate = f"{workspace}:{name}" return resourcedescriptor.RecordDescription( @@ -307,8 +307,8 @@ def _get_resource_descriptor( epsg_code, spatial_extent = _parse_spatial_extent(layer_representation["extent"]) ows_url = harvestable_resource.unique_identifier.rpartition("/")[0] store = slugify(ows_url) - name = layer_representation["id"] - title = layer_representation["name"] + name = layer_representation.get("id", layer_representation.get("name", "Undefined")) + title = layer_representation.get("name", layer_representation.get("title", "Undefined")) workspace = "remoteWorkspace" alternate = f"{workspace}:{name}" return resourcedescriptor.RecordDescription( diff --git a/requirements.txt b/requirements.txt index cd578ba7ce7..9e9debd16cc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -95,7 +95,7 @@ geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 geonode-announcements==2.0.2 geonode-django-activity-stream==0.10.0 -gn-arcrest==10.5.5 +gn-arcrest==10.5.6 geoserver-restconfig==2.0.9 gn-gsimporter==2.0.4 gisdata==0.5.4 diff --git a/setup.cfg b/setup.cfg index 95bf6ac165d..f1a7fa2698f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -121,7 +121,7 @@ install_requires = geonode-user-messages==2.0.2 geonode-announcements==2.0.2 geonode-django-activity-stream==0.10.0 - gn-arcrest==10.5.5 + gn-arcrest==10.5.6 geoserver-restconfig==2.0.9 gn-gsimporter==2.0.4 gisdata==0.5.4 From 799ad9e58432fe617fa3d44aed8b300c2476be2b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 4 Aug 2023 18:49:07 +0200 Subject: [PATCH 029/253] [Fixes #11323] Align the Position labels and translations (#11324) (#11325) * Align the Position labels and translations * Improvement to it translation (cherry picked from commit 2b09aa6df2f2f51f051a8842b50f7fe2cc120c2a) Co-authored-by: Giovanni Allegri --- geonode/locale/en/LC_MESSAGES/django.mo | Bin 143913 -> 143908 bytes geonode/locale/en/LC_MESSAGES/django.po | 2 +- geonode/locale/it/LC_MESSAGES/django.mo | Bin 161119 -> 161121 bytes geonode/locale/it/LC_MESSAGES/django.po | 4 ++-- .../templates/people/profile_detail.html | 16 ++++++++-------- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/geonode/locale/en/LC_MESSAGES/django.mo b/geonode/locale/en/LC_MESSAGES/django.mo index f8663d06708af49835ebb15452c0cb68aec04c63..b7be4680ab464698552a6af0a9b8ec4582b4602f 100644 GIT binary patch delta 5371 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 diff --git a/geonode/locale/en/LC_MESSAGES/django.po b/geonode/locale/en/LC_MESSAGES/django.po index ae445ae92c7..d6ce030a65a 100644 --- a/geonode/locale/en/LC_MESSAGES/django.po +++ b/geonode/locale/en/LC_MESSAGES/django.po @@ -3982,7 +3982,7 @@ msgid "introduce yourself" msgstr "introduce yourself" msgid "Position Name" -msgstr "Position Name" +msgstr "Position" msgid "role or position of the responsible person" msgstr "role or position of the responsible person" diff --git a/geonode/locale/it/LC_MESSAGES/django.mo b/geonode/locale/it/LC_MESSAGES/django.mo index 0a9e88e7f7d43b2150075b76272bf4703f194b8f..ca8e5e1987454996ec2d980155ea22c053d2d976 100644 GIT binary patch delta 7343 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 delta 7341 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 diff --git a/geonode/locale/it/LC_MESSAGES/django.po b/geonode/locale/it/LC_MESSAGES/django.po index f698c7205b5..8791b1cfec4 100644 --- a/geonode/locale/it/LC_MESSAGES/django.po +++ b/geonode/locale/it/LC_MESSAGES/django.po @@ -786,7 +786,7 @@ msgstr "" "controllo, zone postali e servizi, nomi di luoghi." msgid "Location" -msgstr "Posizione" +msgstr "Recapito" msgid "" "Features and characteristics of salt water bodies (excluding inland waters). Examples: " @@ -3775,7 +3775,7 @@ msgid "introduce yourself" msgstr "presentarsi" msgid "Position Name" -msgstr "Ruolo" +msgstr "Incarico" msgid "role or position of the responsible person" msgstr "ruolo o posizione della persona responsabile" diff --git a/geonode/people/templates/people/profile_detail.html b/geonode/people/templates/people/profile_detail.html index 0d6a48269e8..1a3c09ef7f1 100644 --- a/geonode/people/templates/people/profile_detail.html +++ b/geonode/people/templates/people/profile_detail.html @@ -73,14 +73,18 @@

    {{ profile.first_name|default:profile.name_long }}

    {% endif %} {% endif %} - - {% trans 'Position' %} - {{ profile.position | default:_('Not provided.') }} - {% trans 'Organization' %} {{ profile.organization | default:_('Not provided.') }} + + {% trans 'Description' %} + {{ profile.profile | default:_('Not provided.') }} + + + {% trans 'Position Name' %} + {{ profile.position | default:_('Not provided.') }} + {% trans 'Location' %} {{ profile.location | default:_('Not provided.') }} @@ -97,10 +101,6 @@

    {{ profile.first_name|default:profile.name_long }}

    {% trans 'Fax' %} {{ profile.fax | default:_('Not provided.') }} - - {% trans 'Description' %} - {{ profile.profile | default:_('Not provided.') }} - {% trans 'Keywords' %} From ba2cd0cb37b45df148715d567a5920f4deb1f702 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Mon, 7 Aug 2023 10:51:11 +0200 Subject: [PATCH 030/253] Backport monitoring disabled (#11334) --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index 96b166bf2fb..f46f8a930d8 100644 --- a/.env +++ b/.env @@ -186,7 +186,7 @@ BING_API_KEY= GOOGLE_API_KEY= # Monitoring -MONITORING_ENABLED=True +MONITORING_ENABLED=False MONITORING_DATA_TTL=365 USER_ANALYTICS_ENABLED=True USER_ANALYTICS_GZIP=True From f2e4c40897ada781c7f20a9873c0c687eae6fcba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 18:01:15 +0200 Subject: [PATCH 031/253] use bracket notation inside the default feature template (#11343) (#11344) (cherry picked from commit 84b27ae1b54b3f828b1e29fdcf7750120bcf3d75) Co-authored-by: Giovanni Allegri --- geonode/layers/api/serializers.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/geonode/layers/api/serializers.py b/geonode/layers/api/serializers.py index 270c469aa82..3d39fdefe20 100644 --- a/geonode/layers/api/serializers.py +++ b/geonode/layers/api/serializers.py @@ -88,20 +88,20 @@ def get_attribute(self, instance): else: _attributes = instance.attributes.filter(visible=True).order_by("display_order") if _attributes.exists(): - _template = "
    " + _template = '
    ' for _field in _attributes: _label = _field.attribute_label or _field.attribute _template += '
    ' if _field.featureinfo_type == Attribute.TYPE_HREF: _template += ( '
    %s:
    \ -
    ' + ' % (_label, _field, _field) ) elif _field.featureinfo_type == Attribute.TYPE_IMAGE: _template += ( '
    \ - %s
    ' + %s
    ' % (_field.attribute, _field.attribute, _label, _label) ) elif _field.featureinfo_type in ( @@ -115,32 +115,32 @@ def get_attribute(self, instance): if "youtube" in _field.featureinfo_type: _template += ( '
    \ -
    ' +
    ' % (_field.attribute) ) else: _type = f"video/{_field.featureinfo_type[11:]}" _template += ( '
    \ -
    ' +
    ' % (_field.attribute, _type) ) elif _field.featureinfo_type == Attribute.TYPE_AUDIO: _template += ( '
    \ -
    ' +
    ' % (_field.attribute) ) elif _field.featureinfo_type == Attribute.TYPE_IFRAME: _template += ( '
    \ -
    ' +
    ' % (_field.attribute) ) elif _field.featureinfo_type == Attribute.TYPE_PROPERTY: _template += ( '
    %s:
    \ -
    ${properties.%s}
    ' +
    ${properties[\'%s\']}
    ' % (_label, _field.attribute) ) _template += "
    " From 0e9e45487076c3f097dc71333775bc6df44e368d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 18:35:49 +0200 Subject: [PATCH 032/253] remove Django admin widgets for bbox editable fields (#11339) (#11345) (cherry picked from commit 1c8df230c1b44e8631dc8f6b0bec7e18e6d24685) Co-authored-by: Giovanni Allegri --- geonode/documents/admin.py | 2 ++ geonode/geoapps/admin.py | 2 ++ geonode/layers/admin.py | 3 ++- geonode/maps/admin.py | 2 ++ geonode/services/admin.py | 1 + 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/geonode/documents/admin.py b/geonode/documents/admin.py index 36511c7d331..9af881f0e6d 100644 --- a/geonode/documents/admin.py +++ b/geonode/documents/admin.py @@ -36,6 +36,7 @@ class Meta(ResourceBaseAdminForm.Meta): class DocumentAdmin(TabbedTranslationAdmin): + exclude = ("ll_bbox_polygon", "bbox_polygon", "srid") list_display = ("id", "title", "date", "category", "group", "is_approved", "is_published", "metadata_completeness") list_display_links = ("id",) list_editable = ("title", "category", "group", "is_approved", "is_published") @@ -55,6 +56,7 @@ class DocumentAdmin(TabbedTranslationAdmin): "is_approved", "is_published", ) + readonly_fields = ("geographic_bounding_box",) date_hierarchy = "date" form = DocumentAdminForm actions = [metadata_batch_edit] diff --git a/geonode/geoapps/admin.py b/geonode/geoapps/admin.py index f0217db4cb2..33c8ff2f7c6 100644 --- a/geonode/geoapps/admin.py +++ b/geonode/geoapps/admin.py @@ -32,6 +32,7 @@ class Meta(ResourceBaseAdminForm.Meta): class GeoAppAdmin(TabbedTranslationAdmin): + exclude = ("ll_bbox_polygon", "bbox_polygon", "srid") list_display_links = ("title",) list_display = ( "id", @@ -65,6 +66,7 @@ class GeoAppAdmin(TabbedTranslationAdmin): "is_approved", "is_published", ) + readonly_fields = ("geographic_bounding_box",) form = GeoAppAdminForm def delete_queryset(self, request, queryset): diff --git a/geonode/layers/admin.py b/geonode/layers/admin.py index 379d361943b..7cb712206d1 100644 --- a/geonode/layers/admin.py +++ b/geonode/layers/admin.py @@ -55,6 +55,7 @@ class Meta(ResourceBaseAdminForm.Meta): class DatasetAdmin(TabbedTranslationAdmin): + exclude = ("ll_bbox_polygon", "bbox_polygon", "srid") list_display = ( "id", "alternate", @@ -86,7 +87,7 @@ class DatasetAdmin(TabbedTranslationAdmin): search_fields = ("alternate", "title", "abstract", "purpose", "is_approved", "is_published", "state") filter_horizontal = ("contacts",) date_hierarchy = "date" - readonly_fields = ("uuid", "alternate", "workspace") + readonly_fields = ("uuid", "alternate", "workspace", "geographic_bounding_box") inlines = [AttributeInline] form = DatasetAdminForm actions = [metadata_batch_edit] diff --git a/geonode/maps/admin.py b/geonode/maps/admin.py index 6be72dd9982..da6f8bf74a1 100644 --- a/geonode/maps/admin.py +++ b/geonode/maps/admin.py @@ -44,6 +44,7 @@ class MapAdmin(TabbedTranslationAdmin): inlines = [ MapLayerInline, ] + exclude = ("ll_bbox_polygon", "bbox_polygon", "srid") list_display_links = ("title",) list_display = ( "id", @@ -78,6 +79,7 @@ class MapAdmin(TabbedTranslationAdmin): "is_approved", "is_published", ) + readonly_fields = ("geographic_bounding_box",) form = MapAdminForm actions = [metadata_batch_edit] diff --git a/geonode/services/admin.py b/geonode/services/admin.py index d447c4145f0..2e61a21ce3e 100644 --- a/geonode/services/admin.py +++ b/geonode/services/admin.py @@ -31,6 +31,7 @@ class Meta(ResourceBaseAdminForm.Meta): class ServiceAdmin(admin.ModelAdmin): + exclude = ("ll_bbox_polygon", "bbox_polygon", "srid") list_display = ("id", "name", "base_url", "type", "method") list_display_links = ("id", "name") list_filter = ("id", "name", "type", "method") From 1817f4ebd229cca0d1d94d2c4be84bdc5c3fbec0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Aug 2023 12:42:05 +0200 Subject: [PATCH 033/253] fix feature template test (#11351) (#11352) (cherry picked from commit 48613757ca48d92f49191fce6ba4632d91c4949b) Co-authored-by: Giovanni Allegri --- geonode/layers/api/tests.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/geonode/layers/api/tests.py b/geonode/layers/api/tests.py index dc6475bfdcc..7361e5c744a 100644 --- a/geonode/layers/api/tests.py +++ b/geonode/layers/api/tests.py @@ -93,8 +93,8 @@ def test_datasets(self): self.assertIsNotNone(response.data["dataset"].get("featureinfo_custom_template")) self.assertEqual( response.data["dataset"].get("featureinfo_custom_template"), - '
    Name:
    \ -
    ${properties.name}
    ', + '
    Name:
    \ +
    ${properties[\'name\']}
    ', ) _dataset.featureinfo_custom_template = "
    Foo Bar
    " @@ -104,8 +104,8 @@ def test_datasets(self): self.assertIsNotNone(response.data["dataset"].get("featureinfo_custom_template")) self.assertEqual( response.data["dataset"].get("featureinfo_custom_template"), - '
    Name:
    \ -
    ${properties.name}
    ', + '
    Name:
    \ +
    ${properties[\'name\']}
    ', ) _dataset.use_featureinfo_custom_template = True From a7c26f85fcbfc80119299ae3817bfb0d89026170 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Aug 2023 13:11:36 +0200 Subject: [PATCH 034/253] [Fixes #11332] Remove geoip task (#11336) (#11346) * [Fixes #11332] Remove geoip task * [Fixes #11332] Rollback requirements.txt * [Fixes #11332] Rollback setuo.cfg (cherry picked from commit 95eb82e8c79146dbe49ca2146fa405defc012732) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Co-authored-by: Giovanni Allegri --- entrypoint.sh | 1 - geonode/monitoring/models.py | 33 --------------------------------- pavement.py | 18 ------------------ tasks.py | 7 ------- 4 files changed, 59 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 4e394cdc703..620976448cc 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -54,7 +54,6 @@ else invoke prepare if [ ${FORCE_REINIT} = "true" ] || [ ${FORCE_REINIT} = "True" ] || [ ! -e "/mnt/volumes/statics/geonode_init.lock" ]; then - invoke updategeoip invoke fixtures invoke monitoringfixture invoke initialized diff --git a/geonode/monitoring/models.py b/geonode/monitoring/models.py index bbef043b228..18f302c73dc 100644 --- a/geonode/monitoring/models.py +++ b/geonode/monitoring/models.py @@ -701,39 +701,6 @@ def from_geonode(cls, service, request, response): sensitive_data = cls._get_user_data_gn(request) event_type = cls._get_event_type(request) - # ua = request.META.get('HTTP_USER_AGENT') or '' - # ua_family = cls._get_ua_family(ua) - # - # ip, is_routable = get_client_ip(request) - # lat = lon = None - # country = region = city = None - # if ip and is_routable: - # ip = ip.split(':')[0] - # if settings.TEST and ip == 'testserver': - # ip = '127.0.0.1' - # try: - # ip = gethostbyname(ip) - # except Exception as err: - # pass - # - # geoip = get_geoip() - # try: - # client_loc = geoip.city(ip) - # except Exception as err: - # log.warning("Cannot resolve %s: %s", ip, err) - # client_loc = None - # - # if client_loc: - # lat, lon = client_loc['latitude'], client_loc['longitude'], - # country = client_loc.get( - # 'country_code3') or client_loc['country_code'] - # if len(country) == 2: - # _c = pycountry.countries.get(alpha_2=country) - # country = _c.alpha_3 - # - # region = client_loc['region'] - # city = client_loc['city'] - data = { "received": received, "created": created, diff --git a/pavement.py b/pavement.py index 8ef01a09492..eaf71f8ad47 100644 --- a/pavement.py +++ b/pavement.py @@ -261,10 +261,6 @@ def static(options): ) def setup(options): """Get dependencies and prepare a GeoNode development environment.""" - - if MONITORING_ENABLED: - updategeoip(options) - info( "GeoNode development environment successfully set up." "If you have not set up an administrative account," @@ -334,20 +330,6 @@ def upgradedb(options): print(f"Upgrades from version {version} are not yet supported.") -@task -@cmdopts([("settings=", "s", "Specify custom DJANGO_SETTINGS_MODULE")]) -def updategeoip(options): - """ - Update geoip db - """ - if MONITORING_ENABLED: - settings = options.get("settings", "") - if settings and "DJANGO_SETTINGS_MODULE" not in settings: - settings = f"DJANGO_SETTINGS_MODULE={settings}" - - sh(f"{settings} python -W ignore manage.py updategeoip -o") - - @task @cmdopts([("settings=", "s", "Specify custom DJANGO_SETTINGS_MODULE")]) def sync(options): diff --git a/tasks.py b/tasks.py index f3d72a0fff2..5711ab991b9 100755 --- a/tasks.py +++ b/tasks.py @@ -427,13 +427,6 @@ def monitoringfixture(ctx): logger.error(f"ERROR installing monitoring fixture: {str(e)}") -@task -def updategeoip(ctx): - print("**************************update geoip*******************************") - if ast.literal_eval(os.environ.get("MONITORING_ENABLED", "False")): - ctx.run(f"django-admin.py updategeoip --settings={_localsettings()}", pty=True) - - @task def updateadmin(ctx): print("***********************update admin details**************************") From 77919a4d3a3d636cd6c425326539f7614167422a Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Tue, 8 Aug 2023 15:32:34 +0200 Subject: [PATCH 035/253] Bump to 4.1.1 (#11353) * Bump client to 4.1.1 and importer to 1.0.4 * Bump version to version 4.1.1 --- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/geonode/__init__.py b/geonode/__init__.py index e221b120dab..b57eb71543e 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 1, 0, "dev", 0) +__version__ = (4, 1, 1, "final", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 9e9debd16cc..4cd8e13c1d6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. --e git+https://github.com/GeoNode/geonode-mapstore-client.git@master#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.1.1 +geonode-importer==1.0.4 geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From e2d11053cd58fd733d67659bc714dfb273633471 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Tue, 8 Aug 2023 16:02:52 +0200 Subject: [PATCH 036/253] changelog and fixes for packaging (#11355) --- CHANGELOG.md | 9 +++++++++ setup.cfg | 4 ++-- setup.py | 5 +++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 799dbb6035c..b440a931782 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## [4.1.1](https://github.com/GeoNode/geonode/tree/4.1.0) (2023-06-05) +## Security and Bug Fixes +- Upgrade to Ubuntu 22.10 +- Upgrade to Django 3.2.20 +- Fixed direct download URL not working in some cases when local files are not available +- Fixed assignment of regions crossing the dateline +- Fixed harvesting of ArcGIS REST ImageServer services +- Fixed some italian translations +- Disabling of the (deprecated) Monitoring module ## [4.1.0](https://github.com/GeoNode/geonode/tree/4.1.0) (2023-06-05) ### New upload engine GeoNode integrates a brand new importer module based on [GDAL/OGR](https://gdal.org/), which offers increased robustness and reliability to the upload UI and API services. GeoPackage (vector), GeoJSON, KML/KMZ formats and a new CSV handler have been implemented. diff --git a/setup.cfg b/setup.cfg index f1a7fa2698f..3f15d636661 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.1.0 - geonode-importer>=1.0.3 + django-geonode-mapstore-client>=4.1.1 + geonode-importer>=1.0.4 geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.py b/setup.py index 498d391199e..86f10350f9e 100644 --- a/setup.py +++ b/setup.py @@ -28,6 +28,7 @@ setup( version=__import__("geonode").get_version(), long_description=open("README.md").read(), + long_description_content_type='text/markdown', package_data={ "": ["*.*"], # noqa "": ["static/*.*"], # noqa @@ -35,4 +36,8 @@ "": ["templates/*.*"], # noqa "templates": ["*.*"], }, + exclude_package_data={ + "": ["uploaded/*.*"], # noqa + "uploaded": ["*.*"], + } ) From 4cfc8996852aa07fddc29b61f060030db405df68 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Tue, 8 Aug 2023 17:00:26 +0200 Subject: [PATCH 037/253] Bump to dev versions (#11354) --- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/geonode/__init__.py b/geonode/__init__.py index b57eb71543e..bf35145977e 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 1, 1, "final", 0) +__version__ = (4, 1, 1, "dev", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 4cd8e13c1d6..0470468edb4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -django-geonode-mapstore-client==4.1.1 -geonode-importer==1.0.4 +-e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.1.x#egg=django_geonode_mapstore_client +-e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 654144a1baa31d79eb579096bea40eaf57638bc5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 10 Aug 2023 18:51:06 +0200 Subject: [PATCH 038/253] [Fixes #11368] Fix spatial representation type parsing (#11369) (#11370) * Fix spatial representation type parsing * improved code * fixed tests * fixed formatting (cherry picked from commit 3fa9a8690f4aa27282cd815224014bb6cbc6fb00) Co-authored-by: Giovanni Allegri --- geonode/base/fixtures/test_xml.xml | 2 +- geonode/catalogue/templates/catalogue/full_metadata.xml | 2 ++ geonode/layers/metadata.py | 4 +++- geonode/layers/tests.py | 4 ++-- geonode/resource/utils.py | 8 +------- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/geonode/base/fixtures/test_xml.xml b/geonode/base/fixtures/test_xml.xml index 34a2af08443..1b990340631 100755 --- a/geonode/base/fixtures/test_xml.xml +++ b/geonode/base/fixtures/test_xml.xml @@ -406,7 +406,7 @@ - + vector eng diff --git a/geonode/catalogue/templates/catalogue/full_metadata.xml b/geonode/catalogue/templates/catalogue/full_metadata.xml index 39bffae1d3c..955f81c3e55 100644 --- a/geonode/catalogue/templates/catalogue/full_metadata.xml +++ b/geonode/catalogue/templates/catalogue/full_metadata.xml @@ -436,9 +436,11 @@ + {% if layer.spatial_representation_type %} {{layer.spatial_representation_type.identifier}} + {% endif %} {{layer.language}} diff --git a/geonode/layers/metadata.py b/geonode/layers/metadata.py index e61577ff5b5..74aab2ce8a9 100644 --- a/geonode/layers/metadata.py +++ b/geonode/layers/metadata.py @@ -79,7 +79,9 @@ def iso2dict(exml): mdata = MD_Metadata(exml) identifier = mdata.identifier vals["language"] = mdata.language or mdata.languagecode or "eng" - vals["spatial_representation_type"] = mdata.hierarchy + if mdata.identification[0].spatialrepresentationtype: + vals["spatial_representation_type"] = mdata.identification[0].spatialrepresentationtype[0] + vals["date"] = sniff_date(mdata.datestamp) if hasattr(mdata, "identification"): diff --git a/geonode/layers/tests.py b/geonode/layers/tests.py index fbe14c340ba..d7420fc2a84 100644 --- a/geonode/layers/tests.py +++ b/geonode/layers/tests.py @@ -1631,7 +1631,7 @@ def test_set_metadata_return_expected_values_from_xml(self): "date": datetime.datetime(2021, 4, 9, 9, 0, 46), "language": "eng", "purpose": None, - "spatial_representation_type": "dataset", + "spatial_representation_type": "vector", "supplemental_information": "No information provided", "temporal_extent_end": None, "temporal_extent_start": None, @@ -1691,7 +1691,7 @@ def setUp(self): "date": datetime.datetime(2021, 4, 9, 9, 0, 46), "language": "eng", "purpose": None, - "spatial_representation_type": "dataset", + "spatial_representation_type": "vector", "supplemental_information": "No information provided", "temporal_extent_end": None, "temporal_extent_start": None, diff --git a/geonode/resource/utils.py b/geonode/resource/utils.py index ca7175c799b..b8e70a362cb 100644 --- a/geonode/resource/utils.py +++ b/geonode/resource/utils.py @@ -167,13 +167,7 @@ def update_resource( if vals: for key, value in vals.items(): if key == "spatial_representation_type": - spatial_repr = SpatialRepresentationType.objects.filter(identifier=value) - if value is not None and spatial_repr.exists(): - value = SpatialRepresentationType(identifier=value) - # if the SpatialRepresentationType is not available in the DB, we just set it as None - elif value is not None and not spatial_repr.exists(): - value = None - defaults[key] = value + defaults[key] = SpatialRepresentationType.objects.filter(identifier=value).first() if value else None elif key == "topic_category": value, created = TopicCategory.objects.get_or_create( identifier=value, defaults={"description": "", "gn_description": value} From 2d832ace39f4eee0252b346b020dd53404573b99 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Fri, 11 Aug 2023 11:51:41 +0200 Subject: [PATCH 039/253] BUmp to 4.1.x (#11371) --- CHANGELOG.md | 6 +++++- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b440a931782..e2ac7e72bd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log -## [4.1.1](https://github.com/GeoNode/geonode/tree/4.1.0) (2023-06-05) +## [4.1.2](https://github.com/GeoNode/geonode/tree/4.1.2) (2023-08-11) +## Bug Fixes +- Upgrade to importer 1.0.5 which fixes the import with filenames longer then 63 chars +- Fixed parsing and rendering of ISO TC211 spatial representetion type +## [4.1.1](https://github.com/GeoNode/geonode/tree/4.1.1) (2023-06-05) ## Security and Bug Fixes - Upgrade to Ubuntu 22.10 - Upgrade to Django 3.2.20 diff --git a/geonode/__init__.py b/geonode/__init__.py index bf35145977e..9102f026f1f 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 1, 1, "dev", 0) +__version__ = (4, 1, 2, "final", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 0470468edb4..55df34605f3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. --e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.1.x#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.1.1 +geonode-importer==1.0.5 geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 3f15d636661..59fb9ad08cb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.1.1 - geonode-importer>=1.0.4 + django-geonode-mapstore-client==4.1.1 + geonode-importer==1.0.5 geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From ac7f60994d9f9bf1165dd71b0f575c8c4f46c237 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Fri, 11 Aug 2023 12:06:32 +0200 Subject: [PATCH 040/253] Bump to 4.2.x (#11372) --- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/geonode/__init__.py b/geonode/__init__.py index 9102f026f1f..7884b891ac6 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 1, 2, "final", 0) +__version__ = (4, 1, 2, "dev", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 55df34605f3..0470468edb4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -django-geonode-mapstore-client==4.1.1 -geonode-importer==1.0.5 +-e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.1.x#egg=django_geonode_mapstore_client +-e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 59fb9ad08cb..f6d5f90abf2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client==4.1.1 - geonode-importer==1.0.5 + django-geonode-mapstore-client>=4.1.1 + geonode-importer>=1.0.5 geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 21bbee841c5b408d9fcc564b86ee4c46e104c770 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 16 Aug 2023 11:36:25 +0200 Subject: [PATCH 041/253] =?UTF-8?q?[Fixes=20#11320]=20API=20V1=20delivers?= =?UTF-8?q?=20information=20on=20users=20that=20shouldn't=20be=E2=80=A6=20?= =?UTF-8?q?(#11321)=20(#11384)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Fixes #11320] API V1 delivers information on users that shouldn't be visible * Fix black and flake8 * Fix black and flake8 * Fix black and flake8 * Fix black and flake8 * [Fixes #11320] API V1 delivers information on users that shouldn't be visible --------- Co-authored-by: Giovanni Allegri (cherry picked from commit c84f55ef2143b962729bda3b85f749ce15c2afdf) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/api/api.py | 10 ++++++++++ geonode/api/tests.py | 8 +++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/geonode/api/api.py b/geonode/api/api.py index 0663176dec9..4303c0caa4b 100644 --- a/geonode/api/api.py +++ b/geonode/api/api.py @@ -584,6 +584,16 @@ class OwnersResource(TypeFilteredResource): full_name = fields.CharField(null=True) + def apply_filters(self, request, applicable_filters): + """filter by group if applicable by group functionality""" + + semi_filtered = super().apply_filters(request, applicable_filters) + + if request.user and not request.user.is_superuser: + semi_filtered = get_available_users(request.user) + + return semi_filtered + def dehydrate_full_name(self, bundle): return bundle.obj.get_full_name() or bundle.obj.username diff --git a/geonode/api/tests.py b/geonode/api/tests.py index e8fb96626bb..39a428c21fb 100644 --- a/geonode/api/tests.py +++ b/geonode/api/tests.py @@ -321,7 +321,7 @@ def test_owners_lockdown(self): self.api_client.client.login(username="bobby", password="bob") resp = self.api_client.get(filter_url) self.assertValidJSONResponse(resp) - self.assertEqual(len(self.deserialize(resp)["objects"]), 9) + self.assertEqual(len(self.deserialize(resp)["objects"]), 6) # Returns limitted info about other users bobby = get_user_model().objects.get(username="bobby") owners = self.deserialize(resp)["objects"] @@ -332,6 +332,12 @@ def test_owners_lockdown(self): self.assertIsNone(owner.get("email")) self.assertIsNone(owner.get("first_name")) + # now test with logged in admin + self.api_client.client.login(username="admin", password="admin") + resp = self.api_client.get(filter_url) + self.assertValidJSONResponse(resp) + self.assertEqual(len(self.deserialize(resp)["objects"]), 9) + @override_settings(API_LOCKDOWN=True) def test_groups_lockdown(self): groups_list_url = reverse("api_dispatch_list", kwargs={"api_name": "api", "resource_name": "groups"}) From fb7a3f4059f67cd9596957b1784c1cf337ae412c Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 14 Sep 2023 18:00:06 +0200 Subject: [PATCH 042/253] Revert to Ubuntu 22.04 LTS (#11488) --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5d76bb6f25d..6c62736737b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.10 +FROM ubuntu:22.04 LABEL GeoNode development team RUN mkdir -p /usr/src/geonode From f115ed378c5faa1b07db8d0204adfcb0c6735b13 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 18:33:50 +0200 Subject: [PATCH 043/253] [Fixes #11430] Improve metadata template (#11431) (#11485) * Fixup dataset template * Fixup document template * Fixup geoapp and maps template * [Fixes #11430] Fix template typo (cherry picked from commit 1404400c13b95ba7b5c4e282bd0885a49744c70a) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Co-authored-by: G. Allegri --- geonode/documents/templates/layouts/doc_panels.html | 3 +++ geonode/geoapps/templates/layouts/app_panels.html | 12 ++++++++++++ geonode/layers/templates/layouts/panels.html | 4 ++-- geonode/maps/templates/layouts/map_panels.html | 8 +++++++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/geonode/documents/templates/layouts/doc_panels.html b/geonode/documents/templates/layouts/doc_panels.html index bbde7b2e7d5..d02d01085fc 100644 --- a/geonode/documents/templates/layouts/doc_panels.html +++ b/geonode/documents/templates/layouts/doc_panels.html @@ -556,6 +556,7 @@
    + {% block document_poc %}
    {% trans "Responsible Parties" %}
    @@ -563,6 +564,8 @@ {{ document_form.poc }}
    + {% endblock %} +
    {% trans "Responsible and Permissions" %}
    diff --git a/geonode/geoapps/templates/layouts/app_panels.html b/geonode/geoapps/templates/layouts/app_panels.html index d46741d8c2e..cb8aa41f766 100644 --- a/geonode/geoapps/templates/layouts/app_panels.html +++ b/geonode/geoapps/templates/layouts/app_panels.html @@ -292,9 +292,11 @@
    + {% block geoapp_title %} {{ geoapp_form.title }} + {% endblock %}
    @@ -312,6 +314,7 @@ {{ geoapp_form.date }}
    + {% block geoapp_category %}
    + {% block geoapp_attributes %}
    @@ -393,6 +398,7 @@ {{ geoapp_form.attribution }}
    + {% endblock geoapp_attributes %}
    @@ -452,6 +458,7 @@
    + {% block geoapp_temporal_extent_start %}
    @@ -459,6 +466,8 @@ {{ geoapp_form.temporal_extent_start }}
    + {% endblock geoapp_temporal_extent_start %} + {% block geoapp_temporal_extent_end %}
    @@ -466,6 +475,8 @@ {{ geoapp_form.temporal_extent_end }}
    + {% endblock geoapp_temporal_extent_end %} + {% block maintenance_block %}
    @@ -484,6 +495,7 @@
    {% endblock geoapp_extra_metadata %}
    + {% endblock maintenance_block %}
    diff --git a/geonode/layers/templates/layouts/panels.html b/geonode/layers/templates/layouts/panels.html index c10634646f3..579b5f46ea6 100644 --- a/geonode/layers/templates/layouts/panels.html +++ b/geonode/layers/templates/layouts/panels.html @@ -560,15 +560,15 @@
    + {% block dataset_poc %}
    {% trans "Responsible Parties" %}
    - {% block dataset_poc %}
    {{ dataset_form.poc }}
    - {% endblock dataset_poc %}
    + {% endblock dataset_poc %}
    {% trans "Responsible and Permissions" %}
    diff --git a/geonode/maps/templates/layouts/map_panels.html b/geonode/maps/templates/layouts/map_panels.html index 307549913da..dce48088967 100644 --- a/geonode/maps/templates/layouts/map_panels.html +++ b/geonode/maps/templates/layouts/map_panels.html @@ -508,13 +508,15 @@ {% endblock map_supplemental_information %}
    + {% block map_temporal_extent_start %}
    {{ map_form.temporal_extent_start }} -
    +
    + {% endblock %}
    {% block map_temporal_extent_end %}
    @@ -524,6 +526,7 @@
    {% endblock map_temporal_extent_end %}
    + {% block maintenance_block %}
    @@ -542,8 +545,10 @@
    {% endblock map_extra_metadata %}
    + {% endblock maintenance_block %}
    + {% block map_poc %}
    {% trans "Responsible Parties" %}
    @@ -551,6 +556,7 @@ {{ map_form.poc }}
    + {% endblock %}
    {% trans "Responsible and Permissions" %}
    From aabd1f4099a152594585ea2313b61b18c2ca4302 Mon Sep 17 00:00:00 2001 From: Alessio Fabiani Date: Fri, 15 Sep 2023 12:37:41 +0200 Subject: [PATCH 044/253] [Backport 4.1.x] SSRF Bypass to return internal host data (#11486) * [Backport 4.1.x] SSRF Bypass to return internal host data * - Test fix (cherry picked from commit 6503e4242dbc1e524af4c13e8d8259ef89968ce5) --------- Co-authored-by: G. Allegri --- .env_test | 2 +- geonode/proxy/tests.py | 56 ++++++++++++++++++++++++++++++++++++++++++ geonode/proxy/views.py | 11 +++++++-- geonode/utils.py | 38 ++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 3 deletions(-) diff --git a/.env_test b/.env_test index 78eebee94cb..80f7470e485 100644 --- a/.env_test +++ b/.env_test @@ -47,7 +47,7 @@ ASYNC_SIGNALS=True SITEURL=http://localhost:8001/ -ALLOWED_HOSTS="['django', '*']" +ALLOWED_HOSTS="['django', 'localhost']" # Data Uploader DEFAULT_BACKEND_UPLOADER=geonode.importer diff --git a/geonode/proxy/tests.py b/geonode/proxy/tests.py index 73ef8ba989c..637fa54b8c1 100644 --- a/geonode/proxy/tests.py +++ b/geonode/proxy/tests.py @@ -178,6 +178,62 @@ class Response: }, ) + def test_proxy_url_forgery(self): + """The GeoNode Proxy should preserve the original request headers.""" + import geonode.proxy.views + from urllib.parse import urlsplit + + class Response: + status_code = 200 + content = "Hello World" + headers = { + "Content-Type": "text/plain", + "Vary": "Authorization, Accept-Language, Cookie, origin", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "1; mode=block", + "Referrer-Policy": "same-origin", + "X-Frame-Options": "SAMEORIGIN", + "Content-Language": "en-us", + "Content-Length": "119", + "Content-Disposition": 'attachment; filename="filename.tif"', + } + + request_mock = MagicMock() + request_mock.return_value = (Response(), None) + + # Non-Legit requests attempting SSRF + geonode.proxy.views.http_client.request = request_mock + url = f"http://example.org\\@%23{urlsplit(settings.SITEURL).hostname}" + + response = self.client.get(f"{self.proxy_url}?url={url}") + self.assertEqual(response.status_code, 403) + + url = f"http://125.126.127.128\\@%23{urlsplit(settings.SITEURL).hostname}" + + response = self.client.get(f"{self.proxy_url}?url={url}") + self.assertEqual(response.status_code, 403) + + url = f"{settings.SITEURL.rstrip('/')}@db/" + + response = self.client.get(f"{self.proxy_url}?url={url}") + self.assertEqual(response.status_code, 403) + + url = f"{settings.SITEURL.rstrip('/')}%40db/" + + response = self.client.get(f"{self.proxy_url}?url={url}") + self.assertEqual(response.status_code, 403) + + # Legit requests using the local host (SITEURL) + url = f"/\\@%23{urlsplit(settings.SITEURL).hostname}" + + response = self.client.get(f"{self.proxy_url}?url={url}") + self.assertEqual(response.status_code, 200) + + url = f"{settings.SITEURL}\\@%23{urlsplit(settings.SITEURL).hostname}" + + response = self.client.get(f"{self.proxy_url}?url={url}") + self.assertEqual(response.status_code, 200) + class DownloadResourceTestCase(GeoNodeBaseTestSupport): def setUp(self): diff --git a/geonode/proxy/views.py b/geonode/proxy/views.py index 10030f3dc25..fc49163f01b 100644 --- a/geonode/proxy/views.py +++ b/geonode/proxy/views.py @@ -40,7 +40,14 @@ from geonode.upload.models import Upload from geonode.base.models import ResourceBase from geonode.storage.manager import storage_manager -from geonode.utils import resolve_object, check_ogc_backend, get_headers, http_client, json_response +from geonode.utils import ( + resolve_object, + check_ogc_backend, + get_headers, + http_client, + json_response, + extract_ip_or_domain, +) from geonode.base.enumerations import LINK_TYPES as _LT from geonode import geoserver # noqa @@ -130,7 +137,7 @@ def proxy( _remote_host = urlsplit(_s.base_url).hostname PROXY_ALLOWED_HOSTS += (_remote_host,) - if not validate_host(url.hostname, PROXY_ALLOWED_HOSTS): + if not validate_host(extract_ip_or_domain(raw_url), PROXY_ALLOWED_HOSTS): return HttpResponse( "DEBUG is set to False but the host of the path provided to the proxy service" " is not in the PROXY_ALLOWED_HOSTS setting.", diff --git a/geonode/utils.py b/geonode/utils.py index 8dc2443e884..60a501d863a 100755 --- a/geonode/utils.py +++ b/geonode/utils.py @@ -34,6 +34,7 @@ import datetime import requests import tempfile +import ipaddress import traceback import subprocess @@ -87,6 +88,7 @@ urlparse, urlsplit, urlencode, + urlunparse, parse_qsl, ParseResult, ) @@ -1894,6 +1896,42 @@ def build_absolute_uri(url): return url +def remove_credentials_from_url(url): + # Parse the URL + parsed_url = urlparse(url) + + # Remove the username and password from the parsed URL + parsed_url = parsed_url._replace(netloc=parsed_url.netloc.split("@")[-1]) + + # Reconstruct the URL without credentials + cleaned_url = urlunparse(parsed_url) + + return cleaned_url + + +def extract_ip_or_domain(url): + # Decode the URL to handle percent-encoded characters + _url = remove_credentials_from_url(unquote(url)) + + ip_regex = re.compile("^(?:http://|https://)(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})") + domain_regex = re.compile("^(?:http://|https://)([a-zA-Z0-9.-]+)") + + match = ip_regex.findall(_url) + if len(match): + ip_address = match[0] + try: + ipaddress.ip_address(ip_address) # Validate the IP address + return ip_address + except ValueError: + pass + + match = domain_regex.findall(_url) + if len(match): + return match[0] + + return None + + def get_xpath_value( element: etree.Element, xpath_expression: str, nsmap: typing.Optional[dict] = None ) -> typing.Optional[str]: From a6c68f2adad85aae80538056c60f8299afe4d04b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 15 Sep 2023 21:08:29 +0200 Subject: [PATCH 045/253] Update .env_test (#11495) (#11496) (cherry picked from commit 88658844e734d4bf26a3e6781826941c29e04d0b) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- .env_test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env_test b/.env_test index 80f7470e485..c746bfdfe79 100644 --- a/.env_test +++ b/.env_test @@ -47,7 +47,7 @@ ASYNC_SIGNALS=True SITEURL=http://localhost:8001/ -ALLOWED_HOSTS="['django', 'localhost']" +ALLOWED_HOSTS="['django', 'localhost', '127.0.0.1']" # Data Uploader DEFAULT_BACKEND_UPLOADER=geonode.importer From 7ca66b8c761c61d68695337561356b04f260dec2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 09:56:09 +0200 Subject: [PATCH 046/253] [Fixes #11430] Improve metadata template for geoapp (#11489) (#11490) * [Fixes #11430] Improve metadata template for geoapp * [Fixes #11430] Remove typo * [Fixes #11430] add block for doc (cherry picked from commit 66ccb3cb9484ed91f03890677a3fd2db76a533d0) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/documents/templates/layouts/doc_panels.html | 2 ++ geonode/geoapps/templates/layouts/app_panels.html | 2 ++ 2 files changed, 4 insertions(+) diff --git a/geonode/documents/templates/layouts/doc_panels.html b/geonode/documents/templates/layouts/doc_panels.html index d02d01085fc..2a3a7b08004 100644 --- a/geonode/documents/templates/layouts/doc_panels.html +++ b/geonode/documents/templates/layouts/doc_panels.html @@ -514,6 +514,7 @@ {% endblock doc_supplemental_information %}
    + {% block doc_temporal_block %}
    {% block doc_temporal_extent_start %}
    @@ -532,6 +533,7 @@
    {% endblock doc_temporal_extent_end %}
    + {% endblock %}
    {% block doc_maintenance_frequency %}
    diff --git a/geonode/geoapps/templates/layouts/app_panels.html b/geonode/geoapps/templates/layouts/app_panels.html index cb8aa41f766..e5ea2378882 100644 --- a/geonode/geoapps/templates/layouts/app_panels.html +++ b/geonode/geoapps/templates/layouts/app_panels.html @@ -498,6 +498,7 @@ {% endblock maintenance_block %}
    + {% block geoapp_poc %}
    {% trans "Responsible Parties" %}
    @@ -505,6 +506,7 @@ {{ geoapp_form.poc }}
    + {% endblock %}
    {% trans "Responsible and Permissions" %}
    From 24203707877a344bce058a816dd79eeb78b3dd5e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 29 Sep 2022 14:22:48 +0200 Subject: [PATCH 047/253] [Fixes #10066][Depencendies] Security audit and checks (#10067) (#10072) * [Fixes #10066][Depencendies] Security audit and checks * -SNYK security fix Co-authored-by: Alessio Fabiani --- setup.cfg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup.cfg b/setup.cfg index f6d5f90abf2..68e7cfb03fd 100644 --- a/setup.cfg +++ b/setup.cfg @@ -202,6 +202,11 @@ install_requires = certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability jwcrypto>=1.4 # not directly required, pinned by Snyk to avoid a vulnerability + # Security and audit + mistune==2.0.3 + protobuf==4.21.6 + mako==1.2.3 + [options.packages.find] exclude = tests From d67189df76853cf5d4958f9be80c07f15ad17893 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 10:10:12 +0200 Subject: [PATCH 048/253] [Fixes #10055] Modify Metadata form with permissions check (#10057) (#10076) * -[Fixes #10055] Modify Metadata form with permissions check * - check user in form * - update tests * - add tests Co-authored-by: Giovanni Allegri Co-authored-by: NAGGINDA MARTHA Co-authored-by: Giovanni Allegri --- geonode/base/forms.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/geonode/base/forms.py b/geonode/base/forms.py index c888d816670..b0c91ff7d0f 100644 --- a/geonode/base/forms.py +++ b/geonode/base/forms.py @@ -470,6 +470,9 @@ def __init__(self, *args, **kwargs): if field in ["poc", "owner"] and not self.can_change_perms: self.fields[field].disabled = True + if field in ['poc', 'owner'] and not self.can_change_perms: + self.fields[field].disabled = True + def disable_keywords_widget_for_non_superuser(self, user): if settings.FREETEXT_KEYWORDS_READONLY and not user.is_superuser: self["keywords"].field.disabled = True From 4324f80602a6e8d40e34d9961bf13d0f7c647ce3 Mon Sep 17 00:00:00 2001 From: Alessio Fabiani Date: Mon, 10 Oct 2022 16:08:20 +0200 Subject: [PATCH 049/253] [Dependencies] Align setup.cfg to requirements.txt (#10124) (#10128) (cherry picked from commit e66dd985393d7728ddce2cd1f33b737cbb2b5f6e) # Conflicts: # requirements.txt --- setup.cfg | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 68e7cfb03fd..5421d529fdf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -203,8 +203,9 @@ install_requires = jwcrypto>=1.4 # not directly required, pinned by Snyk to avoid a vulnerability # Security and audit - mistune==2.0.3 - protobuf==4.21.6 + mistune==2.0.4 + wandb==0.12.17 + protobuf==3.20.3 mako==1.2.3 [options.packages.find] From e6809ad3656bb0e22e2cab567caaf172eb46d7b9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 12 Oct 2022 09:27:35 +0200 Subject: [PATCH 050/253] [Fixes #7852] Update catalog and background layers url configuration in settings.py and related files (#9950) (#10129) * -[Fixes #7852] Update catalog and background layers url configuration in settings.py and related files * - update geoid url Co-authored-by: NAGGINDA MARTHA --- geonode/local_settings.py.geoserver.sample | 8 -------- 1 file changed, 8 deletions(-) diff --git a/geonode/local_settings.py.geoserver.sample b/geonode/local_settings.py.geoserver.sample index 733589d6d36..7b45e3d77af 100644 --- a/geonode/local_settings.py.geoserver.sample +++ b/geonode/local_settings.py.geoserver.sample @@ -316,14 +316,6 @@ if GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY == 'mapstore': GEONODE_CATALOGUE_SERVICE = get_geonode_catalogue_service() - MAPSTORE_CATALOGUE_SERVICES = {} - - MAPSTORE_CATALOGUE_SELECTED_SERVICE = "" - - if GEONODE_CATALOGUE_SERVICE: - MAPSTORE_CATALOGUE_SERVICES[list(GEONODE_CATALOGUE_SERVICE.keys())[0]] = GEONODE_CATALOGUE_SERVICE[list(GEONODE_CATALOGUE_SERVICE.keys())[0]] - MAPSTORE_CATALOGUE_SELECTED_SERVICE = list(GEONODE_CATALOGUE_SERVICE.keys())[0] - DEFAULT_MS2_BACKGROUNDS = [ { "type": "tileprovider", From 2dd52654b2e27181aa0bc3dd28b467571451271b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 17 Oct 2022 12:54:00 +0200 Subject: [PATCH 051/253] =?UTF-8?q?[Fixes=20#10142]=20storage=5Fmanager=20?= =?UTF-8?q?copy=20dont=20assign=20the=20folder/file=20permi=E2=80=A6=20(#1?= =?UTF-8?q?0143)=20(#10154)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/storage/tests.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/geonode/storage/tests.py b/geonode/storage/tests.py index 89eea61d4ad..c2e6c93b459 100644 --- a/geonode/storage/tests.py +++ b/geonode/storage/tests.py @@ -416,6 +416,22 @@ def test_storage_manager_copy(self): os.remove(output.get("files")[0]) self.assertFalse(os.path.exists(output.get("files")[0])) + @override_settings(FILE_UPLOAD_DIRECTORY_PERMISSIONS=0o777) + @override_settings(FILE_UPLOAD_PERMISSIONS=0o777) + def test_storage_manager_copy(self): + ''' + Test that the copy works as expected and the permissions are corerct + ''' + dataset = create_single_dataset(name="test_copy") + dataset.files = [os.path.join(f"{self.project_root}", "tests/data/test_sld.sld")] + dataset.save() + output = self.sut().copy(dataset) + + self.assertTrue(os.path.exists(output.get("files")[0])) + self.assertEqual(os.stat(os.path.exists(output.get("files")[0])).st_mode, 8592) + os.remove(output.get("files")[0]) + self.assertFalse(os.path.exists(output.get("files")[0])) + class TestDataRetriever(TestCase): @classmethod From 8d7de88c83917c63491a052e15220934d11df9d3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 18 Oct 2022 11:44:16 +0200 Subject: [PATCH 052/253] Align requirements.txt comments with 4.x (#10162) (#10163) Co-authored-by: Alessio Fabiani --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 5421d529fdf..3fc13d93b40 100644 --- a/setup.cfg +++ b/setup.cfg @@ -204,7 +204,7 @@ install_requires = # Security and audit mistune==2.0.4 - wandb==0.12.17 + wandb==0.13.4 protobuf==3.20.3 mako==1.2.3 From d5ec478b2f5e5cb506ff64c18e42f18f53590ade Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 27 Oct 2022 15:19:18 +0200 Subject: [PATCH 053/253] [Fixes #10204] restore mapstore catalog settings (#10205) (#10206) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/local_settings.py.geoserver.sample | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/geonode/local_settings.py.geoserver.sample b/geonode/local_settings.py.geoserver.sample index 7b45e3d77af..733589d6d36 100644 --- a/geonode/local_settings.py.geoserver.sample +++ b/geonode/local_settings.py.geoserver.sample @@ -316,6 +316,14 @@ if GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY == 'mapstore': GEONODE_CATALOGUE_SERVICE = get_geonode_catalogue_service() + MAPSTORE_CATALOGUE_SERVICES = {} + + MAPSTORE_CATALOGUE_SELECTED_SERVICE = "" + + if GEONODE_CATALOGUE_SERVICE: + MAPSTORE_CATALOGUE_SERVICES[list(GEONODE_CATALOGUE_SERVICE.keys())[0]] = GEONODE_CATALOGUE_SERVICE[list(GEONODE_CATALOGUE_SERVICE.keys())[0]] + MAPSTORE_CATALOGUE_SELECTED_SERVICE = list(GEONODE_CATALOGUE_SERVICE.keys())[0] + DEFAULT_MS2_BACKGROUNDS = [ { "type": "tileprovider", From 4c1eb93869f3d156309e62099d9c43a5d392622f Mon Sep 17 00:00:00 2001 From: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Date: Fri, 4 Nov 2022 16:55:34 +0100 Subject: [PATCH 054/253] [4.0.x][Fixes #10208] Add a custom hook at the end of the permissions assign (#10212) * [Fixes #10208] Add a custom hook at the end of the permissions assign --- geonode/geoserver/signals.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/geonode/geoserver/signals.py b/geonode/geoserver/signals.py index 70b96060303..591a1e12552 100644 --- a/geonode/geoserver/signals.py +++ b/geonode/geoserver/signals.py @@ -42,6 +42,8 @@ geofence_rule_assign = Signal(providing_args=["instance"]) +post_set_permissions = Signal(providing_args=['instance']) + def geoserver_delete(typename): # cascading_delete should only be called if From fad9b26744c184fcce283802ac6ffdf696806866 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Nov 2022 10:04:04 +0100 Subject: [PATCH 055/253] Fix broken test (#10266) (#10267) * Fix broken test build * Fix broken test build Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/security/tests.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/geonode/security/tests.py b/geonode/security/tests.py index 52b43a38551..3865528f803 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -1748,6 +1748,15 @@ def test_admin_whitelisted_access_middleware(self): middleware.process_request(request) self.assertTrue(request.user.is_superuser) + # Test valid IP in second element + with self.settings(ADMIN_IP_WHITELIST=['88.88.88.88', '127.0.0.1']): + request = HttpRequest() + request.user = admin + request.path = reverse('home') + request.META['REMOTE_ADDR'] = '127.0.0.1' + middleware.process_request(request) + self.assertTrue(request.user.is_superuser) + class SecurityRulesTests(TestCase): """ From e1e17dc06a0a4fbaff03019c922457c03efc5f68 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 9 Nov 2022 15:04:09 +0100 Subject: [PATCH 056/253] [Fixes #10251] improve feedback to the user and UI experience of batch permisisons assignment (#10281) (#10282) * [Fixes #10251] improve feedback to the user and UI experience * [Fixes #10251] improve feedback to the user and UI experience * [Fixes #10251] improve feedback to the user and UI experience Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/base/views.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/geonode/base/views.py b/geonode/base/views.py index 7d5d08aa692..0a7f6fa8b43 100644 --- a/geonode/base/views.py +++ b/geonode/base/views.py @@ -333,6 +333,20 @@ def get_results(self, context): ] +class DatasetsAutocomplete(SimpleSelect2View): + model = Dataset + filter_arg = 'title__icontains' + + def get_results(self, context): + return [ + { + 'id': self.get_result_value(result), + 'text': self.get_result_label(result.title), + 'selected_text': self.get_selected_result_label(result.title), + } for result in context['object_list'] + ] + + class ThesaurusAvailable(autocomplete.Select2QuerySetView): def get_queryset(self): tid = self.request.GET.get("sysid") From 41de59aec19ef016cac91d07f8fe0f2fffe4eae7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 9 Nov 2022 17:10:36 +0100 Subject: [PATCH 057/253] [Dependencies] Align setup.cfg to requirements.txt (#10284) (#10286) Co-authored-by: Alessio Fabiani --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 3fc13d93b40..04c8832e443 100644 --- a/setup.cfg +++ b/setup.cfg @@ -204,7 +204,7 @@ install_requires = # Security and audit mistune==2.0.4 - wandb==0.13.4 + wandb==0.13.5 protobuf==3.20.3 mako==1.2.3 From ac19068938c8a893e1cdaf411bdac93d9ad94b30 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 14 Nov 2022 22:05:05 +0100 Subject: [PATCH 058/253] [Fixes #10270] Document creation via API v2 (#10271) (#10298) * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 Co-authored-by: Alessio Fabiani Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Co-authored-by: Alessio Fabiani --- geonode/documents/api/tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/geonode/documents/api/tests.py b/geonode/documents/api/tests.py index dbb3b13588b..5ab59dfbbb4 100644 --- a/geonode/documents/api/tests.py +++ b/geonode/documents/api/tests.py @@ -16,6 +16,8 @@ # along with this program. If not, see . # ######################################################################### +import os +from django.contrib.auth import get_user_model import logging from django.contrib.auth import get_user_model From ff264770acf114fd69a8ed59a969ce4cc431f417 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 21 Nov 2022 17:33:14 +0100 Subject: [PATCH 059/253] [Fixes #10303] automatic periodic TaskResult removal (#10306) (#10319) * [Fixes #10303] automatic periodic TaskResult removal * [Fixes #10303] automatic periodic TaskResult removal * [Fixes #10303] automatic periodic TaskResult removal * [Fixes #10303] fix flake8 formatting Co-authored-by: Alessio Fabiani Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Co-authored-by: Alessio Fabiani --- geonode/upload/__init__.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/geonode/upload/__init__.py b/geonode/upload/__init__.py index c50c3f5609f..ec9e9b79a26 100644 --- a/geonode/upload/__init__.py +++ b/geonode/upload/__init__.py @@ -63,6 +63,19 @@ def run_setup_hooks(sender, **kwargs): start_time=timezone.now(), ), ) + daily_interval, _ = IntervalSchedule.objects.get_or_create( + every=1, + period="days" + ) + PeriodicTask.objects.update_or_create( + name="clean-up-old-task-result", + defaults=dict( + task="geonode.upload.tasks.cleanup_celery_task_entries", + interval=daily_interval, + args='', + start_time=timezone.now() + ) + ) class UploadAppConfig(AppConfig): @@ -79,6 +92,10 @@ def ready(self): "task": "geonode.upload.tasks.cleanup_celery_task_entries", "schedule": 86400.0, } + settings.CELERY_BEAT_SCHEDULE['clean-up-old-task-result'] = { + 'task': 'geonode.upload.tasks.cleanup_celery_task_entries', + 'schedule': 86400.0, + } default_app_config = "geonode.upload.UploadAppConfig" From 1803b7866e0fad49c9f118bf20fc569af68bb68e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 23 Nov 2022 12:22:48 +0100 Subject: [PATCH 060/253] [Dependencies] Align setup.cfg with requirements.txt (#10339) (#10341) (#10344) Co-authored-by: Alessio Fabiani Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 04c8832e443..4fedf52c369 100644 --- a/setup.cfg +++ b/setup.cfg @@ -206,7 +206,7 @@ install_requires = mistune==2.0.4 wandb==0.13.5 protobuf==3.20.3 - mako==1.2.3 + mako==1.2.4 [options.packages.find] exclude = tests From d4bda0f14339ae3e5185b6f032dd7344ab634dcd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 Dec 2022 12:25:33 +0100 Subject: [PATCH 061/253] [Dependencies] Align setup.cfg to requirements.txt (#10417) (#10419) Co-authored-by: Alessio Fabiani --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 4fedf52c369..9d972a40f7c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -204,7 +204,7 @@ install_requires = # Security and audit mistune==2.0.4 - wandb==0.13.5 + wandb==0.13.6 protobuf==3.20.3 mako==1.2.4 From bb4e53c3721e2fbe64aa63e0f72bd0e28ab628af Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Dec 2022 12:15:39 +0100 Subject: [PATCH 062/253] [Dependencies] Align setup.cfg to requirements.txt (#10444) (#10445) Co-authored-by: Alessio Fabiani --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 9d972a40f7c..91c2bfcedd9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -204,7 +204,7 @@ install_requires = # Security and audit mistune==2.0.4 - wandb==0.13.6 + wandb==0.13.7 protobuf==3.20.3 mako==1.2.4 From 47035eb9b66b52116bb8e6358e6bb78815ffffc4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 18 Jan 2023 10:27:51 +0100 Subject: [PATCH 063/253] [Dependencies] Align "setup.cfg" to "requirements.txt" (#10555) (#10558) (cherry picked from commit 33d4aa9b4fca04f5cc282b5607ff5d1e72e80e6e) Co-authored-by: Alessio Fabiani --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 91c2bfcedd9..3509d6bfae7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -204,7 +204,7 @@ install_requires = # Security and audit mistune==2.0.4 - wandb==0.13.7 + wandb==0.13.9 protobuf==3.20.3 mako==1.2.4 From 6ebdd0902bf5583510756868d9b59d0225270c6b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 23 Jan 2023 11:21:53 +0100 Subject: [PATCH 064/253] [Fixes #10537] Improve rules creation using GeoFence batch (#10538) (#10567) * [Fixes #10537] Improve rules creation using GeoFence batch * - code improvements accordingly to the PR comments * - code improvements accordingly to the PR comments * - Test fixes Co-authored-by: afabiani (cherry picked from commit d101ead2e2552f3d4f9b6cd355ce1eced3dbaecf) Co-authored-by: Emanuele Tajariol --- geonode/geoserver/helpers.py | 1 + geonode/security/tests.py | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index e46179532c1..30dc6bffa06 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -1874,6 +1874,7 @@ def get_time_info(layer): url, _user, _password, retries=ogc_server_settings.MAX_RETRIES, backoff_factor=ogc_server_settings.BACKOFF_FACTOR ) gs_uploader = Client(url, _user, _password) +gf_client = GeofenceClient(url, _user, _password) def _create_geofence_client(): diff --git a/geonode/security/tests.py b/geonode/security/tests.py index 3865528f803..4651e1f28d0 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -88,6 +88,16 @@ def _log(msg, *args): logger.debug(msg, *args) +def get_geofence_rules_count(): + from geonode.geoserver.helpers import gf_client + return gf_client.get_rules_count() + + +def get_geofence_rules(): + from geonode.geoserver.helpers import gf_client + return gf_client.get_rules() + + class StreamToLogger: """ Fake file-like stream object that redirects writes to a logger instance. From 554df0b7ada76a0897f48db30034ef0cc1e514cc Mon Sep 17 00:00:00 2001 From: Alessio Fabiani Date: Tue, 24 Jan 2023 12:06:22 +0100 Subject: [PATCH 065/253] Backport 10575 to 4.1.x (#10579) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump oauthlib from 3.2.0 to 3.2.1 (#9998) Bumps [oauthlib](https://github.com/oauthlib/oauthlib) from 3.2.0 to 3.2.1. - [Release notes](https://github.com/oauthlib/oauthlib/releases) - [Changelog](https://github.com/oauthlib/oauthlib/blob/master/CHANGELOG.rst) - [Commits](https://github.com/oauthlib/oauthlib/compare/v3.2.0...v3.2.1) --- updated-dependencies: - dependency-name: oauthlib dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump jsonschema from 4.15.0 to 4.16.0 (#9999) Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.15.0 to 4.16.0. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.15.0...v4.16.0) --- updated-dependencies: - dependency-name: jsonschema dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytest-splinter from 3.3.1 to 3.3.2 (#10000) Bumps [pytest-splinter](https://github.com/pytest-dev/pytest-splinter) from 3.3.1 to 3.3.2. - [Release notes](https://github.com/pytest-dev/pytest-splinter/releases) - [Changelog](https://github.com/pytest-dev/pytest-splinter/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-splinter/compare/3.3.1...3.3.2) --- updated-dependencies: - dependency-name: pytest-splinter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump dropbox from 11.33.0 to 11.34.0 (#10001) Bumps [dropbox](https://github.com/dropbox/dropbox-sdk-python) from 11.33.0 to 11.34.0. - [Release notes](https://github.com/dropbox/dropbox-sdk-python/releases) - [Commits](https://github.com/dropbox/dropbox-sdk-python/compare/v11.33.0...v11.34.0) --- updated-dependencies: - dependency-name: dropbox dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump django-select2 from 7.10.0 to 7.10.1 (#10006) Bumps [django-select2](https://github.com/codingjoe/django-select2) from 7.10.0 to 7.10.1. - [Release notes](https://github.com/codingjoe/django-select2/releases) - [Commits](https://github.com/codingjoe/django-select2/compare/7.10.0...7.10.1) --- updated-dependencies: - dependency-name: django-select2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update pyproj requirement from <3.3.0 to <3.5.0 (#10002) Updates the requirements on [pyproj](https://github.com/pyproj4/pyproj) to permit the latest version. - [Release notes](https://github.com/pyproj4/pyproj/releases) - [Changelog](https://github.com/pyproj4/pyproj/blob/main/docs/history.rst) - [Commits](https://github.com/pyproj4/pyproj/compare/v1.9.4rel...3.4.0) --- updated-dependencies: - dependency-name: pyproj dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump sqlalchemy from 1.4.40 to 1.4.41 (#10005) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.40 to 1.4.41. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump twisted from 22.4.0 to 22.8.0 (#10007) Bumps [twisted](https://github.com/twisted/twisted) from 22.4.0 to 22.8.0. - [Release notes](https://github.com/twisted/twisted/releases) - [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst) - [Commits](https://github.com/twisted/twisted/compare/twisted-22.4.0...twisted-22.8.0) --- updated-dependencies: - dependency-name: twisted dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump ipython from 8.4.0 to 8.5.0 (#10004) Bumps [ipython](https://github.com/ipython/ipython) from 8.4.0 to 8.5.0. - [Release notes](https://github.com/ipython/ipython/releases) - [Commits](https://github.com/ipython/ipython/compare/8.4.0...8.5.0) --- updated-dependencies: - dependency-name: ipython dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.24.66 to 1.24.70 (#10003) Bumps [boto3](https://github.com/boto/boto3) from 1.24.66 to 1.24.70. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.24.66...1.24.70) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align setup.cfg to requirements.txt (#10019) * Bump to version 4.0.1 (cherry picked from commit 43cb8049b488b23bbc4886ca9e28d95f8329cf65) * Bump to version 4.0.2 dev 0 (cherry picked from commit c4bd604e1aa453cd9c6b718792e156e8bdf86e3b) # Conflicts: # requirements.txt # setup.cfg * Bump boto3 from 1.24.70 to 1.24.75 (#10031) Bumps [boto3](https://github.com/boto/boto3) from 1.24.70 to 1.24.75. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.24.70...1.24.75) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump smart-open from 6.1.0 to 6.2.0 (#10030) Bumps [smart-open](https://github.com/piskvorky/smart_open) from 6.1.0 to 6.2.0. - [Release notes](https://github.com/piskvorky/smart_open/releases) - [Changelog](https://github.com/RaRe-Technologies/smart_open/blob/develop/CHANGELOG.md) - [Commits](https://github.com/piskvorky/smart_open/compare/v6.1.0...v6.2.0) --- updated-dependencies: - dependency-name: smart-open dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump drf-spectacular from 0.23.1 to 0.24.0 (#10029) Bumps [drf-spectacular](https://github.com/tfranzel/drf-spectacular) from 0.23.1 to 0.24.0. - [Release notes](https://github.com/tfranzel/drf-spectacular/releases) - [Changelog](https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst) - [Commits](https://github.com/tfranzel/drf-spectacular/compare/0.23.1...0.24.0) --- updated-dependencies: - dependency-name: drf-spectacular dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update idna requirement from <2.11,>=2.5 to >=2.5,<3.5 (#10028) Updates the requirements on [idna](https://github.com/kjd/idna) to permit the latest version. - [Release notes](https://github.com/kjd/idna/releases) - [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.rst) - [Commits](https://github.com/kjd/idna/compare/v2.5...v3.4) --- updated-dependencies: - dependency-name: idna dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pyjwt from 2.4.0 to 2.5.0 (#10027) Bumps [pyjwt](https://github.com/jpadilla/pyjwt) from 2.4.0 to 2.5.0. - [Release notes](https://github.com/jpadilla/pyjwt/releases) - [Changelog](https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst) - [Commits](https://github.com/jpadilla/pyjwt/compare/2.4.0...2.5.0) --- updated-dependencies: - dependency-name: pyjwt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * [Fixes #10024] Wrong default style when creating layer (#10035) (cherry picked from commit 40fae5b3240ddf5b033688ce1891d7e7f1cfc304) Co-authored-by: Alessio Fabiani * add installation type to issue template (#10042) * [Dependencies] Align setup.cfg with requirements.txt (#10038) * [Fixes #10040] Remove auto-generated thumbnail for documents (#10045) * -[Fixes #10040] Remove auto-generated thumbnail for documents * - add migration to clean available thumbs * - fix migration * - modify functionality * Bump drf-spectacular from 0.24.0 to 0.24.1 (#10051) Bumps [drf-spectacular](https://github.com/tfranzel/drf-spectacular) from 0.24.0 to 0.24.1. - [Release notes](https://github.com/tfranzel/drf-spectacular/releases) - [Changelog](https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst) - [Commits](https://github.com/tfranzel/drf-spectacular/compare/0.24.0...0.24.1) --- updated-dependencies: - dependency-name: drf-spectacular dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Update setuptools requirement from <65.4.0,>=59.1.1 to >=59.1.1,<65.5.0 (#10047) Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v59.1.1...v65.4.0) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.24.75 to 1.24.80 (#10050) Bumps [boto3](https://github.com/boto/boto3) from 1.24.75 to 1.24.80. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.24.75...1.24.80) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pyopenssl from 22.0.0 to 22.1.0 (#10049) Bumps [pyopenssl](https://github.com/pyca/pyopenssl) from 22.0.0 to 22.1.0. - [Release notes](https://github.com/pyca/pyopenssl/releases) - [Changelog](https://github.com/pyca/pyopenssl/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/pyopenssl/compare/22.0.0...22.1.0) --- updated-dependencies: - dependency-name: pyopenssl dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Bump djangorestframework from 3.12.0 to 3.14.0 (#10048) Bumps [djangorestframework](https://github.com/encode/django-rest-framework) from 3.12.0 to 3.14.0. - [Release notes](https://github.com/encode/django-rest-framework/releases) - [Commits](https://github.com/encode/django-rest-framework/compare/3.12.0...3.14.0) --- updated-dependencies: - dependency-name: djangorestframework dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Revert "Bump djangorestframework from 3.12.0 to 3.14.0 (#10048)" (#10062) This reverts commit 75566560538b38c59873ed9fb7951acc3ba0edfa. * [Dependencies] Align setup.cfg with requirements.txt (#10061) * [Dependencies] Align setup.cfg with requirements.txt * Revert "Bump djangorestframework from 3.12.0 to 3.14.0" * [CLA] Add "edsonflavio" to .clabot * Complete Translate pt_BR (#10056) Tradução completa da localização para Português Brasileiro. Complete translate for pt_BR localization. Co-authored-by: Alessio Fabiani * [Fixes #10041] Review the thumbnail scaling process (#10046) * -[Fixes #10040] Remove auto-generated thumbnail for documents * - update thumbnail pixels * - add tests * - fix-tests * - fix-tests * [Fixes #10066][Depencendies] Security audit and checks (#10067) * [Fixes #10066][Depencendies] Security audit and checks * -SNYK security fix * [Fixes #10055] Modify Metadata form with permissions check (#10057) * -[Fixes #10055] Modify Metadata form with permissions check * - check user in form * - update tests * - add tests Co-authored-by: Giovanni Allegri * Bump django-mptt from 0.13.4 to 0.14.0 (#10081) Bumps [django-mptt](https://github.com/django-mptt/django-mptt) from 0.13.4 to 0.14.0. - [Release notes](https://github.com/django-mptt/django-mptt/releases) - [Changelog](https://github.com/django-mptt/django-mptt/blob/main/CHANGELOG.rst) - [Commits](https://github.com/django-mptt/django-mptt/compare/0.13.4...0.14) --- updated-dependencies: - dependency-name: django-mptt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Fixes #10070] Let the resource manager handle also raw sld (#10071) * [Fixes #10070] Let the resource manager handle also raw sld * [Fixes #10070] Let the resource manager handle also raw sld * [Fixes #10070] Let the resource manager handle also raw sld * Update django-invitations requirement from <1.9.4 to <2.0.1 (#10084) * Update django-invitations requirement from <1.9.4 to <2.0.1 Updates the requirements on [django-invitations](https://github.com/jazzband/django-invitations) to permit the latest version. - [Release notes](https://github.com/jazzband/django-invitations/releases) - [Changelog](https://github.com/jazzband/django-invitations/blob/master/CHANGELOG.md) - [Commits](https://github.com/jazzband/django-invitations/compare/0.1...2.0.0) --- updated-dependencies: - dependency-name: django-invitations dependency-type: direct:production ... Signed-off-by: dependabot[bot] * - fix the adapter Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani * fix: requirements.txt to reduce vulnerabilities (#10099) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-DJANGO-3039675 * Bump drf-spectacular from 0.24.1 to 0.24.2 (#10088) Bumps [drf-spectacular](https://github.com/tfranzel/drf-spectacular) from 0.24.1 to 0.24.2. - [Release notes](https://github.com/tfranzel/drf-spectacular/releases) - [Changelog](https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst) - [Commits](https://github.com/tfranzel/drf-spectacular/compare/0.24.1...0.24.2) --- updated-dependencies: - dependency-name: drf-spectacular dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Bump invoke from 1.7.1 to 1.7.3 (#10086) Bumps [invoke](https://github.com/pyinvoke/invoke) from 1.7.1 to 1.7.3. - [Release notes](https://github.com/pyinvoke/invoke/releases) - [Commits](https://github.com/pyinvoke/invoke/compare/1.7.1...1.7.3) --- updated-dependencies: - dependency-name: invoke dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump protobuf from 4.21.6 to 4.21.7 (#10085) Bumps [protobuf](https://github.com/protocolbuffers/protobuf) from 4.21.6 to 4.21.7. - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/generate_changelog.py) - [Commits](https://github.com/protocolbuffers/protobuf/commits) --- updated-dependencies: - dependency-name: protobuf dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytz from 2022.2.1 to 2022.4 (#10083) Bumps [pytz](https://github.com/stub42/pytz) from 2022.2.1 to 2022.4. - [Release notes](https://github.com/stub42/pytz/releases) - [Commits](https://github.com/stub42/pytz/commits) --- updated-dependencies: - dependency-name: pytz dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * -[Fixes #10073] Unable to view Maps tab in Recent activities (#10074) Co-authored-by: Giovanni Allegri Co-authored-by: Alessio Fabiani * Bump mistune from 2.0.3 to 2.0.4 (#10082) Bumps [mistune](https://github.com/lepture/mistune) from 2.0.3 to 2.0.4. - [Release notes](https://github.com/lepture/mistune/releases) - [Changelog](https://github.com/lepture/mistune/blob/v2.0.4/docs/changes.rst) - [Commits](https://github.com/lepture/mistune/compare/v2.0.3...v2.0.4) --- updated-dependencies: - dependency-name: mistune dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * [Fixes #10091] improve thumbnails quality (#10092) * improve thumbnails quality * force convertion to jpeg * - update tests * - fix tests Co-authored-by: marthamareal Co-authored-by: Alessio Fabiani * [Fixes #10075] Improvements to the upload time step UI (#10094) * -[Fixes #10075] Improvements to the upload time step UI * clarify why user is inside this step Co-authored-by: Giovanni Allegri Co-authored-by: Alessio Fabiani * Bump coverage from 6.4.4 to 6.5.0 (#10079) Bumps [coverage](https://github.com/nedbat/coveragepy) from 6.4.4 to 6.5.0. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/6.4.4...6.5.0) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * [Fixes #10113] Data retriver keep kmz files even if is unzipped (#10114) * [Fixes #10113] Data retriever keeps kmz files even if are unzipped * Bump sherlock from 0.3.2 to 0.4.0 (#10116) Bumps [sherlock](https://github.com/py-sherlock/sherlock) from 0.3.2 to 0.4.0. - [Release notes](https://github.com/py-sherlock/sherlock/releases) - [Changelog](https://github.com/py-sherlock/sherlock/blob/master/CHANGELOG.rst) - [Commits](https://github.com/py-sherlock/sherlock/commits/v0.4.0) --- updated-dependencies: - dependency-name: sherlock dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * -[Fixes #10104] Sort resource APIs with created date (#10105) Co-authored-by: Alessio Fabiani * Bump requests-toolbelt from 0.9.1 to 0.10.0 (#10118) Bumps [requests-toolbelt](https://github.com/requests/toolbelt) from 0.9.1 to 0.10.0. - [Release notes](https://github.com/requests/toolbelt/releases) - [Changelog](https://github.com/requests/toolbelt/blob/master/HISTORY.rst) - [Commits](https://github.com/requests/toolbelt/compare/0.9.1...0.10.0) --- updated-dependencies: - dependency-name: requests-toolbelt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Bump psycopg2 from 2.9.3 to 2.9.4 (#10117) Bumps [psycopg2](https://github.com/psycopg/psycopg2) from 2.9.3 to 2.9.4. - [Release notes](https://github.com/psycopg/psycopg2/releases) - [Changelog](https://github.com/psycopg/psycopg2/blob/master/NEWS) - [Commits](https://github.com/psycopg/psycopg2/commits) --- updated-dependencies: - dependency-name: psycopg2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.24.80 to 1.24.87 (#10107) Bumps [boto3](https://github.com/boto/boto3) from 1.24.80 to 1.24.87. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.24.80...1.24.87) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * [Dependencies] Align setup.cfg to requirements.txt (#10124) * [Fixes #10120] Celery autoscale values are too low and wrongly positioned (#10121) * [Fixes #7852] Update catalog and background layers url configuration in settings.py and related files (#9950) * -[Fixes #7852] Update catalog and background layers url configuration in settings.py and related files * - update geoid url * [Fixes #10130] Data retriever dont assign the folder/file permissions correcly (#10131) Co-authored-by: Alessio Fabiani * [Fixes #10134] New simple renderer to generate thumbnails for PDFs (#10135) * PDF thumbnail renderer * - add unit tests * command to generate thumbnails for docs * flake fix * renamed management command * add requirement to setup.cfg * make command similar to other sync commands * removed unused import * fix flake8 Co-authored-by: marthamareal * [Fixes #10138] Render pdf thumbnails from top margin (#10139) * render pdf thumbnails from top margin * fix flake * [Fixes #10142] storage_manager copy dont assign the folder/file permi… (#10143) * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * Bump wandb from 0.12.17 to 0.13.4 (#10152) Bumps [wandb](https://github.com/wandb/wandb) from 0.12.17 to 0.13.4. - [Release notes](https://github.com/wandb/wandb/releases) - [Changelog](https://github.com/wandb/wandb/blob/main/CHANGELOG.md) - [Commits](https://github.com/wandb/wandb/compare/v0.12.17...v0.13.4) --- updated-dependencies: - dependency-name: wandb dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Update setuptools requirement from <65.5.0,>=59.1.1 to >=59.1.1,<65.6.0 (#10150) Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v59.1.1...v65.5.0) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pip from 22.2.2 to 22.3 (#10149) Bumps [pip](https://github.com/pypa/pip) from 22.2.2 to 22.3. - [Release notes](https://github.com/pypa/pip/releases) - [Changelog](https://github.com/pypa/pip/blob/main/NEWS.rst) - [Commits](https://github.com/pypa/pip/compare/22.2.2...22.3) --- updated-dependencies: - dependency-name: pip dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump shapely from 1.8.4 to 1.8.5.post1 (#10147) Bumps [shapely](https://github.com/shapely/shapely) from 1.8.4 to 1.8.5.post1. - [Release notes](https://github.com/shapely/shapely/releases) - [Changelog](https://github.com/shapely/shapely/blob/1.8.5.post1/CHANGES.txt) - [Commits](https://github.com/shapely/shapely/compare/1.8.4...1.8.5.post1) --- updated-dependencies: - dependency-name: shapely dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump sqlalchemy from 1.4.41 to 1.4.42 (#10145) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.41 to 1.4.42. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump dropbox from 11.34.0 to 11.35.0 (#10146) Bumps [dropbox](https://github.com/dropbox/dropbox-sdk-python) from 11.34.0 to 11.35.0. - [Release notes](https://github.com/dropbox/dropbox-sdk-python/releases) - [Commits](https://github.com/dropbox/dropbox-sdk-python/compare/v11.34.0...v11.35.0) --- updated-dependencies: - dependency-name: dropbox dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.24.87 to 1.24.91 (#10151) Bumps [boto3](https://github.com/boto/boto3) from 1.24.87 to 1.24.91. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.24.87...1.24.91) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Align requirements.txt comments with 4.x (#10162) * [Fixes #10168] Add 'executions' field to concrete instance endpoints (#10169) * [Fixes #10168] Add 'executions' field to concrete instance endpoints * [Fixes #10168] Add 'executions' field to concrete instance endpoints * [Fixes #10171] Dynamic rendering of document_detail view template (#10172) * add preview mode to document metadata page * Remove Return to button inside metadata detail page * [Hardening] Avoid "backup.py" failing while trying to set "w" perms on the GeoServer catalog file * Fix migrations 4x (#10176) * - Fixing migrations upg 33x -> 4x * fix migration * missing files * - Fixing migrations upg 33x -> 4x * - Fixing migrations upg 33x -> 4x Co-authored-by: mattiagiupponi * [Hardening] Make the migration '0074_drop_curated_thumbs' more robust * [Fixes #10198] uwsgi library update (#10199) * [Fixes #10195] Backup and restore procedure is not successful (#10196) * [Fixes #10195] Backup and restore procedure is not successful * [Fixes #10195] Backup and restore procedure is not successful * [Fixes #10195] Backup and restore procedure is not successful * [Fixes #10195] Backup and restore procedure is not successful * [Fixes #10195] Backup and restore procedure is not successful * [Fixes #10195] test fix build * [Fixes #10204] restore mapstore catalog settings (#10205) * [Fixes #10192] Include source into the ExecutionRequest model (#10193) Co-authored-by: Alessio Fabiani * Bump oauthlib from 3.2.1 to 3.2.2 (#10189) Bumps [oauthlib](https://github.com/oauthlib/oauthlib) from 3.2.1 to 3.2.2. - [Release notes](https://github.com/oauthlib/oauthlib/releases) - [Changelog](https://github.com/oauthlib/oauthlib/blob/v3.2.2/CHANGELOG.rst) - [Commits](https://github.com/oauthlib/oauthlib/compare/v3.2.1...v3.2.2) --- updated-dependencies: - dependency-name: oauthlib dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * fix ip whitelisting (#10218) * Update httplib2 requirement from <0.20.5 to <0.21.1 (#10227) Updates the requirements on [httplib2](https://github.com/httplib2/httplib2) to permit the latest version. - [Release notes](https://github.com/httplib2/httplib2/releases) - [Changelog](https://github.com/httplib2/httplib2/blob/master/CHANGELOG) - [Commits](https://github.com/httplib2/httplib2/compare/0.9...v0.21.0) --- updated-dependencies: - dependency-name: httplib2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Bump pillow from 9.1.1 to 9.3.0 (#10229) Bumps [pillow](https://github.com/python-pillow/Pillow) from 9.1.1 to 9.3.0. - [Release notes](https://github.com/python-pillow/Pillow/releases) - [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) - [Commits](https://github.com/python-pillow/Pillow/compare/9.1.1...9.3.0) --- updated-dependencies: - dependency-name: pillow dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump twisted from 22.8.0 to 22.10.0 (#10233) Bumps [twisted](https://github.com/twisted/twisted) from 22.8.0 to 22.10.0. - [Release notes](https://github.com/twisted/twisted/releases) - [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst) - [Commits](https://github.com/twisted/twisted/compare/twisted-22.8.0...twisted-22.10.0) --- updated-dependencies: - dependency-name: twisted dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.24.91 to 1.26.0 (#10235) Bumps [boto3](https://github.com/boto/boto3) from 1.24.91 to 1.26.0. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.24.91...1.26.0) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytz from 2022.4 to 2022.6 (#10234) Bumps [pytz](https://github.com/stub42/pytz) from 2022.4 to 2022.6. - [Release notes](https://github.com/stub42/pytz/releases) - [Commits](https://github.com/stub42/pytz/compare/release_2022.4...release_2022.6) --- updated-dependencies: - dependency-name: pytz dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump ipython from 8.5.0 to 8.6.0 (#10228) Bumps [ipython](https://github.com/ipython/ipython) from 8.5.0 to 8.6.0. - [Release notes](https://github.com/ipython/ipython/releases) - [Commits](https://github.com/ipython/ipython/compare/8.5.0...8.6.0) --- updated-dependencies: - dependency-name: ipython dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump requests-toolbelt from 0.10.0 to 0.10.1 (#10225) Bumps [requests-toolbelt](https://github.com/requests/toolbelt) from 0.10.0 to 0.10.1. - [Release notes](https://github.com/requests/toolbelt/releases) - [Changelog](https://github.com/requests/toolbelt/blob/master/HISTORY.rst) - [Commits](https://github.com/requests/toolbelt/compare/0.10.0...0.10.1) --- updated-dependencies: - dependency-name: requests-toolbelt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytest from 7.1.3 to 7.2.0 (#10224) Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.1.3 to 7.2.0. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/7.1.3...7.2.0) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump django-select2 from 7.10.1 to 7.11.0 (#10223) Bumps [django-select2](https://github.com/codingjoe/django-select2) from 7.10.1 to 7.11.0. - [Release notes](https://github.com/codingjoe/django-select2/releases) - [Commits](https://github.com/codingjoe/django-select2/compare/7.10.1...7.11.0) --- updated-dependencies: - dependency-name: django-select2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump psycopg2 from 2.9.4 to 2.9.5 (#10222) Bumps [psycopg2](https://github.com/psycopg/psycopg2) from 2.9.4 to 2.9.5. - [Release notes](https://github.com/psycopg/psycopg2/releases) - [Changelog](https://github.com/psycopg/psycopg2/blob/master/NEWS) - [Commits](https://github.com/psycopg/psycopg2/commits) --- updated-dependencies: - dependency-name: psycopg2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pyjwt from 2.5.0 to 2.6.0 (#10186) Bumps [pyjwt](https://github.com/jpadilla/pyjwt) from 2.5.0 to 2.6.0. - [Release notes](https://github.com/jpadilla/pyjwt/releases) - [Changelog](https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst) - [Commits](https://github.com/jpadilla/pyjwt/commits) --- updated-dependencies: - dependency-name: pyjwt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump psutil from 5.9.2 to 5.9.3 (#10185) Bumps [psutil](https://github.com/giampaolo/psutil) from 5.9.2 to 5.9.3. - [Release notes](https://github.com/giampaolo/psutil/releases) - [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst) - [Commits](https://github.com/giampaolo/psutil/compare/release-5.9.2...release-5.9.3) --- updated-dependencies: - dependency-name: psutil dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump webdriver-manager from 3.8.3 to 3.8.4 (#10184) Bumps [webdriver-manager](https://github.com/SergeyPirogov/webdriver_manager) from 3.8.3 to 3.8.4. - [Release notes](https://github.com/SergeyPirogov/webdriver_manager/releases) - [Changelog](https://github.com/SergeyPirogov/webdriver_manager/blob/master/CHANGELOG.md) - [Commits](https://github.com/SergeyPirogov/webdriver_manager/compare/v3.8.3...v3.8.4) --- updated-dependencies: - dependency-name: webdriver-manager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: scripts/docker/nginx/Dockerfile to reduce vulnerabilities (#10180) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-ALPINE316-CURL-3011748 - https://snyk.io/vuln/SNYK-ALPINE316-LIBXML2-3040799 - https://snyk.io/vuln/SNYK-ALPINE316-LIBXML2-3050523 - https://snyk.io/vuln/SNYK-ALPINE316-LIBXML2-3050527 - https://snyk.io/vuln/SNYK-ALPINE316-ZLIB-2976176 Co-authored-by: Alessio Fabiani * [Dependencies] Align "setup.cfg" to "requirements.txt" (#10242) * [Fixes #10251] Review geonode management command set_layers_permissions (#10252) * [Fixes #10251] Review geonode management command set_layers_permissions * [Fixes #10251] Review geonode management command set_layers_permissions * [Fixes #10251] Review geonode management command set_layers_permissions * [Fixes #10251] Review geonode management command set_layers_permissions * [Fixes #10251] Review geonode management command set_layers_permissions * [Fixes #10251] Review geonode management command set_layers_permissions * [Fixes #10251] Review geonode management command set_layers_permissions * [Hardening] Prevent migration 0034_maplayer_extra_params_and_current_style to fail abruptly in the case the maplayer has no styles associated with it * [Fixes #10263] non admin user in fresh instance cannot create resources_ (#10264) * [Fixes #10208] Add a custom hook at the end of the permissions assign (#10213) Co-authored-by: Alessio Fabiani * Fix broken test (#10266) * Fix broken test build * Fix broken test build * Bump GeoServer to version 2.20.6 (#10164) * [Fixes #10214] metadata_only filter not working properly (#10215) * [Fixes #10214] metadata_only filter not working properly * [Fixes #10214] metadata_only filter not working properly * [Fixes #10214] metadata_only filter not working properly Co-authored-by: Alessio Fabiani * Bump jsonschema from 4.16.0 to 4.17.0 (#10262) Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.16.0 to 4.17.0. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.16.0...v4.17.0) --- updated-dependencies: - dependency-name: jsonschema dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Bump pip from 22.3 to 22.3.1 (#10261) Bumps [pip](https://github.com/pypa/pip) from 22.3 to 22.3.1. - [Release notes](https://github.com/pypa/pip/releases) - [Changelog](https://github.com/pypa/pip/blob/main/NEWS.rst) - [Commits](https://github.com/pypa/pip/compare/22.3...22.3.1) --- updated-dependencies: - dependency-name: pip dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytest-bdd from 6.0.1 to 6.1.0 (#10260) Bumps [pytest-bdd](https://github.com/pytest-dev/pytest-bdd) from 6.0.1 to 6.1.0. - [Release notes](https://github.com/pytest-dev/pytest-bdd/releases) - [Changelog](https://github.com/pytest-dev/pytest-bdd/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-bdd/compare/6.0.1...6.1.0) --- updated-dependencies: - dependency-name: pytest-bdd dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump django-select2 from 7.11.0 to 8.0.0 (#10259) Bumps [django-select2](https://github.com/codingjoe/django-select2) from 7.11.0 to 8.0.0. - [Release notes](https://github.com/codingjoe/django-select2/releases) - [Commits](https://github.com/codingjoe/django-select2/compare/7.11.0...8.0.0) --- updated-dependencies: - dependency-name: django-select2 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump sqlalchemy from 1.4.42 to 1.4.43 (#10258) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.42 to 1.4.43. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump docker from 6.0.0 to 6.0.1 (#10256) Bumps [docker](https://github.com/docker/docker-py) from 6.0.0 to 6.0.1. - [Release notes](https://github.com/docker/docker-py/releases) - [Commits](https://github.com/docker/docker-py/compare/6.0.0...6.0.1) --- updated-dependencies: - dependency-name: docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump wandb from 0.13.4 to 0.13.5 (#10255) Bumps [wandb](https://github.com/wandb/wandb) from 0.13.4 to 0.13.5. - [Release notes](https://github.com/wandb/wandb/releases) - [Changelog](https://github.com/wandb/wandb/blob/main/CHANGELOG.md) - [Commits](https://github.com/wandb/wandb/compare/v0.13.4...v0.13.5) --- updated-dependencies: - dependency-name: wandb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Fixes #10251] improve feedback to the user and UI experience of batch permisisons assignment (#10281) * [Fixes #10251] improve feedback to the user and UI experience * [Fixes #10251] improve feedback to the user and UI experience * [Fixes #10251] improve feedback to the user and UI experience * Bump boto3 from 1.26.0 to 1.26.4 (#10273) Bumps [boto3](https://github.com/boto/boto3) from 1.26.0 to 1.26.4. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.0...1.26.4) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * [Dependencies] Align setup.cfg to requirements.txt (#10284) * [Fixes #10287] The "set_layer_permissions" management command does not behave correctly with "AnonyousUser" (#10288) * [Fixes #10287] The "set_layer_permissions" management command does not behave correctly with "AnonyousUser" * [Fixes #10270] Document creation via API v2 (#10271) * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 Co-authored-by: Alessio Fabiani * fix: requirements_tests.txt to reduce vulnerabilities (#10299) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-SETUPTOOLS-3113904 * Bump pytest-bdd from 6.1.0 to 6.1.1 (#10297) Bumps [pytest-bdd](https://github.com/pytest-dev/pytest-bdd) from 6.1.0 to 6.1.1. - [Release notes](https://github.com/pytest-dev/pytest-bdd/releases) - [Changelog](https://github.com/pytest-dev/pytest-bdd/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-bdd/compare/6.1.0...6.1.1) --- updated-dependencies: - dependency-name: pytest-bdd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Bump pymupdf from 1.20.2 to 1.21.0 (#10296) Bumps [pymupdf](https://github.com/pymupdf/pymupdf) from 1.20.2 to 1.21.0. - [Release notes](https://github.com/pymupdf/pymupdf/releases) - [Changelog](https://github.com/pymupdf/PyMuPDF/blob/master/changes.txt) - [Commits](https://github.com/pymupdf/pymupdf/compare/1.20.2...1.21.0) --- updated-dependencies: - dependency-name: pymupdf dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump sqlalchemy from 1.4.43 to 1.4.44 (#10294) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.43 to 1.4.44. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump psutil from 5.9.3 to 5.9.4 (#10293) Bumps [psutil](https://github.com/giampaolo/psutil) from 5.9.3 to 5.9.4. - [Release notes](https://github.com/giampaolo/psutil/releases) - [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst) - [Commits](https://github.com/giampaolo/psutil/compare/release-5.9.3...release-5.9.4) --- updated-dependencies: - dependency-name: psutil dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump dropbox from 11.35.0 to 11.36.0 (#10292) Bumps [dropbox](https://github.com/dropbox/dropbox-sdk-python) from 11.35.0 to 11.36.0. - [Release notes](https://github.com/dropbox/dropbox-sdk-python/releases) - [Commits](https://github.com/dropbox/dropbox-sdk-python/compare/v11.35.0...v11.36.0) --- updated-dependencies: - dependency-name: dropbox dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump google-cloud-storage from 2.5.0 to 2.6.0 (#10291) Bumps [google-cloud-storage](https://github.com/googleapis/python-storage) from 2.5.0 to 2.6.0. - [Release notes](https://github.com/googleapis/python-storage/releases) - [Changelog](https://github.com/googleapis/python-storage/blob/main/CHANGELOG.md) - [Commits](https://github.com/googleapis/python-storage/compare/v2.5.0...v2.6.0) --- updated-dependencies: - dependency-name: google-cloud-storage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.4 to 1.26.11 (#10312) Bumps [boto3](https://github.com/boto/boto3) from 1.26.4 to 1.26.11. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.4...1.26.11) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align setup.cfg with requirements.txt (#10315) * [Fixes #10303] automatic periodic TaskResult removal (#10306) * [Fixes #10303] automatic periodic TaskResult removal * [Fixes #10303] automatic periodic TaskResult removal * [Fixes #10303] automatic periodic TaskResult removal * [Fixes #10303] fix flake8 formatting Co-authored-by: Alessio Fabiani * [Fixes #10302] Incorrect permissions assigned on cloning a resource (#10309) * [Fixes #10302] Incorrect permissions assigned on cloning a resource * [Fixes #10302] Incorrect permissions assigned on cloning a resource * [Fixes #10302] Incorrect permissions assigned on cloning a resource * [Fixes #10302] test fix broken tests * [Fixes #10302] fix flake8 formatting * [Fixes #10302] test fix broken tests * [Fixes #10302] fix flake8 * - Fix test case * [Fixes #10302] fix flake8 Co-authored-by: Alessio Fabiani * Create SECURITY.md (#10285) * Create SECURITY.md * Update SECURITY.md fix minor typo Co-authored-by: Florian Hoedt * Update setuptools requirement from <65.6.0,>=59.1.1 to >=59.1.1,<65.7.0 (#10327) Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v65.5.1...v65.6.0) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump python-slugify from 6.1.2 to 7.0.0 (#10322) Bumps [python-slugify](https://github.com/un33k/python-slugify) from 6.1.2 to 7.0.0. - [Release notes](https://github.com/un33k/python-slugify/releases) - [Changelog](https://github.com/un33k/python-slugify/blob/master/CHANGELOG.md) - [Commits](https://github.com/un33k/python-slugify/compare/v6.1.2...v7.0.0) --- updated-dependencies: - dependency-name: python-slugify dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.11 to 1.26.14 (#10330) Bumps [boto3](https://github.com/boto/boto3) from 1.26.11 to 1.26.14. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.11...1.26.14) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump mako from 1.2.3 to 1.2.4 (#10325) Bumps [mako](https://github.com/sqlalchemy/mako) from 1.2.3 to 1.2.4. - [Release notes](https://github.com/sqlalchemy/mako/releases) - [Changelog](https://github.com/sqlalchemy/mako/blob/main/CHANGES) - [Commits](https://github.com/sqlalchemy/mako/commits) --- updated-dependencies: - dependency-name: mako dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump selenium-requests from 2.0.0 to 2.0.1 (#10324) Bumps [selenium-requests]() from 2.0.0 to 2.0.1. --- updated-dependencies: - dependency-name: selenium-requests dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump webdriver-manager from 3.8.4 to 3.8.5 (#10323) Bumps [webdriver-manager](https://github.com/SergeyPirogov/webdriver_manager) from 3.8.4 to 3.8.5. - [Release notes](https://github.com/SergeyPirogov/webdriver_manager/releases) - [Changelog](https://github.com/SergeyPirogov/webdriver_manager/blob/master/CHANGELOG.md) - [Commits](https://github.com/SergeyPirogov/webdriver_manager/compare/v3.8.4...v3.8.5) --- updated-dependencies: - dependency-name: webdriver-manager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Fixes #9041] Docker NGINX listen on ports 80/443 (#10338) * [Dependencies] Align setup.cfg with requirements.txt (#10339) * Bump django-grappelli from 3.0.3 to 3.0.4 (#10351) Bumps [django-grappelli](https://github.com/sehmaschine/django-grappelli) from 3.0.3 to 3.0.4. - [Release notes](https://github.com/sehmaschine/django-grappelli/releases) - [Changelog](https://github.com/sehmaschine/django-grappelli/blob/master/docs/changelog.rst) - [Commits](https://github.com/sehmaschine/django-grappelli/compare/3.0.3...3.0.4) --- updated-dependencies: - dependency-name: django-grappelli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: requirements_dev.txt to reduce vulnerabilities (#10300) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-SETUPTOOLS-3113904 Co-authored-by: snyk-bot * changed bbox_polygon and llbox_polygone to read only in serializer for #10316 (#10317) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Co-authored-by: Giovanni Allegri * Bump urllib3 from 1.26.12 to 1.26.13 (#10350) Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.12 to 1.26.13. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/1.26.13/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.26.12...1.26.13) --- updated-dependencies: - dependency-name: urllib3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump jsonschema from 4.17.0 to 4.17.1 (#10349) Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.17.0 to 4.17.1. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.17.0...v4.17.1) --- updated-dependencies: - dependency-name: jsonschema dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.14 to 1.26.17 (#10354) Bumps [boto3](https://github.com/boto/boto3) from 1.26.14 to 1.26.17. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.14...1.26.17) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump flake8 from 5.0.4 to 6.0.0 (#10348) Bumps [flake8](https://github.com/pycqa/flake8) from 5.0.4 to 6.0.0. - [Release notes](https://github.com/pycqa/flake8/releases) - [Commits](https://github.com/pycqa/flake8/compare/5.0.4...6.0.0) --- updated-dependencies: - dependency-name: flake8 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align "setup.cfg" to "requirements.txt" (#10363) * [CLA] Add MalteIwanicki to clabot (#10381) * Bump jsonschema from 4.17.1 to 4.17.3 (#10372) Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.17.1 to 4.17.3. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.17.1...v4.17.3) --- updated-dependencies: - dependency-name: jsonschema dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump ipython from 8.6.0 to 8.7.0 (#10371) Bumps [ipython](https://github.com/ipython/ipython) from 8.6.0 to 8.7.0. - [Release notes](https://github.com/ipython/ipython/releases) - [Commits](https://github.com/ipython/ipython/compare/8.6.0...8.7.0) --- updated-dependencies: - dependency-name: ipython dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.17 to 1.26.26 (#10386) Bumps [boto3](https://github.com/boto/boto3) from 1.26.17 to 1.26.26. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.17...1.26.26) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Fixes #10376] Time serie dataset, missing permissions (#10377) * fix: requirements_dev.txt to reduce vulnerabilities (#10369) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-IPYTHON-2348630 - https://snyk.io/vuln/SNYK-PYTHON-PYGMENTS-1086606 - https://snyk.io/vuln/SNYK-PYTHON-PYGMENTS-1088505 - https://snyk.io/vuln/SNYK-PYTHON-SETUPTOOLS-3113904 * fix: upgrade react-hot-loader from 4.13.0 to 4.13.1 (#10370) Snyk has created this PR to upgrade react-hot-loader from 4.13.0 to 4.13.1. See this package in npm: https://www.npmjs.com/package/react-hot-loader See this project in Snyk: https://app.snyk.io/org/afabiani/project/4217120c-f173-454b-b620-3b8eaebc4a07?utm_source=github&utm_medium=referral&page=upgrade-pr * [Dependencies] Align setup.cfg to requirements.txt (#10397) * Bump sqlalchemy from 1.4.44 to 1.4.45 (#10402) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.44 to 1.4.45. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump wandb from 0.13.5 to 0.13.6 (#10399) Bumps [wandb](https://github.com/wandb/wandb) from 0.13.5 to 0.13.6. - [Release notes](https://github.com/wandb/wandb/releases) - [Changelog](https://github.com/wandb/wandb/blob/main/CHANGELOG.md) - [Commits](https://github.com/wandb/wandb/compare/v0.13.5...v0.13.6) --- updated-dependencies: - dependency-name: wandb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump selenium-requests from 2.0.1 to 2.0.2 (#10401) Bumps [selenium-requests]() from 2.0.1 to 2.0.2. --- updated-dependencies: - dependency-name: selenium-requests dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump google-cloud-storage from 2.6.0 to 2.7.0 (#10398) Bumps [google-cloud-storage](https://github.com/googleapis/python-storage) from 2.6.0 to 2.7.0. - [Release notes](https://github.com/googleapis/python-storage/releases) - [Changelog](https://github.com/googleapis/python-storage/blob/main/CHANGELOG.md) - [Commits](https://github.com/googleapis/python-storage/compare/v2.6.0...v2.7.0) --- updated-dependencies: - dependency-name: google-cloud-storage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.26 to 1.26.28 (#10407) Bumps [boto3](https://github.com/boto/boto3) from 1.26.26 to 1.26.28. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.26...1.26.28) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align setup.cfg to requirements.txt (#10417) * [Fixes #10374] UUID resolver endpoint (#10375) * Bump lxml from 4.9.1 to 4.9.2 (#10433) Bumps [lxml](https://github.com/lxml/lxml) from 4.9.1 to 4.9.2. - [Release notes](https://github.com/lxml/lxml/releases) - [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt) - [Commits](https://github.com/lxml/lxml/compare/lxml-4.9.1...lxml-4.9.2) --- updated-dependencies: - dependency-name: lxml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pymupdf from 1.21.0 to 1.21.1 (#10432) Bumps [pymupdf](https://github.com/pymupdf/pymupdf) from 1.21.0 to 1.21.1. - [Release notes](https://github.com/pymupdf/pymupdf/releases) - [Changelog](https://github.com/pymupdf/PyMuPDF/blob/1.21.1/changes.txt) - [Commits](https://github.com/pymupdf/pymupdf/compare/1.21.0...1.21.1) --- updated-dependencies: - dependency-name: pymupdf dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytz from 2022.6 to 2022.7 (#10431) Bumps [pytz](https://github.com/stub42/pytz) from 2022.6 to 2022.7. - [Release notes](https://github.com/stub42/pytz/releases) - [Commits](https://github.com/stub42/pytz/compare/release_2022.6...release_2022.7) --- updated-dependencies: - dependency-name: pytz dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump wandb from 0.13.6 to 0.13.7 (#10430) Bumps [wandb](https://github.com/wandb/wandb) from 0.13.6 to 0.13.7. - [Release notes](https://github.com/wandb/wandb/releases) - [Changelog](https://github.com/wandb/wandb/blob/main/CHANGELOG.md) - [Commits](https://github.com/wandb/wandb/compare/v0.13.6...v0.13.7) --- updated-dependencies: - dependency-name: wandb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump coverage from 6.5.0 to 7.0.0 (#10429) Bumps [coverage](https://github.com/nedbat/coveragepy) from 6.5.0 to 7.0.0. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/6.5.0...7.0.0) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump drf-spectacular from 0.24.2 to 0.25.1 (#10428) Bumps [drf-spectacular](https://github.com/tfranzel/drf-spectacular) from 0.24.2 to 0.25.1. - [Release notes](https://github.com/tfranzel/drf-spectacular/releases) - [Changelog](https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst) - [Commits](https://github.com/tfranzel/drf-spectacular/compare/0.24.2...0.25.1) --- updated-dependencies: - dependency-name: drf-spectacular dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update numpy requirement from ==1.23.* to ==1.24.* (#10427) Updates the requirements on [numpy](https://github.com/numpy/numpy) to permit the latest version. - [Release notes](https://github.com/numpy/numpy/releases) - [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst) - [Commits](https://github.com/numpy/numpy/compare/v1.23.0rc1...v1.24.0) --- updated-dependencies: - dependency-name: numpy dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump dj-database-url from 1.0.0 to 1.2.0 (#10426) Bumps [dj-database-url](https://github.com/jazzband/dj-database-url) from 1.0.0 to 1.2.0. - [Release notes](https://github.com/jazzband/dj-database-url/releases) - [Changelog](https://github.com/jazzband/dj-database-url/blob/master/CHANGELOG.md) - [Commits](https://github.com/jazzband/dj-database-url/compare/v1.0.0...v1.2.0) --- updated-dependencies: - dependency-name: dj-database-url dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.28 to 1.26.32 (#10425) Bumps [boto3](https://github.com/boto/boto3) from 1.26.28 to 1.26.32. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.28...1.26.32) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump smart-open from 6.2.0 to 6.3.0 (#10424) Bumps [smart-open](https://github.com/piskvorky/smart_open) from 6.2.0 to 6.3.0. - [Release notes](https://github.com/piskvorky/smart_open/releases) - [Changelog](https://github.com/RaRe-Technologies/smart_open/blob/develop/CHANGELOG.md) - [Commits](https://github.com/piskvorky/smart_open/compare/v6.2.0...v6.3.0) --- updated-dependencies: - dependency-name: smart-open dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align setup.cfg to requirements.txt (#10444) * Bump GeoNode to version 4.1.0 dev (#10461) * Bump GeoNode to version 4.1.0 dev (cherry picked from commit e6dd1f3e92f070d578a4a9fe29881e0f87abda3b) # Conflicts: # geonode/__init__.py * Bump GeoNode to version 4.1.0 dev (cherry picked from commit e6dd1f3e92f070d578a4a9fe29881e0f87abda3b) # Conflicts: # geonode/__init__.py * [Fixes #10462] GeoNode is vulnerable to an XML External Entity (XXE) injection (#10463) * [Fixes #10464] Fix code scanning alert - Uncontrolled data used in path expression (#10465) * [Fixes #10462] GeoNode is vulnerable to an XML External Entity (XXE) injection * [Fixes #10464] Fix code scanning alert - Uncontrolled data used in path expression * fix: Dockerfile to reduce vulnerabilities (#10470) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-DEBIAN10-DPKG-2847944 - https://snyk.io/vuln/SNYK-DEBIAN10-OPENSSL-2807585 - https://snyk.io/vuln/SNYK-DEBIAN10-OPENSSL-2933515 - https://snyk.io/vuln/SNYK-DEBIAN10-PYTHON37-3090928 - https://snyk.io/vuln/SNYK-DEBIAN10-XZUTILS-2444279 Co-authored-by: snyk-bot * Create codeql.yml * Create pyre.yml * Create pysa.yml * [Fixes #10472] Fix code scanning alert - Polynomial regular expression used on uncontrolled data (#10473) * [Fixes #10472] Fix code scanning alert - Polynomial regular expression used on uncontrolled data * - Get rid of pyre and pysa workflows * Update mock requirement from <5.0.0 to <6.0.0 (#10480) Updates the requirements on [mock](https://github.com/testing-cabal/mock) to permit the latest version. - [Release notes](https://github.com/testing-cabal/mock/releases) - [Changelog](https://github.com/testing-cabal/mock/blob/master/CHANGELOG.rst) - [Commits](https://github.com/testing-cabal/mock/compare/release-0.5.0...5.0.0) --- updated-dependencies: - dependency-name: mock dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump django-storages from 1.13.1 to 1.13.2 (#10477) Bumps [django-storages](https://github.com/jschneier/django-storages) from 1.13.1 to 1.13.2. - [Release notes](https://github.com/jschneier/django-storages/releases) - [Changelog](https://github.com/jschneier/django-storages/blob/master/CHANGELOG.rst) - [Commits](https://github.com/jschneier/django-storages/compare/1.13.1...1.13.2) --- updated-dependencies: - dependency-name: django-storages dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump django-allauth from 0.51.0 to 0.52.0 (#10479) Bumps [django-allauth](https://github.com/pennersr/django-allauth) from 0.51.0 to 0.52.0. - [Release notes](https://github.com/pennersr/django-allauth/releases) - [Changelog](https://github.com/pennersr/django-allauth/blob/master/ChangeLog.rst) - [Commits](https://github.com/pennersr/django-allauth/compare/0.51.0...0.52.0) --- updated-dependencies: - dependency-name: django-allauth dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump whitenoise from 6.2.0 to 6.3.0 (#10496) Bumps [whitenoise](https://github.com/evansd/whitenoise) from 6.2.0 to 6.3.0. - [Release notes](https://github.com/evansd/whitenoise/releases) - [Changelog](https://github.com/evansd/whitenoise/blob/main/docs/changelog.rst) - [Commits](https://github.com/evansd/whitenoise/compare/6.2.0...6.3.0) --- updated-dependencies: - dependency-name: whitenoise dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pyopenssl from 22.1.0 to 23.0.0 (#10489) Bumps [pyopenssl](https://github.com/pyca/pyopenssl) from 22.1.0 to 23.0.0. - [Release notes](https://github.com/pyca/pyopenssl/releases) - [Changelog](https://github.com/pyca/pyopenssl/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/pyopenssl/compare/22.1.0...23.0.0) --- updated-dependencies: - dependency-name: pyopenssl dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pillow from 9.3.0 to 9.4.0 (#10495) Bumps [pillow](https://github.com/python-pillow/Pillow) from 9.3.0 to 9.4.0. - [Release notes](https://github.com/python-pillow/Pillow/releases) - [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) - [Commits](https://github.com/python-pillow/Pillow/compare/9.3.0...9.4.0) --- updated-dependencies: - dependency-name: pillow dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump sqlalchemy from 1.4.45 to 1.4.46 (#10490) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.45 to 1.4.46. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump ipython from 8.7.0 to 8.8.0 (#10491) Bumps [ipython](https://github.com/ipython/ipython) from 8.7.0 to 8.8.0. - [Release notes](https://github.com/ipython/ipython/releases) - [Commits](https://github.com/ipython/ipython/compare/8.7.0...8.8.0) --- updated-dependencies: - dependency-name: ipython dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump django-treebeard from 4.5.1 to 4.6.0 (#10492) Bumps [django-treebeard](https://github.com/django-treebeard/django-treebeard) from 4.5.1 to 4.6.0. - [Release notes](https://github.com/django-treebeard/django-treebeard/releases) - [Changelog](https://github.com/django-treebeard/django-treebeard/blob/master/CHANGES.md) - [Commits](https://github.com/django-treebeard/django-treebeard/compare/4.5.1...4.6.0) --- updated-dependencies: - dependency-name: django-treebeard dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump coverage from 7.0.0 to 7.0.4 (#10493) Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.0.0 to 7.0.4. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.0.0...7.0.4) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.32 to 1.26.45 (#10494) Bumps [boto3](https://github.com/boto/boto3) from 1.26.32 to 1.26.45. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.32...1.26.45) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align "setup.cfg" to "requirements.txt" (#10507) * Update backport.yml * [Fixes #10509] Configure UTF-8 encoding for shapefiles in Geoserver by default (#10510) * [CLA] add 52North staff to .clabot (#10512) * fix: scripts/docker/nginx/Dockerfile to reduce vulnerabilities (#10513) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-ALPINE316-CURL-3179541 - https://snyk.io/vuln/SNYK-ALPINE316-CURL-3179541 - https://snyk.io/vuln/SNYK-ALPINE316-CURL-3179542 - https://snyk.io/vuln/SNYK-ALPINE316-CURL-3179542 * Update README.md * [Fixes #7181] fix ISO 19139 metadata validity (#10488) * Adding "ahmdthr" to .clabot * Bump requests from 2.28.1 to 2.28.2 (#10528) Bumps [requests](https://github.com/psf/requests) from 2.28.1 to 2.28.2. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.28.1...v2.28.2) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update setuptools requirement from <65.7.0,>=59.1.1 to >=59.1.1,<66.1.0 (#10542) Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v65.5.1...v66.0.0) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump urllib3 from 1.26.13 to 1.26.14 (#10531) Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.13 to 1.26.14. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.26.13...1.26.14) --- updated-dependencies: - dependency-name: urllib3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump selenium-requests from 2.0.2 to 2.0.3 (#10536) Bumps [selenium-requests]() from 2.0.2 to 2.0.3. --- updated-dependencies: - dependency-name: selenium-requests dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Fixes #10524] Resource permissions are not returned in the users/groups endpoint (#10544) * [Fixes #10524] Resource permissions are not returned in the users/groups endpoint * [Fixes #10524] Resource permissions are not returned in the users/groups endpoint * [Fixes #10482] Upload ISO-19115 xml metadata via the API (#10483) * ISO-19115 xml metadata file can be uploaded via the API * Small changes for PEP8 compliance * Added tests for checking permissions for metadata upload Co-authored-by: Alessio Fabiani * [Fixes #10525] set/unset batch permissions on groups raise an error (#10526) * [Fixes #10525] set/unset batch permissions on groups raise an error * [Fixes #10525] set/unset batch permissions on groups raise an error * Bump pytz from 2022.7 to 2022.7.1 (#10533) Bumps [pytz](https://github.com/stub42/pytz) from 2022.7 to 2022.7.1. - [Release notes](https://github.com/stub42/pytz/releases) - [Commits](https://github.com/stub42/pytz/compare/release_2022.7...release_2022.7.1) --- updated-dependencies: - dependency-name: pytz dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump wandb from 0.13.7 to 0.13.9 (#10530) Bumps [wandb](https://github.com/wandb/wandb) from 0.13.7 to 0.13.9. - [Release notes](https://github.com/wandb/wandb/releases) - [Changelog](https://github.com/wandb/wandb/blob/main/CHANGELOG.md) - [Commits](https://github.com/wandb/wandb/compare/v0.13.7...v0.13.9) --- updated-dependencies: - dependency-name: wandb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump coverage from 7.0.4 to 7.0.5 (#10529) Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.0.4 to 7.0.5. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.0.4...7.0.5) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytest from 7.2.0 to 7.2.1 (#10534) Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.2.0 to 7.2.1. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/7.2.0...7.2.1) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.45 to 1.26.50 (#10535) Bumps [boto3](https://github.com/boto/boto3) from 1.26.45 to 1.26.50. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.45...1.26.50) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align "setup.cfg" to "requirements.txt" (#10555) * [Fixes #10537] Improve rules creation using GeoFence batch (#10538) * [Fixes #10537] Improve rules creation using GeoFence batch * - code improvements accordingly to the PR comments * - code improvements accordingly to the PR comments * - Test fixes Co-authored-by: afabiani * Update setuptools requirement from <66.1.0,>=59.1.1 to >=59.1.1,<66.2.0 (#10563) Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v65.5.1...v66.1.1) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump invoke from 1.7.3 to 2.0.0 (#10565) Bumps [invoke](https://github.com/pyinvoke/invoke) from 1.7.3 to 2.0.0. - [Release notes](https://github.com/pyinvoke/invoke/releases) - [Commits](https://github.com/pyinvoke/invoke/compare/1.7.3...2.0.0) --- updated-dependencies: - dependency-name: invoke dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump splinter from 0.18.1 to 0.19.0 (#10564) Bumps [splinter](https://github.com/cobrateam/splinter) from 0.18.1 to 0.19.0. - [Release notes](https://github.com/cobrateam/splinter/releases) - [Changelog](https://github.com/cobrateam/splinter/blob/master/docs/news.rst) - [Commits](https://github.com/cobrateam/splinter/compare/0.18.1...0.19.0) --- updated-dependencies: - dependency-name: splinter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.50 to 1.26.54 (#10566) Bumps [boto3](https://github.com/boto/boto3) from 1.26.50 to 1.26.54. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.50...1.26.54) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align "setup.cfg" to "requirements.txt" (#10572) * [Fixes #10574] Code formatting with Black (#10575) * auto reformatting by black * relax flake8 * Add black to requirements * Add black to CircleCI * [Fixes #10574] Code formatting with Black (#10575) * auto reformatting by black * relax flake8 * Add black to requirements * Add black to CircleCI (cherry picked from commit e0b7ec94ebb97b0f3eb4fbe5cf82c71f11d0a8d3) # Conflicts: # geonode/base/api/serializers.py # geonode/catalogue/tests.py # geonode/catalogue/urls.py # geonode/catalogue/views.py # geonode/geoserver/manager.py # geonode/geoserver/signals.py * - Upgrade GeoServer to version 2.20.6 Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Emanuele Tajariol Co-authored-by: Giovanni Allegri Co-authored-by: NAGGINDA MARTHA Co-authored-by: Edson Flavio de Souza <44442399+edsonflavio@users.noreply.github.com> Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Co-authored-by: Snyk bot Co-authored-by: mattiagiupponi Co-authored-by: Florian Hoedt Co-authored-by: Francesco Frassinelli Co-authored-by: Malte Iwanicki <45853662+MalteIwanicki@users.noreply.github.com> Co-authored-by: Toni Co-authored-by: Christian Autermann Co-authored-by: matthesrieke Co-authored-by: ahmdthr <116570171+ahmdthr@users.noreply.github.com> --- geonode/base/forms.py | 2 +- geonode/base/views.py | 11 ++++++----- geonode/geoserver/signals.py | 2 +- geonode/security/tests.py | 8 +++++--- geonode/storage/tests.py | 4 ++-- geonode/upload/__init__.py | 13 +++++++------ 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/geonode/base/forms.py b/geonode/base/forms.py index b0c91ff7d0f..b24ad8e935f 100644 --- a/geonode/base/forms.py +++ b/geonode/base/forms.py @@ -470,7 +470,7 @@ def __init__(self, *args, **kwargs): if field in ["poc", "owner"] and not self.can_change_perms: self.fields[field].disabled = True - if field in ['poc', 'owner'] and not self.can_change_perms: + if field in ["poc", "owner"] and not self.can_change_perms: self.fields[field].disabled = True def disable_keywords_widget_for_non_superuser(self, user): diff --git a/geonode/base/views.py b/geonode/base/views.py index 0a7f6fa8b43..30a55e8bff7 100644 --- a/geonode/base/views.py +++ b/geonode/base/views.py @@ -335,15 +335,16 @@ def get_results(self, context): class DatasetsAutocomplete(SimpleSelect2View): model = Dataset - filter_arg = 'title__icontains' + filter_arg = "title__icontains" def get_results(self, context): return [ { - 'id': self.get_result_value(result), - 'text': self.get_result_label(result.title), - 'selected_text': self.get_selected_result_label(result.title), - } for result in context['object_list'] + "id": self.get_result_value(result), + "text": self.get_result_label(result.title), + "selected_text": self.get_selected_result_label(result.title), + } + for result in context["object_list"] ] diff --git a/geonode/geoserver/signals.py b/geonode/geoserver/signals.py index 591a1e12552..cfe1ad6f85b 100644 --- a/geonode/geoserver/signals.py +++ b/geonode/geoserver/signals.py @@ -42,7 +42,7 @@ geofence_rule_assign = Signal(providing_args=["instance"]) -post_set_permissions = Signal(providing_args=['instance']) +geofence_rule_assign = Signal(providing_args=["instance"]) def geoserver_delete(typename): diff --git a/geonode/security/tests.py b/geonode/security/tests.py index 4651e1f28d0..546dbf4ab15 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -90,11 +90,13 @@ def _log(msg, *args): def get_geofence_rules_count(): from geonode.geoserver.helpers import gf_client + return gf_client.get_rules_count() def get_geofence_rules(): from geonode.geoserver.helpers import gf_client + return gf_client.get_rules() @@ -1759,11 +1761,11 @@ def test_admin_whitelisted_access_middleware(self): self.assertTrue(request.user.is_superuser) # Test valid IP in second element - with self.settings(ADMIN_IP_WHITELIST=['88.88.88.88', '127.0.0.1']): + with self.settings(ADMIN_IP_WHITELIST=["88.88.88.88", "127.0.0.1"]): request = HttpRequest() request.user = admin - request.path = reverse('home') - request.META['REMOTE_ADDR'] = '127.0.0.1' + request.path = reverse("home") + request.META["REMOTE_ADDR"] = "127.0.0.1" middleware.process_request(request) self.assertTrue(request.user.is_superuser) diff --git a/geonode/storage/tests.py b/geonode/storage/tests.py index c2e6c93b459..c4ba57817df 100644 --- a/geonode/storage/tests.py +++ b/geonode/storage/tests.py @@ -419,9 +419,9 @@ def test_storage_manager_copy(self): @override_settings(FILE_UPLOAD_DIRECTORY_PERMISSIONS=0o777) @override_settings(FILE_UPLOAD_PERMISSIONS=0o777) def test_storage_manager_copy(self): - ''' + """ Test that the copy works as expected and the permissions are corerct - ''' + """ dataset = create_single_dataset(name="test_copy") dataset.files = [os.path.join(f"{self.project_root}", "tests/data/test_sld.sld")] dataset.save() diff --git a/geonode/upload/__init__.py b/geonode/upload/__init__.py index ec9e9b79a26..f5c5c542718 100644 --- a/geonode/upload/__init__.py +++ b/geonode/upload/__init__.py @@ -67,14 +67,15 @@ def run_setup_hooks(sender, **kwargs): every=1, period="days" ) + daily_interval, _ = IntervalSchedule.objects.get_or_create(every=1, period="days") PeriodicTask.objects.update_or_create( name="clean-up-old-task-result", defaults=dict( task="geonode.upload.tasks.cleanup_celery_task_entries", interval=daily_interval, - args='', - start_time=timezone.now() - ) + args="", + start_time=timezone.now(), + ), ) @@ -92,9 +93,9 @@ def ready(self): "task": "geonode.upload.tasks.cleanup_celery_task_entries", "schedule": 86400.0, } - settings.CELERY_BEAT_SCHEDULE['clean-up-old-task-result'] = { - 'task': 'geonode.upload.tasks.cleanup_celery_task_entries', - 'schedule': 86400.0, + settings.CELERY_BEAT_SCHEDULE["clean-up-old-task-result"] = { + "task": "geonode.upload.tasks.cleanup_celery_task_entries", + "schedule": 86400.0, } From 8d2908ebf7e821849447cad1e0dab977a495c85b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 26 Jan 2023 17:11:04 +0100 Subject: [PATCH 066/253] =?UTF-8?q?[Fixes=20#10537]=20Improve=20rules=20cr?= =?UTF-8?q?eation=20using=20GeoFence=20batch=20-=20more=20imp=E2=80=A6=20(?= =?UTF-8?q?#10585)=20(#10588)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Code Formatting] Revert formatting on conflicting files * [Fixes #10537] Improve rules creation using GeoFence batch - more improvements * [#10574] Align code formatting with black Co-authored-by: afabiani (cherry picked from commit 36f414d02a054ecd328e3d16358992b0a503cc36) Co-authored-by: Emanuele Tajariol --- geonode/geoserver/helpers.py | 16 +++++++++++++++- geonode/geoserver/manager.py | 1 + geonode/security/tests.py | 12 ------------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index 30dc6bffa06..b3326246867 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -1874,7 +1874,21 @@ def get_time_info(layer): url, _user, _password, retries=ogc_server_settings.MAX_RETRIES, backoff_factor=ogc_server_settings.BACKOFF_FACTOR ) gs_uploader = Client(url, _user, _password) -gf_client = GeofenceClient(url, _user, _password) + + +def create_geofence_client(): + gs_url = settings.OGC_SERVER["default"]["LOCATION"] + user = settings.OGC_SERVER["default"]["USER"] + passwd = settings.OGC_SERVER["default"]["PASSWORD"] + + gf_rest_url = f'{gs_url.rstrip("/")}/rest/geofence/' + client = GeoFenceClient(gf_rest_url, user, passwd) + client.set_timeout(settings.OGC_SERVER["default"].get("GEOFENCE_TIMEOUT", 60)) + return client + + +geofence = create_geofence_client() +gf_utils = GeoFenceUtils(geofence) def _create_geofence_client(): diff --git a/geonode/geoserver/manager.py b/geonode/geoserver/manager.py index 18634e06f58..3762b50c89f 100644 --- a/geonode/geoserver/manager.py +++ b/geonode/geoserver/manager.py @@ -442,6 +442,7 @@ def set_permissions( approval_status_changed: bool = False, group_status_changed: bool = False, ) -> bool: + _resource = instance or ResourceManager._get_instance(uuid) try: diff --git a/geonode/security/tests.py b/geonode/security/tests.py index 546dbf4ab15..39dcc36a7a6 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -88,18 +88,6 @@ def _log(msg, *args): logger.debug(msg, *args) -def get_geofence_rules_count(): - from geonode.geoserver.helpers import gf_client - - return gf_client.get_rules_count() - - -def get_geofence_rules(): - from geonode.geoserver.helpers import gf_client - - return gf_client.get_rules() - - class StreamToLogger: """ Fake file-like stream object that redirects writes to a logger instance. From 1082bc273f4eb80612bf600caa837c85c5ca9c36 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 27 Jan 2023 09:27:32 +0100 Subject: [PATCH 067/253] [Code Format] Minor refactoring of geofence create options (#10589) (#10596) * [Code Format] Minor refactoring of geofence create options * - fix test cases (cherry picked from commit 118b8e7c40fcfc55bdd01f669fecb14ef6974918) Co-authored-by: Alessio Fabiani --- geonode/geoserver/helpers.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index b3326246867..5f0d5a627f5 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -1876,18 +1876,14 @@ def get_time_info(layer): gs_uploader = Client(url, _user, _password) -def create_geofence_client(): - gs_url = settings.OGC_SERVER["default"]["LOCATION"] - user = settings.OGC_SERVER["default"]["USER"] - passwd = settings.OGC_SERVER["default"]["PASSWORD"] - - gf_rest_url = f'{gs_url.rstrip("/")}/rest/geofence/' - client = GeoFenceClient(gf_rest_url, user, passwd) - client.set_timeout(settings.OGC_SERVER["default"].get("GEOFENCE_TIMEOUT", 60)) +def _create_geofence_client(): + gf_rest_url = f'{url.rstrip("/")}/geofence/' + client = GeoFenceClient(gf_rest_url, _user, _password) + client.set_timeout(ogc_server_settings.GEOFENCE_TIMEOUT) return client -geofence = create_geofence_client() +geofence = _create_geofence_client() gf_utils = GeoFenceUtils(geofence) From a45666e76088ad1f337fe4559417b1ce217c9289 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 09:27:26 +0100 Subject: [PATCH 068/253] [Dependencies] Align "setup.cfg" to "requirements.txt" (#10623) (#10624) (cherry picked from commit cb8d2aac6dae90ab61a266d902b5b1a38f957431) Co-authored-by: Alessio Fabiani --- setup.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup.cfg b/setup.cfg index 3509d6bfae7..12b727c9d08 100644 --- a/setup.cfg +++ b/setup.cfg @@ -207,6 +207,8 @@ install_requires = wandb==0.13.9 protobuf==3.20.3 mako==1.2.4 + certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability + jwcrypto>=1.4 # not directly required, pinned by Snyk to avoid a vulnerability [options.packages.find] exclude = tests From 9324304827c078a5b18bb7dd35af7d3ae8fb99de Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 18:34:23 +0100 Subject: [PATCH 069/253] [Dependencies] Align "setup.cfg" to "requirements.txt" (#10642) (#10643) * [Dependencies] Align "setup.cfg" to "requirements.txt" * - Fix black formatting (cherry picked from commit b73cc24226568d010bffb862edef6706ff1c98c5) Co-authored-by: Alessio Fabiani --- geonode/geoserver/manager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/geonode/geoserver/manager.py b/geonode/geoserver/manager.py index 3762b50c89f..18634e06f58 100644 --- a/geonode/geoserver/manager.py +++ b/geonode/geoserver/manager.py @@ -442,7 +442,6 @@ def set_permissions( approval_status_changed: bool = False, group_status_changed: bool = False, ) -> bool: - _resource = instance or ResourceManager._get_instance(uuid) try: From 29b8e544e8860adb733fc8894c59949b471c0b46 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 17:26:02 +0100 Subject: [PATCH 070/253] [Fixes #10521] Make metadata wizard more flexible for custom metadata (#10592) (#10653) * [Fixes: 10521] Make metadata wizard more flexible for custom metadata * add tests for extrametadata query; pep8 format imports * fix map test for metadata response (cherry picked from commit 5ccc0d6a225115ef05c8121cbed6616888f2134c) Co-authored-by: Toni --- geonode/documents/api/tests.py | 1 - geonode/layers/api/serializers.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/documents/api/tests.py b/geonode/documents/api/tests.py index 5ab59dfbbb4..856e72efd34 100644 --- a/geonode/documents/api/tests.py +++ b/geonode/documents/api/tests.py @@ -17,7 +17,6 @@ # ######################################################################### import os -from django.contrib.auth import get_user_model import logging from django.contrib.auth import get_user_model diff --git a/geonode/layers/api/serializers.py b/geonode/layers/api/serializers.py index 3d39fdefe20..27b1e6a1d6a 100644 --- a/geonode/layers/api/serializers.py +++ b/geonode/layers/api/serializers.py @@ -181,6 +181,7 @@ class Meta: "subtype", "ptype", "executions", + "metadata", ) name = serializers.CharField(read_only=True) From 2fce14f41c7bb4eecc2a895ef7b9f2ec448b187d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 16:57:52 +0100 Subject: [PATCH 071/253] [Dependencies] align "setup.cfg" to "requirements.txt" (#10665) (#10666) (cherry picked from commit 0e89afe806f359a1a0b700c233f292999249af5f) Co-authored-by: Alessio Fabiani --- setup.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 12b727c9d08..736f81d85cb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -203,8 +203,8 @@ install_requires = jwcrypto>=1.4 # not directly required, pinned by Snyk to avoid a vulnerability # Security and audit - mistune==2.0.4 - wandb==0.13.9 + mistune==2.0.5 + wandb==0.13.10 protobuf==3.20.3 mako==1.2.4 certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability From 688528469fd138f01e66b478437c316fb1c071a2 Mon Sep 17 00:00:00 2001 From: Alessio Fabiani Date: Fri, 17 Mar 2023 11:42:24 +0100 Subject: [PATCH 072/253] [Dependencies] Align setup.cfg to requirements.txt (#10788) (#10789) (cherry picked from commit e7620effb065ca8b4bf9a0e4969adfd454ed36b3) # Conflicts: # setup.cfg --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 736f81d85cb..39709bce937 100644 --- a/setup.cfg +++ b/setup.cfg @@ -204,7 +204,7 @@ install_requires = # Security and audit mistune==2.0.5 - wandb==0.13.10 + wandb==0.13.11 protobuf==3.20.3 mako==1.2.4 certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability From 6e33c12ec0c862f96432f0d9fb1000f7c098c7ee Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 28 Feb 2023 14:17:12 +0100 Subject: [PATCH 073/253] Make sure to keep all unzipped files as file_paths CSV and JSON are both valid `base_file`s. However, the content of a ZIP file containing a JSON file along with one or multiple CSV files will not be stored as `data_retriever` will override all allowed `base_file`s until just one file remain. --- geonode/storage/data_retriever.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/geonode/storage/data_retriever.py b/geonode/storage/data_retriever.py index 059a3122a74..7d35f93bf29 100644 --- a/geonode/storage/data_retriever.py +++ b/geonode/storage/data_retriever.py @@ -211,12 +211,25 @@ def _unzip(self, zip_name: str) -> Mapping: not_main_files = ["xml", "sld", "zip", "kmz"] base_file_choices = [x for x in available_choices if x not in not_main_files] for _file in Path(self.temporary_folder).iterdir(): + if not zipfile.is_zipfile(str(_file)): if any([_file.name.endswith(_ext) for _ext in base_file_choices]): self.file_paths["base_file"] = Path(str(_file)) elif not zipfile.is_zipfile(str(_file)): ext = _file.name.split(".")[-1] + if f"{ext}_file" in self.file_paths: + existing = self.file_paths[f"{ext}_file"] + self.file_paths[f"{ext}_file"] = [ Path(str(_file)), *(existing if type(existing) == list else [existing]) ] + else: self.file_paths[f"{ext}_file"] = Path(str(_file)) + tmp = self.file_paths.copy() + for key, value in self.file_paths.items(): + if type(value) == list: + for index, file_path in enumerate(value): + n = f"{key}_{index}" if index > 0 else key + tmp[n] = file_path + self.file_paths = tmp + # remiving the zip file os.remove(zip_name) From 875398195b6ad042d4090296bb5bf6ab9a8ffc49 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Thu, 23 Mar 2023 16:34:17 +0100 Subject: [PATCH 074/253] Keep all uploaded zip content accessible iterdir() is platform dependent, that is the order of the returned items may be different on different platforms. In cases where a zip file contains multiple base_file candidates it will be overridden by the last one found (which varies on different platforms). Also, different files with the same extension (file1.csv, file2.csv) will not be accessible from file_paths as they get overridden, too. The fix enumerates all files to make them accessible from file_paths. --- geonode/storage/data_retriever.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/geonode/storage/data_retriever.py b/geonode/storage/data_retriever.py index 7d35f93bf29..9395b4ed827 100644 --- a/geonode/storage/data_retriever.py +++ b/geonode/storage/data_retriever.py @@ -213,8 +213,7 @@ def _unzip(self, zip_name: str) -> Mapping: for _file in Path(self.temporary_folder).iterdir(): if not zipfile.is_zipfile(str(_file)): if any([_file.name.endswith(_ext) for _ext in base_file_choices]): - self.file_paths["base_file"] = Path(str(_file)) - elif not zipfile.is_zipfile(str(_file)): + self.file_paths['base_file'] = Path(str(_file)) ext = _file.name.split(".")[-1] if f"{ext}_file" in self.file_paths: existing = self.file_paths[f"{ext}_file"] From e53440a396baebda800b1683603bb5dfad624f79 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 17 Apr 2023 09:03:54 +0200 Subject: [PATCH 075/253] Use context manager during unzip --- geonode/storage/data_retriever.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/geonode/storage/data_retriever.py b/geonode/storage/data_retriever.py index 9395b4ed827..29cf8beb51c 100644 --- a/geonode/storage/data_retriever.py +++ b/geonode/storage/data_retriever.py @@ -205,8 +205,9 @@ def _unzip(self, zip_name: str) -> Mapping: at the end the zip is deleted """ zip_file = self.file_paths["base_file"] - the_zip = zipfile.ZipFile(zip_file, allowZip64=True) + with zipfile.ZipFile(zip_file, allowZip64=True) as the_zip: the_zip.extractall(self.temporary_folder) + available_choices = get_allowed_extensions() not_main_files = ["xml", "sld", "zip", "kmz"] base_file_choices = [x for x in available_choices if x not in not_main_files] From f24457bb2ec86c43d9baa9fd1ee056516e9aeddd Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 18 Apr 2023 19:43:45 +0200 Subject: [PATCH 076/253] Sorts files during unzip Ensures that related content are unpacked accordingly in a mixed content case --- geonode/storage/data_retriever.py | 3 +- geonode/storage/tests.py | 27 ++++++++++++++++++ .../storage/tests/data/data_collection.zip | Bin 0 -> 14261 bytes 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 geonode/storage/tests/data/data_collection.zip diff --git a/geonode/storage/data_retriever.py b/geonode/storage/data_retriever.py index 29cf8beb51c..b535f948328 100644 --- a/geonode/storage/data_retriever.py +++ b/geonode/storage/data_retriever.py @@ -211,7 +211,8 @@ def _unzip(self, zip_name: str) -> Mapping: available_choices = get_allowed_extensions() not_main_files = ["xml", "sld", "zip", "kmz"] base_file_choices = [x for x in available_choices if x not in not_main_files] - for _file in Path(self.temporary_folder).iterdir(): + sorted_files = sorted(Path(self.temporary_folder).iterdir()) + for _file in sorted_files: if not zipfile.is_zipfile(str(_file)): if any([_file.name.endswith(_ext) for _ext in base_file_choices]): self.file_paths['base_file'] = Path(str(_file)) diff --git a/geonode/storage/tests.py b/geonode/storage/tests.py index c4ba57817df..e76c3b6feaa 100644 --- a/geonode/storage/tests.py +++ b/geonode/storage/tests.py @@ -624,3 +624,30 @@ def test_zip_file_should_correctly_recognize_main_extension_with_shp(self): self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) _files = storage_manager.get_retrieved_paths() self.assertTrue("single_point.shp" in _files.get("base_file")) + + def test_zip_file_should_correctly_relate_mixed_content(self): + zip_file = os.path.join(f"{self.project_root}", "tests/data/data_collection.zip") + storage_manager = self.sut( + remote_files={"base_file": zip_file} + ) + storage_manager.clone_remote_files() + self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) + _files = storage_manager.get_retrieved_paths() + base_file = _files.get("base_file") + + def strip_extension(filename): + return filename.split(".")[0] if filename else filename + + base_name = strip_extension(base_file) + available_files = [ + _files.get("shp_file"), + _files.get("prj_file"), + _files.get("shx_file"), + _files.get("dbf_file") + ] + + def assert_same_base_name(base_name, file_name): + self.assertEqual(base_name, strip_extension(file_name)) + + for file in available_files: + assert_same_base_name(base_name, file) diff --git a/geonode/storage/tests/data/data_collection.zip b/geonode/storage/tests/data/data_collection.zip new file mode 100644 index 0000000000000000000000000000000000000000..0702327be361a2bfda7c9c2a6eb13bd08ca5a9b4 GIT binary patch literal 14261 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 Cq!$1H literal 0 HcmV?d00001 From 4cc4bfae9890a603b0e3c96dfd306471d3357273 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Thu, 11 May 2023 15:21:56 +0200 Subject: [PATCH 077/253] fix: requirements.txt to reduce vulnerabilities (#11029) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-DJANGO-5496950 Co-authored-by: Alessio Fabiani From 3d20ed1cbdd029319f214fa3cbe74017400a6e7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 15:40:26 +0200 Subject: [PATCH 078/253] Bump django-autocomplete-light from 3.5.1 to 3.9.7 (#11056) * Bump django-autocomplete-light from 3.5.1 to 3.9.7 Bumps [django-autocomplete-light](https://github.com/yourlabs/django-autocomplete-light) from 3.5.1 to 3.9.7. - [Release notes](https://github.com/yourlabs/django-autocomplete-light/releases) - [Changelog](https://github.com/yourlabs/django-autocomplete-light/blob/master/CHANGELOG) - [Commits](https://github.com/yourlabs/django-autocomplete-light/compare/3.5.1...3.9.7) --- updated-dependencies: - dependency-name: django-autocomplete-light dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * [Dependencies] Align setup.cfg to requirements.txt (#11048) --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 0470468edb4..9ba2ebd9057 100644 --- a/requirements.txt +++ b/requirements.txt @@ -70,7 +70,7 @@ dj-pagination==2.5.0 django-select2==8.1.1 django-floppyforms<1.10.0 django-forms-bootstrap<=3.1.0 -django-autocomplete-light==3.5.1 +django-autocomplete-light==3.9.7 django-invitations<2.0.1 django-recaptcha==3.0.0 diff --git a/setup.cfg b/setup.cfg index 39709bce937..850b57543f3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -96,7 +96,7 @@ install_requires = django-select2==8.1.1 django-floppyforms<1.10.0 django-forms-bootstrap<=3.1.0 - django-autocomplete-light==3.5.1 + django-autocomplete-light==3.9.7 django-invitations<2.0.1 django-recaptcha==3.0.0 From 9c62b014b700e06b255825fa209bce077205f7e6 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Tue, 16 May 2023 13:02:24 +0200 Subject: [PATCH 079/253] revert django-autocomplete-light upgrade (#11073) --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 9ba2ebd9057..0470468edb4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -70,7 +70,7 @@ dj-pagination==2.5.0 django-select2==8.1.1 django-floppyforms<1.10.0 django-forms-bootstrap<=3.1.0 -django-autocomplete-light==3.9.7 +django-autocomplete-light==3.5.1 django-invitations<2.0.1 django-recaptcha==3.0.0 diff --git a/setup.cfg b/setup.cfg index 850b57543f3..39709bce937 100644 --- a/setup.cfg +++ b/setup.cfg @@ -96,7 +96,7 @@ install_requires = django-select2==8.1.1 django-floppyforms<1.10.0 django-forms-bootstrap<=3.1.0 - django-autocomplete-light==3.9.7 + django-autocomplete-light==3.5.1 django-invitations<2.0.1 django-recaptcha==3.0.0 From fd04ce3f33b8b976f274d9ffab66db922b28c430 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 09:52:47 +0200 Subject: [PATCH 080/253] [Fixes #11100] Bump to Geoserver 2.23.1 (#11104) (#11107) * Bump to Geoserver 2.23.1 * fixed typo (cherry picked from commit a5d75529921a14bee833912c6b3c1283aed1f21d) Co-authored-by: Giovanni Allegri --- dev_config.yml | 4 ++-- docker-compose-geoserver-server.yml | 4 ++-- docker-compose-test.yml | 4 ++-- docker-compose.yml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dev_config.yml b/dev_config.yml index 3fa02cd768e..b6c89644210 100644 --- a/dev_config.yml +++ b/dev_config.yml @@ -1,6 +1,6 @@ --- -GEOSERVER_URL: "https://artifacts.geonode.org/geoserver/2.23.0/geoserver.war" -DATA_DIR_URL: "https://artifacts.geonode.org/geoserver/2.23.0/geonode-geoserver-ext-web-app-data.zip" +GEOSERVER_URL: "https://artifacts.geonode.org/geoserver/2.23.1/geoserver.war" +DATA_DIR_URL: "https://artifacts.geonode.org/geoserver/2.23.1/geonode-geoserver-ext-web-app-data.zip" JETTY_RUNNER_URL: "https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-runner/9.4.31.v20200723/jetty-runner-9.4.31.v20200723.jar" WINDOWS: py2exe: "http://downloads.sourceforge.net/project/py2exe/py2exe/0.6.9/py2exe-0.6.9.win32-py2.7.exe" diff --git a/docker-compose-geoserver-server.yml b/docker-compose-geoserver-server.yml index 10785a5794a..8dfc08b06c0 100644 --- a/docker-compose-geoserver-server.yml +++ b/docker-compose-geoserver-server.yml @@ -2,7 +2,7 @@ version: '2.2' services: data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:2.23.1 restart: on-failure container_name: gsconf4${COMPOSE_PROJECT_NAME} labels: @@ -13,7 +13,7 @@ services: - geoserver-data-dir:/geoserver_data/data geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:2.23.1 restart: unless-stopped container_name: geoserver4${COMPOSE_PROJECT_NAME} stdin_open: true diff --git a/docker-compose-test.yml b/docker-compose-test.yml index de398f099a7..9fed05cbb8d 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -89,7 +89,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:2.23.1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://127.0.0.1:8080/geoserver/ows" @@ -113,7 +113,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:2.23.1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: diff --git a/docker-compose.yml b/docker-compose.yml index a4fc63d9b88..5bf831b1ff5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -89,7 +89,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:2.23.1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://127.0.0.1:8080/geoserver/ows" @@ -113,7 +113,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:2.23.1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: From cd8746bb713634a5c659b61de8ad3217634597d0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 17:07:05 +0200 Subject: [PATCH 081/253] Remove doc_file and file_path from document serializer (#11117) (#11119) (cherry picked from commit 927a302bb4494a3d7dce5c829d7c6a646247704c) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/documents/api/tests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/geonode/documents/api/tests.py b/geonode/documents/api/tests.py index 856e72efd34..dbb3b13588b 100644 --- a/geonode/documents/api/tests.py +++ b/geonode/documents/api/tests.py @@ -16,7 +16,6 @@ # along with this program. If not, see . # ######################################################################### -import os import logging from django.contrib.auth import get_user_model From 0c3653ee00d007e7129e8f2efb9420c978a225bc Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 1 Jun 2023 15:04:31 +0200 Subject: [PATCH 082/253] Revert "[Fixes #11100] Bump to Geoserver 2.23.1 (#11104) (#11107)" (#11136) This reverts commit 91e68714ecf5bfd3afe9262855337e7f959f752c. --- dev_config.yml | 4 ++-- docker-compose-geoserver-server.yml | 4 ++-- docker-compose-test.yml | 4 ++-- docker-compose.yml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dev_config.yml b/dev_config.yml index b6c89644210..3fa02cd768e 100644 --- a/dev_config.yml +++ b/dev_config.yml @@ -1,6 +1,6 @@ --- -GEOSERVER_URL: "https://artifacts.geonode.org/geoserver/2.23.1/geoserver.war" -DATA_DIR_URL: "https://artifacts.geonode.org/geoserver/2.23.1/geonode-geoserver-ext-web-app-data.zip" +GEOSERVER_URL: "https://artifacts.geonode.org/geoserver/2.23.0/geoserver.war" +DATA_DIR_URL: "https://artifacts.geonode.org/geoserver/2.23.0/geonode-geoserver-ext-web-app-data.zip" JETTY_RUNNER_URL: "https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-runner/9.4.31.v20200723/jetty-runner-9.4.31.v20200723.jar" WINDOWS: py2exe: "http://downloads.sourceforge.net/project/py2exe/py2exe/0.6.9/py2exe-0.6.9.win32-py2.7.exe" diff --git a/docker-compose-geoserver-server.yml b/docker-compose-geoserver-server.yml index 8dfc08b06c0..10785a5794a 100644 --- a/docker-compose-geoserver-server.yml +++ b/docker-compose-geoserver-server.yml @@ -2,7 +2,7 @@ version: '2.2' services: data-dir-conf: - image: geonode/geoserver_data:2.23.1 + image: geonode/geoserver_data:2.23.0 restart: on-failure container_name: gsconf4${COMPOSE_PROJECT_NAME} labels: @@ -13,7 +13,7 @@ services: - geoserver-data-dir:/geoserver_data/data geoserver: - image: geonode/geoserver:2.23.1 + image: geonode/geoserver:2.23.0 restart: unless-stopped container_name: geoserver4${COMPOSE_PROJECT_NAME} stdin_open: true diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 9fed05cbb8d..de398f099a7 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -89,7 +89,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.1 + image: geonode/geoserver:2.23.0 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://127.0.0.1:8080/geoserver/ows" @@ -113,7 +113,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.1 + image: geonode/geoserver_data:2.23.0 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: diff --git a/docker-compose.yml b/docker-compose.yml index 5bf831b1ff5..a4fc63d9b88 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -89,7 +89,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.1 + image: geonode/geoserver:2.23.0 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://127.0.0.1:8080/geoserver/ows" @@ -113,7 +113,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.1 + image: geonode/geoserver_data:2.23.0 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: From 840124a0272a11e1ba6183a43c709e2d2c1e1d67 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 11 Sep 2023 14:53:45 +0200 Subject: [PATCH 083/253] Add github workflow files --- .github/workflows/build-and-push.yaml | 62 +++++++++++++++++++++++++ .github/workflows/release.yaml | 66 +++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 .github/workflows/build-and-push.yaml create mode 100644 .github/workflows/release.yaml diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/build-and-push.yaml new file mode 100644 index 00000000000..1ca4e975540 --- /dev/null +++ b/.github/workflows/build-and-push.yaml @@ -0,0 +1,62 @@ +name: Release GeoNode Docker Images + +env: + TITLE: "52°North GeoNode Docker Image" + VENDOR: "52°North GmbH" + AUTHORS: "https://52North.org/" + DESCRIPTION: "Builds and publishes the GeoNode Docker development image for Thuenen" + LICENSE: "GPL-3.0" + +on: + push: + branches: + - "thuenen-dev" + +jobs: + build_and_push_geonode: + runs-on: ubuntu-22.04 + env: + IMAGE: 52north/geonode_thuenen + DEVELOPMENT_VERSION: "4.x" + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.IMAGE }} + labels: | + "org.opencontainers.image.authors=${{ env.AUTHORS }}" + "org.opencontainers.image.vendor=${{ env.VENDOR }}" + "org.opencontainers.image.description=${{ env.DESCRIPTION }}" + "org.opencontainers.image.title=${{ env.TITLE }}" + "org.opencontainers.image.licenses=${{ env.LICENSE }}" + tags: | + latest + ${{ env.DEVELOPMENT_VERSION }} + - + name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Build and push + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache + cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000000..0aeac429729 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,66 @@ +name: Release GeoNode Docker Images + +env: + TITLE: "52°North GeoNode Docker Image" + VENDOR: "52°North GmbH" + AUTHORS: "https://52North.org/" + DESCRIPTION: "Builds and publishes the GeoNode Docker image for Thuenen" + LICENSE: "GPL-3.0" + +on: + push: + tags: + - "v*" + +jobs: + build_and_push_geonode: + runs-on: ubuntu-22.04 + env: + IMAGE: 52north/geonode_thuenen + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Parse semver string + id: semver_parser + uses: booxmedialtd/ws-action-parse-semver@v1 + with: + input_string: "${{github.ref_name}}" + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.IMAGE }} + labels: | + "org.opencontainers.image.authors=${{ env.AUTHORS }}" + "org.opencontainers.image.vendor=${{ env.VENDOR }}" + "org.opencontainers.image.description=${{ env.DESCRIPTION }}" + "org.opencontainers.image.title=${{ env.TITLE }}" + "org.opencontainers.image.licenses=${{ env.LICENSE }}" + tags: | + latest + ${{ steps.semver_parser.outputs.major }} + ${{ steps.semver_parser.outputs.minor }} + ${{ steps.semver_parser.outputs.patch }} + - + name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Build and push + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache + cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max From 783528c16e8effe8209eabccb267224a8b052adb Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 11 Sep 2023 15:00:26 +0200 Subject: [PATCH 084/253] Update branch to build --- .github/workflows/build-and-push.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/build-and-push.yaml index 1ca4e975540..49797d7ac29 100644 --- a/.github/workflows/build-and-push.yaml +++ b/.github/workflows/build-and-push.yaml @@ -10,7 +10,7 @@ env: on: push: branches: - - "thuenen-dev" + - "thuenen_4.x" jobs: build_and_push_geonode: From e286371e1134307726f95020b732cc557b3476a5 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 11 Sep 2023 15:04:51 +0200 Subject: [PATCH 085/253] Cancels running builds on new push --- .github/workflows/build-and-push.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/build-and-push.yaml index 49797d7ac29..d2283a14dfb 100644 --- a/.github/workflows/build-and-push.yaml +++ b/.github/workflows/build-and-push.yaml @@ -1,4 +1,8 @@ -name: Release GeoNode Docker Images +name: Push GeoNode Docker Images + +concurrency: + group: "geonode_build" + cancel-in-progress: true env: TITLE: "52°North GeoNode Docker Image" From 4a75e6ecc78130486107d4985ae5e30ad356ca59 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 11 Sep 2023 15:18:23 +0200 Subject: [PATCH 086/253] Push to 52north/geonode and use different versions --- .github/workflows/build-and-push.yaml | 5 ++--- .github/workflows/release.yaml | 11 +++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/build-and-push.yaml index d2283a14dfb..ca75363ac92 100644 --- a/.github/workflows/build-and-push.yaml +++ b/.github/workflows/build-and-push.yaml @@ -20,7 +20,7 @@ jobs: build_and_push_geonode: runs-on: ubuntu-22.04 env: - IMAGE: 52north/geonode_thuenen + IMAGE: 52north/geonode DEVELOPMENT_VERSION: "4.x" steps: - @@ -45,8 +45,7 @@ jobs: "org.opencontainers.image.title=${{ env.TITLE }}" "org.opencontainers.image.licenses=${{ env.LICENSE }}" tags: | - latest - ${{ env.DEVELOPMENT_VERSION }} + ${{ env.DEVELOPMENT_VERSION }}-thuenen - name: Login to Docker Hub uses: docker/login-action@v2 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0aeac429729..18bb9817a11 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -10,13 +10,13 @@ env: on: push: tags: - - "v*" + - "v*-thuenen" jobs: build_and_push_geonode: runs-on: ubuntu-22.04 env: - IMAGE: 52north/geonode_thuenen + IMAGE: 52north/geonode steps: - name: Checkout @@ -43,10 +43,9 @@ jobs: "org.opencontainers.image.title=${{ env.TITLE }}" "org.opencontainers.image.licenses=${{ env.LICENSE }}" tags: | - latest - ${{ steps.semver_parser.outputs.major }} - ${{ steps.semver_parser.outputs.minor }} - ${{ steps.semver_parser.outputs.patch }} + ${{ steps.semver_parser.outputs.major }}-thuenen + ${{ steps.semver_parser.outputs.minor }}-thuenen + ${{ steps.semver_parser.outputs.patch }}-thuenen - name: Login to Docker Hub uses: docker/login-action@v2 From b3764182a0df17b97e2adf0f4d7c844b4c9bfce8 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 11 Sep 2023 15:33:12 +0200 Subject: [PATCH 087/253] Use dedicated image repository --- .github/workflows/build-and-push.yaml | 9 +++------ .github/workflows/release.yaml | 8 ++++---- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/build-and-push.yaml index ca75363ac92..2785d012047 100644 --- a/.github/workflows/build-and-push.yaml +++ b/.github/workflows/build-and-push.yaml @@ -20,15 +20,12 @@ jobs: build_and_push_geonode: runs-on: ubuntu-22.04 env: - IMAGE: 52north/geonode + IMAGE: 52north/geonode_thuenen DEVELOPMENT_VERSION: "4.x" steps: - name: Checkout uses: actions/checkout@v3 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 @@ -45,7 +42,7 @@ jobs: "org.opencontainers.image.title=${{ env.TITLE }}" "org.opencontainers.image.licenses=${{ env.LICENSE }}" tags: | - ${{ env.DEVELOPMENT_VERSION }}-thuenen + ${{ env.DEVELOPMENT_VERSION }} - name: Login to Docker Hub uses: docker/login-action@v2 @@ -58,7 +55,7 @@ jobs: with: context: . file: ./Dockerfile - push: true + push: false tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 18bb9817a11..ec4e54cdf9e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -16,7 +16,7 @@ jobs: build_and_push_geonode: runs-on: ubuntu-22.04 env: - IMAGE: 52north/geonode + IMAGE: 52north/geonode_thuenen steps: - name: Checkout @@ -43,9 +43,9 @@ jobs: "org.opencontainers.image.title=${{ env.TITLE }}" "org.opencontainers.image.licenses=${{ env.LICENSE }}" tags: | - ${{ steps.semver_parser.outputs.major }}-thuenen - ${{ steps.semver_parser.outputs.minor }}-thuenen - ${{ steps.semver_parser.outputs.patch }}-thuenen + ${{ steps.semver_parser.outputs.major }} + ${{ steps.semver_parser.outputs.minor }} + ${{ steps.semver_parser.outputs.patch }} - name: Login to Docker Hub uses: docker/login-action@v2 From 686f7b33ead53a9e17a5f32192931460c5015caf Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 11 Sep 2023 16:37:25 +0200 Subject: [PATCH 088/253] push to registry after build --- .github/workflows/build-and-push.yaml | 2 +- .github/workflows/release.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/build-and-push.yaml index 2785d012047..0cfb52d4174 100644 --- a/.github/workflows/build-and-push.yaml +++ b/.github/workflows/build-and-push.yaml @@ -55,7 +55,7 @@ jobs: with: context: . file: ./Dockerfile - push: false + push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ec4e54cdf9e..bce7da86980 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -44,8 +44,8 @@ jobs: "org.opencontainers.image.licenses=${{ env.LICENSE }}" tags: | ${{ steps.semver_parser.outputs.major }} - ${{ steps.semver_parser.outputs.minor }} - ${{ steps.semver_parser.outputs.patch }} + ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }} + ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }}-${{ steps.semver_parser.outputs.patch }} - name: Login to Docker Hub uses: docker/login-action@v2 From 8e3ff62b34097bb39dbc68d60285b3671481fa2c Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Wed, 13 Sep 2023 11:16:49 +0200 Subject: [PATCH 089/253] Adjust tag management on built images --- .../{build-and-push.yaml => 52n-build.yaml} | 4 ++-- .../workflows/{release.yaml => 52n-release.yaml} | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) rename .github/workflows/{build-and-push.yaml => 52n-build.yaml} (93%) rename .github/workflows/{release.yaml => 52n-release.yaml} (72%) diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/52n-build.yaml similarity index 93% rename from .github/workflows/build-and-push.yaml rename to .github/workflows/52n-build.yaml index 0cfb52d4174..df1a12d6259 100644 --- a/.github/workflows/build-and-push.yaml +++ b/.github/workflows/52n-build.yaml @@ -1,4 +1,4 @@ -name: Push GeoNode Docker Images +name: Push Thünen Atlas Docker Image(s) concurrency: group: "geonode_build" @@ -8,7 +8,7 @@ env: TITLE: "52°North GeoNode Docker Image" VENDOR: "52°North GmbH" AUTHORS: "https://52North.org/" - DESCRIPTION: "Builds and publishes the GeoNode Docker development image for Thuenen" + DESCRIPTION: "Builds and publishes Thuenen Atlas GeoNode image(s)" LICENSE: "GPL-3.0" on: diff --git a/.github/workflows/release.yaml b/.github/workflows/52n-release.yaml similarity index 72% rename from .github/workflows/release.yaml rename to .github/workflows/52n-release.yaml index bce7da86980..c98640c39bd 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/52n-release.yaml @@ -34,6 +34,10 @@ jobs: name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@v4 + env: + MAJOR_VERSION: ${{ steps.semver_parser.outputs.major }} + MAJOR_MINOR_VERSION: ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }} + MAJOR_MINOR_PATCH_VERSION: ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }}-${{ steps.semver_parser.outputs.patch }} with: images: ${{ env.IMAGE }} labels: | @@ -43,15 +47,19 @@ jobs: "org.opencontainers.image.title=${{ env.TITLE }}" "org.opencontainers.image.licenses=${{ env.LICENSE }}" tags: | - ${{ steps.semver_parser.outputs.major }} - ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }} - ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }}-${{ steps.semver_parser.outputs.patch }} + latest + ${{ env.MAJOR_VERSION }} + ${{ env.MAJOR_MINOR_VERSION }} + ${{ env.MAJOR_MINOR_PATCH_VERSION }} - name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Fail in case fully tagged version already exists + run: docker manifest inspect ${{ env.IMAGE }}:${{ steps.meta.env.MAJOR_MINOR_PATCH_VERSION }} > /dev/null ; test $? != 0 - name: Build and push uses: docker/build-push-action@v4 From 08ee49339905cd9f052c844c30e1e355fea56cda Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 18 Sep 2023 12:06:12 +0200 Subject: [PATCH 090/253] Align with upstream 4.1.x --- geonode/base/forms.py | 3 --- geonode/base/views.py | 15 ------------- geonode/geoserver/helpers.py | 11 ---------- geonode/geoserver/signals.py | 2 -- geonode/layers/api/serializers.py | 1 - geonode/security/tests.py | 9 -------- geonode/storage/data_retriever.py | 15 +++++++------ geonode/storage/tests.py | 20 ++---------------- .../storage/tests/data/data_collection.zip | Bin 14261 -> 0 bytes geonode/upload/__init__.py | 18 ---------------- setup.cfg | 8 ------- 11 files changed, 11 insertions(+), 91 deletions(-) delete mode 100644 geonode/storage/tests/data/data_collection.zip diff --git a/geonode/base/forms.py b/geonode/base/forms.py index b24ad8e935f..c888d816670 100644 --- a/geonode/base/forms.py +++ b/geonode/base/forms.py @@ -470,9 +470,6 @@ def __init__(self, *args, **kwargs): if field in ["poc", "owner"] and not self.can_change_perms: self.fields[field].disabled = True - if field in ["poc", "owner"] and not self.can_change_perms: - self.fields[field].disabled = True - def disable_keywords_widget_for_non_superuser(self, user): if settings.FREETEXT_KEYWORDS_READONLY and not user.is_superuser: self["keywords"].field.disabled = True diff --git a/geonode/base/views.py b/geonode/base/views.py index 30a55e8bff7..7d5d08aa692 100644 --- a/geonode/base/views.py +++ b/geonode/base/views.py @@ -333,21 +333,6 @@ def get_results(self, context): ] -class DatasetsAutocomplete(SimpleSelect2View): - model = Dataset - filter_arg = "title__icontains" - - def get_results(self, context): - return [ - { - "id": self.get_result_value(result), - "text": self.get_result_label(result.title), - "selected_text": self.get_selected_result_label(result.title), - } - for result in context["object_list"] - ] - - class ThesaurusAvailable(autocomplete.Select2QuerySetView): def get_queryset(self): tid = self.request.GET.get("sysid") diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index 5f0d5a627f5..e46179532c1 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -1876,17 +1876,6 @@ def get_time_info(layer): gs_uploader = Client(url, _user, _password) -def _create_geofence_client(): - gf_rest_url = f'{url.rstrip("/")}/geofence/' - client = GeoFenceClient(gf_rest_url, _user, _password) - client.set_timeout(ogc_server_settings.GEOFENCE_TIMEOUT) - return client - - -geofence = _create_geofence_client() -gf_utils = GeoFenceUtils(geofence) - - def _create_geofence_client(): gf_rest_url = f'{url.rstrip("/")}/geofence/' client = GeoFenceClient(gf_rest_url, _user, _password) diff --git a/geonode/geoserver/signals.py b/geonode/geoserver/signals.py index cfe1ad6f85b..70b96060303 100644 --- a/geonode/geoserver/signals.py +++ b/geonode/geoserver/signals.py @@ -42,8 +42,6 @@ geofence_rule_assign = Signal(providing_args=["instance"]) -geofence_rule_assign = Signal(providing_args=["instance"]) - def geoserver_delete(typename): # cascading_delete should only be called if diff --git a/geonode/layers/api/serializers.py b/geonode/layers/api/serializers.py index 27b1e6a1d6a..3d39fdefe20 100644 --- a/geonode/layers/api/serializers.py +++ b/geonode/layers/api/serializers.py @@ -181,7 +181,6 @@ class Meta: "subtype", "ptype", "executions", - "metadata", ) name = serializers.CharField(read_only=True) diff --git a/geonode/security/tests.py b/geonode/security/tests.py index 39dcc36a7a6..52b43a38551 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -1748,15 +1748,6 @@ def test_admin_whitelisted_access_middleware(self): middleware.process_request(request) self.assertTrue(request.user.is_superuser) - # Test valid IP in second element - with self.settings(ADMIN_IP_WHITELIST=["88.88.88.88", "127.0.0.1"]): - request = HttpRequest() - request.user = admin - request.path = reverse("home") - request.META["REMOTE_ADDR"] = "127.0.0.1" - middleware.process_request(request) - self.assertTrue(request.user.is_superuser) - class SecurityRulesTests(TestCase): """ diff --git a/geonode/storage/data_retriever.py b/geonode/storage/data_retriever.py index b535f948328..68a14c2e864 100644 --- a/geonode/storage/data_retriever.py +++ b/geonode/storage/data_retriever.py @@ -206,7 +206,7 @@ def _unzip(self, zip_name: str) -> Mapping: """ zip_file = self.file_paths["base_file"] with zipfile.ZipFile(zip_file, allowZip64=True) as the_zip: - the_zip.extractall(self.temporary_folder) + the_zip.extractall(self.temporary_folder) available_choices = get_allowed_extensions() not_main_files = ["xml", "sld", "zip", "kmz"] @@ -214,14 +214,17 @@ def _unzip(self, zip_name: str) -> Mapping: sorted_files = sorted(Path(self.temporary_folder).iterdir()) for _file in sorted_files: if not zipfile.is_zipfile(str(_file)): - if any([_file.name.endswith(_ext) for _ext in base_file_choices]): - self.file_paths['base_file'] = Path(str(_file)) + if any([_file.name.endswith(_ext) for _ext in base_file_choices]): + self.file_paths["base_file"] = Path(str(_file)) ext = _file.name.split(".")[-1] if f"{ext}_file" in self.file_paths: existing = self.file_paths[f"{ext}_file"] - self.file_paths[f"{ext}_file"] = [ Path(str(_file)), *(existing if type(existing) == list else [existing]) ] - else: - self.file_paths[f"{ext}_file"] = Path(str(_file)) + self.file_paths[f"{ext}_file"] = [ + Path(str(_file)), + *(existing if type(existing) == list else [existing]), + ] + else: + self.file_paths[f"{ext}_file"] = Path(str(_file)) tmp = self.file_paths.copy() for key, value in self.file_paths.items(): diff --git a/geonode/storage/tests.py b/geonode/storage/tests.py index e76c3b6feaa..3d496dba6f7 100644 --- a/geonode/storage/tests.py +++ b/geonode/storage/tests.py @@ -416,22 +416,6 @@ def test_storage_manager_copy(self): os.remove(output.get("files")[0]) self.assertFalse(os.path.exists(output.get("files")[0])) - @override_settings(FILE_UPLOAD_DIRECTORY_PERMISSIONS=0o777) - @override_settings(FILE_UPLOAD_PERMISSIONS=0o777) - def test_storage_manager_copy(self): - """ - Test that the copy works as expected and the permissions are corerct - """ - dataset = create_single_dataset(name="test_copy") - dataset.files = [os.path.join(f"{self.project_root}", "tests/data/test_sld.sld")] - dataset.save() - output = self.sut().copy(dataset) - - self.assertTrue(os.path.exists(output.get("files")[0])) - self.assertEqual(os.stat(os.path.exists(output.get("files")[0])).st_mode, 8592) - os.remove(output.get("files")[0]) - self.assertFalse(os.path.exists(output.get("files")[0])) - class TestDataRetriever(TestCase): @classmethod @@ -624,7 +608,7 @@ def test_zip_file_should_correctly_recognize_main_extension_with_shp(self): self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) _files = storage_manager.get_retrieved_paths() self.assertTrue("single_point.shp" in _files.get("base_file")) - + def test_zip_file_should_correctly_relate_mixed_content(self): zip_file = os.path.join(f"{self.project_root}", "tests/data/data_collection.zip") storage_manager = self.sut( @@ -634,7 +618,7 @@ def test_zip_file_should_correctly_relate_mixed_content(self): self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) _files = storage_manager.get_retrieved_paths() base_file = _files.get("base_file") - + def strip_extension(filename): return filename.split(".")[0] if filename else filename diff --git a/geonode/storage/tests/data/data_collection.zip b/geonode/storage/tests/data/data_collection.zip deleted file mode 100644 index 0702327be361a2bfda7c9c2a6eb13bd08ca5a9b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14261 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 Cq!$1H diff --git a/geonode/upload/__init__.py b/geonode/upload/__init__.py index f5c5c542718..c50c3f5609f 100644 --- a/geonode/upload/__init__.py +++ b/geonode/upload/__init__.py @@ -63,20 +63,6 @@ def run_setup_hooks(sender, **kwargs): start_time=timezone.now(), ), ) - daily_interval, _ = IntervalSchedule.objects.get_or_create( - every=1, - period="days" - ) - daily_interval, _ = IntervalSchedule.objects.get_or_create(every=1, period="days") - PeriodicTask.objects.update_or_create( - name="clean-up-old-task-result", - defaults=dict( - task="geonode.upload.tasks.cleanup_celery_task_entries", - interval=daily_interval, - args="", - start_time=timezone.now(), - ), - ) class UploadAppConfig(AppConfig): @@ -93,10 +79,6 @@ def ready(self): "task": "geonode.upload.tasks.cleanup_celery_task_entries", "schedule": 86400.0, } - settings.CELERY_BEAT_SCHEDULE["clean-up-old-task-result"] = { - "task": "geonode.upload.tasks.cleanup_celery_task_entries", - "schedule": 86400.0, - } default_app_config = "geonode.upload.UploadAppConfig" diff --git a/setup.cfg b/setup.cfg index 39709bce937..f6d5f90abf2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -202,14 +202,6 @@ install_requires = certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability jwcrypto>=1.4 # not directly required, pinned by Snyk to avoid a vulnerability - # Security and audit - mistune==2.0.5 - wandb==0.13.11 - protobuf==3.20.3 - mako==1.2.4 - certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability - jwcrypto>=1.4 # not directly required, pinned by Snyk to avoid a vulnerability - [options.packages.find] exclude = tests From 0fe99b9a22bc606f84c3bb1ea2d5eabe3e99d0cc Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 18 Sep 2023 16:35:46 +0200 Subject: [PATCH 091/253] Add docker hub description --- .github/workflows/52n-build.yaml | 3 +++ .../workflows/52n-dockerhub-description.yaml | 23 +++++++++++++++++++ README_thuenen.md | 8 +++++++ 3 files changed, 34 insertions(+) create mode 100644 .github/workflows/52n-dockerhub-description.yaml create mode 100644 README_thuenen.md diff --git a/.github/workflows/52n-build.yaml b/.github/workflows/52n-build.yaml index df1a12d6259..b30a7643827 100644 --- a/.github/workflows/52n-build.yaml +++ b/.github/workflows/52n-build.yaml @@ -15,6 +15,9 @@ on: push: branches: - "thuenen_4.x" + paths: + - "!./.github/workflows/52n-dockerhub-description.yaml" + - "!./README_thuenen.md" jobs: build_and_push_geonode: diff --git a/.github/workflows/52n-dockerhub-description.yaml b/.github/workflows/52n-dockerhub-description.yaml new file mode 100644 index 00000000000..1bd1b5f84f6 --- /dev/null +++ b/.github/workflows/52n-dockerhub-description.yaml @@ -0,0 +1,23 @@ +name: Update Docker Hub Description +on: + push: + branches: + - thuenen_4.x + paths: + - README_thuenen.md + - .github/workflows/52n-dockerhub-description.yaml +jobs: + dockerHubDescription: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Docker Hub Description + uses: peter-evans/dockerhub-description@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + repository: 52north/geonode + short-description: "Geospatial content management system" + readme-filepath: ./README_thuenen.md + enable-url-completion: true \ No newline at end of file diff --git a/README_thuenen.md b/README_thuenen.md new file mode 100644 index 00000000000..5ebf30dbe77 --- /dev/null +++ b/README_thuenen.md @@ -0,0 +1,8 @@ +# Thünen Atlas Fork of GeoNode + +This image is built from a fork of [Geonode](https://github.com/geonode/geonode). +[Thünen Institute](https://thuenen.de) maintains an own fork of GeoNode in order to make necessary adjustments within projects which are not (yet) part of GeoNode core. + +However, we are interested to stay as close to upstream as possible, to benefit from ongoing development, but also to contribute features and fixes we develop in [Thünen Atlas project](https://atlas.thuenen.de). + +This image (`52north/geonode_thuenen`) is built from the `thuenen_4.x` branch of the [`Thuenen-GeoNode-Development/geonode` repository](https://github.com/Thuenen-GeoNode-Development/geonode/tree/thuenen_4.x). From 6e241c346ec2c13341efd0c9eb2fcfe316c6ba1d Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Mon, 18 Sep 2023 16:37:21 +0200 Subject: [PATCH 092/253] Bump version to version 4.1.3 (#11506) --- geonode/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/__init__.py b/geonode/__init__.py index 7884b891ac6..3f30a094da9 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 1, 2, "dev", 0) +__version__ = (4, 1, 3, "final", 0) default_app_config = "geonode.apps.AppConfig" From b442e94f5d2a9390ff1f9a69c061045d0b99493e Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Mon, 18 Sep 2023 16:37:21 +0200 Subject: [PATCH 093/253] Bump version to version 4.1.3 (#11506) --- geonode/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/__init__.py b/geonode/__init__.py index 7884b891ac6..3f30a094da9 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 1, 2, "dev", 0) +__version__ = (4, 1, 3, "final", 0) default_app_config = "geonode.apps.AppConfig" From a5002cad67e4148aa0822f32626096379783c96a Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Tue, 19 Sep 2023 09:32:48 +0200 Subject: [PATCH 094/253] Fix client and importer versions for 4.1.3 (#11508) --- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 0470468edb4..55df34605f3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. --e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.1.x#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.1.1 +geonode-importer==1.0.5 geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index f6d5f90abf2..59fb9ad08cb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.1.1 - geonode-importer>=1.0.5 + django-geonode-mapstore-client==4.1.1 + geonode-importer==1.0.5 geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 6d2c174c7b48f8cda0a07b79a114d4ff098e655d Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Tue, 19 Sep 2023 10:30:15 +0200 Subject: [PATCH 095/253] Bump to dev branch (#11510) --- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/geonode/__init__.py b/geonode/__init__.py index 3f30a094da9..fd057ed56e3 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 1, 3, "final", 0) +__version__ = (4, 1, 3, "dev", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 55df34605f3..0470468edb4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -django-geonode-mapstore-client==4.1.1 -geonode-importer==1.0.5 +-e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.1.x#egg=django_geonode_mapstore_client +-e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 59fb9ad08cb..f6d5f90abf2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client==4.1.1 - geonode-importer==1.0.5 + django-geonode-mapstore-client>=4.1.1 + geonode-importer>=1.0.5 geonode-avatar==5.0.8 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 5e8bc63d70de97e835e947c398a2083ee111e823 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 26 Sep 2023 11:04:10 +0200 Subject: [PATCH 096/253] Fix parsing release version --- .github/workflows/52n-release.yaml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/52n-release.yaml b/.github/workflows/52n-release.yaml index c98640c39bd..3c7aad9527a 100644 --- a/.github/workflows/52n-release.yaml +++ b/.github/workflows/52n-release.yaml @@ -27,6 +27,7 @@ jobs: uses: booxmedialtd/ws-action-parse-semver@v1 with: input_string: "${{github.ref_name}}" + version_extractor_regex: 'v(.*)-thuenen' - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 @@ -37,7 +38,7 @@ jobs: env: MAJOR_VERSION: ${{ steps.semver_parser.outputs.major }} MAJOR_MINOR_VERSION: ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }} - MAJOR_MINOR_PATCH_VERSION: ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }}-${{ steps.semver_parser.outputs.patch }} + MAJOR_MINOR_PATCH_VERSION: ${{ steps.semver_parser.outputs.fullversion }} with: images: ${{ env.IMAGE }} labels: | @@ -59,7 +60,11 @@ jobs: password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Fail in case fully tagged version already exists - run: docker manifest inspect ${{ env.IMAGE }}:${{ steps.meta.env.MAJOR_MINOR_PATCH_VERSION }} > /dev/null ; test $? != 0 + run: | + if docker manifest inspect ${{ env.IMAGE }}:${{ steps.semver_parser.outputs.fullversion }}; then + echo "tag version already exists! Will not override." + exit 1 + fi - name: Build and push uses: docker/build-push-action@v4 From e0c62a853279129f37ee8549427e40f3df2d6413 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Thu, 11 May 2023 15:21:56 +0200 Subject: [PATCH 097/253] fix: requirements.txt to reduce vulnerabilities (#11029) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-DJANGO-5496950 Co-authored-by: Alessio Fabiani From 80580b0ced4033db73293a7557da79cde5727156 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 19 Sep 2023 17:23:17 +0200 Subject: [PATCH 098/253] Fix target image for docker README --- .github/workflows/52n-dockerhub-description.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/52n-dockerhub-description.yaml b/.github/workflows/52n-dockerhub-description.yaml index 1bd1b5f84f6..6d9a0352a54 100644 --- a/.github/workflows/52n-dockerhub-description.yaml +++ b/.github/workflows/52n-dockerhub-description.yaml @@ -17,7 +17,7 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - repository: 52north/geonode + repository: 52north/geonode_thuenen short-description: "Geospatial content management system" readme-filepath: ./README_thuenen.md enable-url-completion: true \ No newline at end of file From 104270d020ca9f72dce65a1c51e4dc4111845ec8 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Wed, 20 Sep 2023 14:46:18 +0200 Subject: [PATCH 099/253] Remove example test Test example is available still from the PR https://github.com/GeoNode/geonode/pull/10842 --- geonode/storage/tests.py | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/geonode/storage/tests.py b/geonode/storage/tests.py index 3d496dba6f7..89eea61d4ad 100644 --- a/geonode/storage/tests.py +++ b/geonode/storage/tests.py @@ -608,30 +608,3 @@ def test_zip_file_should_correctly_recognize_main_extension_with_shp(self): self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) _files = storage_manager.get_retrieved_paths() self.assertTrue("single_point.shp" in _files.get("base_file")) - - def test_zip_file_should_correctly_relate_mixed_content(self): - zip_file = os.path.join(f"{self.project_root}", "tests/data/data_collection.zip") - storage_manager = self.sut( - remote_files={"base_file": zip_file} - ) - storage_manager.clone_remote_files() - self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) - _files = storage_manager.get_retrieved_paths() - base_file = _files.get("base_file") - - def strip_extension(filename): - return filename.split(".")[0] if filename else filename - - base_name = strip_extension(base_file) - available_files = [ - _files.get("shp_file"), - _files.get("prj_file"), - _files.get("shx_file"), - _files.get("dbf_file") - ] - - def assert_same_base_name(base_name, file_name): - self.assertEqual(base_name, strip_extension(file_name)) - - for file in available_files: - assert_same_base_name(base_name, file) From f661f59f54d63eeb66bc049a48e1cc80819f8ded Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Wed, 20 Sep 2023 14:51:31 +0200 Subject: [PATCH 100/253] Reconfigure pipeline regarding ignored paths --- .github/workflows/52n-build.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/52n-build.yaml b/.github/workflows/52n-build.yaml index b30a7643827..18a9b21175f 100644 --- a/.github/workflows/52n-build.yaml +++ b/.github/workflows/52n-build.yaml @@ -15,9 +15,9 @@ on: push: branches: - "thuenen_4.x" - paths: - - "!./.github/workflows/52n-dockerhub-description.yaml" - - "!./README_thuenen.md" + paths-ignore: + - "./.github/workflows/52n-dockerhub-description.yaml" + - "./README_thuenen.md" jobs: build_and_push_geonode: From 0501d041fff04815ff2671f7704350ce37f40044 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Fri, 13 Oct 2023 12:09:37 +0200 Subject: [PATCH 101/253] Rename workflow build --- .github/workflows/52n-build.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/52n-build.yaml b/.github/workflows/52n-build.yaml index 18a9b21175f..cf82d61d0ee 100644 --- a/.github/workflows/52n-build.yaml +++ b/.github/workflows/52n-build.yaml @@ -1,7 +1,7 @@ -name: Push Thünen Atlas Docker Image(s) +name: "[thuenen_4.x -> 4.x] Push Thünen Atlas Docker Image(s)" -concurrency: - group: "geonode_build" +concurrency: + group: "geonode_build_thuenen_4.x" cancel-in-progress: true env: @@ -15,7 +15,7 @@ on: push: branches: - "thuenen_4.x" - paths-ignore: + paths-ignore: - "./.github/workflows/52n-dockerhub-description.yaml" - "./README_thuenen.md" @@ -32,7 +32,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - - + - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@v4 From bba1840ca4e41c473d76d78d41b834faf96d9a35 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Fri, 13 Oct 2023 12:24:05 +0200 Subject: [PATCH 102/253] Rename workflow file --- .github/workflows/{52n-build.yaml => 52n-build-4.x.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{52n-build.yaml => 52n-build-4.x.yaml} (100%) diff --git a/.github/workflows/52n-build.yaml b/.github/workflows/52n-build-4.x.yaml similarity index 100% rename from .github/workflows/52n-build.yaml rename to .github/workflows/52n-build-4.x.yaml From 8325e6e8dc66db88fe389f58280a535f659e3160 Mon Sep 17 00:00:00 2001 From: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Date: Thu, 5 Oct 2023 13:12:49 +0200 Subject: [PATCH 103/253] Test fix CircleCi test (#11560) * Test fix CircleCi test * Test fix CircleCi test * Test fix CircleCi test --- geonode/upload/api/tests.py | 80 ++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 23 deletions(-) diff --git a/geonode/upload/api/tests.py b/geonode/upload/api/tests.py index 8f84fec6a92..81cd4a3ea3f 100644 --- a/geonode/upload/api/tests.py +++ b/geonode/upload/api/tests.py @@ -17,7 +17,9 @@ # ######################################################################### +from geonode.base.models import ResourceBase from geonode.resource.models import ExecutionRequest +from geonode.geoserver.helpers import gs_catalog import os import shutil import logging @@ -233,35 +235,67 @@ def test_rest_uploads(self): """ Ensure we can access the Local Server Uploads list. """ - # Try to upload a good raster file and check the session IDs - fname = os.path.join(GOOD_DATA, "raster", "relief_san_andres.tif") - resp, data = rest_upload_by_path(fname, self.client) - self.assertEqual(resp.status_code, 201) - - url = reverse("uploads-list") - # Anonymous - self.client.logout() - response = self.client.get(url, format="json") - self.assertEqual(response.status_code, 200) - self.assertEqual(len(response.data), 5) - self.assertEqual(response.data["total"], 0) - # Pagination - self.assertEqual(len(response.data["uploads"]), 0) - logger.debug(response.data) + resp = None + layer_name = "relief_san_andres" + try: + self._cleanup_layer(layer_name=layer_name) + # Try to upload a good raster file and check the session IDs + fname = os.path.join(GOOD_DATA, "raster", "relief_san_andres.tif") + resp, data = rest_upload_by_path(fname, self.client) + self.assertEqual(resp.status_code, 201) + + url = reverse("uploads-list") + # Anonymous + self.client.logout() + response = self.client.get(url, format="json") + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data), 5) + self.assertEqual(response.data["total"], 0) + # Pagination + self.assertEqual(len(response.data["uploads"]), 0) + logger.debug(response.data) + except Exception: + if resp.json().get("errors"): + layer_name = resp.json().get("errors")[0].split("for : ")[1].split(",")[0] + finally: + self._cleanup_layer(layer_name) @override_settings(CELERY_TASK_ALWAYS_EAGER=True) def test_rest_uploads_non_interactive(self): """ Ensure we can access the Local Server Uploads list. """ - # Try to upload a good raster file and check the session IDs - fname = os.path.join(GOOD_DATA, "raster", "relief_san_andres.tif") - resp, data = rest_upload_by_path(fname, self.client, non_interactive=True) - self.assertEqual(resp.status_code, 201) - - exec_id = data.get("execution_id", None) - _exec = ExecutionRequest.objects.get(exec_id=exec_id) - self.assertEqual(_exec.status, "finished") + resp = None + layer_name = "relief_san_andres" + try: + self._cleanup_layer(layer_name=layer_name) + # Try to upload a good raster file and check the session IDs + fname = os.path.join(GOOD_DATA, "raster", "relief_san_andres.tif") + resp, data = rest_upload_by_path(fname, self.client, non_interactive=True) + self.assertEqual(resp.status_code, 201) + exec_id = data.get("execution_id", None) + _exec = ExecutionRequest.objects.get(exec_id=exec_id) + self.assertEqual(_exec.status, "finished") + except Exception: + if resp.json().get("errors"): + layer_name = resp.json().get("errors")[0].split("for : ")[1].split(",")[0] + finally: + self._cleanup_layer(layer_name) + + def _cleanup_layer(self, layer_name): + # removing the layer from geonode + x = ResourceBase.objects.filter(alternate__icontains=layer_name) + if x.exists(): + for el in x.iterator(): + el.delete() + # removing the layer from geoserver + dataset = gs_catalog.get_layer(layer_name) + if dataset: + gs_catalog.delete(dataset, purge="all", recurse=True) + # removing the layer from geoserver + store = gs_catalog.get_store(layer_name, workspace="geonode") + if store: + gs_catalog.delete(store, purge="all", recurse=True) @mock.patch("geonode.upload.uploadhandler.SimpleUploadedFile") def test_rest_uploads_with_size_limit(self, mocked_uploaded_file): From 628e5f1e76b430349f4e671d4557af344c7df572 Mon Sep 17 00:00:00 2001 From: Gleb Kilichenko Date: Thu, 23 Nov 2023 20:53:28 +0100 Subject: [PATCH 104/253] overriding update method in dataset serializer class --- geonode/layers/api/serializers.py | 33 ++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/geonode/layers/api/serializers.py b/geonode/layers/api/serializers.py index 3d39fdefe20..864e2af1c73 100644 --- a/geonode/layers/api/serializers.py +++ b/geonode/layers/api/serializers.py @@ -17,7 +17,7 @@ # ######################################################################### from rest_framework import serializers - +from rest_framework.exceptions import ValidationError, ParseError from urllib.parse import urlparse from django.conf import settings @@ -195,6 +195,37 @@ class Meta: featureinfo_custom_template = FeatureInfoTemplateField() + def update(self, instance, validated_data): + super().update(instance, validated_data) + + # Handle updates to attribute_set + allowed_fields = ["pk", "description", "attribute_label", "visible", "display_order"] + if "blob" in validated_data and "attribute_set" in validated_data["blob"]: + attributes = validated_data["blob"]["attribute_set"] + + for attribute in attributes: + for field, _ in attribute.items(): + if field not in allowed_fields: + raise ValidationError( + f"{field} is not one of the fields that could be edited directly. \ + Only {str(allowed_fields)} are allowed" + ) + + for attribute in attributes: + try: + if "pk" in attribute: + attribute_instance = Attribute.objects.get(pk=attribute["pk"], dataset=instance) + for field, value in attribute.items(): + setattr(attribute_instance, field, value) + attribute_instance.save() + else: + raise Exception("Primary key of the attribute to be patched not specified") + except Exception as e: + logger.error(e) + raise ParseError(str(e)) + + return instance + class DatasetListSerializer(DatasetSerializer): class Meta(DatasetSerializer.Meta): From 91de5c37b5abd522248ac868e95c73a41b5eecdd Mon Sep 17 00:00:00 2001 From: ahmdthr Date: Mon, 4 Dec 2023 09:19:43 +0100 Subject: [PATCH 105/253] Documents can now be uploaded without specifying title via the REST API. --- geonode/documents/api/serializers.py | 2 ++ geonode/documents/models.py | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/geonode/documents/api/serializers.py b/geonode/documents/api/serializers.py index dc11cb201f5..534a6c3fafb 100644 --- a/geonode/documents/api/serializers.py +++ b/geonode/documents/api/serializers.py @@ -19,6 +19,7 @@ import logging from dynamic_rest.fields.fields import DynamicComputedField +from rest_framework import serializers from geonode.base.api.serializers import ResourceBaseSerializer from geonode.documents.models import Document @@ -39,6 +40,7 @@ class DocumentSerializer(ResourceBaseSerializer): def __init__(self, *args, **kwargs): # Instantiate the superclass normally super().__init__(*args, **kwargs) + self.fields["title"] = serializers.CharField(required=False) file_path = GeonodeFilePathField(required=False) doc_file = DocumentFieldField(required=False) diff --git a/geonode/documents/models.py b/geonode/documents/models.py index e9a81dac1dc..c5f1a49fdc2 100644 --- a/geonode/documents/models.py +++ b/geonode/documents/models.py @@ -85,7 +85,10 @@ def compact_permission_labels(cls): @property def name(self): if not self.title: - return str(self.id) + if len(self.files) > 0: + return self.files[0].split("/")[-1] + else: + return str(self.id) else: return self.title From fb7ced3ea531624be94a520e8e9b1db4235c2fd6 Mon Sep 17 00:00:00 2001 From: ahmdthr <116570171+ahmdthr@users.noreply.github.com> Date: Mon, 18 Dec 2023 10:40:09 +0100 Subject: [PATCH 106/253] Integrates PyCSW v3 to provide DataCite metadata format Integrates pyCSW `v3` (as alpha) to provide DataCite download format on the backend. Relates to PR Thuenen-GeoNode-Development/geonode-mapstore-client#27 which adds a button to download metadata as DataCite format. --- geonode/base/utils.py | 1 + geonode/catalogue/backends/generic.py | 1 + geonode/catalogue/backends/pycsw_http.py | 2 +- geonode/catalogue/backends/pycsw_local.py | 2 +- geonode/catalogue/backends/pycsw_local_mappings.py | 10 +++++++++- geonode/settings.py | 1 + requirements.txt | 2 +- setup.cfg | 2 +- 8 files changed, 16 insertions(+), 5 deletions(-) diff --git a/geonode/base/utils.py b/geonode/base/utils.py index 0afee6192e1..e647c079d5c 100644 --- a/geonode/base/utils.py +++ b/geonode/base/utils.py @@ -60,6 +60,7 @@ "KML", "KMZ", "Atom", + "DataCite", "DIF", "Dublin Core", "ebRIM", diff --git a/geonode/catalogue/backends/generic.py b/geonode/catalogue/backends/generic.py index 94eb2198ab2..4019b04c22e 100644 --- a/geonode/catalogue/backends/generic.py +++ b/geonode/catalogue/backends/generic.py @@ -34,6 +34,7 @@ TIMEOUT = 10 METADATA_FORMATS = { "Atom": ("atom:entry", "http://www.w3.org/2005/Atom"), + "DataCite": ("csw:Record", "http://datacite.org/schema/kernel-4"), "DIF": ("dif:DIF", "http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/"), "Dublin Core": ("csw:Record", "http://www.opengis.net/cat/csw/2.0.2"), "ebRIM": ("rim:RegistryObject", "urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0"), diff --git a/geonode/catalogue/backends/pycsw_http.py b/geonode/catalogue/backends/pycsw_http.py index 0058c41359c..4cd5305d0c2 100644 --- a/geonode/catalogue/backends/pycsw_http.py +++ b/geonode/catalogue/backends/pycsw_http.py @@ -26,4 +26,4 @@ class CatalogueBackend(GenericCatalogueBackend): def __init__(self, *args, **kwargs): """initialize pycsw HTTP CSW backend""" GenericCatalogueBackend.__init__(CatalogueBackend, self, *args, **kwargs) - self.catalogue.formats = ["Atom", "DIF", "Dublin Core", "ebRIM", "FGDC", "ISO"] + self.catalogue.formats = ["Atom", "DataCite", "DIF", "Dublin Core", "ebRIM", "FGDC", "ISO"] diff --git a/geonode/catalogue/backends/pycsw_local.py b/geonode/catalogue/backends/pycsw_local.py index 75c66e96498..4be10f9b633 100644 --- a/geonode/catalogue/backends/pycsw_local.py +++ b/geonode/catalogue/backends/pycsw_local.py @@ -65,7 +65,7 @@ class CatalogueBackend(GenericCatalogueBackend): def __init__(self, *args, **kwargs): GenericCatalogueBackend.__init__(CatalogueBackend, self, *args, **kwargs) - self.catalogue.formats = ["Atom", "DIF", "Dublin Core", "ebRIM", "FGDC", "ISO"] + self.catalogue.formats = ["Atom", "DataCite", "DIF", "Dublin Core", "ebRIM", "FGDC", "ISO"] self.catalogue.local = True def remove_record(self, uuid): diff --git a/geonode/catalogue/backends/pycsw_local_mappings.py b/geonode/catalogue/backends/pycsw_local_mappings.py index 4ba4f7902ff..4818390a08b 100644 --- a/geonode/catalogue/backends/pycsw_local_mappings.py +++ b/geonode/catalogue/backends/pycsw_local_mappings.py @@ -30,6 +30,14 @@ "pycsw:AnyText": "csw_anytext", "pycsw:Language": "language", "pycsw:Title": "title", + "pycsw:Edition": "edition", + "pycsw:Platform": "platform", + "pycsw:Instrument": "instrument", + "pycsw:SensorType": "sensortype", + "pycsw:CloudCover": "cloudcover", + "pycsw:Bands": "bands", + "pycsw:Themes": "themes", + "pycsw:Contacts": "contacts", "pycsw:Abstract": "raw_abstract", "pycsw:Keywords": "keyword_csv", "pycsw:KeywordType": "keywordstype", @@ -77,6 +85,6 @@ "pycsw:Publisher": "publisher", "pycsw:Contributor": "contributor", "pycsw:Relation": "relation", - "pycsw:Links": "download_links", + "pycsw:Links": "download_urls", }, } diff --git a/geonode/settings.py b/geonode/settings.py index d408093575b..2c3f64d8c3e 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -1303,6 +1303,7 @@ # Available download formats DOWNLOAD_FORMATS_METADATA = [ "Atom", + "DataCite", "DIF", "Dublin Core", "ebRIM", diff --git a/requirements.txt b/requirements.txt index 0470468edb4..5ec4ba5f54a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -55,7 +55,7 @@ pyjwt==2.7.0 # geopython dependencies pyproj<3.6.0 OWSLib==0.29.2 -pycsw==2.6.1 +-e git+https://github.com/geopython/pycsw.git@3.0.0-alpha5#egg=pycsw SQLAlchemy==2.0.15 # required by PyCSW Shapely==1.8.5.post1 mercantile==1.2.1 diff --git a/setup.cfg b/setup.cfg index f6d5f90abf2..c701c67c48e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -81,7 +81,7 @@ install_requires = # geopython dependencies pyproj<3.6.0 OWSLib==0.29.2 - pycsw==2.6.1 + pycsw @ git+https://github.com/geopython/pycsw.git@3.0.0-alpha5 SQLAlchemy==2.0.15 # required by PyCSW Shapely==1.8.5.post1 mercantile==1.2.1 From 785fbf86dad1e88a02513443e48576f06970ebfd Mon Sep 17 00:00:00 2001 From: Henning Bredel <881756+ridoo@users.noreply.github.com> Date: Mon, 18 Dec 2023 12:16:48 +0100 Subject: [PATCH 107/253] Allows metadata upload with different UUID Co-authored-by: ahmdthr --- geonode/layers/api/tests.py | 2 +- geonode/layers/api/views.py | 9 ++++----- .../datasets/dataset_metadata_upload.html | 1 + geonode/layers/tests.py | 20 +++++++++---------- geonode/layers/views.py | 11 +++++----- geonode/locale/en/LC_MESSAGES/django.po | 3 +++ geonode/static/geonode/js/upload/LayerInfo.js | 12 +++++++++-- 7 files changed, 35 insertions(+), 23 deletions(-) diff --git a/geonode/layers/api/tests.py b/geonode/layers/api/tests.py index 7361e5c744a..fd0e4adae3d 100644 --- a/geonode/layers/api/tests.py +++ b/geonode/layers/api/tests.py @@ -361,7 +361,7 @@ def test_valid_metadata_file_with_different_uuid(self): f = open(self.exml_path, "r") put_data = {"metadata_file": f} response = self.client.put(url, data=put_data) - self.assertEqual(500, response.status_code) + self.assertEqual(200, response.status_code) def test_permissions_for_not_permitted_user(self): get_user_model().objects.create_user( diff --git a/geonode/layers/api/views.py b/geonode/layers/api/views.py index 3ad985c7781..5c45fd8d509 100644 --- a/geonode/layers/api/views.py +++ b/geonode/layers/api/views.py @@ -141,17 +141,16 @@ def metadata(self, request, pk=None): dataset_uuid, vals, regions, keywords, _ = parse_metadata(open(metadata_file).read()) except Exception: raise InvalidMetadataException(detail="Unsupported metadata format") - if dataset_uuid and dataset.uuid != dataset_uuid: - raise InvalidMetadataException( - detail="The UUID identifier from the XML Metadata, is different from the one saved" - ) try: updated_dataset = update_resource(dataset, metadata_file, regions, keywords, vals) updated_dataset.save() # This also triggers the recreation of the XML metadata file according to the updated values except Exception: raise GeneralDatasetException(detail="Failed to update metadata") out["success"] = True - out["message"] = ["Metadata successfully updated"] + out_message = "Metadata successfully updated" + if dataset_uuid and dataset.uuid != dataset_uuid: + out_message += " The UUID identifier from the XML Metadata is different from the one saved" + out["message"] = [out_message] return Response(out) except Exception as e: raise e diff --git a/geonode/layers/templates/datasets/dataset_metadata_upload.html b/geonode/layers/templates/datasets/dataset_metadata_upload.html index 6ef4d3d2e55..a5a0168e9ef 100644 --- a/geonode/layers/templates/datasets/dataset_metadata_upload.html +++ b/geonode/layers/templates/datasets/dataset_metadata_upload.html @@ -63,6 +63,7 @@

    {% trans "Files to be uploaded" %}

    +
    {% trans "WARNING" %}: {% trans "This will most probably overwrite the current metadata!" %}
    {% trans "Clear" %} {% trans "Upload files" %}
    diff --git a/geonode/layers/tests.py b/geonode/layers/tests.py index d7420fc2a84..70627226426 100644 --- a/geonode/layers/tests.py +++ b/geonode/layers/tests.py @@ -1003,9 +1003,10 @@ def test_xml_should_update_the_dataset_with_the_expected_values(self): prev_dataset = Dataset.objects.get(typename="geonode:single_point") self.assertEqual(0, prev_dataset.keywords.count()) resp = self.client.post(reverse("dataset_upload"), params) - self.assertEqual(404, resp.status_code) + self.assertEqual(200, resp.status_code) self.assertEqual( - resp.json()["errors"], "The UUID identifier from the XML Metadata, is different from the one saved" + resp.json()["warning"], + "WARNING: The XML's UUID was ignored while updating this dataset's metadata because that UUID is already present in this system. The rest of the XML's metadata was applied.", ) def test_sld_should_raise_500_if_is_invalid(self): @@ -1053,10 +1054,10 @@ def test_sld_should_update_the_dataset_with_the_expected_values(self): self.assertIsNotNone(updated_dataset.styles.first()) self.assertEqual(layer.styles.first().sld_title, updated_dataset.styles.first().sld_title) - def test_xml_should_raise_an_error_if_the_uuid_is_changed(self): + def test_xml_should_not_raise_an_error_if_the_uuid_is_changed(self): """ If the UUID coming from the XML and the one saved in the DB are different - The system should raise an error + The system should not raise an error, instead it should simply update the values """ params = { "permissions": '{ "users": {"AnonymousUser": ["view_resourcebase"]} , "groups":{}}', @@ -1072,12 +1073,11 @@ def test_xml_should_raise_an_error_if_the_uuid_is_changed(self): prev_dataset = Dataset.objects.get(typename="geonode:single_point") self.assertEqual(0, prev_dataset.keywords.count()) resp = self.client.post(reverse("dataset_upload"), params) - self.assertEqual(404, resp.status_code) - expected = { - "success": False, - "errors": "The UUID identifier from the XML Metadata, is different from the one saved", - } - self.assertDictEqual(expected, resp.json()) + self.assertEqual(200, resp.status_code) + self.assertEqual( + resp.json()["warning"], + "WARNING: The XML's UUID was ignored while updating this dataset's metadata because that UUID is already present in this system. The rest of the XML's metadata was applied.", + ) def test_will_raise_exception_for_replace_vector_dataset_with_raster(self): layer = Dataset.objects.get(name="single_point") diff --git a/geonode/layers/views.py b/geonode/layers/views.py index 609a7f0c839..5e385cee813 100644 --- a/geonode/layers/views.py +++ b/geonode/layers/views.py @@ -171,10 +171,6 @@ def dataset_upload_metadata(request): ) if layer: dataset_uuid, vals, regions, keywords, _ = parse_metadata(open(base_file).read()) - if dataset_uuid and layer.uuid != dataset_uuid: - out["success"] = False - out["errors"] = "The UUID identifier from the XML Metadata, is different from the one saved" - return HttpResponse(json.dumps(out), content_type="application/json", status=404) updated_dataset = update_resource(layer, base_file, regions, keywords, vals) updated_dataset.save() out["status"] = ["finished"] @@ -186,9 +182,14 @@ def dataset_upload_metadata(request): upload_session = updated_dataset.upload_session upload_session.processed = True upload_session.save() - status_code = 200 out["success"] = True + status_code = 200 + if dataset_uuid and layer.uuid != dataset_uuid: + out[ + "warning" + ] = "WARNING: The XML's UUID was ignored while updating this dataset's metadata because that UUID is already present in this system. The rest of the XML's metadata was applied." return HttpResponse(json.dumps(out), content_type="application/json", status=status_code) + else: out["success"] = False out["errors"] = "Dataset selected does not exists" diff --git a/geonode/locale/en/LC_MESSAGES/django.po b/geonode/locale/en/LC_MESSAGES/django.po index d6ce030a65a..5a110507052 100644 --- a/geonode/locale/en/LC_MESSAGES/django.po +++ b/geonode/locale/en/LC_MESSAGES/django.po @@ -1168,6 +1168,9 @@ msgstr "Files to be uploaded" msgid "Is Upload Metadata XML Form" msgstr "Is Upload Metadata XML Form" +msgid "This will most probably overwrite the current metadata!" +msgstr "This will most probably overwrite the current metadata!" + msgid "Upload files" msgstr "Upload files" diff --git a/geonode/static/geonode/js/upload/LayerInfo.js b/geonode/static/geonode/js/upload/LayerInfo.js index 4d4c4385172..574776a8977 100644 --- a/geonode/static/geonode/js/upload/LayerInfo.js +++ b/geonode/static/geonode/js/upload/LayerInfo.js @@ -458,7 +458,15 @@ define(function (require, exports) { } catch (err) { // pass } - var info_message = gettext('Your ' + resourceType +' was successfully created.'); + var info_message = '' + var level = 'alert-success' + if (resp.warning){ + info_message = resp.warning + level = 'alert-warning' + } + else{ + info_message = gettext('Your ' + resourceType +' was successfully created.'); + } var a = '' + gettext(resourceType.capitalize() + ' Info') + '   '; if(resourceType == 'dataset') { // Only Layers have Metadata and SLD Upload features for the moment @@ -474,7 +482,7 @@ define(function (require, exports) { } self.logStatus({ msg: '

    ' + info_message + '
    ' + msg_col + '
    ' + a + '

    ', - level: 'alert-success', + level: level, empty: 'true' }); }; From 2039eb7cd4d62adad954cbe89d237867ecd4e52f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 12:58:53 +0100 Subject: [PATCH 108/253] Don't quote JAVA_OPTS (#11807) (#11810) (cherry picked from commit 8d2dfbf7f71f0a186016b3fd8ef1180a57b45925) Co-authored-by: Giovanni Allegri --- .env.sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.sample b/.env.sample index 962f5a82258..afc97264bc3 100644 --- a/.env.sample +++ b/.env.sample @@ -101,7 +101,7 @@ OGC_REQUEST_POOL_CONNECTIONS=10 # Java Options & Memory ENABLE_JSONP=true outFormat=text/javascript -GEOSERVER_JAVA_OPTS='-Djava.awt.headless=true -Xms4G -Xmx4G -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:PerfDataSamplingInterval=500 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:-UseGCOverheadLimit -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL={geoserver_ui}/geoserver/pdf -DALLOW_ENV_PARAMETRIZATION=true -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3-Unsafe.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine' +GEOSERVER_JAVA_OPTS=-Djava.awt.headless=true -Xms4G -Xmx4G -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:PerfDataSamplingInterval=500 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:-UseGCOverheadLimit -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL={geoserver_ui}/geoserver/pdf -DALLOW_ENV_PARAMETRIZATION=true -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3-Unsafe.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine # ################# # Security From b4e8838ecc75fbb297d9ce175b5c7ffc31ced621 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Tue, 9 Jan 2024 16:19:59 +0100 Subject: [PATCH 109/253] Fix template variable for print base url (#11813) --- .env.sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.sample b/.env.sample index afc97264bc3..6e5dd10da9d 100644 --- a/.env.sample +++ b/.env.sample @@ -101,7 +101,7 @@ OGC_REQUEST_POOL_CONNECTIONS=10 # Java Options & Memory ENABLE_JSONP=true outFormat=text/javascript -GEOSERVER_JAVA_OPTS=-Djava.awt.headless=true -Xms4G -Xmx4G -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:PerfDataSamplingInterval=500 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:-UseGCOverheadLimit -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL={geoserver_ui}/geoserver/pdf -DALLOW_ENV_PARAMETRIZATION=true -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3-Unsafe.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine +GEOSERVER_JAVA_OPTS=-Djava.awt.headless=true -Xms4G -Xmx4G -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:PerfDataSamplingInterval=500 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:-UseGCOverheadLimit -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL={siteurl}/geoserver/pdf -DALLOW_ENV_PARAMETRIZATION=true -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3-Unsafe.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine # ################# # Security From aadf0979cb3f85fd25c315caa74dfef2ced1d67c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 10 Jan 2024 11:34:19 +0100 Subject: [PATCH 110/253] [Fixes #11817] Drop Nginx and Letsencrypt Dockerfiles (#11818) (#11820) * Drop Nginx and Letsencrypt Dockerfiles * align compose files * algin compose filew (2) (cherry picked from commit 535f08cb5d2385b6e6d0aa0e314998a723f896ba) Co-authored-by: Giovanni Allegri --- docker-compose-dev.yml | 9 +- docker-compose-geoserver-server.yml | 4 +- docker-compose-test.yml | 10 +- docker-compose.yml | 10 +- scripts/docker/letsencrypt/Dockerfile | 18 --- scripts/docker/letsencrypt/README.md | 15 -- scripts/docker/letsencrypt/crontab | 8 -- .../docker/letsencrypt/docker-entrypoint.sh | 52 ------- scripts/docker/nginx/Dockerfile | 18 --- scripts/docker/nginx/docker-autoreload.sh | 37 ----- scripts/docker/nginx/docker-entrypoint.sh | 67 --------- scripts/docker/nginx/geonode.conf.envsubst | 134 ------------------ scripts/docker/nginx/nginx.conf.envsubst | 39 ----- .../nginx/nginx.https.available.conf.envsubst | 37 ----- 14 files changed, 14 insertions(+), 444 deletions(-) delete mode 100644 scripts/docker/letsencrypt/Dockerfile delete mode 100644 scripts/docker/letsencrypt/README.md delete mode 100644 scripts/docker/letsencrypt/crontab delete mode 100644 scripts/docker/letsencrypt/docker-entrypoint.sh delete mode 100644 scripts/docker/nginx/Dockerfile delete mode 100644 scripts/docker/nginx/docker-autoreload.sh delete mode 100644 scripts/docker/nginx/docker-entrypoint.sh delete mode 100644 scripts/docker/nginx/geonode.conf.envsubst delete mode 100644 scripts/docker/nginx/nginx.conf.envsubst delete mode 100644 scripts/docker/nginx/nginx.https.available.conf.envsubst diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 0ac801a9621..7c21d3ec374 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -52,7 +52,7 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: - image: geonode/nginx:1.25.1 + image: geonode/nginx:latest build: ./scripts/docker/nginx/ container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: @@ -71,7 +71,6 @@ services: # Gets and installs letsencrypt certificates letsencrypt: image: geonode/letsencrypt:latest - build: ./scripts/docker/letsencrypt/ container_name: letsencrypt4${COMPOSE_PROJECT_NAME} env_file: - .env @@ -81,7 +80,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:latest container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -107,7 +106,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:latest container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: @@ -119,7 +118,7 @@ services: # PostGIS database. db: # use geonode official postgis 15 image - image: geonode/postgis:15 + image: geonode/postgis:latest command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" container_name: db4${COMPOSE_PROJECT_NAME} env_file: diff --git a/docker-compose-geoserver-server.yml b/docker-compose-geoserver-server.yml index 10785a5794a..5a83f79b7c7 100644 --- a/docker-compose-geoserver-server.yml +++ b/docker-compose-geoserver-server.yml @@ -2,7 +2,7 @@ version: '2.2' services: data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:latest restart: on-failure container_name: gsconf4${COMPOSE_PROJECT_NAME} labels: @@ -13,7 +13,7 @@ services: - geoserver-data-dir:/geoserver_data/data geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:latest restart: unless-stopped container_name: geoserver4${COMPOSE_PROJECT_NAME} stdin_open: true diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 9bd764f8da3..22ac6dd0093 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -52,8 +52,7 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: - image: geonode/nginx:1.25.1 - build: ./scripts/docker/nginx/ + image: geonode/nginx:latest container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: - .env_test @@ -84,7 +83,6 @@ services: # Gets and installs letsencrypt certificates letsencrypt: image: geonode/letsencrypt:latest - build: ./scripts/docker/letsencrypt/ container_name: letsencrypt4${COMPOSE_PROJECT_NAME} env_file: - .env_test @@ -94,7 +92,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:latest container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -120,7 +118,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:latest container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: @@ -132,7 +130,7 @@ services: # PostGIS database. db: # use geonode official postgis 15 image - image: geonode/postgis:15 + image: geonode/postgis:latest command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" container_name: db4${COMPOSE_PROJECT_NAME} env_file: diff --git a/docker-compose.yml b/docker-compose.yml index 7cc150f129c..61b85d10503 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -61,8 +61,7 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: - image: geonode/nginx:1.25.1 - build: ./scripts/docker/nginx/ + image: geonode/nginx:latest container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: - .env @@ -80,7 +79,6 @@ services: # Gets and installs letsencrypt certificates letsencrypt: image: geonode/letsencrypt:latest - build: ./scripts/docker/letsencrypt/ container_name: letsencrypt4${COMPOSE_PROJECT_NAME} env_file: - .env @@ -90,7 +88,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:latest container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -116,7 +114,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:latest container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: @@ -128,7 +126,7 @@ services: # PostGIS database. db: # use geonode official postgis 15 image - image: geonode/postgis:15 + image: geonode/postgis:latest command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" container_name: db4${COMPOSE_PROJECT_NAME} env_file: diff --git a/scripts/docker/letsencrypt/Dockerfile b/scripts/docker/letsencrypt/Dockerfile deleted file mode 100644 index 1480342e8f1..00000000000 --- a/scripts/docker/letsencrypt/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM alpine:latest - -RUN apk add --no-cache certbot - -# Installing scripts -ADD docker-entrypoint.sh /docker-entrypoint.sh -RUN chmod +x /docker-entrypoint.sh - -# Installing cronjobs -ADD crontab /crontab -RUN /usr/bin/crontab /crontab && \ - rm /crontab - -# Setup the entrypoint -ENTRYPOINT ["./docker-entrypoint.sh"] - -# We run cron in foreground to update the certificates -CMD /usr/sbin/crond -f diff --git a/scripts/docker/letsencrypt/README.md b/scripts/docker/letsencrypt/README.md deleted file mode 100644 index d6b1ec2247e..00000000000 --- a/scripts/docker/letsencrypt/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Letsencrypt service for Geonode - -This service generates SSL certificates to be used by Nginx. - -## Let's Encrypt - -Upon startup, it generates one SSL certificate from Let's Encrypt using Certbot. It then starts cron (in foreground) to renew the certificates using Certbot renew. - -If for some reason getting the certificate fails, a placeholder certificate is generated. This certificate is invalid, but still allows to encrypt the data and to start the webserver. - -To avoid hitting Let's Encrypt very low rate limits when developping or doing tests, LETSENCRYPT_MODE env var can be set to "disabled" (which will completely bypass Let'sEncrypt, simulating a failure) or to "staging" (using Let'sEncrypt test certificates with higher rates). - -## Autoissued - -An auto-issued certificate is also generate to be used on the LAN if needed. It is also renewed every now and then using the same cron process than above. diff --git a/scripts/docker/letsencrypt/crontab b/scripts/docker/letsencrypt/crontab deleted file mode 100644 index 7ea7203b8f8..00000000000 --- a/scripts/docker/letsencrypt/crontab +++ /dev/null @@ -1,8 +0,0 @@ -# +------------- minute (0 - 59) -# ¦ +------------- hour (0 - 23) -# ¦ ¦ +------------- day of month (1 - 31) -# ¦ ¦ ¦ +------------- month (1 - 12) -# ¦ ¦ ¦ ¦ +------------- day of week (0 - 6) (Sunday to Saturday; 7 is also Sunday on some systems) -# ¦ ¦ ¦ ¦ ¦ - - 0 0,12 * * * date && echo "daily " && /docker-entrypoint.sh diff --git a/scripts/docker/letsencrypt/docker-entrypoint.sh b/scripts/docker/letsencrypt/docker-entrypoint.sh deleted file mode 100644 index d1c4541b075..00000000000 --- a/scripts/docker/letsencrypt/docker-entrypoint.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/sh - -# Exit script in case of error -set -e - -echo $"\n\n\n" -echo "-----------------------------------------------------" -echo "STARTING LETSENCRYPT ENTRYPOINT ---------------------" -date - -# We make the config dir -mkdir -p "/geonode-certificates/$LETSENCRYPT_MODE" - -# Do not exit script in case of error -set +e - -# We run the command -if [ "$LETSENCRYPT_MODE" == "staging" ]; then - printf "\nTrying to get STAGING certificate\n" - certbot --config-dir "/geonode-certificates/$LETSENCRYPT_MODE" certonly --webroot -w "/geonode-certificates" -d "$HTTPS_HOST" -m "$ADMIN_EMAIL" --agree-tos --non-interactive --test-cert -elif [ "$LETSENCRYPT_MODE" == "production" ]; then - printf "\nTrying to get PRODUCTION certificate\n" - certbot --config-dir "/geonode-certificates/$LETSENCRYPT_MODE" certonly --webroot -w "/geonode-certificates" -d "$HTTPS_HOST" -m "$ADMIN_EMAIL" --agree-tos --non-interactive --server https://acme-v02.api.letsencrypt.org/directory -elif [ "$LETSENCRYPT_MODE" == "disabled" ]; then - printf "\nNot trying to get certificate (because LETSENCRYPT_MODE variable is set to disabled) - and stop container\n" - exit 0 -else - printf "\nNot trying to get certificate (simulating failure, because LETSENCRYPT_MODE variable was neither staging nor production\n" - /bin/false -fi - -# If the certbot comand failed, we will create a placeholder certificate -if [ ! $? -eq 0 ]; then - # Exit script in case of error - set -e - - printf "\nFailed to get the certificates !\n" - - printf "\nWaiting 30s to avoid hitting Letsencrypt rate limits before it's even possible to react\n" - sleep 30 - - exit 1 -fi - -printf "\nCertificate have been created/renewed successfully\n" - -echo "-----------------------------------------------------" -echo "FINISHED LETSENCRYPT ENTRYPOINT ---------------------" -echo "-----------------------------------------------------" - -# Run the CMD -exec "$@" diff --git a/scripts/docker/nginx/Dockerfile b/scripts/docker/nginx/Dockerfile deleted file mode 100644 index 9b0fe5b4f30..00000000000 --- a/scripts/docker/nginx/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM nginx:1.25.3-alpine - -RUN apk add --no-cache openssl inotify-tools vim - -WORKDIR /etc/nginx/ - -RUN mkdir -p /etc/nginx/html -RUN touch /etc/nginx/html/index.html - -ADD nginx.conf.envsubst nginx.https.available.conf.envsubst ./ -ADD geonode.conf.envsubst ./sites-enabled/ - -ADD docker-autoreload.sh docker-entrypoint.sh / -ENTRYPOINT ["/docker-entrypoint.sh"] -RUN chmod +x /docker-autoreload.sh -RUN chmod +x /docker-entrypoint.sh - -CMD ["nginx", "-g", "daemon off;"] diff --git a/scripts/docker/nginx/docker-autoreload.sh b/scripts/docker/nginx/docker-autoreload.sh deleted file mode 100644 index 812cc76d723..00000000000 --- a/scripts/docker/nginx/docker-autoreload.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -# This will watch the /geonode-certificates folder and run nginx -s reload whenever there are some changes. -# We use this to reload nginx config when certificates changed. - -# inspired/copied from https://github.com/kubernetes/kubernetes/blob/master/examples/https-nginx/auto-reload-nginx.sh - -while true -do - inotifywait -e create -e modify -e delete -e move -r --exclude "\\.certbot\\.lock|\\.well-known" "/geonode-certificates/$LETSENCRYPT_MODE" - echo "Changes noticed in /geonode-certificates" - - echo "Waiting 5s for additionnal changes" - sleep 5 - - echo "Creating symbolic link for WAN host" - # for some reason, the ln -f flag doesn't work below... - rm -f /certificate_symlink - if [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/fullchain.pem" ] && [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/privkey.pem" ]; then - echo "Certbot certificate exists, we symlink to the live cert" - ln -sf "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST" /certificate_symlink - else - echo "Certbot certificate does not exist, we symlink to autoissued" - ln -sf "/geonode-certificates/autoissued" /certificate_symlink - fi - - # Test nginx configuration - nginx -t - # If it passes, we reload - if [ $? -eq 0 ] - then - echo "Configuration valid, we reload..." - nginx -s reload - else - echo "Configuration not valid, we do not reload." - fi -done diff --git a/scripts/docker/nginx/docker-entrypoint.sh b/scripts/docker/nginx/docker-entrypoint.sh deleted file mode 100644 index e6bec7a1db2..00000000000 --- a/scripts/docker/nginx/docker-entrypoint.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/sh - -# Exit script in case of error -set -e - -echo $"\n\n\n" -echo "-----------------------------------------------------" -echo "STARTING NGINX ENTRYPOINT ---------------------------" -date - -# We make the config dir -mkdir -p "/geonode-certificates/$LETSENCRYPT_MODE" - -echo "Creating autoissued certificates for HTTP host" -if [ ! -f "/geonode-certificates/autoissued/privkey.pem" ] || [[ $(find /geonode-certificates/autoissued/privkey.pem -mtime +365 -print) ]]; then - echo "Autoissued certificate does not exist or is too old, we generate one" - mkdir -p "/geonode-certificates/autoissued/" - openssl req -x509 -nodes -days 1825 -newkey rsa:2048 -keyout "/geonode-certificates/autoissued/privkey.pem" -out "/geonode-certificates/autoissued/fullchain.pem" -subj "/CN=${HTTP_HOST:-HTTPS_HOST}" -else - echo "Autoissued certificate already exists" -fi - -echo "Creating symbolic link for HTTPS certificate" -# for some reason, the ln -f flag doesn't work below... -# TODO : not DRY (reuse same scripts as docker-autoreload.sh) -rm -f /certificate_symlink -if [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/fullchain.pem" ] && [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/privkey.pem" ]; then - echo "Certbot certificate exists, we symlink to the live cert" - ln -sf "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST" /certificate_symlink -else - echo "Certbot certificate does not exist, we symlink to autoissued" - ln -sf "/geonode-certificates/autoissued" /certificate_symlink -fi - -if [ -z "${HTTPS_HOST}" ]; then - HTTP_SCHEME="http" -else - HTTP_SCHEME="https" -fi - -export HTTP_SCHEME=${HTTP_SCHEME:-http} -export GEONODE_LB_HOST_IP=${GEONODE_LB_HOST_IP:-django} -export GEONODE_LB_PORT=${GEONODE_LB_PORT:-8000} -export GEOSERVER_LB_HOST_IP=${GEOSERVER_LB_HOST_IP:-geoserver} -export GEOSERVER_LB_PORT=${GEOSERVER_LB_PORT:-8080} - -echo "Replacing environement variables" -envsubst '\$HTTP_HOST \$HTTPS_HOST \$HTTP_SCHEME \$GEONODE_LB_HOST_IP \$GEONODE_LB_PORT \$GEOSERVER_LB_HOST_IP \$GEOSERVER_LB_PORT \$RESOLVER' < /etc/nginx/nginx.conf.envsubst > /etc/nginx/nginx.conf -envsubst '\$HTTP_HOST \$HTTPS_HOST \$HTTP_SCHEME \$GEONODE_LB_HOST_IP \$GEONODE_LB_PORT \$GEOSERVER_LB_HOST_IP \$GEOSERVER_LB_PORT \$RESOLVER' < /etc/nginx/nginx.https.available.conf.envsubst > /etc/nginx/nginx.https.available.conf -envsubst '\$HTTP_HOST \$HTTPS_HOST \$HTTP_SCHEME \$GEONODE_LB_HOST_IP \$GEONODE_LB_PORT \$GEOSERVER_LB_HOST_IP \$GEOSERVER_LB_PORT' < /etc/nginx/sites-enabled/geonode.conf.envsubst > /etc/nginx/sites-enabled/geonode.conf - -echo "Enabling or not https configuration" -if [ -z "${HTTPS_HOST}" ]; then - echo "" > /etc/nginx/nginx.https.enabled.conf -else - ln -sf /etc/nginx/nginx.https.available.conf /etc/nginx/nginx.https.enabled.conf -fi - -echo "Loading nginx autoreloader" -sh /docker-autoreload.sh & - -echo "-----------------------------------------------------" -echo "FINISHED NGINX ENTRYPOINT ---------------------------" -echo "-----------------------------------------------------" - -# Run the CMD -exec "$@" diff --git a/scripts/docker/nginx/geonode.conf.envsubst b/scripts/docker/nginx/geonode.conf.envsubst deleted file mode 100644 index 1176ce2cc2b..00000000000 --- a/scripts/docker/nginx/geonode.conf.envsubst +++ /dev/null @@ -1,134 +0,0 @@ -include /etc/nginx/mime.types; - -# This is the main geonode conf -charset utf-8; - -# max upload size -client_max_body_size 100G; -client_body_buffer_size 256K; -client_body_timeout 600s; -large_client_header_buffers 4 64k; - -proxy_connect_timeout 600; -proxy_send_timeout 600; -proxy_read_timeout 600; -uwsgi_read_timeout 600; -send_timeout 600; - -fastcgi_hide_header Set-Cookie; - -etag on; - -# compression -gzip on; -gzip_vary on; -gzip_proxied any; -gzip_http_version 1.1; -gzip_disable "MSIE [1-6]\."; -gzip_buffers 16 8k; -gzip_min_length 1100; -gzip_comp_level 6; -gzip_types - text/css - text/javascript - text/xml - text/plain - application/xml - application/xml+rss - application/javascript - application/x-javascript - application/json; - -# GeoServer -location /geoserver { - # Using a variable is a trick to let Nginx start even if upstream host is not up yet - # (see https://sandro-keil.de/blog/2017/07/24/let-nginx-start-if-upstream-host-is-unavailable-or-down/) - set $upstream $GEOSERVER_LB_HOST_IP:$GEOSERVER_LB_PORT; - - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Server $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Proto $HTTP_SCHEME; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_hide_header X-Frame-Options; - proxy_pass http://$upstream; - proxy_http_version 1.1; - proxy_redirect http://$upstream $HTTP_SCHEME://$HTTP_HOST; - proxy_request_buffering off; - client_max_body_size 0; -} - -# GeoNode -location /static/ { - alias /mnt/volumes/statics/static/; - - location ~* \.(?:html|js|jpg|jpeg|gif|png|css|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|ttf|rtf|swf|ico|flv|txt|woff|woff2|svg|xml)$ { - gzip_static always; - expires 30d; - access_log off; - add_header Pragma "public"; - add_header Cache-Control "max-age=31536000, public"; - } -} - -location /uploaded/ { - alias /mnt/volumes/statics/uploaded/; - - location ~* \.(?:html|js|jpg|jpeg|gif|png|css|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|ttf|rtf|swf|ico|flv|txt|woff|woff2|svg|xml)$ { - gzip_static always; - expires 30d; - access_log off; - add_header Pragma "public"; - add_header Cache-Control "max-age=31536000, public"; - } -} - -location / { - # Using a variable is a trick to let Nginx start even if upstream host is not up yet - # (see https://sandro-keil.de/blog/2017/07/24/let-nginx-start-if-upstream-host-is-unavailable-or-down/) - set $upstream $GEONODE_LB_HOST_IP:$GEONODE_LB_PORT; - - if ($request_method = OPTIONS) { - add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, OPTIONS"; - add_header Access-Control-Allow-Headers "Authorization, Content-Type, Accept"; - add_header Access-Control-Allow-Credentials true; - add_header Content-Length 0; - add_header Content-Type text/plain; - add_header Access-Control-Max-Age 1728000; - return 200; - } - - add_header Access-Control-Allow-Credentials false; - add_header Access-Control-Allow-Headers "Content-Type, Accept, Authorization, Origin, User-Agent"; - add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, OPTIONS"; - - proxy_redirect off; - proxy_set_header Host $host; - proxy_set_header Origin $HTTP_SCHEME://$host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Host $server_name; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $HTTP_SCHEME; - proxy_hide_header X-Frame-Options; - proxy_request_buffering off; - - # uwsgi_params - include /etc/nginx/uwsgi_params; - - proxy_pass http://$upstream; - # uwsgi_pass $upstream; - - # when a client closes the connection then keep the channel to uwsgi open. Otherwise uwsgi throws an IOError - uwsgi_ignore_client_abort on; - uwsgi_request_buffering off; - - location ~* \.(?:js|jpg|jpeg|gif|png|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|ttf|rtf|swf|ico|flv|woff|woff2|svg|xml)$ { - gzip_static always; - expires 30d; - access_log off; - add_header Pragma "public"; - add_header Cache-Control "max-age=31536000, public"; - } -} diff --git a/scripts/docker/nginx/nginx.conf.envsubst b/scripts/docker/nginx/nginx.conf.envsubst deleted file mode 100644 index b6065209d51..00000000000 --- a/scripts/docker/nginx/nginx.conf.envsubst +++ /dev/null @@ -1,39 +0,0 @@ -# NOTE : $VARIABLES are env variables replaced by entrypoint.sh using envsubst -# not to be mistaken for nginx variables (also starting with $, but usually lowercase) - -worker_processes auto; - -events { - -} - -http { - server_names_hash_bucket_size 64; - - # Allow Nginx to resolve Docker host names (see https://sandro-keil.de/blog/2017/07/24/let-nginx-start-if-upstream-host-is-unavailable-or-down/) - resolver $RESOLVER; # it seems rancher uses 169.254.169.250 instead of 127.0.0.11 which works well in docker-compose (see /etc/resolv.conf) - - # https - listens on specific name - this uses letsencrypt cert - # this includes a symlink that links either to nginx.https.available.conf if https in enabled - # or to an empty file if https is disabled. - include nginx.https.enabled.conf; - - # http - listens to specific HTTP_HOST only - this is not encrypted (not ideal but admissible on LAN for instance) - # even if not used (HTTP_HOST empty), we must keep it as it's used for internal API calls between django and geoserver - # TODO : do not use unencrypted connection even on LAN, but is it possible to have browser not complaining about unknown authority ? - server { - listen 80; - server_name $HTTP_HOST 127.0.0.1; - - include sites-enabled/*.conf; - } - - # Default server closes the connection (we can connect only using HTTP_HOST and HTTPS_HOST) - server { - listen 80 default_server; - listen 443; - server_name _; - return 444; - } - -} diff --git a/scripts/docker/nginx/nginx.https.available.conf.envsubst b/scripts/docker/nginx/nginx.https.available.conf.envsubst deleted file mode 100644 index fcd1cb34367..00000000000 --- a/scripts/docker/nginx/nginx.https.available.conf.envsubst +++ /dev/null @@ -1,37 +0,0 @@ -# NOTE : $VARIABLES are env variables replaced by entrypoint.sh using envsubst -# not to be mistaken for nginx variables (also starting with $, but usually lowercase) - -# This file is to be included in the main nginx.conf configuration if HTTPS_HOST is set -ssl_session_cache shared:SSL:10m; -ssl_session_timeout 10m; - -# this is the actual HTTPS host -server { - listen 443 ssl; - server_name $HTTPS_HOST; - keepalive_timeout 70; - - ssl_certificate /certificate_symlink/fullchain.pem; - ssl_certificate_key /certificate_symlink/privkey.pem; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers HIGH:!aNULL:!MD5; - - include sites-enabled/*.conf; -} - -# if we try to connect from http, we redirect to https -server { - listen 80; - server_name $HTTPS_HOST $HTTP_HOST; # TODO : once geoserver supports relative urls, we should allow access though both HTTP and HTTPS at the same time and hence remove HTTP_HOST from this line - - # Except for let's encrypt challenge - location /.well-known { - alias /geonode-certificates/.well-known; - include /etc/nginx/mime.types; - } - - # Redirect to https - location / { - return 302 https://$HTTPS_HOST$request_uri; # TODO : we should use 301 (permanent redirect, but not practical for debug) - } -} From 7b99387f0ef3a5528e8e418fedaebe0a56a0ecf4 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 10 Jan 2024 16:10:26 +0100 Subject: [PATCH 111/253] Update Docker tags for 4.2.x (#11824) --- docker-compose.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 61b85d10503..e11bf319688 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -61,7 +61,7 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: - image: geonode/nginx:latest + image: geonode/nginx:1.25.3-v1 container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: - .env @@ -78,7 +78,7 @@ services: # Gets and installs letsencrypt certificates letsencrypt: - image: geonode/letsencrypt:latest + image: geonode/letsencrypt:2.6.0-v1 container_name: letsencrypt4${COMPOSE_PROJECT_NAME} env_file: - .env @@ -88,7 +88,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:latest + image: geonode/geoserver:2.23.3-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -114,7 +114,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:latest + image: geonode/geoserver_data:2.23.3-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: @@ -126,7 +126,7 @@ services: # PostGIS database. db: # use geonode official postgis 15 image - image: geonode/postgis:latest + image: geonode/postgis:15.3-v1 command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" container_name: db4${COMPOSE_PROJECT_NAME} env_file: From 4137c249f1a74aa9dbb36df4f6013537bfe9d42b Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 10 Jan 2024 16:29:09 +0100 Subject: [PATCH 112/253] Use GeoNode 4.2.x Docker image (#11826) --- docker-compose-test.yml | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 22ac6dd0093..8780e0aea7b 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:latest-ubuntu-22.04 + image: geonode/geonode:local restart: unless-stopped env_file: - .env_test diff --git a/docker-compose.yml b/docker-compose.yml index e11bf319688..0f7bfcfd1fc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:latest-ubuntu-22.04 + image: geonode/geonode:4.2.x restart: unless-stopped env_file: - .env From 8e03c53b39197c9ca24015605a66afb85dfd29aa Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 10 Jan 2024 17:17:11 +0100 Subject: [PATCH 113/253] Release 4.2.0 (#11827) * Bump client to 4.2.0 and importer to version 1.0.6 * Bump version to 4.2.0 * fixed docker image tags for test and dev compose files --- docker-compose-dev.yml | 10 +++++----- docker-compose-test.yml | 10 +++++----- geonode/__init__.py | 2 +- requirements.txt | 5 ++--- setup.cfg | 4 ++-- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 7c21d3ec374..7c355038429 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -52,7 +52,7 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: - image: geonode/nginx:latest + image: geonode/nginx:1.25.3-v1 build: ./scripts/docker/nginx/ container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: @@ -70,7 +70,7 @@ services: # Gets and installs letsencrypt certificates letsencrypt: - image: geonode/letsencrypt:latest + image: geonode/letsencrypt:2.6.0-v1 container_name: letsencrypt4${COMPOSE_PROJECT_NAME} env_file: - .env @@ -80,7 +80,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:latest + image: geonode/geoserver:2.23.3-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -106,7 +106,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:latest + image: geonode/geoserver_data:2.23.3-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: @@ -118,7 +118,7 @@ services: # PostGIS database. db: # use geonode official postgis 15 image - image: geonode/postgis:latest + image: geonode/postgis:15.3-v1 command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" container_name: db4${COMPOSE_PROJECT_NAME} env_file: diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 8780e0aea7b..276523a3a4d 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -52,7 +52,7 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: - image: geonode/nginx:latest + image: geonode/nginx:1.25.3-v1 container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: - .env_test @@ -82,7 +82,7 @@ services: # Gets and installs letsencrypt certificates letsencrypt: - image: geonode/letsencrypt:latest + image: geonode/letsencrypt:2.6.0-v1 container_name: letsencrypt4${COMPOSE_PROJECT_NAME} env_file: - .env_test @@ -92,7 +92,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:latest + image: geonode/geoserver:2.23.3-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -118,7 +118,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:latest + image: geonode/geoserver_data:2.23.3-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: @@ -130,7 +130,7 @@ services: # PostGIS database. db: # use geonode official postgis 15 image - image: geonode/postgis:latest + image: geonode/postgis:15.3-v1 command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" container_name: db4${COMPOSE_PROJECT_NAME} env_file: diff --git a/geonode/__init__.py b/geonode/__init__.py index 9b1e32fbb4d..5d15032b0a3 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 0, "dev", 0) +__version__ = (4, 2, 0, "final", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 81a794a4559..124910335d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,9 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -# django-geonode-mapstore-client==4.0.5 --e git+https://github.com/GeoNode/geonode-mapstore-client.git@master#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.2.0 +geonode-importer==1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 37e8ae01318..5e24e8fd6be 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.0.5,<5.0.0 - geonode-importer>=1.0.2 + django-geonode-mapstore-client==4.2.0 + geonode-importer==1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 73f6ba91da28899a1e0d09d84bcd550e3511688a Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Wed, 10 Jan 2024 17:30:35 +0100 Subject: [PATCH 114/253] Bump to dev dependencies --- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/geonode/__init__.py b/geonode/__init__.py index 5d15032b0a3..9b1e32fbb4d 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 0, "final", 0) +__version__ = (4, 2, 0, "dev", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 124910335d9..4ea6cf81017 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -django-geonode-mapstore-client==4.2.0 -geonode-importer==1.0.6 +-e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client +-e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 5e24e8fd6be..a7e644e412e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client==4.2.0 - geonode-importer==1.0.6 + django-geonode-mapstore-client>=4.2.0,<5.0.0 + geonode-importer>=1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From b1682dbafce403cc91daf965682d654c261a1c85 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 10 Jan 2024 18:55:58 +0100 Subject: [PATCH 115/253] Add long_description_content_type for Markdown (#11831) (#11832) (cherry picked from commit b556709e24fde3122fb480757349afab2df3b1e4) Co-authored-by: Giovanni Allegri --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 498d391199e..2109bd21603 100644 --- a/setup.py +++ b/setup.py @@ -28,6 +28,7 @@ setup( version=__import__("geonode").get_version(), long_description=open("README.md").read(), + long_description_content_type="text/markdown", package_data={ "": ["*.*"], # noqa "": ["static/*.*"], # noqa From 3e1c326ddf0cacc1af71ad6bb652e5f582fbdbca Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 11 Jan 2024 10:35:22 +0100 Subject: [PATCH 116/253] Remove docker-compose-dev reference to nginx script (#11835) --- docker-compose-dev.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 7c355038429..f77b69a506f 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -53,7 +53,6 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: image: geonode/nginx:1.25.3-v1 - build: ./scripts/docker/nginx/ container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: - .env From b8814998155c03b2412e90c7672d897191986885 Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Thu, 11 Jan 2024 10:37:11 +0100 Subject: [PATCH 117/253] Local build for development branch --- docker-compose.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 0f7bfcfd1fc..9c241372858 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,6 +22,9 @@ services: # Our custom django application. It includes Geonode. django: << : *default-common-django + build: + context: ./ + dockerfile: Dockerfile container_name: django4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://django:8000/" From 9f65512c35412767a716b1c04fbac7a16b453d76 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 17 Jan 2024 18:04:05 +0100 Subject: [PATCH 118/253] Fix minimum version for the client (#11854) Since 4.2.0.dev0 is not considered >= 4.2.0 --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index a7e644e412e..79feeaeb61d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,7 +114,7 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.2.0,<5.0.0 + django-geonode-mapstore-client>=4.1.1,<5.0.0 geonode-importer>=1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 From 97c75de51bb16cb4364d41ba32918294ab0b93f6 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Wed, 9 Aug 2023 16:15:37 +0200 Subject: [PATCH 119/253] Init workflow for 52n build pipeline Add docker container registry workflow Update meta tags in workflow Add version tag 4.1 Add further images to build Fix geoserver's context path Add tags for mayor, minor, and bugfix version BUmp to 4.1.x (GeoNode#11371) Update geonode version to 4.1.2 Clean up versions metadata Push core images to dedicated repos Push geonode image to 52north/geonode Upload a dockerhub description Update dockerhub description workflow config Update 52n readme Fix image repository config Fix workflow name Link to 52n fork on github Add a note to version 3 tags Add a note to version 3 tags Update dockerhub readme Do not use commit SHA for labels Separates 4.1.x and a release builds Cancel running builds Trigger release build on tag having -52n suffix Fix dockerhub secret refs Failing action tested successfully Adds release build jobs for nginx and geoserver Add missing image tags in meta step Build latest from master Remove path exclusions Rename workflow build Rename workflow file Release are built from dedicated branches --- .github/workflows/52n-build-master.yml | 133 +++++++++++++++ .github/workflows/dockerhub-description.yml | 23 +++ .gitignore | 2 +- README_52n.md | 25 +++ scripts/docker/geoserver/Dockerfile | 113 +++++++++++++ scripts/docker/geoserver/README.md | 132 +++++++++++++++ scripts/docker/geoserver/docker-compose.yml | 61 +++++++ scripts/docker/geoserver/entrypoint.sh | 152 ++++++++++++++++++ scripts/docker/geoserver/get_dockerhost_ip.py | 24 +++ scripts/docker/geoserver/get_nginxhost_ip.py | 45 ++++++ scripts/docker/geoserver/multidump-alt.sh | 16 ++ scripts/docker/geoserver/multidump.sh | 18 +++ scripts/docker/geoserver/requirements.txt | 1 + .../docker/geoserver/set_geoserver_auth.sh | 91 +++++++++++ scripts/docker/geoserver/setup_auth.sh | 3 + .../geofence-datasource-ovr.properties.j2 | 12 ++ 16 files changed, 850 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/52n-build-master.yml create mode 100644 .github/workflows/dockerhub-description.yml create mode 100644 README_52n.md create mode 100644 scripts/docker/geoserver/Dockerfile create mode 100644 scripts/docker/geoserver/README.md create mode 100644 scripts/docker/geoserver/docker-compose.yml create mode 100644 scripts/docker/geoserver/entrypoint.sh create mode 100644 scripts/docker/geoserver/get_dockerhost_ip.py create mode 100644 scripts/docker/geoserver/get_nginxhost_ip.py create mode 100644 scripts/docker/geoserver/multidump-alt.sh create mode 100644 scripts/docker/geoserver/multidump.sh create mode 100644 scripts/docker/geoserver/requirements.txt create mode 100644 scripts/docker/geoserver/set_geoserver_auth.sh create mode 100644 scripts/docker/geoserver/setup_auth.sh create mode 100644 scripts/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 diff --git a/.github/workflows/52n-build-master.yml b/.github/workflows/52n-build-master.yml new file mode 100644 index 00000000000..59a3ce8954b --- /dev/null +++ b/.github/workflows/52n-build-master.yml @@ -0,0 +1,133 @@ +name: "[52n_master -> lastest] Builds GeoNode Docker Images" + +concurrency: + group: "geonode_build_master" + cancel-in-progress: true + +env: + TITLE: "52°North GeoNode Docker Image" + VENDOR: "52°North GmbH" + AUTHORS: "https://52North.org/" + DESCRIPTION: "Builds and publishes the Docker images GeoNode, GeoServer, Nginx" + LICENSE: "GPL-3.0" + TAG: latest + +on: + push: + branches: + - "52n-master" + +jobs: + build_and_push_geonode: + runs-on: ubuntu-22.04 + env: + IMAGE: 52north/geonode + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.IMAGE }} + labels: | + "org.opencontainers.image.authors=${{ env.AUTHORS }}" + "org.opencontainers.image.vendor=${{ env.VENDOR }}" + "org.opencontainers.image.description=${{ env.DESCRIPTION }}" + "org.opencontainers.image.title=${{ env.TITLE }}" + "org.opencontainers.image.licenses=${{ env.LICENSE }}" + tags: | + ${{ env.TAG }} + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN_52N_MASTER }} + - name: Build and push + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache + cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max + + build_and_push_nginx: + runs-on: ubuntu-22.04 + env: + IMAGE: 52north/geonode-nginx + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.IMAGE }} + labels: | + "org.opencontainers.image.authors=${{ env.AUTHORS }}" + "org.opencontainers.image.vendor=${{ env.VENDOR }}" + "org.opencontainers.image.description=${{ env.DESCRIPTION }}" + "org.opencontainers.image.title=${{ env.TITLE }}" + "org.opencontainers.image.licenses=${{ env.LICENSE }}" + tags: | + ${{ env.TAG }} + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN_52N_MASTER }} + - name: Build and push + uses: docker/build-push-action@v4 + with: + context: ./scripts/docker/nginx/ + file: ./scripts/docker/nginx/Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache + cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max + + build_and_push_geoserver: + runs-on: ubuntu-22.04 + env: + IMAGE: 52north/geonode-geoserver + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: "${{ env.IMAGE }}" + labels: | + "org.opencontainers.image.authors=${{ env.AUTHORS }}" + "org.opencontainers.image.vendor=${{ env.VENDOR }}" + "org.opencontainers.image.description=${{ env.DESCRIPTION }}" + "org.opencontainers.image.title=${{ env.TITLE }}" + "org.opencontainers.image.licenses=${{ env.LICENSE }}" + tags: | + ${{ env.TAG }} + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN_52N_MASTER }} + - name: Build and push + uses: docker/build-push-action@v4 + with: + context: ./scripts/docker/geoserver/ + file: ./scripts/docker/geoserver/Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache + cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max diff --git a/.github/workflows/dockerhub-description.yml b/.github/workflows/dockerhub-description.yml new file mode 100644 index 00000000000..3dbe8fbb583 --- /dev/null +++ b/.github/workflows/dockerhub-description.yml @@ -0,0 +1,23 @@ +name: Update Docker Hub Description +on: + push: + branches: + - 52n-master + paths: + - README_52n.md + - .github/workflows/dockerhub-description.yml +jobs: + dockerHubDescription: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Docker Hub Description + uses: peter-evans/dockerhub-description@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN_52N_MASTER }} + repository: 52north/geonode + short-description: "Geospatial content management system" + readme-filepath: ./README_52n.md + enable-url-completion: true \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7a455624878..60f95d0efc8 100644 --- a/.gitignore +++ b/.gitignore @@ -96,4 +96,4 @@ scripts/spcgeonode/_volume_* !hooks/* .env - +.secret diff --git a/README_52n.md b/README_52n.md new file mode 100644 index 00000000000..3e92b9009b5 --- /dev/null +++ b/README_52n.md @@ -0,0 +1,25 @@ +# 52°North Fork of GeoNode + +This image is built from a fork of [Geonode](https://github.com/geonode/geonode). +[52°North GmbH](https://52north.org) maintains an own fork of GeoNode in order to make necessary adjustments within projects which are not part of GeoNode core. + +However, we are interested to stay as close to upstream as possible, to benefit from ongoing development, but also to contribute features and fixes we develop in our projects. + +Starting from version `4` this image is built from the `52n-master` branch of the [`52north/geonode` repository](https://github.com/52North/geonode/tree/52n-master). +The repository builds and publishes three images: + +* [`52north/geonode`](https://hub.docker.com/r/52north/geonode) (this image) +* [`52north/geonode-nginx`](https://hub.docker.com/r/52north/geonode-nginx) +* [`52north/geonode-geoserver`](https://hub.docker.com/r/52north/geonode-geoserver) + +The Dockerfiles can be found under the [`./scripts/docker` folder](https://github.com/52North/geonode/tree/52n-master/scripts/docker). + +The official Docker configuration of [GeoServer for GeoNode](https://github.com/GeoNode/geoserver-docker) seems to be outdated. +Therefore, our fork adds a `./scripts/docker/geoserver` Docker config which is based on [the geonode-project](https://github.com/geonode/geonode-project) template. + +Depending on our current project contexts we merge regularly from upstream, and create new pull requests based on this fork. + +> **Note on version `3` tags** +> +> Images containing a `3.x` version tag were experimental and do have a different code base. +> These image are considered to be removed in the near future. \ No newline at end of file diff --git a/scripts/docker/geoserver/Dockerfile b/scripts/docker/geoserver/Dockerfile new file mode 100644 index 00000000000..cf69384629f --- /dev/null +++ b/scripts/docker/geoserver/Dockerfile @@ -0,0 +1,113 @@ +ARG IMAGE_VERSION=9.0-jdk11-openjdk-slim-bullseye +ARG JAVA_HOME=/usr/local/openjdk-11 +FROM tomcat:$IMAGE_VERSION +LABEL GeoNode Development Team + +ARG GEOSERVER_CORS_ENABLED=False +ARG GEOSERVER_CORS_ALLOWED_ORIGINS=* +ARG GEOSERVER_CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE,HEAD,OPTIONS +ARG GEOSERVER_CORS_ALLOWED_HEADERS=* +# +# Set GeoServer version and data directory +# +ENV GEOSERVER_VERSION=2.23.0 +ENV GEOSERVER_DATA_DIR="/geoserver_data/data" +ENV GEOSERVER_CORS_ENABLED=$GEOSERVER_CORS_ENABLED +ENV GEOSERVER_CORS_ALLOWED_ORIGINS=$GEOSERVER_CORS_ALLOWED_ORIGINS +ENV GEOSERVER_CORS_ALLOWED_METHODS=$GEOSERVER_CORS_ALLOWED_METHODS +ENV GEOSERVER_CORS_ALLOWED_HEADERS=$GEOSERVER_CORS_ALLOWED_HEADERS +# +# Download and install GeoServer +# +RUN apt-get update -y && apt-get install curl wget unzip -y +RUN cd /usr/local/tomcat/webapps \ + && wget --no-check-certificate --progress=bar:force:noscroll https://artifacts.geonode.org/geoserver/${GEOSERVER_VERSION}/geoserver.war -O geoserver.war \ + && unzip -q geoserver.war -d geoserver \ + && rm geoserver.war \ + && mkdir -p $GEOSERVER_DATA_DIR + +VOLUME $GEOSERVER_DATA_DIR + +# added by simonelanucara https://github.com/simonelanucara +# Optionally add JAI, ImageIO and Marlin Render for improved Geoserver performance +WORKDIR /tmp + +RUN wget --no-check-certificate https://repo1.maven.org/maven2/org/postgis/postgis-jdbc/1.3.3/postgis-jdbc-1.3.3.jar -O postgis-jdbc-1.3.3.jar && \ + wget --no-check-certificate https://maven.geo-solutions.it/org/hibernatespatial/hibernate-spatial-postgis/1.1.3.2/hibernate-spatial-postgis-1.1.3.2.jar -O hibernate-spatial-postgis-1.1.3.2.jar && \ + rm /usr/local/tomcat/webapps/geoserver/WEB-INF/lib/hibernate-spatial-h2-geodb-1.1.3.2.jar && \ + mv hibernate-spatial-postgis-1.1.3.2.jar /usr/local/tomcat/webapps/geoserver/WEB-INF/lib/ && \ + mv postgis-jdbc-1.3.3.jar /usr/local/tomcat/webapps/geoserver/WEB-INF/lib/ + +###########docker host############### +# Set DOCKERHOST variable if DOCKER_HOST exists +ARG DOCKERHOST=${DOCKERHOST} +# for debugging +RUN echo -n #1===>DOCKERHOST=${DOCKERHOST} +# +ENV DOCKERHOST ${DOCKERHOST} +# for debugging +RUN echo -n #2===>DOCKERHOST=${DOCKERHOST} + +###########docker host ip############# +# Set GEONODE_HOST_IP address if it exists +ARG GEONODE_HOST_IP=${GEONODE_HOST_IP} +# for debugging +RUN echo -n #1===>GEONODE_HOST_IP=${GEONODE_HOST_IP} +# +ENV GEONODE_HOST_IP ${GEONODE_HOST_IP} +# for debugging +RUN echo -n #2===>GEONODE_HOST_IP=${GEONODE_HOST_IP} +# If empty set DOCKER_HOST_IP to GEONODE_HOST_IP +ENV DOCKER_HOST_IP=${DOCKER_HOST_IP:-${GEONODE_HOST_IP}} +# for debugging +RUN echo -n #1===>DOCKER_HOST_IP=${DOCKER_HOST_IP} +# Trying to set the value of DOCKER_HOST_IP from DOCKER_HOST +RUN if ! [ -z ${DOCKER_HOST_IP} ]; \ + then echo export DOCKER_HOST_IP=${DOCKERHOST} | \ + sed 's/tcp:\/\/\([^:]*\).*/\1/' >> /root/.bashrc; \ + else echo "DOCKER_HOST_IP is already set!"; fi +# for debugging +RUN echo -n #2===>DOCKER_HOST_IP=${DOCKER_HOST_IP} + +# Set WEBSERVER public port +ARG PUBLIC_PORT=${PUBLIC_PORT} +# for debugging +RUN echo -n #1===>PUBLIC_PORT=${PUBLIC_PORT} +# +ENV PUBLIC_PORT=${PUBLIC_PORT} +# for debugging +RUN echo -n #2===>PUBLIC_PORT=${PUBLIC_PORT} + +# set nginx base url for geoserver +RUN echo export NGINX_BASE_URL=http://${NGINX_HOST}:${NGINX_PORT}/ | \ + sed 's/tcp:\/\/\([^:]*\).*/\1/' >> /root/.bashrc + +# copy the script and perform the run of scripts from entrypoint.sh +RUN mkdir -p /usr/local/tomcat/tmp +WORKDIR /usr/local/tomcat/tmp +COPY set_geoserver_auth.sh /usr/local/tomcat/tmp +COPY setup_auth.sh /usr/local/tomcat/tmp +COPY requirements.txt /usr/local/tomcat/tmp +COPY get_dockerhost_ip.py /usr/local/tomcat/tmp +COPY get_nginxhost_ip.py /usr/local/tomcat/tmp +COPY entrypoint.sh /usr/local/tomcat/tmp +COPY ./templates /templates +COPY multidump.sh /usr/local/tomcat/tmp +COPY multidump-alt.sh /usr/local/tomcat/tmp + +RUN apt-get update \ + && apt-get install -y procps less \ + && apt-get install -y python3 python3-pip python3-dev \ + && chmod +x /usr/local/tomcat/tmp/set_geoserver_auth.sh \ + && chmod +x /usr/local/tomcat/tmp/setup_auth.sh \ + && chmod +x /usr/local/tomcat/tmp/entrypoint.sh \ + && pip3 install pip --upgrade \ + && pip3 install -r requirements.txt \ + && chmod +x /usr/local/tomcat/tmp/get_dockerhost_ip.py \ + && chmod +x /usr/local/tomcat/tmp/get_nginxhost_ip.py + +RUN pip install j2cli + +ENV JAVA_OPTS="-Djava.awt.headless=true -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:MaxPermSize=512m -XX:PermSize=256m -Xms512m -Xmx2048m -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL=http://geoserver:8080/geoserver/pdf -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine" + +CMD ["/usr/local/tomcat/tmp/entrypoint.sh"] \ No newline at end of file diff --git a/scripts/docker/geoserver/README.md b/scripts/docker/geoserver/README.md new file mode 100644 index 00000000000..9d00a465066 --- /dev/null +++ b/scripts/docker/geoserver/README.md @@ -0,0 +1,132 @@ +# geoserver-docker + + +**The scripts/docker/geonode folder is a copy from geonode-project* to be able to build GeoServer image from this repository directly. In case of an update, just replace the whole folder.** + + +[GeoServer](http://geoserver.org) is an open source server for sharing geospatial data. +This is a docker image that eases setting up a GeoServer running specifically for [GeoNode](https://github.com/GeoNode/geoserver-geonode-ext) with an additional separated data directory. + +The image is based on the official Tomcat 9 image + +## Installation + +This image is available as a [trusted build on the docker hub](https://registry.hub.docker.com/r/geonode/geoserver/), and is the recommended method of installation. +Simple pull the image from the docker hub. + +```bash +$ docker pull geonode/geoserver +``` + +Alternatively you can build the image locally + +```bash +$ git clone https://github.com/geonode/geoserver-docker.git +$ cd geoserver-docker +$ docker build -t "geonode/geoserver" . +``` + +## Quick start + +You can quick start the image using the command line + +```bash +$ docker run --name "geoserver" -v /var/run/docker.sock:/var/run/docker.sock -d -p 8080:8080 geonode/geoserver +``` + +Point your browser to `http://localhost:8080/geoserver` and login using GeoServer's default username and password: + +* Username: admin +* Password: geoserver + +## How to use different versions + +There are mainly two different versions of this image which are useful for running **GeoNode** with different authentication system types. These versions are released as specific tags for two authentication mechanisms: + +**Cookie based authn**: +- [geonode/geoserver:2.9.x](https://hub.docker.com/r/geonode/geoserver/builds/bx7ydhghnlrfnsppduyva73/) + +**Oauth2 based authn**: +- [geonode/geoserver:2.9.x-oauth2](https://hub.docker.com/r/geonode/geoserver/builds/bwca5rtexeoegzgroavftdr/) +- [geonode/geoserver:2.10.x](https://hub.docker.com/r/geonode/geoserver/builds/bjohcnc29vm69acqjrvndxf/) +- [geonode/geoserver:2.12.x](https://hub.docker.com/r/geonode/geoserver/builds/bh7pyw5atmkcljurwsnzbs7/) +- [geonode/geoserver:2.13.x](https://hub.docker.com/r/geonode/geoserver/builds/btmjctbuvrjfnnrxrs4wyrs/) +- [geonode/geoserver:2.14.x](https://hub.docker.com/r/geonode/geoserver/builds/bj53pi8he8uksz6ggvrs3wc/) + +You can declare what version to use along with the data directory tag which corresponds to the same version. + +## Configuration + +### Data volume + +This GeoServer container keeps its configuration data at `/geoserver_data/data` which is exposed as volume in the dockerfile. +The volume allows for stopping and starting new containers from the same image without losing all the data and custom configuration. + +You may want to map this volume to a directory on the host. It will also ease the upgrade process in the future. Volumes can be mounted by passing the `-v` flag to the docker run command: + +```bash +-v /your/host/data/path:/geoserver_data/data +``` + +### Data volume container + +In case you are running Compose for automatically having GeoServer up and running then a data volume container will be mounted with a default preloaded *GEOSERVER_DATA_DIR* at the configuration data directory of the container. +Make sure that the image from the repository [data-docker](https://github.com/GeoNode/data-docker) is available from the [GeoNode Docker Hub](https://hub.docker.com/u/geonode/) or has been built locally: + +```bash +docker build -t geonode/geoserver_data . +``` + +#### Persistance behavior + +If you run: + +```bash +docker-compose stop +``` + +Data are retained in the *GEOSERVER_DATA_DIR* and can then be mounted in a new GeoServer instance by running again: + +```bash +docker-compose up +``` + +If you run: + +```bash +docker-compose down +``` + +Data are completely gone but you can ever start from the base GeoServer Data Directory built for Geonode. + +#### Data directory versions + +There has to be a correspondence one-to-one between the data directory version and the tag of the GeoServer image used in the Docker compose file. So at the end you can consume these images below: + +* **2.9.x**: [geonode/geoserver_data:2.9.x](https://hub.docker.com/r/geonode/geoserver_data/builds/bsus6alnddg4bc7icwymevp/) +* **2.9.x-oauth2**: [geonode/geoserver_data:2.9.x-oauth2](https://hub.docker.com/r/geonode/geoserver_data/builds/bwkxcupsunvuitzusi9gsnt/) +* **2.10.x**: [geonode/geoserver_data:2.10.x](https://hub.docker.com/r/geonode/geoserver_data/builds/b5jqhpzapkqxzyevjizccug/) +* **2.12.x**: [geonode/geoserver_data:2.12.x](https://hub.docker.com/r/geonode/geoserver_data/builds/byaaalw3lnasunpveyg3x4i/) +* **2.13.x**: [geonode/geoserver_data:2.13.x](https://hub.docker.com/r/geonode/geoserver_data/builds/bunuqzq7a7dk65iumjhkbtc/) +* **2.14.x**: [geonode/geoserver_data:2.14.x](https://hub.docker.com/r/geonode/geoserver_data/builds/blpdjzkrv7pm3stunzpn4pp/) + +### Database + +GeoServer recommends the usage of a spatial database + +#### PostGIS container (PostgreSQL + GIS Extension) + +If you want to use a [PostGIS](http://postgis.org/) container, you can link it to this image. You're free to use any PostGIS container. +An example with [kartooza/postgis](https://registry.hub.docker.com/u/kartoza/postgis/) image: + +```bash +$ docker run -d --name="postgis" kartoza/postgis +``` + +For further information see [kartooza/postgis](https://registry.hub.docker.com/u/kartoza/postgis/). + +Now start the GeoServer instance by adding the `--link` option to the docker run command: + +```bash +--link postgis:postgis +``` diff --git a/scripts/docker/geoserver/docker-compose.yml b/scripts/docker/geoserver/docker-compose.yml new file mode 100644 index 00000000000..5f3dc1cf34e --- /dev/null +++ b/scripts/docker/geoserver/docker-compose.yml @@ -0,0 +1,61 @@ +version: '3.9' + +services: + + postgis: + image: geonode/postgis:13 + ports: + - "25432:5432" + volumes: + - /srv/docker/geoserver/postgis:/var/lib/postgresql + #volumes_from: + #- pgstore + healthcheck: + test: "pg_isready -d postgres -U postgres" + restart: on-failure + + geoserver: + image: geonode/geoserver:2.23.0 + build: + context: . + args: + - DOCKERHOST + - GEONODE_HOST_IP + - PUBLIC_PORT=80 + links: + - postgis + ports: + - "8080:8080" + volumes: + - /geoserver_data/data + environment: + - DOCKERHOST + - GEONODE_HOST_IP + - PUBLIC_PORT=80 + - DOCKER_HOST_IP + - DJANGO_URL=http://localhost/ + depends_on: + postgis: + condition: service_completed_successfully + data-dir-conf: + condition: service_healthy + healthcheck: + test: curl --fail -s http://localhost:8080/geoserver/rest/workspaces/geonode.html || exit 1 + interval: 1m30s + timeout: 10s + retries: 3 + restart: on-failure + + data-dir-conf: + image: geonode/geoserver_data:2.23.0 + container_name: geoserver_data_dir # named data container + entrypoint: sleep infinity + volumes: + - /geoserver_data/data + healthcheck: + test: "ls -A '/geoserver_data/data' | wc -l" + restart: on-failure + +volumes: + # reference to the named data container that holds the preloaded geoserver data directory + geoserver_data_dir: \ No newline at end of file diff --git a/scripts/docker/geoserver/entrypoint.sh b/scripts/docker/geoserver/entrypoint.sh new file mode 100644 index 00000000000..f9af5f42024 --- /dev/null +++ b/scripts/docker/geoserver/entrypoint.sh @@ -0,0 +1,152 @@ +#!/bin/bash +set -e + +source /root/.bashrc + +# control the value of DOCKER_HOST_IP variable +if [ -z ${DOCKER_HOST_IP} ] +then + + echo "DOCKER_HOST_IP is empty so I'll run the python utility \n" + echo export DOCKER_HOST_IP=`python3 /usr/local/tomcat/tmp/get_dockerhost_ip.py` >> /root/.override_env + echo "The calculated value is now DOCKER_HOST_IP='$DOCKER_HOST_IP' \n" + +else + + echo "DOCKER_HOST_IP is filled so I'll leave the found value '$DOCKER_HOST_IP' \n" + +fi + +# control the values of LB settings if present +if [ ${GEONODE_LB_HOST_IP} ] +then + + echo "GEONODE_LB_HOST_IP is filled so I replace the value of '$DOCKER_HOST_IP' with '$GEONODE_LB_HOST_IP' \n" + echo export DOCKER_HOST_IP=${GEONODE_LB_HOST_IP} >> /root/.override_env + +fi + +if [ ${GEONODE_LB_PORT} ] +then + + echo "GEONODE_LB_PORT is filled so I replace the value of '$PUBLIC_PORT' with '$GEONODE_LB_PORT' \n" + echo export PUBLIC_PORT=${GEONODE_LB_PORT} >> /root/.override_env + +fi + +if [ ! -z "${GEOSERVER_JAVA_OPTS}" ] +then + + echo "GEOSERVER_JAVA_OPTS is filled so I replace the value of '$JAVA_OPTS' with '$GEOSERVER_JAVA_OPTS' \n" + JAVA_OPTS=${GEOSERVER_JAVA_OPTS} + +fi + +# control the value of NGINX_BASE_URL variable +if [ -z `echo ${NGINX_BASE_URL} | sed 's/http:\/\/\([^:]*\).*/\1/'` ] +then + echo "NGINX_BASE_URL is empty so I'll use the static nginx hostname \n" + # echo export NGINX_BASE_URL=`python3 /usr/local/tomcat/tmp/get_nginxhost_ip.py` >> /root/.override_env + # TODO rework get_nginxhost_ip to get URL with static hostname from nginx service name + # + exposed port of that container i.e. http://geonode:80 + echo export NGINX_BASE_URL=http://geonode:80 >> /root/.override_env + echo "The calculated value is now NGINX_BASE_URL='$NGINX_BASE_URL' \n" +else + echo "NGINX_BASE_URL is filled so I'll leave the found value '$NGINX_BASE_URL' \n" +fi + +# set basic tagname +TAGNAME=( "baseUrl" ) + +if ! [ -f ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ] +then + + echo "Configuration file '$GEOSERVER_DATA_DIR'/security/auth/geonodeAuthProvider/config.xml is not available so it is gone to skip \n" + +else + + # backup geonodeAuthProvider config.xml + cp ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml.orig + # run the setting script for geonodeAuthProvider + /usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/ ${TAGNAME} > /dev/null 2>&1 + +fi + +# backup geonode REST role service config.xml +cp "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml" "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml.orig" +# run the setting script for geonode REST role service +/usr/local/tomcat/tmp/set_geoserver_auth.sh "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml" "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/" ${TAGNAME} > /dev/null 2>&1 + +# set oauth2 filter tagname +TAGNAME=( "accessTokenUri" "userAuthorizationUri" "redirectUri" "checkTokenEndpointUrl" "logoutUri" ) + +# backup geonode-oauth2 config.xml +cp ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml.orig +# run the setting script for geonode-oauth2 +/usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/ "${TAGNAME[@]}" > /dev/null 2>&1 + +# set global tagname +TAGNAME=( "proxyBaseUrl" ) + +# backup global.xml +cp ${GEOSERVER_DATA_DIR}/global.xml ${GEOSERVER_DATA_DIR}/global.xml.orig +# run the setting script for global configuration +/usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/global.xml ${GEOSERVER_DATA_DIR}/ ${TAGNAME} > /dev/null 2>&1 + +# set correct amqp broker url +sed -i -e 's/localhost/rabbitmq/g' ${GEOSERVER_DATA_DIR}/notifier/notifier.xml + +# exclude wrong dependencies +sed -i -e 's/xom-\*\.jar/xom-\*\.jar,bcprov\*\.jar/g' /usr/local/tomcat/conf/catalina.properties + +# J2 templating for this docker image we should also do it for other configuration files in /usr/local/tomcat/tmp + +declare -a geoserver_datadir_template_dirs=("geofence") + +for template in in ${geoserver_datadir_template_dirs[*]}; do + #Geofence templates + if [ "$template" == "geofence" ]; then + cp -R /templates/$template/* ${GEOSERVER_DATA_DIR}/geofence + + for f in $(find ${GEOSERVER_DATA_DIR}/geofence/ -type f -name "*.j2"); do + echo -e "Evaluating template\n\tSource: $f\n\tDest: ${f%.j2}" + /usr/local/bin/j2 $f > ${f%.j2} + rm -f $f + done + + fi +done + +# configure CORS (inspired by https://github.com/oscarfonts/docker-geoserver) +# if enabled, this will add the filter definitions +# to the end of the web.xml +# (this will only happen if our filter has not yet been added before) +if [ "${GEOSERVER_CORS_ENABLED}" = "true" ] || [ "${GEOSERVER_CORS_ENABLED}" = "True" ]; then + if ! grep -q DockerGeoServerCorsFilter "$CATALINA_HOME/webapps/geoserver/WEB-INF/web.xml"; then + echo "Enable CORS for $CATALINA_HOME/webapps/geoserver/WEB-INF/web.xml" + sed -i "\::i\\ + \n\ + DockerGeoServerCorsFilter\n\ + org.apache.catalina.filters.CorsFilter\n\ + \n\ + cors.allowed.origins\n\ + ${GEOSERVER_CORS_ALLOWED_ORIGINS}\n\ + \n\ + \n\ + cors.allowed.methods\n\ + ${GEOSERVER_CORS_ALLOWED_METHODS}\n\ + \n\ + \n\ + cors.allowed.headers\n\ + ${GEOSERVER_CORS_ALLOWED_HEADERS}\n\ + \n\ + \n\ + \n\ + DockerGeoServerCorsFilter\n\ + /*\n\ + " "$CATALINA_HOME/webapps/geoserver/WEB-INF/web.xml"; + fi +fi + +# start tomcat +exec env JAVA_OPTS="${JAVA_OPTS}" catalina.sh run \ No newline at end of file diff --git a/scripts/docker/geoserver/get_dockerhost_ip.py b/scripts/docker/geoserver/get_dockerhost_ip.py new file mode 100644 index 00000000000..7b5a42ed310 --- /dev/null +++ b/scripts/docker/geoserver/get_dockerhost_ip.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 + +import logging + +import docker + +BOOTSTRAP_IMAGE_CHEIP = 'codenvy/che-ip:nightly' +# AF: why call before definition? print _docker_host_ip() + +def _docker_host_ip(): + client = docker.from_env() + ip_list = client.containers.run(BOOTSTRAP_IMAGE_CHEIP, + network_mode='host' + ).split("\n") + if len(ip_list) > 1: + logging.info("Docker daemon is running on more than one \ +address {0}".format(ip_list)) + logging.info("Only the first address:{0} will be returned!".format( + ip_list[0] + )) + else: + logging.info("Docker daemon is running at the following \ +address {0}".format(ip_list[0])) + return ip_list[0] diff --git a/scripts/docker/geoserver/get_nginxhost_ip.py b/scripts/docker/geoserver/get_nginxhost_ip.py new file mode 100644 index 00000000000..c6a67d8490d --- /dev/null +++ b/scripts/docker/geoserver/get_nginxhost_ip.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 + +import logging +import os + +import docker + +client = docker.from_env() +# print(client.info()) +# TODO avoid this script can fail and fall in the loop where the geoserver +# service is not available and consequently the nginx too which has geoserver +# as a reference link +for network in client.networks.list(): + if 'geonode' in network.name: + geonode_network = network.name + else: + geonode_network = 'geonode_default' + +try: + containers = { + c.attrs['Config']['Image']: c.attrs['NetworkSettings']['\ +Networks'][geonode_network]['\ +IPAddress'] for c in client.containers.list() if c.status in 'running' + } + for item in containers.items(): + if "geonode/nginx" in item[0]: + ipaddr = item[1] + + try: + os.environ["NGINX_BASE_URL"] = "http://" + ipaddr + ":" + "80" + nginx_base_url = "http://{}:80".format(ipaddr) + except NameError as er: + logging.info("NGINX container is not running maybe exited! Running\ +containers are:{0}".format(containers)) +except KeyError as ke: + logging.info("There has been a problem with the docker\ +network which has raised the following exception: {0}".format(ke)) +else: + # nginx_base_url = None + pass +finally: + try: + print(nginx_base_url) + except NameError as ne: + print("http://geonode:80") diff --git a/scripts/docker/geoserver/multidump-alt.sh b/scripts/docker/geoserver/multidump-alt.sh new file mode 100644 index 00000000000..cc237e17bec --- /dev/null +++ b/scripts/docker/geoserver/multidump-alt.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +if [ $# -ne 3 ]; then + echo "Usage: $0 pid interval count" + exit 1 +fi + +PID=$1 +INTERVAL=$2 +COUNT=$3 + +top -bH -d $INTERVAL -n $COUNT -p $PID >> top.out 2>&1 & +for i in `seq $COUNT`; do + kill -3 $PID + sleep $INTERVAL +done diff --git a/scripts/docker/geoserver/multidump.sh b/scripts/docker/geoserver/multidump.sh new file mode 100644 index 00000000000..21dfd2ba660 --- /dev/null +++ b/scripts/docker/geoserver/multidump.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +if [ $# -ne 3 ]; then + echo "Usage: $0 pid interval count" + exit 1 +fi + +PID=$1 +INTERVAL=$2 +COUNT=$3 + +top -bH -d $INTERVAL -n $COUNT -p $PID >> top.out 2>&1 & +for i in `seq $COUNT`; do + echo "stack trace $i of $COUNT" >> jstack.out + jstack -l $PID >> jstack.out + echo "--------------------" >> jstack.out + sleep $INTERVAL +done diff --git a/scripts/docker/geoserver/requirements.txt b/scripts/docker/geoserver/requirements.txt new file mode 100644 index 00000000000..0b31242fdae --- /dev/null +++ b/scripts/docker/geoserver/requirements.txt @@ -0,0 +1 @@ +docker==3.1.1 diff --git a/scripts/docker/geoserver/set_geoserver_auth.sh b/scripts/docker/geoserver/set_geoserver_auth.sh new file mode 100644 index 00000000000..27dd11ef54e --- /dev/null +++ b/scripts/docker/geoserver/set_geoserver_auth.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +auth_conf_source="$1" +auth_conf_target="$2" +# Creating a temporary file for sed to write the changes to +temp_file="xml.tmp" +touch $temp_file + +source /root/.bashrc +source /root/.override_env + +test -z "$auth_conf_source" && echo "You must specify a source file" && exit 1 +test -z "$auth_conf_target" && echo "You must specify a target conf directory" && exit 1 + +test ! -f "$auth_conf_source" && echo "Source $auth_conf_source does not exist or is not a file" && exit 1 +test ! -d "$auth_conf_target" && echo "Target directory $auth_conf_target does not exist or is not a directory" && exit 1 + +# for debugging +echo -e "NGINX_BASE_URL=${NGINX_BASE_URL}\n" +if [ "$PUBLIC_PORT" == "443" ]; then + SUBSTITUTION_URL="https://${DOCKER_HOST_IP}" + if [ "$PUBLIC_PORT" != "443" ]; then + SUBSTITUTION_URL="https://${DOCKER_HOST_IP}:${PUBLIC_PORT}" + fi +else + SUBSTITUTION_URL="http://${DOCKER_HOST_IP}" + if [ "$PUBLIC_PORT" != "80" ]; then + SUBSTITUTION_URL="http://${DOCKER_HOST_IP}:${PUBLIC_PORT}" + fi +fi + +echo -e "SUBSTITUTION_URL=$SUBSTITUTION_URL\n" +echo -e "auth_conf_source=$auth_conf_source\n" +echo -e "auth_conf_target=$auth_conf_target\n" + +# Elegance is the key -> adding an empty last line for Mr. “sed” to pick up +echo " " >> "$auth_conf_source" + +cat "$auth_conf_source" + +tagname=( ${@:3:5} ) + +# for debugging +for i in "${tagname[@]}" +do + echo "tagname=<$i>" +done + +echo "DEBUG: Starting... [Ok]\n" + +for i in "${tagname[@]}" +do + echo "DEBUG: Working on '$auth_conf_source' for tagname <$i>" + # Extracting the value from the <$tagname> element + # echo -ne "<$i>$tagvalue" | xmlstarlet sel -t -m "//a" -v . -n + tagvalue=`grep "<$i>.*<.$i>" "$auth_conf_source" | sed -e "s/^.*<$i/<$i/" | cut -f2 -d">"| cut -f1 -d"<"` + + echo "DEBUG: Found the current value for the element <$i> - '$tagvalue'" + + # Setting new substituted value + case $i in + proxyBaseUrl ) + if [ ${GEONODE_LB_HOST_IP} ] + then + echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$SUBSTITUTION_URL'" + newvalue=`echo -ne "$tagvalue" | sed -re "s@http://localhost(:8.*0)@$SUBSTITUTION_URL@"` + else + echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$NGINX_BASE_URL'" + newvalue=`echo -ne "$tagvalue" | sed -re "s@http://localhost(:8.*0)@$NGINX_BASE_URL@"` + fi;; + accessTokenUri | checkTokenEndpointUrl | baseUrl ) + echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$NGINX_BASE_URL'" + newvalue=`echo -ne "$tagvalue" | sed -re "s@http://localhost(:8.*0)@$NGINX_BASE_URL@"`;; + userAuthorizationUri | redirectUri | logoutUri ) + echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$SUBSTITUTION_URL'" + newvalue=`echo -ne "$tagvalue" | sed -re "s@http://localhost(:8.*0)@$SUBSTITUTION_URL@"`;; + *) echo -n "an unknown variable has been found";; + esac + + echo "DEBUG: Found the new value for the element <$i> - '$newvalue'" + # Replacing element’s value with $SUBSTITUTION_URL + # echo -ne "<$i>$tagvalue" | xmlstarlet sel -t -m "//a" -v . -n + sed -e "s@<$i>$tagvalue<\/$i>@<$i>$newvalue<\/$i>@g" "$auth_conf_source" > "$temp_file" + cp "$temp_file" "$auth_conf_source" +done +# Writing our changes back to the original file ($auth_conf_source) +# no longer needed +# mv $temp_file $auth_conf_source + +echo "DEBUG: Finished... [Ok] --- Final xml file is \n" +cat "$auth_conf_source" diff --git a/scripts/docker/geoserver/setup_auth.sh b/scripts/docker/geoserver/setup_auth.sh new file mode 100644 index 00000000000..6f9373b978c --- /dev/null +++ b/scripts/docker/geoserver/setup_auth.sh @@ -0,0 +1,3 @@ +#!/bin/sh +sed -i.bak 's@\([^<][^<]*\)@'"$DJANGO_URL"'@'\ + /geoserver_data/data/security/auth/geonodeAuthProvider/config.xml \ No newline at end of file diff --git a/scripts/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 b/scripts/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 new file mode 100644 index 00000000000..7b18d3e55f3 --- /dev/null +++ b/scripts/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 @@ -0,0 +1,12 @@ +geofenceVendorAdapter.databasePlatform=org.hibernatespatial.postgis.PostgisDialect +geofenceDataSource.driverClassName=org.postgresql.Driver +geofenceDataSource.url=jdbc:postgresql://{{ DATABASE_HOST }}:{{ DATABASE_PORT }}/{{ GEONODE_GEODATABASE }} +geofenceDataSource.username={{ GEONODE_GEODATABASE }} +geofenceDataSource.password={{ GEONODE_GEODATABASE_PASSWORD }} +geofenceEntityManagerFactory.jpaPropertyMap[hibernate.default_schema]={{ GEONODE_GEODATABASE_SCHEMA }} + +# avoid hibernate transaction issues +geofenceDataSource.testOnBorrow=true +geofenceDataSource.validationQuery=SELECT 1 +geofenceEntityManagerFactory.jpaPropertyMap[hibernate.testOnBorrow]=true +geofenceEntityManagerFactory.jpaPropertyMap[hibernate.validationQuery]=SELECT 1 \ No newline at end of file From 3f03d7c8dc080cdc78da2d6925cb969942a21d13 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Mon, 22 Jan 2024 16:46:12 +0100 Subject: [PATCH 120/253] recreated .mo file for italian (#11873) --- geonode/locale/it/LC_MESSAGES/django.mo | Bin 20525 -> 161424 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/geonode/locale/it/LC_MESSAGES/django.mo b/geonode/locale/it/LC_MESSAGES/django.mo index e76a048452590e26ad196fe83e0625f9356e8fdf..cc42b56d611c29c8119d59fe9df28ca870d02a55 100644 GIT binary patch literal 161424 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

    Q1;$r@>+O4@-g6eO3I2Lw= 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⪙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 From 445c84c4ababb678b874f1efb21cb61262742d66 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Mon, 22 Jan 2024 16:48:15 +0100 Subject: [PATCH 121/253] [Fixes #11855] Reduce log level in donwload handler (#11856) (#11874) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/layers/download_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/layers/download_handler.py b/geonode/layers/download_handler.py index d969a0d3703..09eb032a53a 100644 --- a/geonode/layers/download_handler.py +++ b/geonode/layers/download_handler.py @@ -97,7 +97,7 @@ def get_resource(self): _("You do not have download permissions for this dataset."), ) except Exception as e: - logger.exception(e) + logger.debug(e) return self._resource From 47fd6760573645615f2ff4d9dac2dc3129ca06e3 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Mon, 22 Jan 2024 18:00:21 +0100 Subject: [PATCH 122/253] release 4.2.1 (#11875) --- docker-compose.yml | 5 +---- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 9c241372858..37d34a0ad44 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:4.2.x + image: geonode/geonode:4.2.1 restart: unless-stopped env_file: - .env @@ -22,9 +22,6 @@ services: # Our custom django application. It includes Geonode. django: << : *default-common-django - build: - context: ./ - dockerfile: Dockerfile container_name: django4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://django:8000/" diff --git a/geonode/__init__.py b/geonode/__init__.py index 9b1e32fbb4d..db7f3b46ea2 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 0, "dev", 0) +__version__ = (4, 2, 1, "final", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 4ea6cf81017..124910335d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. --e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.2.0 +geonode-importer==1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 79feeaeb61d..5e24e8fd6be 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.1.1,<5.0.0 - geonode-importer>=1.0.6 + django-geonode-mapstore-client==4.2.0 + geonode-importer==1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From cdeb2d95d6224cb364c1dfc52e3a6addf18c0b2c Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Mon, 22 Jan 2024 18:06:08 +0100 Subject: [PATCH 123/253] Bump to 4.2.x --- docker-compose.yml | 5 ++++- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 37d34a0ad44..9c241372858 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:4.2.1 + image: geonode/geonode:4.2.x restart: unless-stopped env_file: - .env @@ -22,6 +22,9 @@ services: # Our custom django application. It includes Geonode. django: << : *default-common-django + build: + context: ./ + dockerfile: Dockerfile container_name: django4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://django:8000/" diff --git a/geonode/__init__.py b/geonode/__init__.py index db7f3b46ea2..9b1e32fbb4d 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 1, "final", 0) +__version__ = (4, 2, 0, "dev", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 124910335d9..4ea6cf81017 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -django-geonode-mapstore-client==4.2.0 -geonode-importer==1.0.6 +-e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client +-e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 5e24e8fd6be..79feeaeb61d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client==4.2.0 - geonode-importer==1.0.6 + django-geonode-mapstore-client>=4.1.1,<5.0.0 + geonode-importer>=1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 842bb5aca5199330d696d33c9840be8447288c81 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 22 Jan 2024 16:47:04 +0100 Subject: [PATCH 124/253] Update docker build workflow --- .github/workflows/52n-build-4.2.x.yml | 59 +++++++ .github/workflows/52n-build-master.yml | 133 --------------- .github/workflows/52n-release.yml | 78 +++++++++ README_52n.md | 23 ++- scripts/docker/geoserver/Dockerfile | 113 ------------- scripts/docker/geoserver/README.md | 132 --------------- scripts/docker/geoserver/docker-compose.yml | 61 ------- scripts/docker/geoserver/entrypoint.sh | 152 ------------------ scripts/docker/geoserver/get_dockerhost_ip.py | 24 --- scripts/docker/geoserver/get_nginxhost_ip.py | 45 ------ scripts/docker/geoserver/multidump-alt.sh | 16 -- scripts/docker/geoserver/multidump.sh | 18 --- scripts/docker/geoserver/requirements.txt | 1 - .../docker/geoserver/set_geoserver_auth.sh | 91 ----------- scripts/docker/geoserver/setup_auth.sh | 3 - .../geofence-datasource-ovr.properties.j2 | 12 -- 16 files changed, 155 insertions(+), 806 deletions(-) create mode 100644 .github/workflows/52n-build-4.2.x.yml delete mode 100644 .github/workflows/52n-build-master.yml create mode 100644 .github/workflows/52n-release.yml delete mode 100644 scripts/docker/geoserver/Dockerfile delete mode 100644 scripts/docker/geoserver/README.md delete mode 100644 scripts/docker/geoserver/docker-compose.yml delete mode 100644 scripts/docker/geoserver/entrypoint.sh delete mode 100644 scripts/docker/geoserver/get_dockerhost_ip.py delete mode 100644 scripts/docker/geoserver/get_nginxhost_ip.py delete mode 100644 scripts/docker/geoserver/multidump-alt.sh delete mode 100644 scripts/docker/geoserver/multidump.sh delete mode 100644 scripts/docker/geoserver/requirements.txt delete mode 100644 scripts/docker/geoserver/set_geoserver_auth.sh delete mode 100644 scripts/docker/geoserver/setup_auth.sh delete mode 100644 scripts/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 diff --git a/.github/workflows/52n-build-4.2.x.yml b/.github/workflows/52n-build-4.2.x.yml new file mode 100644 index 00000000000..13aae68a94a --- /dev/null +++ b/.github/workflows/52n-build-4.2.x.yml @@ -0,0 +1,59 @@ +name: "[52n-4.2.x -> 4.2.x] Builds GeoNode Docker Images" + +concurrency: + group: "geonode_build_master" + cancel-in-progress: true + +env: + TITLE: "52°North GeoNode Docker Image" + VENDOR: "52°North GmbH" + AUTHORS: "https://52North.org/" + DESCRIPTION: "Builds and publishes the Docker images GeoNode, GeoServer, Nginx" + LICENSE: "GPL-3.0" + TAG: 4.2.x + +on: + push: + branches: + - "52n-4.2.x" + +jobs: + build_and_push_geonode: + runs-on: ubuntu-22.04 + env: + IMAGE: 52north/geonode + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.IMAGE }} + labels: | + "org.opencontainers.image.authors=${{ env.AUTHORS }}" + "org.opencontainers.image.vendor=${{ env.VENDOR }}" + "org.opencontainers.image.description=${{ env.DESCRIPTION }}" + "org.opencontainers.image.title=${{ env.TITLE }}" + "org.opencontainers.image.licenses=${{ env.LICENSE }}" + tags: | + latest + ${{ env.TAG }} + + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN_52N_MASTER }} + - name: Build and push + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache + cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max diff --git a/.github/workflows/52n-build-master.yml b/.github/workflows/52n-build-master.yml deleted file mode 100644 index 59a3ce8954b..00000000000 --- a/.github/workflows/52n-build-master.yml +++ /dev/null @@ -1,133 +0,0 @@ -name: "[52n_master -> lastest] Builds GeoNode Docker Images" - -concurrency: - group: "geonode_build_master" - cancel-in-progress: true - -env: - TITLE: "52°North GeoNode Docker Image" - VENDOR: "52°North GmbH" - AUTHORS: "https://52North.org/" - DESCRIPTION: "Builds and publishes the Docker images GeoNode, GeoServer, Nginx" - LICENSE: "GPL-3.0" - TAG: latest - -on: - push: - branches: - - "52n-master" - -jobs: - build_and_push_geonode: - runs-on: ubuntu-22.04 - env: - IMAGE: 52north/geonode - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.IMAGE }} - labels: | - "org.opencontainers.image.authors=${{ env.AUTHORS }}" - "org.opencontainers.image.vendor=${{ env.VENDOR }}" - "org.opencontainers.image.description=${{ env.DESCRIPTION }}" - "org.opencontainers.image.title=${{ env.TITLE }}" - "org.opencontainers.image.licenses=${{ env.LICENSE }}" - tags: | - ${{ env.TAG }} - - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN_52N_MASTER }} - - name: Build and push - uses: docker/build-push-action@v4 - with: - context: . - file: ./Dockerfile - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache - cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max - - build_and_push_nginx: - runs-on: ubuntu-22.04 - env: - IMAGE: 52north/geonode-nginx - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.IMAGE }} - labels: | - "org.opencontainers.image.authors=${{ env.AUTHORS }}" - "org.opencontainers.image.vendor=${{ env.VENDOR }}" - "org.opencontainers.image.description=${{ env.DESCRIPTION }}" - "org.opencontainers.image.title=${{ env.TITLE }}" - "org.opencontainers.image.licenses=${{ env.LICENSE }}" - tags: | - ${{ env.TAG }} - - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN_52N_MASTER }} - - name: Build and push - uses: docker/build-push-action@v4 - with: - context: ./scripts/docker/nginx/ - file: ./scripts/docker/nginx/Dockerfile - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache - cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max - - build_and_push_geoserver: - runs-on: ubuntu-22.04 - env: - IMAGE: 52north/geonode-geoserver - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: "${{ env.IMAGE }}" - labels: | - "org.opencontainers.image.authors=${{ env.AUTHORS }}" - "org.opencontainers.image.vendor=${{ env.VENDOR }}" - "org.opencontainers.image.description=${{ env.DESCRIPTION }}" - "org.opencontainers.image.title=${{ env.TITLE }}" - "org.opencontainers.image.licenses=${{ env.LICENSE }}" - tags: | - ${{ env.TAG }} - - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN_52N_MASTER }} - - name: Build and push - uses: docker/build-push-action@v4 - with: - context: ./scripts/docker/geoserver/ - file: ./scripts/docker/geoserver/Dockerfile - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache - cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max diff --git a/.github/workflows/52n-release.yml b/.github/workflows/52n-release.yml new file mode 100644 index 00000000000..983fec64aae --- /dev/null +++ b/.github/workflows/52n-release.yml @@ -0,0 +1,78 @@ +name: Release GeoNode Docker Images + +concurrency: + group: "geonode_build_release" + cancel-in-progress: true + +env: + TITLE: "52°North GeoNode Docker Image" + VENDOR: "52°North GmbH" + AUTHORS: "https://52North.org/" + DESCRIPTION: "Builds and publishes the Docker images GeoNode, GeoServer, Nginx" + LICENSE: "GPL-3.0" + +on: + push: + tags: + - "*-52n" + +jobs: + build_and_push_geonode: + runs-on: ubuntu-22.04 + env: + IMAGE: 52north/geonode + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Parse semver string + id: semver_parser + uses: booxmedialtd/ws-action-parse-semver@v1 + with: + input_string: "${{github.ref_name}}" + version_extractor_regex: '(.*)-52n' + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.IMAGE }} + labels: | + "org.opencontainers.image.authors=${{ env.AUTHORS }}" + "org.opencontainers.image.vendor=${{ env.VENDOR }}" + "org.opencontainers.image.description=${{ env.DESCRIPTION }}" + "org.opencontainers.image.title=${{ env.TITLE }}" + "org.opencontainers.image.licenses=${{ env.LICENSE }}" + tags: | + latest + ${{ steps.semver_parser.outputs.fullversion }} + - + name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN_52N_MASTER }} + - + name: Fail in case fully tagged version already exists + run: | + if docker manifest inspect ${{ env.IMAGE }}:${{ steps.semver_parser.outputs.fullversion }}; then + echo "tag version already exists! Will not override." + exit 1 + fi + - + name: Build and push + if: ${{ !github.event.act }} # skip during local actions testing + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache + cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max + diff --git a/README_52n.md b/README_52n.md index 3e92b9009b5..51f68b028c3 100644 --- a/README_52n.md +++ b/README_52n.md @@ -5,17 +5,30 @@ This image is built from a fork of [Geonode](https://github.com/geonode/geonode) However, we are interested to stay as close to upstream as possible, to benefit from ongoing development, but also to contribute features and fixes we develop in our projects. -Starting from version `4` this image is built from the `52n-master` branch of the [`52north/geonode` repository](https://github.com/52North/geonode/tree/52n-master). -The repository builds and publishes three images: + +Starting from version `4` this image is built from branch `52n-` of the [`52north/geonode` repository](https://github.com/52North/geonode/tree/52n-master). +Please note, that GeoNode depends on other components which are also available as Docker images. +These images, however, are maintained, built and published from a [`52north/geonode-docker` repository](https://github.com/52North/geonode-docker). + +> :bulb: **Note:** +> +> Please note that the versioning schema is different from the upstream project. +> All images are released and tagged using the GeoNode version. + + +You can obtain all images from here: * [`52north/geonode`](https://hub.docker.com/r/52north/geonode) (this image) +* [`52north/geonode-geoserver`](https://hub.docker.com/r/52north/geonode-geoserver) +* [`52north/geonode-geoserver_data`](https://hub.docker.com/r/52north/geonode-geoserver_data) * [`52north/geonode-nginx`](https://hub.docker.com/r/52north/geonode-nginx) -* [`52north/geonode-geoserver`](https://hub.docker.com/r/52north/geonode-geoserver) +* [`52north/geonode-postgis`](https://hub.docker.com/r/52north/geonode-postgis) The Dockerfiles can be found under the [`./scripts/docker` folder](https://github.com/52North/geonode/tree/52n-master/scripts/docker). -The official Docker configuration of [GeoServer for GeoNode](https://github.com/GeoNode/geoserver-docker) seems to be outdated. -Therefore, our fork adds a `./scripts/docker/geoserver` Docker config which is based on [the geonode-project](https://github.com/geonode/geonode-project) template. +The GeoNode Dockerfile can be found under the [`./scripts/docker` folder](https://github.com/52North/geonode/tree/52n-master/scripts/docker). +The Dockerfiles for the dependent components are available at [the geonode-docker repository](https://github.com/52North/geonode-docker). + Depending on our current project contexts we merge regularly from upstream, and create new pull requests based on this fork. diff --git a/scripts/docker/geoserver/Dockerfile b/scripts/docker/geoserver/Dockerfile deleted file mode 100644 index cf69384629f..00000000000 --- a/scripts/docker/geoserver/Dockerfile +++ /dev/null @@ -1,113 +0,0 @@ -ARG IMAGE_VERSION=9.0-jdk11-openjdk-slim-bullseye -ARG JAVA_HOME=/usr/local/openjdk-11 -FROM tomcat:$IMAGE_VERSION -LABEL GeoNode Development Team - -ARG GEOSERVER_CORS_ENABLED=False -ARG GEOSERVER_CORS_ALLOWED_ORIGINS=* -ARG GEOSERVER_CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE,HEAD,OPTIONS -ARG GEOSERVER_CORS_ALLOWED_HEADERS=* -# -# Set GeoServer version and data directory -# -ENV GEOSERVER_VERSION=2.23.0 -ENV GEOSERVER_DATA_DIR="/geoserver_data/data" -ENV GEOSERVER_CORS_ENABLED=$GEOSERVER_CORS_ENABLED -ENV GEOSERVER_CORS_ALLOWED_ORIGINS=$GEOSERVER_CORS_ALLOWED_ORIGINS -ENV GEOSERVER_CORS_ALLOWED_METHODS=$GEOSERVER_CORS_ALLOWED_METHODS -ENV GEOSERVER_CORS_ALLOWED_HEADERS=$GEOSERVER_CORS_ALLOWED_HEADERS -# -# Download and install GeoServer -# -RUN apt-get update -y && apt-get install curl wget unzip -y -RUN cd /usr/local/tomcat/webapps \ - && wget --no-check-certificate --progress=bar:force:noscroll https://artifacts.geonode.org/geoserver/${GEOSERVER_VERSION}/geoserver.war -O geoserver.war \ - && unzip -q geoserver.war -d geoserver \ - && rm geoserver.war \ - && mkdir -p $GEOSERVER_DATA_DIR - -VOLUME $GEOSERVER_DATA_DIR - -# added by simonelanucara https://github.com/simonelanucara -# Optionally add JAI, ImageIO and Marlin Render for improved Geoserver performance -WORKDIR /tmp - -RUN wget --no-check-certificate https://repo1.maven.org/maven2/org/postgis/postgis-jdbc/1.3.3/postgis-jdbc-1.3.3.jar -O postgis-jdbc-1.3.3.jar && \ - wget --no-check-certificate https://maven.geo-solutions.it/org/hibernatespatial/hibernate-spatial-postgis/1.1.3.2/hibernate-spatial-postgis-1.1.3.2.jar -O hibernate-spatial-postgis-1.1.3.2.jar && \ - rm /usr/local/tomcat/webapps/geoserver/WEB-INF/lib/hibernate-spatial-h2-geodb-1.1.3.2.jar && \ - mv hibernate-spatial-postgis-1.1.3.2.jar /usr/local/tomcat/webapps/geoserver/WEB-INF/lib/ && \ - mv postgis-jdbc-1.3.3.jar /usr/local/tomcat/webapps/geoserver/WEB-INF/lib/ - -###########docker host############### -# Set DOCKERHOST variable if DOCKER_HOST exists -ARG DOCKERHOST=${DOCKERHOST} -# for debugging -RUN echo -n #1===>DOCKERHOST=${DOCKERHOST} -# -ENV DOCKERHOST ${DOCKERHOST} -# for debugging -RUN echo -n #2===>DOCKERHOST=${DOCKERHOST} - -###########docker host ip############# -# Set GEONODE_HOST_IP address if it exists -ARG GEONODE_HOST_IP=${GEONODE_HOST_IP} -# for debugging -RUN echo -n #1===>GEONODE_HOST_IP=${GEONODE_HOST_IP} -# -ENV GEONODE_HOST_IP ${GEONODE_HOST_IP} -# for debugging -RUN echo -n #2===>GEONODE_HOST_IP=${GEONODE_HOST_IP} -# If empty set DOCKER_HOST_IP to GEONODE_HOST_IP -ENV DOCKER_HOST_IP=${DOCKER_HOST_IP:-${GEONODE_HOST_IP}} -# for debugging -RUN echo -n #1===>DOCKER_HOST_IP=${DOCKER_HOST_IP} -# Trying to set the value of DOCKER_HOST_IP from DOCKER_HOST -RUN if ! [ -z ${DOCKER_HOST_IP} ]; \ - then echo export DOCKER_HOST_IP=${DOCKERHOST} | \ - sed 's/tcp:\/\/\([^:]*\).*/\1/' >> /root/.bashrc; \ - else echo "DOCKER_HOST_IP is already set!"; fi -# for debugging -RUN echo -n #2===>DOCKER_HOST_IP=${DOCKER_HOST_IP} - -# Set WEBSERVER public port -ARG PUBLIC_PORT=${PUBLIC_PORT} -# for debugging -RUN echo -n #1===>PUBLIC_PORT=${PUBLIC_PORT} -# -ENV PUBLIC_PORT=${PUBLIC_PORT} -# for debugging -RUN echo -n #2===>PUBLIC_PORT=${PUBLIC_PORT} - -# set nginx base url for geoserver -RUN echo export NGINX_BASE_URL=http://${NGINX_HOST}:${NGINX_PORT}/ | \ - sed 's/tcp:\/\/\([^:]*\).*/\1/' >> /root/.bashrc - -# copy the script and perform the run of scripts from entrypoint.sh -RUN mkdir -p /usr/local/tomcat/tmp -WORKDIR /usr/local/tomcat/tmp -COPY set_geoserver_auth.sh /usr/local/tomcat/tmp -COPY setup_auth.sh /usr/local/tomcat/tmp -COPY requirements.txt /usr/local/tomcat/tmp -COPY get_dockerhost_ip.py /usr/local/tomcat/tmp -COPY get_nginxhost_ip.py /usr/local/tomcat/tmp -COPY entrypoint.sh /usr/local/tomcat/tmp -COPY ./templates /templates -COPY multidump.sh /usr/local/tomcat/tmp -COPY multidump-alt.sh /usr/local/tomcat/tmp - -RUN apt-get update \ - && apt-get install -y procps less \ - && apt-get install -y python3 python3-pip python3-dev \ - && chmod +x /usr/local/tomcat/tmp/set_geoserver_auth.sh \ - && chmod +x /usr/local/tomcat/tmp/setup_auth.sh \ - && chmod +x /usr/local/tomcat/tmp/entrypoint.sh \ - && pip3 install pip --upgrade \ - && pip3 install -r requirements.txt \ - && chmod +x /usr/local/tomcat/tmp/get_dockerhost_ip.py \ - && chmod +x /usr/local/tomcat/tmp/get_nginxhost_ip.py - -RUN pip install j2cli - -ENV JAVA_OPTS="-Djava.awt.headless=true -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:MaxPermSize=512m -XX:PermSize=256m -Xms512m -Xmx2048m -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL=http://geoserver:8080/geoserver/pdf -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine" - -CMD ["/usr/local/tomcat/tmp/entrypoint.sh"] \ No newline at end of file diff --git a/scripts/docker/geoserver/README.md b/scripts/docker/geoserver/README.md deleted file mode 100644 index 9d00a465066..00000000000 --- a/scripts/docker/geoserver/README.md +++ /dev/null @@ -1,132 +0,0 @@ -# geoserver-docker - - -**The scripts/docker/geonode folder is a copy from geonode-project* to be able to build GeoServer image from this repository directly. In case of an update, just replace the whole folder.** - - -[GeoServer](http://geoserver.org) is an open source server for sharing geospatial data. -This is a docker image that eases setting up a GeoServer running specifically for [GeoNode](https://github.com/GeoNode/geoserver-geonode-ext) with an additional separated data directory. - -The image is based on the official Tomcat 9 image - -## Installation - -This image is available as a [trusted build on the docker hub](https://registry.hub.docker.com/r/geonode/geoserver/), and is the recommended method of installation. -Simple pull the image from the docker hub. - -```bash -$ docker pull geonode/geoserver -``` - -Alternatively you can build the image locally - -```bash -$ git clone https://github.com/geonode/geoserver-docker.git -$ cd geoserver-docker -$ docker build -t "geonode/geoserver" . -``` - -## Quick start - -You can quick start the image using the command line - -```bash -$ docker run --name "geoserver" -v /var/run/docker.sock:/var/run/docker.sock -d -p 8080:8080 geonode/geoserver -``` - -Point your browser to `http://localhost:8080/geoserver` and login using GeoServer's default username and password: - -* Username: admin -* Password: geoserver - -## How to use different versions - -There are mainly two different versions of this image which are useful for running **GeoNode** with different authentication system types. These versions are released as specific tags for two authentication mechanisms: - -**Cookie based authn**: -- [geonode/geoserver:2.9.x](https://hub.docker.com/r/geonode/geoserver/builds/bx7ydhghnlrfnsppduyva73/) - -**Oauth2 based authn**: -- [geonode/geoserver:2.9.x-oauth2](https://hub.docker.com/r/geonode/geoserver/builds/bwca5rtexeoegzgroavftdr/) -- [geonode/geoserver:2.10.x](https://hub.docker.com/r/geonode/geoserver/builds/bjohcnc29vm69acqjrvndxf/) -- [geonode/geoserver:2.12.x](https://hub.docker.com/r/geonode/geoserver/builds/bh7pyw5atmkcljurwsnzbs7/) -- [geonode/geoserver:2.13.x](https://hub.docker.com/r/geonode/geoserver/builds/btmjctbuvrjfnnrxrs4wyrs/) -- [geonode/geoserver:2.14.x](https://hub.docker.com/r/geonode/geoserver/builds/bj53pi8he8uksz6ggvrs3wc/) - -You can declare what version to use along with the data directory tag which corresponds to the same version. - -## Configuration - -### Data volume - -This GeoServer container keeps its configuration data at `/geoserver_data/data` which is exposed as volume in the dockerfile. -The volume allows for stopping and starting new containers from the same image without losing all the data and custom configuration. - -You may want to map this volume to a directory on the host. It will also ease the upgrade process in the future. Volumes can be mounted by passing the `-v` flag to the docker run command: - -```bash --v /your/host/data/path:/geoserver_data/data -``` - -### Data volume container - -In case you are running Compose for automatically having GeoServer up and running then a data volume container will be mounted with a default preloaded *GEOSERVER_DATA_DIR* at the configuration data directory of the container. -Make sure that the image from the repository [data-docker](https://github.com/GeoNode/data-docker) is available from the [GeoNode Docker Hub](https://hub.docker.com/u/geonode/) or has been built locally: - -```bash -docker build -t geonode/geoserver_data . -``` - -#### Persistance behavior - -If you run: - -```bash -docker-compose stop -``` - -Data are retained in the *GEOSERVER_DATA_DIR* and can then be mounted in a new GeoServer instance by running again: - -```bash -docker-compose up -``` - -If you run: - -```bash -docker-compose down -``` - -Data are completely gone but you can ever start from the base GeoServer Data Directory built for Geonode. - -#### Data directory versions - -There has to be a correspondence one-to-one between the data directory version and the tag of the GeoServer image used in the Docker compose file. So at the end you can consume these images below: - -* **2.9.x**: [geonode/geoserver_data:2.9.x](https://hub.docker.com/r/geonode/geoserver_data/builds/bsus6alnddg4bc7icwymevp/) -* **2.9.x-oauth2**: [geonode/geoserver_data:2.9.x-oauth2](https://hub.docker.com/r/geonode/geoserver_data/builds/bwkxcupsunvuitzusi9gsnt/) -* **2.10.x**: [geonode/geoserver_data:2.10.x](https://hub.docker.com/r/geonode/geoserver_data/builds/b5jqhpzapkqxzyevjizccug/) -* **2.12.x**: [geonode/geoserver_data:2.12.x](https://hub.docker.com/r/geonode/geoserver_data/builds/byaaalw3lnasunpveyg3x4i/) -* **2.13.x**: [geonode/geoserver_data:2.13.x](https://hub.docker.com/r/geonode/geoserver_data/builds/bunuqzq7a7dk65iumjhkbtc/) -* **2.14.x**: [geonode/geoserver_data:2.14.x](https://hub.docker.com/r/geonode/geoserver_data/builds/blpdjzkrv7pm3stunzpn4pp/) - -### Database - -GeoServer recommends the usage of a spatial database - -#### PostGIS container (PostgreSQL + GIS Extension) - -If you want to use a [PostGIS](http://postgis.org/) container, you can link it to this image. You're free to use any PostGIS container. -An example with [kartooza/postgis](https://registry.hub.docker.com/u/kartoza/postgis/) image: - -```bash -$ docker run -d --name="postgis" kartoza/postgis -``` - -For further information see [kartooza/postgis](https://registry.hub.docker.com/u/kartoza/postgis/). - -Now start the GeoServer instance by adding the `--link` option to the docker run command: - -```bash ---link postgis:postgis -``` diff --git a/scripts/docker/geoserver/docker-compose.yml b/scripts/docker/geoserver/docker-compose.yml deleted file mode 100644 index 5f3dc1cf34e..00000000000 --- a/scripts/docker/geoserver/docker-compose.yml +++ /dev/null @@ -1,61 +0,0 @@ -version: '3.9' - -services: - - postgis: - image: geonode/postgis:13 - ports: - - "25432:5432" - volumes: - - /srv/docker/geoserver/postgis:/var/lib/postgresql - #volumes_from: - #- pgstore - healthcheck: - test: "pg_isready -d postgres -U postgres" - restart: on-failure - - geoserver: - image: geonode/geoserver:2.23.0 - build: - context: . - args: - - DOCKERHOST - - GEONODE_HOST_IP - - PUBLIC_PORT=80 - links: - - postgis - ports: - - "8080:8080" - volumes: - - /geoserver_data/data - environment: - - DOCKERHOST - - GEONODE_HOST_IP - - PUBLIC_PORT=80 - - DOCKER_HOST_IP - - DJANGO_URL=http://localhost/ - depends_on: - postgis: - condition: service_completed_successfully - data-dir-conf: - condition: service_healthy - healthcheck: - test: curl --fail -s http://localhost:8080/geoserver/rest/workspaces/geonode.html || exit 1 - interval: 1m30s - timeout: 10s - retries: 3 - restart: on-failure - - data-dir-conf: - image: geonode/geoserver_data:2.23.0 - container_name: geoserver_data_dir # named data container - entrypoint: sleep infinity - volumes: - - /geoserver_data/data - healthcheck: - test: "ls -A '/geoserver_data/data' | wc -l" - restart: on-failure - -volumes: - # reference to the named data container that holds the preloaded geoserver data directory - geoserver_data_dir: \ No newline at end of file diff --git a/scripts/docker/geoserver/entrypoint.sh b/scripts/docker/geoserver/entrypoint.sh deleted file mode 100644 index f9af5f42024..00000000000 --- a/scripts/docker/geoserver/entrypoint.sh +++ /dev/null @@ -1,152 +0,0 @@ -#!/bin/bash -set -e - -source /root/.bashrc - -# control the value of DOCKER_HOST_IP variable -if [ -z ${DOCKER_HOST_IP} ] -then - - echo "DOCKER_HOST_IP is empty so I'll run the python utility \n" - echo export DOCKER_HOST_IP=`python3 /usr/local/tomcat/tmp/get_dockerhost_ip.py` >> /root/.override_env - echo "The calculated value is now DOCKER_HOST_IP='$DOCKER_HOST_IP' \n" - -else - - echo "DOCKER_HOST_IP is filled so I'll leave the found value '$DOCKER_HOST_IP' \n" - -fi - -# control the values of LB settings if present -if [ ${GEONODE_LB_HOST_IP} ] -then - - echo "GEONODE_LB_HOST_IP is filled so I replace the value of '$DOCKER_HOST_IP' with '$GEONODE_LB_HOST_IP' \n" - echo export DOCKER_HOST_IP=${GEONODE_LB_HOST_IP} >> /root/.override_env - -fi - -if [ ${GEONODE_LB_PORT} ] -then - - echo "GEONODE_LB_PORT is filled so I replace the value of '$PUBLIC_PORT' with '$GEONODE_LB_PORT' \n" - echo export PUBLIC_PORT=${GEONODE_LB_PORT} >> /root/.override_env - -fi - -if [ ! -z "${GEOSERVER_JAVA_OPTS}" ] -then - - echo "GEOSERVER_JAVA_OPTS is filled so I replace the value of '$JAVA_OPTS' with '$GEOSERVER_JAVA_OPTS' \n" - JAVA_OPTS=${GEOSERVER_JAVA_OPTS} - -fi - -# control the value of NGINX_BASE_URL variable -if [ -z `echo ${NGINX_BASE_URL} | sed 's/http:\/\/\([^:]*\).*/\1/'` ] -then - echo "NGINX_BASE_URL is empty so I'll use the static nginx hostname \n" - # echo export NGINX_BASE_URL=`python3 /usr/local/tomcat/tmp/get_nginxhost_ip.py` >> /root/.override_env - # TODO rework get_nginxhost_ip to get URL with static hostname from nginx service name - # + exposed port of that container i.e. http://geonode:80 - echo export NGINX_BASE_URL=http://geonode:80 >> /root/.override_env - echo "The calculated value is now NGINX_BASE_URL='$NGINX_BASE_URL' \n" -else - echo "NGINX_BASE_URL is filled so I'll leave the found value '$NGINX_BASE_URL' \n" -fi - -# set basic tagname -TAGNAME=( "baseUrl" ) - -if ! [ -f ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ] -then - - echo "Configuration file '$GEOSERVER_DATA_DIR'/security/auth/geonodeAuthProvider/config.xml is not available so it is gone to skip \n" - -else - - # backup geonodeAuthProvider config.xml - cp ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml.orig - # run the setting script for geonodeAuthProvider - /usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/ ${TAGNAME} > /dev/null 2>&1 - -fi - -# backup geonode REST role service config.xml -cp "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml" "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml.orig" -# run the setting script for geonode REST role service -/usr/local/tomcat/tmp/set_geoserver_auth.sh "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml" "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/" ${TAGNAME} > /dev/null 2>&1 - -# set oauth2 filter tagname -TAGNAME=( "accessTokenUri" "userAuthorizationUri" "redirectUri" "checkTokenEndpointUrl" "logoutUri" ) - -# backup geonode-oauth2 config.xml -cp ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml.orig -# run the setting script for geonode-oauth2 -/usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/ "${TAGNAME[@]}" > /dev/null 2>&1 - -# set global tagname -TAGNAME=( "proxyBaseUrl" ) - -# backup global.xml -cp ${GEOSERVER_DATA_DIR}/global.xml ${GEOSERVER_DATA_DIR}/global.xml.orig -# run the setting script for global configuration -/usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/global.xml ${GEOSERVER_DATA_DIR}/ ${TAGNAME} > /dev/null 2>&1 - -# set correct amqp broker url -sed -i -e 's/localhost/rabbitmq/g' ${GEOSERVER_DATA_DIR}/notifier/notifier.xml - -# exclude wrong dependencies -sed -i -e 's/xom-\*\.jar/xom-\*\.jar,bcprov\*\.jar/g' /usr/local/tomcat/conf/catalina.properties - -# J2 templating for this docker image we should also do it for other configuration files in /usr/local/tomcat/tmp - -declare -a geoserver_datadir_template_dirs=("geofence") - -for template in in ${geoserver_datadir_template_dirs[*]}; do - #Geofence templates - if [ "$template" == "geofence" ]; then - cp -R /templates/$template/* ${GEOSERVER_DATA_DIR}/geofence - - for f in $(find ${GEOSERVER_DATA_DIR}/geofence/ -type f -name "*.j2"); do - echo -e "Evaluating template\n\tSource: $f\n\tDest: ${f%.j2}" - /usr/local/bin/j2 $f > ${f%.j2} - rm -f $f - done - - fi -done - -# configure CORS (inspired by https://github.com/oscarfonts/docker-geoserver) -# if enabled, this will add the filter definitions -# to the end of the web.xml -# (this will only happen if our filter has not yet been added before) -if [ "${GEOSERVER_CORS_ENABLED}" = "true" ] || [ "${GEOSERVER_CORS_ENABLED}" = "True" ]; then - if ! grep -q DockerGeoServerCorsFilter "$CATALINA_HOME/webapps/geoserver/WEB-INF/web.xml"; then - echo "Enable CORS for $CATALINA_HOME/webapps/geoserver/WEB-INF/web.xml" - sed -i "\::i\\ - \n\ - DockerGeoServerCorsFilter\n\ - org.apache.catalina.filters.CorsFilter\n\ - \n\ - cors.allowed.origins\n\ - ${GEOSERVER_CORS_ALLOWED_ORIGINS}\n\ - \n\ - \n\ - cors.allowed.methods\n\ - ${GEOSERVER_CORS_ALLOWED_METHODS}\n\ - \n\ - \n\ - cors.allowed.headers\n\ - ${GEOSERVER_CORS_ALLOWED_HEADERS}\n\ - \n\ - \n\ - \n\ - DockerGeoServerCorsFilter\n\ - /*\n\ - " "$CATALINA_HOME/webapps/geoserver/WEB-INF/web.xml"; - fi -fi - -# start tomcat -exec env JAVA_OPTS="${JAVA_OPTS}" catalina.sh run \ No newline at end of file diff --git a/scripts/docker/geoserver/get_dockerhost_ip.py b/scripts/docker/geoserver/get_dockerhost_ip.py deleted file mode 100644 index 7b5a42ed310..00000000000 --- a/scripts/docker/geoserver/get_dockerhost_ip.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python3 - -import logging - -import docker - -BOOTSTRAP_IMAGE_CHEIP = 'codenvy/che-ip:nightly' -# AF: why call before definition? print _docker_host_ip() - -def _docker_host_ip(): - client = docker.from_env() - ip_list = client.containers.run(BOOTSTRAP_IMAGE_CHEIP, - network_mode='host' - ).split("\n") - if len(ip_list) > 1: - logging.info("Docker daemon is running on more than one \ -address {0}".format(ip_list)) - logging.info("Only the first address:{0} will be returned!".format( - ip_list[0] - )) - else: - logging.info("Docker daemon is running at the following \ -address {0}".format(ip_list[0])) - return ip_list[0] diff --git a/scripts/docker/geoserver/get_nginxhost_ip.py b/scripts/docker/geoserver/get_nginxhost_ip.py deleted file mode 100644 index c6a67d8490d..00000000000 --- a/scripts/docker/geoserver/get_nginxhost_ip.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python3 - -import logging -import os - -import docker - -client = docker.from_env() -# print(client.info()) -# TODO avoid this script can fail and fall in the loop where the geoserver -# service is not available and consequently the nginx too which has geoserver -# as a reference link -for network in client.networks.list(): - if 'geonode' in network.name: - geonode_network = network.name - else: - geonode_network = 'geonode_default' - -try: - containers = { - c.attrs['Config']['Image']: c.attrs['NetworkSettings']['\ -Networks'][geonode_network]['\ -IPAddress'] for c in client.containers.list() if c.status in 'running' - } - for item in containers.items(): - if "geonode/nginx" in item[0]: - ipaddr = item[1] - - try: - os.environ["NGINX_BASE_URL"] = "http://" + ipaddr + ":" + "80" - nginx_base_url = "http://{}:80".format(ipaddr) - except NameError as er: - logging.info("NGINX container is not running maybe exited! Running\ -containers are:{0}".format(containers)) -except KeyError as ke: - logging.info("There has been a problem with the docker\ -network which has raised the following exception: {0}".format(ke)) -else: - # nginx_base_url = None - pass -finally: - try: - print(nginx_base_url) - except NameError as ne: - print("http://geonode:80") diff --git a/scripts/docker/geoserver/multidump-alt.sh b/scripts/docker/geoserver/multidump-alt.sh deleted file mode 100644 index cc237e17bec..00000000000 --- a/scripts/docker/geoserver/multidump-alt.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -if [ $# -ne 3 ]; then - echo "Usage: $0 pid interval count" - exit 1 -fi - -PID=$1 -INTERVAL=$2 -COUNT=$3 - -top -bH -d $INTERVAL -n $COUNT -p $PID >> top.out 2>&1 & -for i in `seq $COUNT`; do - kill -3 $PID - sleep $INTERVAL -done diff --git a/scripts/docker/geoserver/multidump.sh b/scripts/docker/geoserver/multidump.sh deleted file mode 100644 index 21dfd2ba660..00000000000 --- a/scripts/docker/geoserver/multidump.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -if [ $# -ne 3 ]; then - echo "Usage: $0 pid interval count" - exit 1 -fi - -PID=$1 -INTERVAL=$2 -COUNT=$3 - -top -bH -d $INTERVAL -n $COUNT -p $PID >> top.out 2>&1 & -for i in `seq $COUNT`; do - echo "stack trace $i of $COUNT" >> jstack.out - jstack -l $PID >> jstack.out - echo "--------------------" >> jstack.out - sleep $INTERVAL -done diff --git a/scripts/docker/geoserver/requirements.txt b/scripts/docker/geoserver/requirements.txt deleted file mode 100644 index 0b31242fdae..00000000000 --- a/scripts/docker/geoserver/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -docker==3.1.1 diff --git a/scripts/docker/geoserver/set_geoserver_auth.sh b/scripts/docker/geoserver/set_geoserver_auth.sh deleted file mode 100644 index 27dd11ef54e..00000000000 --- a/scripts/docker/geoserver/set_geoserver_auth.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/bash - -auth_conf_source="$1" -auth_conf_target="$2" -# Creating a temporary file for sed to write the changes to -temp_file="xml.tmp" -touch $temp_file - -source /root/.bashrc -source /root/.override_env - -test -z "$auth_conf_source" && echo "You must specify a source file" && exit 1 -test -z "$auth_conf_target" && echo "You must specify a target conf directory" && exit 1 - -test ! -f "$auth_conf_source" && echo "Source $auth_conf_source does not exist or is not a file" && exit 1 -test ! -d "$auth_conf_target" && echo "Target directory $auth_conf_target does not exist or is not a directory" && exit 1 - -# for debugging -echo -e "NGINX_BASE_URL=${NGINX_BASE_URL}\n" -if [ "$PUBLIC_PORT" == "443" ]; then - SUBSTITUTION_URL="https://${DOCKER_HOST_IP}" - if [ "$PUBLIC_PORT" != "443" ]; then - SUBSTITUTION_URL="https://${DOCKER_HOST_IP}:${PUBLIC_PORT}" - fi -else - SUBSTITUTION_URL="http://${DOCKER_HOST_IP}" - if [ "$PUBLIC_PORT" != "80" ]; then - SUBSTITUTION_URL="http://${DOCKER_HOST_IP}:${PUBLIC_PORT}" - fi -fi - -echo -e "SUBSTITUTION_URL=$SUBSTITUTION_URL\n" -echo -e "auth_conf_source=$auth_conf_source\n" -echo -e "auth_conf_target=$auth_conf_target\n" - -# Elegance is the key -> adding an empty last line for Mr. “sed” to pick up -echo " " >> "$auth_conf_source" - -cat "$auth_conf_source" - -tagname=( ${@:3:5} ) - -# for debugging -for i in "${tagname[@]}" -do - echo "tagname=<$i>" -done - -echo "DEBUG: Starting... [Ok]\n" - -for i in "${tagname[@]}" -do - echo "DEBUG: Working on '$auth_conf_source' for tagname <$i>" - # Extracting the value from the <$tagname> element - # echo -ne "<$i>$tagvalue" | xmlstarlet sel -t -m "//a" -v . -n - tagvalue=`grep "<$i>.*<.$i>" "$auth_conf_source" | sed -e "s/^.*<$i/<$i/" | cut -f2 -d">"| cut -f1 -d"<"` - - echo "DEBUG: Found the current value for the element <$i> - '$tagvalue'" - - # Setting new substituted value - case $i in - proxyBaseUrl ) - if [ ${GEONODE_LB_HOST_IP} ] - then - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$SUBSTITUTION_URL'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@http://localhost(:8.*0)@$SUBSTITUTION_URL@"` - else - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$NGINX_BASE_URL'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@http://localhost(:8.*0)@$NGINX_BASE_URL@"` - fi;; - accessTokenUri | checkTokenEndpointUrl | baseUrl ) - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$NGINX_BASE_URL'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@http://localhost(:8.*0)@$NGINX_BASE_URL@"`;; - userAuthorizationUri | redirectUri | logoutUri ) - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$SUBSTITUTION_URL'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@http://localhost(:8.*0)@$SUBSTITUTION_URL@"`;; - *) echo -n "an unknown variable has been found";; - esac - - echo "DEBUG: Found the new value for the element <$i> - '$newvalue'" - # Replacing element’s value with $SUBSTITUTION_URL - # echo -ne "<$i>$tagvalue" | xmlstarlet sel -t -m "//a" -v . -n - sed -e "s@<$i>$tagvalue<\/$i>@<$i>$newvalue<\/$i>@g" "$auth_conf_source" > "$temp_file" - cp "$temp_file" "$auth_conf_source" -done -# Writing our changes back to the original file ($auth_conf_source) -# no longer needed -# mv $temp_file $auth_conf_source - -echo "DEBUG: Finished... [Ok] --- Final xml file is \n" -cat "$auth_conf_source" diff --git a/scripts/docker/geoserver/setup_auth.sh b/scripts/docker/geoserver/setup_auth.sh deleted file mode 100644 index 6f9373b978c..00000000000 --- a/scripts/docker/geoserver/setup_auth.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -sed -i.bak 's@\([^<][^<]*\)@'"$DJANGO_URL"'@'\ - /geoserver_data/data/security/auth/geonodeAuthProvider/config.xml \ No newline at end of file diff --git a/scripts/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 b/scripts/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 deleted file mode 100644 index 7b18d3e55f3..00000000000 --- a/scripts/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 +++ /dev/null @@ -1,12 +0,0 @@ -geofenceVendorAdapter.databasePlatform=org.hibernatespatial.postgis.PostgisDialect -geofenceDataSource.driverClassName=org.postgresql.Driver -geofenceDataSource.url=jdbc:postgresql://{{ DATABASE_HOST }}:{{ DATABASE_PORT }}/{{ GEONODE_GEODATABASE }} -geofenceDataSource.username={{ GEONODE_GEODATABASE }} -geofenceDataSource.password={{ GEONODE_GEODATABASE_PASSWORD }} -geofenceEntityManagerFactory.jpaPropertyMap[hibernate.default_schema]={{ GEONODE_GEODATABASE_SCHEMA }} - -# avoid hibernate transaction issues -geofenceDataSource.testOnBorrow=true -geofenceDataSource.validationQuery=SELECT 1 -geofenceEntityManagerFactory.jpaPropertyMap[hibernate.testOnBorrow]=true -geofenceEntityManagerFactory.jpaPropertyMap[hibernate.validationQuery]=SELECT 1 \ No newline at end of file From bf9b500ccd36c0895eacab0bb2343a0e683cf4bf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:40:57 +0100 Subject: [PATCH 125/253] update version action (#11916) (#11917) (cherry picked from commit 372eb21945172865b2f7cb22718dda352083e573) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- .github/workflows/flake8.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index a8304f8a1ac..b1b3db4a52e 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -27,7 +27,7 @@ jobs: python-version: ${{matrix.python-version}} - name: Install flake8 & black - run: pip install flake8 black + run: pip install --upgrade $(grep 'flake8\|black' requirements.txt) - name: "Check: flake8" run: | From 5a97c34399c980109145faf0f55253ff5a34fbdc Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 1 Feb 2024 12:49:18 +0100 Subject: [PATCH 126/253] Reformatting for latest Black (#11915) --- create-envfile.py | 6 ++--- geonode/api/resourcebase_api.py | 6 ----- geonode/api/tests.py | 1 - geonode/base/api/permissions.py | 5 ---- geonode/base/api/serializers.py | 2 +- geonode/base/api/tests.py | 6 ++--- geonode/base/forms.py | 1 - geonode/base/tests.py | 1 - geonode/catalogue/metadataxsl/tests.py | 1 - geonode/context_processors.py | 18 +++++++------- geonode/documents/forms.py | 1 - geonode/documents/models.py | 1 - geonode/documents/views.py | 8 ++++--- geonode/geoapps/models.py | 1 - geonode/geoapps/tests.py | 1 - geonode/geoapps/views.py | 8 ++++--- geonode/geoserver/createlayer/tests.py | 1 - geonode/geoserver/tests/integration.py | 2 -- .../harvesting/harvesters/geonodeharvester.py | 24 +++++++++---------- geonode/layers/models.py | 4 ---- geonode/layers/tests.py | 1 - geonode/layers/views.py | 8 ++++--- geonode/maps/models.py | 2 -- geonode/maps/tests.py | 1 - geonode/maps/views.py | 8 ++++--- geonode/monitoring/models.py | 3 --- geonode/security/middleware.py | 1 - geonode/security/models.py | 1 - geonode/security/oauth2_grant_types.py | 1 - geonode/security/oauth2_servers.py | 1 - geonode/security/oauth2_validators.py | 1 - geonode/security/tests.py | 1 - geonode/services/models.py | 1 - geonode/tests/utils.py | 2 -- geonode/upload/upload.py | 1 - geonode/upload/utils.py | 1 - geonode/utils.py | 2 -- 37 files changed, 48 insertions(+), 86 deletions(-) diff --git a/create-envfile.py b/create-envfile.py index c910e912618..88604088ef4 100644 --- a/create-envfile.py +++ b/create-envfile.py @@ -92,9 +92,7 @@ def _get_vals_to_replace(args): _vals_to_replace["letsencrypt_mode"] = ( "disabled" if not _vals_to_replace.get("https_host") - else "staging" - if _jsfile.get("env_type", args.env_type) in ["test"] - else "production" + else "staging" if _jsfile.get("env_type", args.env_type) in ["test"] else "production" ) _vals_to_replace["debug"] = False if _jsfile.get("env_type", args.env_type) in ["prod", "test"] else True _vals_to_replace["email"] = _jsfile.get("email", args.email) @@ -124,7 +122,7 @@ def _get_vals_to_replace(args): prog="ENV file builder", description="Tool for generate environment file automatically. The information can be passed or via CLI or via JSON file ( --file /path/env.json)", usage="python create-envfile.py localhost -f /path/to/json/file.json", - allow_abbrev=False + allow_abbrev=False, ) parser.add_argument( "--noinput", diff --git a/geonode/api/resourcebase_api.py b/geonode/api/resourcebase_api.py index d3a17d08c8a..794a29c884e 100644 --- a/geonode/api/resourcebase_api.py +++ b/geonode/api/resourcebase_api.py @@ -593,7 +593,6 @@ def hydrate_title(self, bundle): class ResourceBaseResource(CommonModelApi): - """ResourceBase api""" class Meta(CommonMetaApi): @@ -607,7 +606,6 @@ class Meta(CommonMetaApi): class FeaturedResourceBaseResource(CommonModelApi): - """Only the featured resourcebases""" class Meta(CommonMetaApi): @@ -620,7 +618,6 @@ class Meta(CommonMetaApi): class LayerResource(CommonModelApi): - """Dataset API""" links = fields.ListField(attribute="links", null=True, use_in="all", default=[]) @@ -756,7 +753,6 @@ class Meta(CommonMetaApi): class MapResource(CommonModelApi): - """Maps API""" def build_filters(self, filters=None, ignore_bad_filters=False, **kwargs): @@ -822,7 +818,6 @@ class Meta(CommonMetaApi): class GeoAppResource(CommonModelApi): - """GeoApps API""" def format_objects(self, objects): @@ -874,7 +869,6 @@ class Meta(CommonMetaApi): class DocumentResource(CommonModelApi): - """Documents API""" def build_filters(self, filters=None, ignore_bad_filters=False, **kwargs): diff --git a/geonode/api/tests.py b/geonode/api/tests.py index 39a428c21fb..61c9214a2c5 100644 --- a/geonode/api/tests.py +++ b/geonode/api/tests.py @@ -386,7 +386,6 @@ def test_tags_lockdown(self): class SearchApiTests(ResourceTestCaseMixin, GeoNodeBaseTestSupport): - """Test the search""" # loading test thesausuri and initial data diff --git a/geonode/base/api/permissions.py b/geonode/base/api/permissions.py index 5dff5b1d33b..75d19ea36d3 100644 --- a/geonode/base/api/permissions.py +++ b/geonode/base/api/permissions.py @@ -41,7 +41,6 @@ class IsSelf(permissions.BasePermission): - """Grant permission only if the current instance is the request user. Used to allow users to edit their own account, nothing to others (even superusers). @@ -62,7 +61,6 @@ def has_object_permission(self, request, view, obj): class IsSelfOrReadOnly(IsSelf): - """Grant permissions if instance *IS* the request user, or read-only. Used to allow users to edit their own account, and others to read. """ @@ -75,7 +73,6 @@ def has_object_permission(self, request, view, obj): class IsSelfOrAdmin(IsSelf): - """Grant R/W to self and superusers/staff members. Deny others.""" def has_permission(self, request, view): @@ -94,7 +91,6 @@ def has_object_permission(self, request, view, obj): class IsSelfOrAdminOrReadOnly(IsSelfOrAdmin): - """Grant R/W to self and superusers/staff members, R/O to others.""" def has_permission(self, request, view): @@ -111,7 +107,6 @@ def has_object_permission(self, request, view, obj): class IsSelfOrAdminOrAuthenticatedReadOnly(IsSelfOrAdmin): - """Grant R/W to self and superusers/staff members, R/O to auth.""" def has_object_permission(self, request, view, obj): diff --git a/geonode/base/api/serializers.py b/geonode/base/api/serializers.py index 01887f4fe4e..eba681a69a1 100644 --- a/geonode/base/api/serializers.py +++ b/geonode/base/api/serializers.py @@ -655,7 +655,7 @@ class Meta: "is_copyable", "blob", "metadata", - "executions" + "executions", # TODO # csw_typename, csw_schema, csw_mdsource, csw_insert_date, csw_type, csw_anytext, csw_wkt_geometry, # metadata_uploaded, metadata_uploaded_preserve, metadata_xml, diff --git a/geonode/base/api/tests.py b/geonode/base/api/tests.py index 4833a955484..fa534cc2bbd 100644 --- a/geonode/base/api/tests.py +++ b/geonode/base/api/tests.py @@ -1951,10 +1951,10 @@ def test_set_resource_thumbnail(self): self.assertEqual(response.json(), "The url must be of an image with format (png, jpeg or jpg)") # using Base64 data as an ASCII byte string - data[ - "file" - ] = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\ + data["file"] = ( + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\ fAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAANSURBVAiZYzAxMfkPAALYAZzx61+bAAAAAElFTkSuQmCC" + ) with patch("geonode.base.models.is_monochromatic_image") as _mck: _mck.return_value = False response = self.client.put(url, data=data, format="json") diff --git a/geonode/base/forms.py b/geonode/base/forms.py index 8c6bd6bd816..8152da290e5 100644 --- a/geonode/base/forms.py +++ b/geonode/base/forms.py @@ -412,7 +412,6 @@ def build_attrs(self, base_attrs=None, extra_attrs=None, **kwargs): class ResourceBaseForm(TranslationModelForm, LinkedResourceForm): - """Base form for metadata, should be inherited by childres classes of ResourceBase""" abstract = forms.CharField(label=_("Abstract"), required=False, widget=TinyMCE()) diff --git a/geonode/base/tests.py b/geonode/base/tests.py index f3741425074..bcadaa07931 100644 --- a/geonode/base/tests.py +++ b/geonode/base/tests.py @@ -166,7 +166,6 @@ def test_add_missing_metadata_author_or_poc(self): class TestCreationOfContactRolesByDifferentInputTypes(ThumbnailTests): - """ Test that contact roles can be set as people profile """ diff --git a/geonode/catalogue/metadataxsl/tests.py b/geonode/catalogue/metadataxsl/tests.py index e09c1291a5f..bce9b262c6e 100644 --- a/geonode/catalogue/metadataxsl/tests.py +++ b/geonode/catalogue/metadataxsl/tests.py @@ -25,7 +25,6 @@ class MetadataXSLTest(GeoNodeBaseTestSupport): - """ Tests geonode.catalogue.metadataxsl app/module """ diff --git a/geonode/context_processors.py b/geonode/context_processors.py index e4ce5757521..1230a20cbf8 100644 --- a/geonode/context_processors.py +++ b/geonode/context_processors.py @@ -86,15 +86,17 @@ def resource_urls(request): EXIF_ENABLED=getattr(settings, "EXIF_ENABLED", False), FAVORITE_ENABLED=getattr(settings, "FAVORITE_ENABLED", False), SEARCH_FILTERS=getattr(settings, "SEARCH_FILTERS", False), - THESAURI_FILTERS=[ - t["name"] - for t in [ - settings.THESAURUS, + THESAURI_FILTERS=( + [ + t["name"] + for t in [ + settings.THESAURUS, + ] + if t.get("filter") ] - if t.get("filter") - ] - if hasattr(settings, "THESAURUS") - else [t.identifier for t in thesaurus], + if hasattr(settings, "THESAURUS") + else [t.identifier for t in thesaurus] + ), MAP_CLIENT_USE_CROSS_ORIGIN_CREDENTIALS=getattr(settings, "MAP_CLIENT_USE_CROSS_ORIGIN_CREDENTIALS", False), SHOW_PROFILE_EMAIL=getattr(settings, "SHOW_PROFILE_EMAIL", False), OGC_SERVER=getattr(settings, "OGC_SERVER", None), diff --git a/geonode/documents/forms.py b/geonode/documents/forms.py index 42671e98172..7568dc6863b 100644 --- a/geonode/documents/forms.py +++ b/geonode/documents/forms.py @@ -117,7 +117,6 @@ class DocumentDescriptionForm(forms.Form): class DocumentCreateForm(TranslationModelForm): - """ The document upload form. """ diff --git a/geonode/documents/models.py b/geonode/documents/models.py index d7650f5b0ae..e4815dc8da9 100644 --- a/geonode/documents/models.py +++ b/geonode/documents/models.py @@ -37,7 +37,6 @@ class Document(ResourceBase): - """ A document is any kind of information that can be attached to a map such as pdf, images, videos, xls... """ diff --git a/geonode/documents/views.py b/geonode/documents/views.py index ca72be2f6a4..49a4c605b1b 100644 --- a/geonode/documents/views.py +++ b/geonode/documents/views.py @@ -322,9 +322,11 @@ def document_metadata( category_form = CategoryForm( request.POST, prefix="category_choice_field", - initial=int(request.POST["category_choice_field"]) - if "category_choice_field" in request.POST and request.POST["category_choice_field"] - else None, + initial=( + int(request.POST["category_choice_field"]) + if "category_choice_field" in request.POST and request.POST["category_choice_field"] + else None + ), ) if hasattr(settings, "THESAURUS"): diff --git a/geonode/geoapps/models.py b/geonode/geoapps/models.py index db57d96f3e3..a3edfff60e1 100644 --- a/geonode/geoapps/models.py +++ b/geonode/geoapps/models.py @@ -31,7 +31,6 @@ class GeoApp(ResourceBase): - """ A GeoApp it is a generic container for every client applications the user might want to create or define. diff --git a/geonode/geoapps/tests.py b/geonode/geoapps/tests.py index c42c1733af6..c4566d604e2 100644 --- a/geonode/geoapps/tests.py +++ b/geonode/geoapps/tests.py @@ -31,7 +31,6 @@ class GeoAppTests(GeoNodeBaseTestSupport): - """Tests geonode.geoapps module""" fixtures = ["initial_data.json", "group_test_data.json", "default_oauth_apps.json"] diff --git a/geonode/geoapps/views.py b/geonode/geoapps/views.py index f83457ae67e..6cb6814bb25 100644 --- a/geonode/geoapps/views.py +++ b/geonode/geoapps/views.py @@ -216,9 +216,11 @@ def geoapp_metadata( category_form = CategoryForm( request.POST, prefix="category_choice_field", - initial=int(request.POST["category_choice_field"]) - if "category_choice_field" in request.POST and request.POST["category_choice_field"] - else None, + initial=( + int(request.POST["category_choice_field"]) + if "category_choice_field" in request.POST and request.POST["category_choice_field"] + else None + ), ) if hasattr(settings, "THESAURUS"): diff --git a/geonode/geoserver/createlayer/tests.py b/geonode/geoserver/createlayer/tests.py index 87d40a4d56d..eb18bc45b34 100644 --- a/geonode/geoserver/createlayer/tests.py +++ b/geonode/geoserver/createlayer/tests.py @@ -33,7 +33,6 @@ class CreateLayerCoreTest(GeoNodeBaseTestSupport): - """ Test createlayer application. """ diff --git a/geonode/geoserver/tests/integration.py b/geonode/geoserver/tests/integration.py index 7fd155210ca..39d8040e80f 100644 --- a/geonode/geoserver/tests/integration.py +++ b/geonode/geoserver/tests/integration.py @@ -56,7 +56,6 @@ def _log(msg, *args): @override_settings(SITEURL="http://localhost:8001/") class GeoNodeGeoServerSync(GeoNodeLiveTestSupport): - """ Tests GeoNode/GeoServer syncronization """ @@ -104,7 +103,6 @@ def test_set_attributes_from_geoserver(self): @override_settings(SITEURL="http://localhost:8002/") class GeoNodeGeoServerCapabilities(GeoNodeLiveTestSupport): - """ Tests GeoNode/GeoServer GetCapabilities per layer, user, category and map """ diff --git a/geonode/harvesting/harvesters/geonodeharvester.py b/geonode/harvesting/harvesters/geonodeharvester.py index 0f9de873476..dad1571b920 100644 --- a/geonode/harvesting/harvesters/geonodeharvester.py +++ b/geonode/harvesting/harvesters/geonodeharvester.py @@ -433,14 +433,14 @@ def _get_resource_list_params(self, offset: typing.Optional[int] = 0) -> typing. result["filter{title.icontains}"] = self.resource_title_filter if self.start_date_filter is not None: start_date = dateutil.parser.parse(self.start_date_filter) - result[ - "filter{date.gte}" - ] = f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + result["filter{date.gte}"] = ( + f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + ) if self.end_date_filter is not None: end_date = dateutil.parser.parse(self.end_date_filter) - result[ - "filter{date.lte}" - ] = f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + result["filter{date.lte}"] = ( + f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + ) if self.keywords_filter is not None: result["filter{keywords.slug.in}"] = self.keywords_filter if self.categories_filter is not None: @@ -738,14 +738,14 @@ def _get_resource_list_params(self, offset: typing.Optional[int] = 0) -> typing. result["title__icontains"] = self.resource_title_filter if self.start_date_filter is not None: start_date = dateutil.parser.parse(self.start_date_filter) - result[ - "date__gte" - ] = f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + result["date__gte"] = ( + f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + ) if self.end_date_filter is not None: end_date = dateutil.parser.parse(self.end_date_filter) - result[ - "date__lte" - ] = f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + result["date__lte"] = ( + f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + ) if self.keywords_filter is not None: result["keywords__slug__in"] = ",".join(self.keywords_filter) if self.categories_filter is not None: diff --git a/geonode/layers/models.py b/geonode/layers/models.py index 22eb2eff0cd..bed803f7220 100644 --- a/geonode/layers/models.py +++ b/geonode/layers/models.py @@ -61,7 +61,6 @@ class Style(models.Model, PermissionLevelMixin): - """Model for storing styles.""" name = models.CharField(_("style name"), max_length=255, unique=True) @@ -103,7 +102,6 @@ def __init__(self): class Dataset(ResourceBase): - """ Dataset (inherits ResourceBase fields) """ @@ -376,7 +374,6 @@ def view_count_up(self, user, do_local=False): class AttributeManager(models.Manager): - """Helper class to access filtered attributes""" def visible(self): @@ -384,7 +381,6 @@ def visible(self): class Attribute(models.Model): - """ Auxiliary model for storing layer attributes. diff --git a/geonode/layers/tests.py b/geonode/layers/tests.py index c4d0bf88f0b..bc7d6ff27b6 100644 --- a/geonode/layers/tests.py +++ b/geonode/layers/tests.py @@ -90,7 +90,6 @@ class DatasetsTest(GeoNodeBaseTestSupport): - """Tests geonode.layers app/module""" type = "dataset" diff --git a/geonode/layers/views.py b/geonode/layers/views.py index f7729d2ce09..8b0c585af9c 100644 --- a/geonode/layers/views.py +++ b/geonode/layers/views.py @@ -414,9 +414,11 @@ def dataset_metadata( category_form = CategoryForm( request.POST, prefix="category_choice_field", - initial=int(request.POST["category_choice_field"]) - if "category_choice_field" in request.POST and request.POST["category_choice_field"] - else None, + initial=( + int(request.POST["category_choice_field"]) + if "category_choice_field" in request.POST and request.POST["category_choice_field"] + else None + ), ) if not category_form.is_valid(): logger.error(f"Dataset Category form is not valid: {category_form.errors}") diff --git a/geonode/maps/models.py b/geonode/maps/models.py index 546b71fb8ce..ad7630abc99 100644 --- a/geonode/maps/models.py +++ b/geonode/maps/models.py @@ -37,7 +37,6 @@ class Map(ResourceBase): - """ A Map aggregates several layers together and annotates them with a viewport configuration. @@ -231,7 +230,6 @@ class Meta(ResourceBase.Meta): class MapLayer(models.Model): - """ The MapLayer model represents a layer included in a map. This doesn't just identify the dataset, but also extra options such as which style to load diff --git a/geonode/maps/tests.py b/geonode/maps/tests.py index fdb5d74bb42..9d0748a8db2 100644 --- a/geonode/maps/tests.py +++ b/geonode/maps/tests.py @@ -79,7 +79,6 @@ class MapsTest(NotificationsTestsHelper): - """Tests geonode.maps app/module""" fixtures = ["initial_data.json", "group_test_data.json", "default_oauth_apps.json"] diff --git a/geonode/maps/views.py b/geonode/maps/views.py index bc4271b8799..a82c1741e74 100644 --- a/geonode/maps/views.py +++ b/geonode/maps/views.py @@ -107,9 +107,11 @@ def map_metadata( category_form = CategoryForm( request.POST, prefix="category_choice_field", - initial=int(request.POST["category_choice_field"]) - if "category_choice_field" in request.POST and request.POST["category_choice_field"] - else None, + initial=( + int(request.POST["category_choice_field"]) + if "category_choice_field" in request.POST and request.POST["category_choice_field"] + else None + ), ) if hasattr(settings, "THESAURUS"): diff --git a/geonode/monitoring/models.py b/geonode/monitoring/models.py index 18f302c73dc..dd28350f81a 100644 --- a/geonode/monitoring/models.py +++ b/geonode/monitoring/models.py @@ -69,7 +69,6 @@ def get_geoip(): class Host(models.Model): - """ Describes one physical instance """ @@ -83,7 +82,6 @@ def __str__(self): class ServiceType(models.Model): - """ Service Type list """ @@ -129,7 +127,6 @@ def is_system_monitor(self): class Service(models.Model): - """ Service is a entity describing deployed processes. """ diff --git a/geonode/security/middleware.py b/geonode/security/middleware.py index 07fa80ed745..82bdc6ea9b3 100644 --- a/geonode/security/middleware.py +++ b/geonode/security/middleware.py @@ -70,7 +70,6 @@ class LoginRequiredMiddleware(MiddlewareMixin): - """ Requires a user to be logged in to access any page that is not white-listed. diff --git a/geonode/security/models.py b/geonode/security/models.py index b89a00c2782..2a878368827 100644 --- a/geonode/security/models.py +++ b/geonode/security/models.py @@ -57,7 +57,6 @@ class PermissionLevelError(Exception): class PermissionLevelMixin: - """ Mixin for adding "Permission Level" methods to a model class -- eg role systems where a diff --git a/geonode/security/oauth2_grant_types.py b/geonode/security/oauth2_grant_types.py index 63b865269a6..7ab3575fca1 100644 --- a/geonode/security/oauth2_grant_types.py +++ b/geonode/security/oauth2_grant_types.py @@ -76,7 +76,6 @@ def code_challenge_method_plain(verifier, challenge): class OAuth2AuthorizationCodeGrant(GrantTypeBase): - """`Authorization Code Grant`_ The authorization code grant type is used to obtain both access diff --git a/geonode/security/oauth2_servers.py b/geonode/security/oauth2_servers.py index ead8a714e5b..5a1890aefd6 100644 --- a/geonode/security/oauth2_servers.py +++ b/geonode/security/oauth2_servers.py @@ -46,7 +46,6 @@ class OIDCServer( AuthorizationEndpoint, IntrospectEndpoint, TokenEndpoint, ResourceEndpoint, RevocationEndpoint, UserInfoEndpoint ): - """An all-in-one endpoint featuring all four major grant types.""" def __init__( diff --git a/geonode/security/oauth2_validators.py b/geonode/security/oauth2_validators.py index 0b93b6ed0c6..c5b0bfea230 100644 --- a/geonode/security/oauth2_validators.py +++ b/geonode/security/oauth2_validators.py @@ -34,7 +34,6 @@ class OIDCValidator(OAuth2Validator): - """e.g. Check username and password correspond to a valid and active User, if fails try Facebook token authentication diff --git a/geonode/security/tests.py b/geonode/security/tests.py index f80a0ef8a52..433f4aa6de7 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -104,7 +104,6 @@ def write(self, buf): class SecurityTests(ResourceTestCaseMixin, GeoNodeBaseTestSupport): - """ Tests for the Geonode security app. """ diff --git a/geonode/services/models.py b/geonode/services/models.py index db56adba495..c6ccf3874b4 100644 --- a/geonode/services/models.py +++ b/geonode/services/models.py @@ -118,7 +118,6 @@ class Meta: class ServiceProfileRole(models.Model): - """ ServiceProfileRole is an intermediate model to bind Profiles and Services and apply roles. """ diff --git a/geonode/tests/utils.py b/geonode/tests/utils.py index 4466f76a6e2..b861f2a0e8a 100644 --- a/geonode/tests/utils.py +++ b/geonode/tests/utils.py @@ -62,7 +62,6 @@ def upload_step(step=None): class Client(DjangoTestClient): - """client for making http requests""" def __init__(self, url, user, passwd, *args, **kwargs): @@ -310,7 +309,6 @@ def check_dataset(uploaded): from pinax.notifications.models import NoticeQueueBatch class NotificationsTestsHelper(GeoNodeBaseTestSupport): - """ Helper class for notification tests This provides: diff --git a/geonode/upload/upload.py b/geonode/upload/upload.py index 0777cb83d3a..4a3feb25d7b 100644 --- a/geonode/upload/upload.py +++ b/geonode/upload/upload.py @@ -39,7 +39,6 @@ class UploaderSession: - """All objects held must be able to survive a good pickling""" # the gsimporter session object diff --git a/geonode/upload/utils.py b/geonode/upload/utils.py index d81f63e9ba5..ea8189e47b9 100644 --- a/geonode/upload/utils.py +++ b/geonode/upload/utils.py @@ -111,7 +111,6 @@ def _log(msg, *args, level="error"): class JSONResponse(HttpResponse): - """JSON response class.""" def __init__(self, obj="", json_opts=None, content_type="application/json", *args, **kwargs): diff --git a/geonode/utils.py b/geonode/utils.py index d15dafe3162..ffa931c3cf4 100755 --- a/geonode/utils.py +++ b/geonode/utils.py @@ -137,7 +137,6 @@ class ServerDoesNotExist(Exception): class OGC_Server(object): # LGTM: @property will not work in old-style classes - """ OGC Server object. """ @@ -211,7 +210,6 @@ def __str__(self): class OGC_Servers_Handler: - """ OGC Server Settings Convenience dict. """ From c4c52c18405885a1f2699e3b8723b8760026605b Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 1 Feb 2024 13:29:25 +0100 Subject: [PATCH 127/253] =?UTF-8?q?[Backport=204.2.x=20]=20[Fixes=20#11912?= =?UTF-8?q?]=20GWC=20layers=20only=20cache=20default=20style=20after=20B/R?= =?UTF-8?q?=20restore=20=E2=80=A6=20(#11914)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Fixes #11912] GWC layers only cache default style after B/R restore (#11913) Co-authored-by: G. Allegri * Reformatting for latest Black --------- Co-authored-by: Emanuele Tajariol --- .../management/commands/create_tile_layers.py | 73 +++++++++++++++---- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/geonode/br/management/commands/create_tile_layers.py b/geonode/br/management/commands/create_tile_layers.py index eb5d2cfc12b..57b81d805aa 100644 --- a/geonode/br/management/commands/create_tile_layers.py +++ b/geonode/br/management/commands/create_tile_layers.py @@ -42,12 +42,12 @@ application/json;type=utfgrid + image/gif + image/jpeg image/png + image/png8 image/vnd.jpeg-png - image/jpeg image/vnd.jpeg-png8 - image/gif - image/png8 @@ -66,6 +66,11 @@ EPSG:900913 + 0 + 0 + true + 0 + """ @@ -73,9 +78,36 @@ class Command(BaseCommand): help = "Create missing TileLayers in GWC" def add_arguments(self, parser): - pass + parser.add_argument( + '-f', + '--force', + dest="force", + action='store_true', + help="Force tile layer re-creation also if it already exists in GWC") + + parser.add_argument( + '-l', + '--layer', + dest="layers", + action='append', + help="Only process specified layers ") + + parser.add_argument( + '-d', + '--dry-run', + dest="dry-run", + action='store_true', + help="Do not actually perform any change on GWC") def handle(self, **options): + force = options.get('force') + requested_layers = options.get('layers') + dry_run = options.get('dry-run') + + logger.debug(f"FORCE is {force}") + logger.debug(f"DRY-RUN is {dry_run}") + logger.debug(f"LAYERS is {requested_layers}") + try: baseurl = settings.OGC_SERVER["default"]["LOCATION"] user = settings.OGC_SERVER["default"]["USER"] @@ -91,24 +123,38 @@ def handle(self, **options): cnt_old = 0 cnt_new = 0 cnt_bad = 0 + cnt_skip = 0 + cnt_force = 0 for layer in layers: i += 1 logger.info(f"- {i}/{tot} Processing layer: {layer.typename}") + + if requested_layers and layer.typename not in requested_layers: + logger.info(" - Layer filtered out by args") + cnt_skip += 1 + continue + r = requests.get(f"{baseurl}gwc/rest/layers/{layer.typename}.xml", auth=HTTPBasicAuth(user, passwd)) if r.status_code == 200: - logger.info(" - Layer already configured") - cnt_old += 1 - continue + if force: + logger.info(" - Forcing layer configuration in GWC") + cnt_force += 1 + else: + logger.info(" - Layer already configured in GWC") + cnt_old += 1 + continue try: data = REQ_TEMPLATE.format(layer.name) url = f"{baseurl}gwc/rest/layers/{layer.typename}.xml" logger.info(" - Configuring...") - response = requests.put( - url, data=data, headers={"Content-Type": "text/xml"}, auth=HTTPBasicAuth(user, passwd) - ) - if response.status_code == 200: + if not dry_run: + response = requests.put( + url, data=data, headers={"Content-Type": "text/xml"}, auth=HTTPBasicAuth(user, passwd) + ) + + if dry_run or response.status_code == 200: logger.info(f" - Done {layer.name}") cnt_new += 1 else: @@ -121,6 +167,7 @@ def handle(self, **options): raise e logger.info("Work completed") - logger.info(f"- TileLayers configured: {cnt_new}") + logger.info(f"- TileLayers configured: {cnt_new}" + (f" (forced {cnt_force})" if cnt_force else "")) logger.info(f"- TileLayers in error : {cnt_bad}") - logger.info(f"- TileLayers found : {cnt_old}") + logger.info(f"- TileLayers untouched : {cnt_old}") + logger.info(f"- TileLayers skipped : {cnt_skip}") From 3f382b28053c4d2e8d97fe803efc83a1f67ae0a9 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Fri, 2 Feb 2024 16:17:14 +0100 Subject: [PATCH 128/253] Upgrade Geoserver with fix for oauth2 (#11929) * Upgrade Geoserver with fix for oauth2 * fixes to black formaating --- docker-compose-dev.yml | 2 +- docker-compose-test.yml | 2 +- docker-compose.yml | 2 +- geonode/base/api/tests.py | 6 ++--- .../harvesting/harvesters/geonodeharvester.py | 24 +++++++++---------- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index f77b69a506f..19b81b0985a 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -79,7 +79,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.3-v1 + image: geonode/geoserver:2.23.3-v2 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 276523a3a4d..a0da45aafa0 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -92,7 +92,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.3-v1 + image: geonode/geoserver:2.23.3-v2 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" diff --git a/docker-compose.yml b/docker-compose.yml index 9c241372858..d073b1cbbcf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -91,7 +91,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.3-v1 + image: geonode/geoserver:2.23.3-v2 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" diff --git a/geonode/base/api/tests.py b/geonode/base/api/tests.py index fa534cc2bbd..4833a955484 100644 --- a/geonode/base/api/tests.py +++ b/geonode/base/api/tests.py @@ -1951,10 +1951,10 @@ def test_set_resource_thumbnail(self): self.assertEqual(response.json(), "The url must be of an image with format (png, jpeg or jpg)") # using Base64 data as an ASCII byte string - data["file"] = ( - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\ + data[ + "file" + ] = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\ fAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAANSURBVAiZYzAxMfkPAALYAZzx61+bAAAAAElFTkSuQmCC" - ) with patch("geonode.base.models.is_monochromatic_image") as _mck: _mck.return_value = False response = self.client.put(url, data=data, format="json") diff --git a/geonode/harvesting/harvesters/geonodeharvester.py b/geonode/harvesting/harvesters/geonodeharvester.py index dad1571b920..0f9de873476 100644 --- a/geonode/harvesting/harvesters/geonodeharvester.py +++ b/geonode/harvesting/harvesters/geonodeharvester.py @@ -433,14 +433,14 @@ def _get_resource_list_params(self, offset: typing.Optional[int] = 0) -> typing. result["filter{title.icontains}"] = self.resource_title_filter if self.start_date_filter is not None: start_date = dateutil.parser.parse(self.start_date_filter) - result["filter{date.gte}"] = ( - f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" - ) + result[ + "filter{date.gte}" + ] = f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" if self.end_date_filter is not None: end_date = dateutil.parser.parse(self.end_date_filter) - result["filter{date.lte}"] = ( - f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" - ) + result[ + "filter{date.lte}" + ] = f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" if self.keywords_filter is not None: result["filter{keywords.slug.in}"] = self.keywords_filter if self.categories_filter is not None: @@ -738,14 +738,14 @@ def _get_resource_list_params(self, offset: typing.Optional[int] = 0) -> typing. result["title__icontains"] = self.resource_title_filter if self.start_date_filter is not None: start_date = dateutil.parser.parse(self.start_date_filter) - result["date__gte"] = ( - f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" - ) + result[ + "date__gte" + ] = f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" if self.end_date_filter is not None: end_date = dateutil.parser.parse(self.end_date_filter) - result["date__lte"] = ( - f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" - ) + result[ + "date__lte" + ] = f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" if self.keywords_filter is not None: result["keywords__slug__in"] = ",".join(self.keywords_filter) if self.categories_filter is not None: From 6128b84993e6f58cf2b9ce031a7cb337e363fe0a Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Mon, 5 Feb 2024 10:41:06 +0100 Subject: [PATCH 129/253] Prepare release 4.2.2 --- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/geonode/__init__.py b/geonode/__init__.py index 9b1e32fbb4d..95d5717c446 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 0, "dev", 0) +__version__ = (4, 2, 2, "final", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 4ea6cf81017..124910335d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. --e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.2.0 +geonode-importer==1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 79feeaeb61d..5e24e8fd6be 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.1.1,<5.0.0 - geonode-importer>=1.0.6 + django-geonode-mapstore-client==4.2.0 + geonode-importer==1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 8dbb3af6a07a1e34ee6ebcd7e6789fe9a87e0fb8 Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Mon, 5 Feb 2024 10:43:50 +0100 Subject: [PATCH 130/253] Bump to 4.2.x --- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/geonode/__init__.py b/geonode/__init__.py index 95d5717c446..9b1e32fbb4d 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 2, "final", 0) +__version__ = (4, 2, 0, "dev", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 124910335d9..4ea6cf81017 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -django-geonode-mapstore-client==4.2.0 -geonode-importer==1.0.6 +-e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client +-e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 5e24e8fd6be..79feeaeb61d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client==4.2.0 - geonode-importer==1.0.6 + django-geonode-mapstore-client>=4.1.1,<5.0.0 + geonode-importer>=1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From e53bdeff331f4b577918927d60477d4b50cca02f Mon Sep 17 00:00:00 2001 From: Toni Date: Tue, 13 Feb 2024 18:27:06 +0100 Subject: [PATCH 131/253] [Fixes #11862] Sanitize HTML data (#11958) --- geonode/base/templatetags/sanitize_html.py | 36 ++++++++++++++++++++++ geonode/base/tests.py | 9 ++++++ geonode/templates/metadata_detail.html | 13 ++++---- requirements.txt | 1 + setup.cfg | 1 + 5 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 geonode/base/templatetags/sanitize_html.py diff --git a/geonode/base/templatetags/sanitize_html.py b/geonode/base/templatetags/sanitize_html.py new file mode 100644 index 00000000000..70b4822afcb --- /dev/null +++ b/geonode/base/templatetags/sanitize_html.py @@ -0,0 +1,36 @@ +from django import template +from django.conf import settings +import nh3 +from django.utils.encoding import force_str + +register = template.Library() + + +@register.filter(name="sanitize_html") +def sanitize_html(value): + """ + This filter can be used in Django templates to ensure that HTML content is safe to render. It leverages the + nh3 library (https://github.com/messense/nh3) to remove dangerous tags and JavaScript patterns. + + The allowed HTML tags and attributes can be + configured via the 'NH3_DEFAULT_CONFIG' setting in Django's settings.py. If this configuration is not set, a default + set of safe tags will be used. + + Usage in templates: {{ some_variable|sanitize_html|safe }} + + :param value: The HTML content to be sanitized within the template. + :return: Sanitized HTML content safe for rendering in templates. + """ + + # Tests: Ensure the value is converted to a string if it's a lazy object + value = force_str(value) + + nh3_config = getattr( + settings, + "NH3_DEFAULT_CONFIG", + { + "tags": {"b", "a", "img", "p", "ul", "li", "strong", "em", "span"}, + }, + ) + + return nh3.clean(value, **nh3_config) diff --git a/geonode/base/tests.py b/geonode/base/tests.py index bcadaa07931..31681475624 100644 --- a/geonode/base/tests.py +++ b/geonode/base/tests.py @@ -51,6 +51,7 @@ from geonode.documents.models import Document from geonode.tests.base import GeoNodeBaseTestSupport from geonode.base.templatetags.base_tags import display_change_perms_button +from geonode.base.templatetags.sanitize_html import sanitize_html from geonode.base.utils import OwnerRightsRequestViewUtils from geonode.base.models import ( HierarchicalKeyword, @@ -729,6 +730,14 @@ def test_display_change_perms_button_tag_standard(self): self.assertTrue(user_perms) +class SanitizedHtmlTest(TestCase): + def test_sanitized_html(self): + test_html = "Allowed Text" + expected_output = "Allowed Text" + sanitized_output = sanitize_html(test_html) + self.assertEqual(sanitized_output, expected_output) + + class TestGetVisibleResource(TestCase): def setUp(self): self.user = get_user_model().objects.create(username="mikel_arteta") diff --git a/geonode/templates/metadata_detail.html b/geonode/templates/metadata_detail.html index ff852b321e9..f09b341eecd 100644 --- a/geonode/templates/metadata_detail.html +++ b/geonode/templates/metadata_detail.html @@ -3,6 +3,7 @@ {% load bootstrap_tags %} {% load thesaurus %} {% load client_lib_tags %} +{% load sanitize_html %} {% block title %}{{ resource.title }} — {{ block.super }}{% endblock %} @@ -45,7 +46,7 @@

    {% trans "Metadata" %} : {{ resource.title }}

    {% block abstract %} {% if resource.abstract %}
    {% trans "Abstract" %}
    -
    {{ resource.abstract|safe }}
    +
    {{ resource.abstract|sanitize_html|safe }}
    {% endif %} {% endblock abstract %} @@ -91,7 +92,7 @@

    {% trans "Metadata" %} : {{ resource.title }}

    {% for keyword in resource.keywords.all %}
  • - {{ keyword.name| safe }} + {{ keyword.name|sanitize_html|safe }}
  • {% endfor %} @@ -299,7 +300,7 @@

    {% trans "Metadata" %} : {{ resource.title }}

    {% if resource.restriction_code_type or resource.constraints_other %}
    {% trans "Restrictions" %}
    {% if resource.constraints_other %} - {{ resource.constraints_other|safe }} + {{ resource.constraints_other|sanitize_html|safe }} {% else %} {{ resource.restriction_code_type }} {% endif %}
    @@ -316,7 +317,7 @@

    {% trans "Metadata" %} : {{ resource.title }}

    {% block purpose %} {% if resource.purpose %}
    {% trans "Purpose" %}
    -
    {{ resource.purpose|safe }}
    +
    {{ resource.purpose|sanitize_html|safe }}
    {% endif %} {% endblock purpose %} @@ -337,14 +338,14 @@

    {% trans "Metadata" %} : {{ resource.title }}

    {% block data_quality_statement %} {% if resource.data_quality_statement %}
    {% trans "Data Quality" %}
    -
    {{ resource.data_quality_statement|safe }}
    +
    {{ resource.data_quality_statement|sanitize_html|safe }}
    {% endif %} {% endblock data_quality_statement %} {% block supplemental_information %} {% if resource.supplemental_information %}
    {% trans "Supplemental Information" %}
    -
    {{ resource.supplemental_information|safe }}
    +
    {{ resource.supplemental_information|sanitize_html|safe }}
    {% endif %} {% endblock supplemental_information %} diff --git a/requirements.txt b/requirements.txt index 4ea6cf81017..70f7db16c82 100644 --- a/requirements.txt +++ b/requirements.txt @@ -176,3 +176,4 @@ paramiko==3.3.1 # not directly required, fixes Blowfish deprecation warning certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability jwcrypto>=1.4 # not directly required, pinned by Snyk to avoid a vulnerability cryptography>=41.0.0 # not directly required, pinned by Snyk to avoid a vulnerability +nh3==0.2.15 diff --git a/setup.cfg b/setup.cfg index 79feeaeb61d..01c83ee8f1f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -202,6 +202,7 @@ install_requires = certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability jwcrypto>=1.4 # not directly required, pinned by Snyk to avoid a vulnerability cryptography>=41.0.0 # not directly required, pinned by Snyk to avoid a vulnerability + nh3==0.2.15 [options.packages.find] exclude = tests From 8e2d4352503672b11a06aeda5f97e82616c6790e Mon Sep 17 00:00:00 2001 From: ahmdthr Date: Wed, 14 Feb 2024 15:20:07 +0100 Subject: [PATCH 132/253] Added test to verify that document is uploaded without specifying a title. --- geonode/documents/api/tests.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/geonode/documents/api/tests.py b/geonode/documents/api/tests.py index dbb3b13588b..b39c81a2d63 100644 --- a/geonode/documents/api/tests.py +++ b/geonode/documents/api/tests.py @@ -44,6 +44,7 @@ def setUp(self): self.url = reverse("documents-list") self.invalid_file_path = f"{settings.PROJECT_ROOT}/tests/data/thesaurus.rdf" self.valid_file_path = f"{settings.PROJECT_ROOT}/base/fixtures/test_xml.xml" + self.no_title_file_path = f"{settings.PROJECT_ROOT}/base/fixtures/test_sld.sld" def test_documents(self): """ @@ -142,6 +143,18 @@ def test_creation_should_create_the_doc(self): self.assertEqual("xml", extension) self.assertTrue(Document.objects.filter(title="New document for testing").exists()) + def test_uploading_doc_without_title(self): + """ + A document should be uploaded without specifying a title + """ + self.client.force_login(self.admin) + payload = {"document": {"metadata_only": True, "file_path": self.no_title_file_path}} + actual = self.client.post(self.url, data=payload, format="json") + self.assertEqual(201, actual.status_code) + extension = actual.json().get("document", {}).get("extension", "") + self.assertEqual("sld", extension) + self.assertTrue(Document.objects.filter(title="test_sld.sld").exists()) + def test_file_path_and_doc_path_are_not_returned(self): """ If file_path and doc_path should not be visible From 8e85224fb872a219a806a85021ff4c4675570659 Mon Sep 17 00:00:00 2001 From: ahmdthr Date: Thu, 15 Feb 2024 16:31:37 +0100 Subject: [PATCH 133/253] Removed unnecessary else statement. --- geonode/documents/models.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/geonode/documents/models.py b/geonode/documents/models.py index 191b4e0a2c8..b3889d5f87d 100644 --- a/geonode/documents/models.py +++ b/geonode/documents/models.py @@ -82,8 +82,6 @@ def name(self): if not self.title: if len(self.files) > 0: return self.files[0].split("/")[-1] - else: - return str(self.id) else: return self.title From 13c6a72e76100acf9a4be7c539f93e3038df2f5a Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 20 Feb 2024 19:16:28 +0100 Subject: [PATCH 134/253] Use own images for compose --- docker-compose-dev.yml | 2 +- docker-compose-test.yml | 2 +- docker-compose.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 19b81b0985a..955c05a6cce 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:local + image: 52north/geonode:local restart: unless-stopped env_file: - .env diff --git a/docker-compose-test.yml b/docker-compose-test.yml index a0da45aafa0..5ac51e9d6ea 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:local + image: 52north/geonode:local restart: unless-stopped env_file: - .env_test diff --git a/docker-compose.yml b/docker-compose.yml index d073b1cbbcf..af7f91931e9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:4.2.x + image: 52north/geonode:4.2.x restart: unless-stopped env_file: - .env From 3438a7f16188001b9d66577fc4da340b40cc440b Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 7 Jun 2023 15:35:01 +0200 Subject: [PATCH 135/253] updated changelog --- CHANGELOG.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee54d4a6d2e..799dbb6035c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,50 @@ # Change Log +## [4.1.0](https://github.com/GeoNode/geonode/tree/4.1.0) (2023-06-05) +### New upload engine +GeoNode integrates a brand new importer module based on [GDAL/OGR](https://gdal.org/), which offers increased robustness and reliability to the upload UI and API services. GeoPackage (vector), GeoJSON, KML/KMZ formats and a new CSV handler have been implemented. + +### Thesaurus faceting and date filtering +If thesaurus and thesaurus keywords are configured and assigned to resources, they will be available inside the filters panel, along with the number of associated resources. +Date filtering (from/top) has also been added. + +### Time series configurable after the upload +The configuration of (potential) time series at upload time was confusing for users, and not very robust. +With the new importer, the optional configuration of vector time series can be done afterward, through the Settings tab inside the Metadata editing page +Only vector fomats that provide date(time) fields natively are supported. Conversion from string fields is not implemented. + +### Related resources +This restore a functionality available in previous versions of GeoNode. +A tab inside the info panel has been added where relationships between datasets, maps and documents are reported. + +### Vector dataset attributes +A tab inside the info panel has been added showing the attributes of vector datasets + +### Remote documents +The API has been extended to permit the creation of document resources referencing remote URLs + +### ISO-19115 XML upload via API +The API now supports the upload of a metadata XML file along with the resource data + +### Software upgrades + + - [Geoserver 2.23.0](https://geoserver.org/announcements/2023/04/05/geoserver-2-23-0-released.html) is now the reference version. This version includes Geofence WPS rules which are employed by GeoNode to strengthen the security of the OGC/WPS processes. +- [MapStore 2022.02.xx](https://github.com/geosolutions-it/MapStore2/tree/2022.02.xx) +- [Django 3.2.19](https://docs.djangoproject.com/en/4.2/releases/3.2.19/) +- PostgreSQL 13 and PostGIS 3.3.3 + + +## Security and Bug Fixes +- [CVE-2023-26043](https://github.com/GeoNode/geonode/security/advisories/GHSA-mcmc-c59m-pqq8) +Fixed a vulnerability to XML External Entity (XXE) injection +- [CVE-2023-28442](https://github.com/GeoNode/geonode/security/advisories/GHSA-87mh-vw7c-5v6w) +Fixed information leak + +You can see the **full list of closed issues [here](https://github.com/GeoNode/geonode/compare/4.1.0...4.0.3)**. + +## System requirements +Python >3.9 is required to run GeoNode 4.1.0, since many of its dependencies have dropped support for older versions. + ## [4.0.2](https://github.com/GeoNode/geonode/tree/4.0.2) (2022-12-20) ### Breaking Changes From 4309585b2b6947aa5a7a4c2dbd6105218f6678e1 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Tue, 8 Aug 2023 16:02:52 +0200 Subject: [PATCH 136/253] changelog and fixes for packaging (#11355) --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 799dbb6035c..b440a931782 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## [4.1.1](https://github.com/GeoNode/geonode/tree/4.1.0) (2023-06-05) +## Security and Bug Fixes +- Upgrade to Ubuntu 22.10 +- Upgrade to Django 3.2.20 +- Fixed direct download URL not working in some cases when local files are not available +- Fixed assignment of regions crossing the dateline +- Fixed harvesting of ArcGIS REST ImageServer services +- Fixed some italian translations +- Disabling of the (deprecated) Monitoring module ## [4.1.0](https://github.com/GeoNode/geonode/tree/4.1.0) (2023-06-05) ### New upload engine GeoNode integrates a brand new importer module based on [GDAL/OGR](https://gdal.org/), which offers increased robustness and reliability to the upload UI and API services. GeoPackage (vector), GeoJSON, KML/KMZ formats and a new CSV handler have been implemented. From 61490f1b72f9f68c91e5a8285d11019356c25c27 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Fri, 11 Aug 2023 11:51:41 +0200 Subject: [PATCH 137/253] BUmp to 4.1.x (#11371) --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b440a931782..e2ac7e72bd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log -## [4.1.1](https://github.com/GeoNode/geonode/tree/4.1.0) (2023-06-05) +## [4.1.2](https://github.com/GeoNode/geonode/tree/4.1.2) (2023-08-11) +## Bug Fixes +- Upgrade to importer 1.0.5 which fixes the import with filenames longer then 63 chars +- Fixed parsing and rendering of ISO TC211 spatial representetion type +## [4.1.1](https://github.com/GeoNode/geonode/tree/4.1.1) (2023-06-05) ## Security and Bug Fixes - Upgrade to Ubuntu 22.10 - Upgrade to Django 3.2.20 From 2e462d568e352e382e1c3c9aa6ebdd8e38e5ef2e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 29 Sep 2022 14:22:48 +0200 Subject: [PATCH 138/253] [Fixes #10066][Depencendies] Security audit and checks (#10067) (#10072) * [Fixes #10066][Depencendies] Security audit and checks * -SNYK security fix Co-authored-by: Alessio Fabiani --- setup.cfg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup.cfg b/setup.cfg index 01c83ee8f1f..50cad6963d1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -204,6 +204,11 @@ install_requires = cryptography>=41.0.0 # not directly required, pinned by Snyk to avoid a vulnerability nh3==0.2.15 + # Security and audit + mistune==2.0.3 + protobuf==4.21.6 + mako==1.2.3 + [options.packages.find] exclude = tests From 1a237538e54629eec2974b71c4169abe78e5a1ce Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 10:10:12 +0200 Subject: [PATCH 139/253] [Fixes #10055] Modify Metadata form with permissions check (#10057) (#10076) * -[Fixes #10055] Modify Metadata form with permissions check * - check user in form * - update tests * - add tests Co-authored-by: Giovanni Allegri Co-authored-by: NAGGINDA MARTHA Co-authored-by: Giovanni Allegri --- geonode/base/forms.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/geonode/base/forms.py b/geonode/base/forms.py index 8152da290e5..bfceef992f9 100644 --- a/geonode/base/forms.py +++ b/geonode/base/forms.py @@ -579,6 +579,9 @@ def __init__(self, *args, **kwargs): if field in ["owner"] and not self.can_change_perms: self.fields[field].disabled = True + if field in ['poc', 'owner'] and not self.can_change_perms: + self.fields[field].disabled = True + def disable_keywords_widget_for_non_superuser(self, user): if settings.FREETEXT_KEYWORDS_READONLY and not user.is_superuser: self["keywords"].field.disabled = True From 6d2cad3777d1e4a77ae936030c95bb2127afe303 Mon Sep 17 00:00:00 2001 From: Alessio Fabiani Date: Mon, 10 Oct 2022 16:08:20 +0200 Subject: [PATCH 140/253] [Dependencies] Align setup.cfg to requirements.txt (#10124) (#10128) (cherry picked from commit e66dd985393d7728ddce2cd1f33b737cbb2b5f6e) # Conflicts: # requirements.txt --- setup.cfg | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 50cad6963d1..3fa2ebcb229 100644 --- a/setup.cfg +++ b/setup.cfg @@ -205,8 +205,9 @@ install_requires = nh3==0.2.15 # Security and audit - mistune==2.0.3 - protobuf==4.21.6 + mistune==2.0.4 + wandb==0.12.17 + protobuf==3.20.3 mako==1.2.3 [options.packages.find] From 145ff73187c6426dc40a46e358bae5ab7c0e214a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 17 Oct 2022 12:54:00 +0200 Subject: [PATCH 141/253] =?UTF-8?q?[Fixes=20#10142]=20storage=5Fmanager=20?= =?UTF-8?q?copy=20dont=20assign=20the=20folder/file=20permi=E2=80=A6=20(#1?= =?UTF-8?q?0143)=20(#10154)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/storage/tests.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/geonode/storage/tests.py b/geonode/storage/tests.py index 9a96186ab3e..dedef558e0c 100644 --- a/geonode/storage/tests.py +++ b/geonode/storage/tests.py @@ -417,6 +417,22 @@ def test_storage_manager_copy(self): os.remove(output.get("files")[0]) self.assertFalse(os.path.exists(output.get("files")[0])) + @override_settings(FILE_UPLOAD_DIRECTORY_PERMISSIONS=0o777) + @override_settings(FILE_UPLOAD_PERMISSIONS=0o777) + def test_storage_manager_copy(self): + ''' + Test that the copy works as expected and the permissions are corerct + ''' + dataset = create_single_dataset(name="test_copy") + dataset.files = [os.path.join(f"{self.project_root}", "tests/data/test_sld.sld")] + dataset.save() + output = self.sut().copy(dataset) + + self.assertTrue(os.path.exists(output.get("files")[0])) + self.assertEqual(os.stat(os.path.exists(output.get("files")[0])).st_mode, 8592) + os.remove(output.get("files")[0]) + self.assertFalse(os.path.exists(output.get("files")[0])) + class TestDataRetriever(TestCase): @classmethod From 9cd537d048df9c5c77456b53a0b062942d5e228f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 18 Oct 2022 11:44:16 +0200 Subject: [PATCH 142/253] Align requirements.txt comments with 4.x (#10162) (#10163) Co-authored-by: Alessio Fabiani --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 3fa2ebcb229..9b613aaa1f1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -206,7 +206,7 @@ install_requires = # Security and audit mistune==2.0.4 - wandb==0.12.17 + wandb==0.13.4 protobuf==3.20.3 mako==1.2.3 From 7c08751ded87070f1ba022c6e5efa35c1957567d Mon Sep 17 00:00:00 2001 From: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Date: Fri, 4 Nov 2022 16:55:34 +0100 Subject: [PATCH 143/253] [4.0.x][Fixes #10208] Add a custom hook at the end of the permissions assign (#10212) * [Fixes #10208] Add a custom hook at the end of the permissions assign --- geonode/geoserver/signals.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/geonode/geoserver/signals.py b/geonode/geoserver/signals.py index 70b96060303..591a1e12552 100644 --- a/geonode/geoserver/signals.py +++ b/geonode/geoserver/signals.py @@ -42,6 +42,8 @@ geofence_rule_assign = Signal(providing_args=["instance"]) +post_set_permissions = Signal(providing_args=['instance']) + def geoserver_delete(typename): # cascading_delete should only be called if From c277cd66d56ddf1ae8290dc48ff870eca5aed9a0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Nov 2022 10:04:04 +0100 Subject: [PATCH 144/253] Fix broken test (#10266) (#10267) * Fix broken test build * Fix broken test build Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/security/tests.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/geonode/security/tests.py b/geonode/security/tests.py index 433f4aa6de7..073c69a7215 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -1747,6 +1747,15 @@ def test_admin_whitelisted_access_middleware(self): middleware.process_request(request) self.assertTrue(request.user.is_superuser) + # Test valid IP in second element + with self.settings(ADMIN_IP_WHITELIST=['88.88.88.88', '127.0.0.1']): + request = HttpRequest() + request.user = admin + request.path = reverse('home') + request.META['REMOTE_ADDR'] = '127.0.0.1' + middleware.process_request(request) + self.assertTrue(request.user.is_superuser) + class SecurityRulesTests(TestCase): """ From e844f11b7d2f5a722b312ee05f7b519e05acc08e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 9 Nov 2022 15:04:09 +0100 Subject: [PATCH 145/253] [Fixes #10251] improve feedback to the user and UI experience of batch permisisons assignment (#10281) (#10282) * [Fixes #10251] improve feedback to the user and UI experience * [Fixes #10251] improve feedback to the user and UI experience * [Fixes #10251] improve feedback to the user and UI experience Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/base/views.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/geonode/base/views.py b/geonode/base/views.py index ab7359c8b3b..86a8c1b58a4 100644 --- a/geonode/base/views.py +++ b/geonode/base/views.py @@ -355,6 +355,20 @@ def get_results(self, context): ] +class DatasetsAutocomplete(SimpleSelect2View): + model = Dataset + filter_arg = 'title__icontains' + + def get_results(self, context): + return [ + { + 'id': self.get_result_value(result), + 'text': self.get_result_label(result.title), + 'selected_text': self.get_selected_result_label(result.title), + } for result in context['object_list'] + ] + + class ThesaurusAvailable(autocomplete.Select2QuerySetView): def get_queryset(self): tid = self.request.GET.get("sysid") From 2acba200aefdcb9ca9cc9410ec7a31b717ce5932 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 9 Nov 2022 17:10:36 +0100 Subject: [PATCH 146/253] [Dependencies] Align setup.cfg to requirements.txt (#10284) (#10286) Co-authored-by: Alessio Fabiani --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 9b613aaa1f1..6c3bf56e85a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -206,7 +206,7 @@ install_requires = # Security and audit mistune==2.0.4 - wandb==0.13.4 + wandb==0.13.5 protobuf==3.20.3 mako==1.2.3 From da00b9cd2b2cc08a69b2ec10cfacaab188d6f3a0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 14 Nov 2022 22:05:05 +0100 Subject: [PATCH 147/253] [Fixes #10270] Document creation via API v2 (#10271) (#10298) * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 Co-authored-by: Alessio Fabiani Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Co-authored-by: Alessio Fabiani --- geonode/documents/api/tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/geonode/documents/api/tests.py b/geonode/documents/api/tests.py index 3f6b4d6bf2e..daa8fff413e 100644 --- a/geonode/documents/api/tests.py +++ b/geonode/documents/api/tests.py @@ -16,6 +16,8 @@ # along with this program. If not, see . # ######################################################################### +import os +from django.contrib.auth import get_user_model import logging from django.contrib.auth import get_user_model From c00385f1181e54dfc633ca9c2faa5f8a5bfbaad4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 21 Nov 2022 17:33:14 +0100 Subject: [PATCH 148/253] [Fixes #10303] automatic periodic TaskResult removal (#10306) (#10319) * [Fixes #10303] automatic periodic TaskResult removal * [Fixes #10303] automatic periodic TaskResult removal * [Fixes #10303] automatic periodic TaskResult removal * [Fixes #10303] fix flake8 formatting Co-authored-by: Alessio Fabiani Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Co-authored-by: Alessio Fabiani --- geonode/upload/__init__.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/geonode/upload/__init__.py b/geonode/upload/__init__.py index c3ad74d2b54..f8afdf61568 100644 --- a/geonode/upload/__init__.py +++ b/geonode/upload/__init__.py @@ -48,6 +48,19 @@ def run_setup_hooks(sender, **kwargs): start_time=timezone.now(), ), ) + daily_interval, _ = IntervalSchedule.objects.get_or_create( + every=1, + period="days" + ) + PeriodicTask.objects.update_or_create( + name="clean-up-old-task-result", + defaults=dict( + task="geonode.upload.tasks.cleanup_celery_task_entries", + interval=daily_interval, + args='', + start_time=timezone.now() + ) + ) class UploadAppConfig(AppConfig): @@ -60,6 +73,10 @@ def ready(self): "task": "geonode.upload.tasks.cleanup_celery_task_entries", "schedule": 86400.0, } + settings.CELERY_BEAT_SCHEDULE['clean-up-old-task-result'] = { + 'task': 'geonode.upload.tasks.cleanup_celery_task_entries', + 'schedule': 86400.0, + } default_app_config = "geonode.upload.UploadAppConfig" From 64e3e146ad039da18a186042607fd89150d1d9ac Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 23 Nov 2022 12:22:48 +0100 Subject: [PATCH 149/253] [Dependencies] Align setup.cfg with requirements.txt (#10339) (#10341) (#10344) Co-authored-by: Alessio Fabiani Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 6c3bf56e85a..19b7e762903 100644 --- a/setup.cfg +++ b/setup.cfg @@ -208,7 +208,7 @@ install_requires = mistune==2.0.4 wandb==0.13.5 protobuf==3.20.3 - mako==1.2.3 + mako==1.2.4 [options.packages.find] exclude = tests From 8eb6ceea05a39f4f9b8149487bdb33e05a666005 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 Dec 2022 12:25:33 +0100 Subject: [PATCH 150/253] [Dependencies] Align setup.cfg to requirements.txt (#10417) (#10419) Co-authored-by: Alessio Fabiani --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 19b7e762903..8beff08dc86 100644 --- a/setup.cfg +++ b/setup.cfg @@ -206,7 +206,7 @@ install_requires = # Security and audit mistune==2.0.4 - wandb==0.13.5 + wandb==0.13.6 protobuf==3.20.3 mako==1.2.4 From 0bf817c22c540f4a226db3cfd471b26d8613255f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Dec 2022 12:15:39 +0100 Subject: [PATCH 151/253] [Dependencies] Align setup.cfg to requirements.txt (#10444) (#10445) Co-authored-by: Alessio Fabiani --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 8beff08dc86..1b18d39de2f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -206,7 +206,7 @@ install_requires = # Security and audit mistune==2.0.4 - wandb==0.13.6 + wandb==0.13.7 protobuf==3.20.3 mako==1.2.4 From 591e68c667695bbf5f5adf94e873d17481cbbf8a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 18 Jan 2023 10:27:51 +0100 Subject: [PATCH 152/253] [Dependencies] Align "setup.cfg" to "requirements.txt" (#10555) (#10558) (cherry picked from commit 33d4aa9b4fca04f5cc282b5607ff5d1e72e80e6e) Co-authored-by: Alessio Fabiani --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 1b18d39de2f..5f5f08158f3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -206,7 +206,7 @@ install_requires = # Security and audit mistune==2.0.4 - wandb==0.13.7 + wandb==0.13.9 protobuf==3.20.3 mako==1.2.4 From 15200d6a194fb5e3a6dd725834fefc254f2b7bf7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 23 Jan 2023 11:21:53 +0100 Subject: [PATCH 153/253] [Fixes #10537] Improve rules creation using GeoFence batch (#10538) (#10567) * [Fixes #10537] Improve rules creation using GeoFence batch * - code improvements accordingly to the PR comments * - code improvements accordingly to the PR comments * - Test fixes Co-authored-by: afabiani (cherry picked from commit d101ead2e2552f3d4f9b6cd355ce1eced3dbaecf) Co-authored-by: Emanuele Tajariol --- geonode/geoserver/helpers.py | 1 + geonode/security/tests.py | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index 8067f272adb..193b2df05ed 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -1874,6 +1874,7 @@ def get_time_info(layer): url, _user, _password, retries=ogc_server_settings.MAX_RETRIES, backoff_factor=ogc_server_settings.BACKOFF_FACTOR ) gs_uploader = Client(url, _user, _password) +gf_client = GeofenceClient(url, _user, _password) def _create_geofence_client(): diff --git a/geonode/security/tests.py b/geonode/security/tests.py index 073c69a7215..b04dba3b2ae 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -88,6 +88,16 @@ def _log(msg, *args): logger.debug(msg, *args) +def get_geofence_rules_count(): + from geonode.geoserver.helpers import gf_client + return gf_client.get_rules_count() + + +def get_geofence_rules(): + from geonode.geoserver.helpers import gf_client + return gf_client.get_rules() + + class StreamToLogger: """ Fake file-like stream object that redirects writes to a logger instance. From c01e029fb73b55f985b9b1c4b7855da07c9daa80 Mon Sep 17 00:00:00 2001 From: Alessio Fabiani Date: Tue, 24 Jan 2023 12:06:22 +0100 Subject: [PATCH 154/253] Backport 10575 to 4.1.x (#10579) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump oauthlib from 3.2.0 to 3.2.1 (#9998) Bumps [oauthlib](https://github.com/oauthlib/oauthlib) from 3.2.0 to 3.2.1. - [Release notes](https://github.com/oauthlib/oauthlib/releases) - [Changelog](https://github.com/oauthlib/oauthlib/blob/master/CHANGELOG.rst) - [Commits](https://github.com/oauthlib/oauthlib/compare/v3.2.0...v3.2.1) --- updated-dependencies: - dependency-name: oauthlib dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump jsonschema from 4.15.0 to 4.16.0 (#9999) Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.15.0 to 4.16.0. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.15.0...v4.16.0) --- updated-dependencies: - dependency-name: jsonschema dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytest-splinter from 3.3.1 to 3.3.2 (#10000) Bumps [pytest-splinter](https://github.com/pytest-dev/pytest-splinter) from 3.3.1 to 3.3.2. - [Release notes](https://github.com/pytest-dev/pytest-splinter/releases) - [Changelog](https://github.com/pytest-dev/pytest-splinter/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-splinter/compare/3.3.1...3.3.2) --- updated-dependencies: - dependency-name: pytest-splinter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump dropbox from 11.33.0 to 11.34.0 (#10001) Bumps [dropbox](https://github.com/dropbox/dropbox-sdk-python) from 11.33.0 to 11.34.0. - [Release notes](https://github.com/dropbox/dropbox-sdk-python/releases) - [Commits](https://github.com/dropbox/dropbox-sdk-python/compare/v11.33.0...v11.34.0) --- updated-dependencies: - dependency-name: dropbox dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump django-select2 from 7.10.0 to 7.10.1 (#10006) Bumps [django-select2](https://github.com/codingjoe/django-select2) from 7.10.0 to 7.10.1. - [Release notes](https://github.com/codingjoe/django-select2/releases) - [Commits](https://github.com/codingjoe/django-select2/compare/7.10.0...7.10.1) --- updated-dependencies: - dependency-name: django-select2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update pyproj requirement from <3.3.0 to <3.5.0 (#10002) Updates the requirements on [pyproj](https://github.com/pyproj4/pyproj) to permit the latest version. - [Release notes](https://github.com/pyproj4/pyproj/releases) - [Changelog](https://github.com/pyproj4/pyproj/blob/main/docs/history.rst) - [Commits](https://github.com/pyproj4/pyproj/compare/v1.9.4rel...3.4.0) --- updated-dependencies: - dependency-name: pyproj dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump sqlalchemy from 1.4.40 to 1.4.41 (#10005) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.40 to 1.4.41. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump twisted from 22.4.0 to 22.8.0 (#10007) Bumps [twisted](https://github.com/twisted/twisted) from 22.4.0 to 22.8.0. - [Release notes](https://github.com/twisted/twisted/releases) - [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst) - [Commits](https://github.com/twisted/twisted/compare/twisted-22.4.0...twisted-22.8.0) --- updated-dependencies: - dependency-name: twisted dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump ipython from 8.4.0 to 8.5.0 (#10004) Bumps [ipython](https://github.com/ipython/ipython) from 8.4.0 to 8.5.0. - [Release notes](https://github.com/ipython/ipython/releases) - [Commits](https://github.com/ipython/ipython/compare/8.4.0...8.5.0) --- updated-dependencies: - dependency-name: ipython dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.24.66 to 1.24.70 (#10003) Bumps [boto3](https://github.com/boto/boto3) from 1.24.66 to 1.24.70. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.24.66...1.24.70) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align setup.cfg to requirements.txt (#10019) * Bump to version 4.0.1 (cherry picked from commit 43cb8049b488b23bbc4886ca9e28d95f8329cf65) * Bump to version 4.0.2 dev 0 (cherry picked from commit c4bd604e1aa453cd9c6b718792e156e8bdf86e3b) # Conflicts: # requirements.txt # setup.cfg * Bump boto3 from 1.24.70 to 1.24.75 (#10031) Bumps [boto3](https://github.com/boto/boto3) from 1.24.70 to 1.24.75. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.24.70...1.24.75) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump smart-open from 6.1.0 to 6.2.0 (#10030) Bumps [smart-open](https://github.com/piskvorky/smart_open) from 6.1.0 to 6.2.0. - [Release notes](https://github.com/piskvorky/smart_open/releases) - [Changelog](https://github.com/RaRe-Technologies/smart_open/blob/develop/CHANGELOG.md) - [Commits](https://github.com/piskvorky/smart_open/compare/v6.1.0...v6.2.0) --- updated-dependencies: - dependency-name: smart-open dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump drf-spectacular from 0.23.1 to 0.24.0 (#10029) Bumps [drf-spectacular](https://github.com/tfranzel/drf-spectacular) from 0.23.1 to 0.24.0. - [Release notes](https://github.com/tfranzel/drf-spectacular/releases) - [Changelog](https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst) - [Commits](https://github.com/tfranzel/drf-spectacular/compare/0.23.1...0.24.0) --- updated-dependencies: - dependency-name: drf-spectacular dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update idna requirement from <2.11,>=2.5 to >=2.5,<3.5 (#10028) Updates the requirements on [idna](https://github.com/kjd/idna) to permit the latest version. - [Release notes](https://github.com/kjd/idna/releases) - [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.rst) - [Commits](https://github.com/kjd/idna/compare/v2.5...v3.4) --- updated-dependencies: - dependency-name: idna dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pyjwt from 2.4.0 to 2.5.0 (#10027) Bumps [pyjwt](https://github.com/jpadilla/pyjwt) from 2.4.0 to 2.5.0. - [Release notes](https://github.com/jpadilla/pyjwt/releases) - [Changelog](https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst) - [Commits](https://github.com/jpadilla/pyjwt/compare/2.4.0...2.5.0) --- updated-dependencies: - dependency-name: pyjwt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * [Fixes #10024] Wrong default style when creating layer (#10035) (cherry picked from commit 40fae5b3240ddf5b033688ce1891d7e7f1cfc304) Co-authored-by: Alessio Fabiani * add installation type to issue template (#10042) * [Dependencies] Align setup.cfg with requirements.txt (#10038) * [Fixes #10040] Remove auto-generated thumbnail for documents (#10045) * -[Fixes #10040] Remove auto-generated thumbnail for documents * - add migration to clean available thumbs * - fix migration * - modify functionality * Bump drf-spectacular from 0.24.0 to 0.24.1 (#10051) Bumps [drf-spectacular](https://github.com/tfranzel/drf-spectacular) from 0.24.0 to 0.24.1. - [Release notes](https://github.com/tfranzel/drf-spectacular/releases) - [Changelog](https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst) - [Commits](https://github.com/tfranzel/drf-spectacular/compare/0.24.0...0.24.1) --- updated-dependencies: - dependency-name: drf-spectacular dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Update setuptools requirement from <65.4.0,>=59.1.1 to >=59.1.1,<65.5.0 (#10047) Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v59.1.1...v65.4.0) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.24.75 to 1.24.80 (#10050) Bumps [boto3](https://github.com/boto/boto3) from 1.24.75 to 1.24.80. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.24.75...1.24.80) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pyopenssl from 22.0.0 to 22.1.0 (#10049) Bumps [pyopenssl](https://github.com/pyca/pyopenssl) from 22.0.0 to 22.1.0. - [Release notes](https://github.com/pyca/pyopenssl/releases) - [Changelog](https://github.com/pyca/pyopenssl/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/pyopenssl/compare/22.0.0...22.1.0) --- updated-dependencies: - dependency-name: pyopenssl dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Bump djangorestframework from 3.12.0 to 3.14.0 (#10048) Bumps [djangorestframework](https://github.com/encode/django-rest-framework) from 3.12.0 to 3.14.0. - [Release notes](https://github.com/encode/django-rest-framework/releases) - [Commits](https://github.com/encode/django-rest-framework/compare/3.12.0...3.14.0) --- updated-dependencies: - dependency-name: djangorestframework dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Revert "Bump djangorestframework from 3.12.0 to 3.14.0 (#10048)" (#10062) This reverts commit 75566560538b38c59873ed9fb7951acc3ba0edfa. * [Dependencies] Align setup.cfg with requirements.txt (#10061) * [Dependencies] Align setup.cfg with requirements.txt * Revert "Bump djangorestframework from 3.12.0 to 3.14.0" * [CLA] Add "edsonflavio" to .clabot * Complete Translate pt_BR (#10056) Tradução completa da localização para Português Brasileiro. Complete translate for pt_BR localization. Co-authored-by: Alessio Fabiani * [Fixes #10041] Review the thumbnail scaling process (#10046) * -[Fixes #10040] Remove auto-generated thumbnail for documents * - update thumbnail pixels * - add tests * - fix-tests * - fix-tests * [Fixes #10066][Depencendies] Security audit and checks (#10067) * [Fixes #10066][Depencendies] Security audit and checks * -SNYK security fix * [Fixes #10055] Modify Metadata form with permissions check (#10057) * -[Fixes #10055] Modify Metadata form with permissions check * - check user in form * - update tests * - add tests Co-authored-by: Giovanni Allegri * Bump django-mptt from 0.13.4 to 0.14.0 (#10081) Bumps [django-mptt](https://github.com/django-mptt/django-mptt) from 0.13.4 to 0.14.0. - [Release notes](https://github.com/django-mptt/django-mptt/releases) - [Changelog](https://github.com/django-mptt/django-mptt/blob/main/CHANGELOG.rst) - [Commits](https://github.com/django-mptt/django-mptt/compare/0.13.4...0.14) --- updated-dependencies: - dependency-name: django-mptt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Fixes #10070] Let the resource manager handle also raw sld (#10071) * [Fixes #10070] Let the resource manager handle also raw sld * [Fixes #10070] Let the resource manager handle also raw sld * [Fixes #10070] Let the resource manager handle also raw sld * Update django-invitations requirement from <1.9.4 to <2.0.1 (#10084) * Update django-invitations requirement from <1.9.4 to <2.0.1 Updates the requirements on [django-invitations](https://github.com/jazzband/django-invitations) to permit the latest version. - [Release notes](https://github.com/jazzband/django-invitations/releases) - [Changelog](https://github.com/jazzband/django-invitations/blob/master/CHANGELOG.md) - [Commits](https://github.com/jazzband/django-invitations/compare/0.1...2.0.0) --- updated-dependencies: - dependency-name: django-invitations dependency-type: direct:production ... Signed-off-by: dependabot[bot] * - fix the adapter Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani * fix: requirements.txt to reduce vulnerabilities (#10099) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-DJANGO-3039675 * Bump drf-spectacular from 0.24.1 to 0.24.2 (#10088) Bumps [drf-spectacular](https://github.com/tfranzel/drf-spectacular) from 0.24.1 to 0.24.2. - [Release notes](https://github.com/tfranzel/drf-spectacular/releases) - [Changelog](https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst) - [Commits](https://github.com/tfranzel/drf-spectacular/compare/0.24.1...0.24.2) --- updated-dependencies: - dependency-name: drf-spectacular dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Bump invoke from 1.7.1 to 1.7.3 (#10086) Bumps [invoke](https://github.com/pyinvoke/invoke) from 1.7.1 to 1.7.3. - [Release notes](https://github.com/pyinvoke/invoke/releases) - [Commits](https://github.com/pyinvoke/invoke/compare/1.7.1...1.7.3) --- updated-dependencies: - dependency-name: invoke dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump protobuf from 4.21.6 to 4.21.7 (#10085) Bumps [protobuf](https://github.com/protocolbuffers/protobuf) from 4.21.6 to 4.21.7. - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/generate_changelog.py) - [Commits](https://github.com/protocolbuffers/protobuf/commits) --- updated-dependencies: - dependency-name: protobuf dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytz from 2022.2.1 to 2022.4 (#10083) Bumps [pytz](https://github.com/stub42/pytz) from 2022.2.1 to 2022.4. - [Release notes](https://github.com/stub42/pytz/releases) - [Commits](https://github.com/stub42/pytz/commits) --- updated-dependencies: - dependency-name: pytz dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * -[Fixes #10073] Unable to view Maps tab in Recent activities (#10074) Co-authored-by: Giovanni Allegri Co-authored-by: Alessio Fabiani * Bump mistune from 2.0.3 to 2.0.4 (#10082) Bumps [mistune](https://github.com/lepture/mistune) from 2.0.3 to 2.0.4. - [Release notes](https://github.com/lepture/mistune/releases) - [Changelog](https://github.com/lepture/mistune/blob/v2.0.4/docs/changes.rst) - [Commits](https://github.com/lepture/mistune/compare/v2.0.3...v2.0.4) --- updated-dependencies: - dependency-name: mistune dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * [Fixes #10091] improve thumbnails quality (#10092) * improve thumbnails quality * force convertion to jpeg * - update tests * - fix tests Co-authored-by: marthamareal Co-authored-by: Alessio Fabiani * [Fixes #10075] Improvements to the upload time step UI (#10094) * -[Fixes #10075] Improvements to the upload time step UI * clarify why user is inside this step Co-authored-by: Giovanni Allegri Co-authored-by: Alessio Fabiani * Bump coverage from 6.4.4 to 6.5.0 (#10079) Bumps [coverage](https://github.com/nedbat/coveragepy) from 6.4.4 to 6.5.0. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/6.4.4...6.5.0) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * [Fixes #10113] Data retriver keep kmz files even if is unzipped (#10114) * [Fixes #10113] Data retriever keeps kmz files even if are unzipped * Bump sherlock from 0.3.2 to 0.4.0 (#10116) Bumps [sherlock](https://github.com/py-sherlock/sherlock) from 0.3.2 to 0.4.0. - [Release notes](https://github.com/py-sherlock/sherlock/releases) - [Changelog](https://github.com/py-sherlock/sherlock/blob/master/CHANGELOG.rst) - [Commits](https://github.com/py-sherlock/sherlock/commits/v0.4.0) --- updated-dependencies: - dependency-name: sherlock dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * -[Fixes #10104] Sort resource APIs with created date (#10105) Co-authored-by: Alessio Fabiani * Bump requests-toolbelt from 0.9.1 to 0.10.0 (#10118) Bumps [requests-toolbelt](https://github.com/requests/toolbelt) from 0.9.1 to 0.10.0. - [Release notes](https://github.com/requests/toolbelt/releases) - [Changelog](https://github.com/requests/toolbelt/blob/master/HISTORY.rst) - [Commits](https://github.com/requests/toolbelt/compare/0.9.1...0.10.0) --- updated-dependencies: - dependency-name: requests-toolbelt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Bump psycopg2 from 2.9.3 to 2.9.4 (#10117) Bumps [psycopg2](https://github.com/psycopg/psycopg2) from 2.9.3 to 2.9.4. - [Release notes](https://github.com/psycopg/psycopg2/releases) - [Changelog](https://github.com/psycopg/psycopg2/blob/master/NEWS) - [Commits](https://github.com/psycopg/psycopg2/commits) --- updated-dependencies: - dependency-name: psycopg2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.24.80 to 1.24.87 (#10107) Bumps [boto3](https://github.com/boto/boto3) from 1.24.80 to 1.24.87. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.24.80...1.24.87) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * [Dependencies] Align setup.cfg to requirements.txt (#10124) * [Fixes #10120] Celery autoscale values are too low and wrongly positioned (#10121) * [Fixes #7852] Update catalog and background layers url configuration in settings.py and related files (#9950) * -[Fixes #7852] Update catalog and background layers url configuration in settings.py and related files * - update geoid url * [Fixes #10130] Data retriever dont assign the folder/file permissions correcly (#10131) Co-authored-by: Alessio Fabiani * [Fixes #10134] New simple renderer to generate thumbnails for PDFs (#10135) * PDF thumbnail renderer * - add unit tests * command to generate thumbnails for docs * flake fix * renamed management command * add requirement to setup.cfg * make command similar to other sync commands * removed unused import * fix flake8 Co-authored-by: marthamareal * [Fixes #10138] Render pdf thumbnails from top margin (#10139) * render pdf thumbnails from top margin * fix flake * [Fixes #10142] storage_manager copy dont assign the folder/file permi… (#10143) * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * [Fixes #10142] storage_manager copy dont assign the folder/file permissions correcly * Bump wandb from 0.12.17 to 0.13.4 (#10152) Bumps [wandb](https://github.com/wandb/wandb) from 0.12.17 to 0.13.4. - [Release notes](https://github.com/wandb/wandb/releases) - [Changelog](https://github.com/wandb/wandb/blob/main/CHANGELOG.md) - [Commits](https://github.com/wandb/wandb/compare/v0.12.17...v0.13.4) --- updated-dependencies: - dependency-name: wandb dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Update setuptools requirement from <65.5.0,>=59.1.1 to >=59.1.1,<65.6.0 (#10150) Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v59.1.1...v65.5.0) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pip from 22.2.2 to 22.3 (#10149) Bumps [pip](https://github.com/pypa/pip) from 22.2.2 to 22.3. - [Release notes](https://github.com/pypa/pip/releases) - [Changelog](https://github.com/pypa/pip/blob/main/NEWS.rst) - [Commits](https://github.com/pypa/pip/compare/22.2.2...22.3) --- updated-dependencies: - dependency-name: pip dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump shapely from 1.8.4 to 1.8.5.post1 (#10147) Bumps [shapely](https://github.com/shapely/shapely) from 1.8.4 to 1.8.5.post1. - [Release notes](https://github.com/shapely/shapely/releases) - [Changelog](https://github.com/shapely/shapely/blob/1.8.5.post1/CHANGES.txt) - [Commits](https://github.com/shapely/shapely/compare/1.8.4...1.8.5.post1) --- updated-dependencies: - dependency-name: shapely dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump sqlalchemy from 1.4.41 to 1.4.42 (#10145) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.41 to 1.4.42. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump dropbox from 11.34.0 to 11.35.0 (#10146) Bumps [dropbox](https://github.com/dropbox/dropbox-sdk-python) from 11.34.0 to 11.35.0. - [Release notes](https://github.com/dropbox/dropbox-sdk-python/releases) - [Commits](https://github.com/dropbox/dropbox-sdk-python/compare/v11.34.0...v11.35.0) --- updated-dependencies: - dependency-name: dropbox dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.24.87 to 1.24.91 (#10151) Bumps [boto3](https://github.com/boto/boto3) from 1.24.87 to 1.24.91. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.24.87...1.24.91) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Align requirements.txt comments with 4.x (#10162) * [Fixes #10168] Add 'executions' field to concrete instance endpoints (#10169) * [Fixes #10168] Add 'executions' field to concrete instance endpoints * [Fixes #10168] Add 'executions' field to concrete instance endpoints * [Fixes #10171] Dynamic rendering of document_detail view template (#10172) * add preview mode to document metadata page * Remove Return to button inside metadata detail page * [Hardening] Avoid "backup.py" failing while trying to set "w" perms on the GeoServer catalog file * Fix migrations 4x (#10176) * - Fixing migrations upg 33x -> 4x * fix migration * missing files * - Fixing migrations upg 33x -> 4x * - Fixing migrations upg 33x -> 4x Co-authored-by: mattiagiupponi * [Hardening] Make the migration '0074_drop_curated_thumbs' more robust * [Fixes #10198] uwsgi library update (#10199) * [Fixes #10195] Backup and restore procedure is not successful (#10196) * [Fixes #10195] Backup and restore procedure is not successful * [Fixes #10195] Backup and restore procedure is not successful * [Fixes #10195] Backup and restore procedure is not successful * [Fixes #10195] Backup and restore procedure is not successful * [Fixes #10195] Backup and restore procedure is not successful * [Fixes #10195] test fix build * [Fixes #10204] restore mapstore catalog settings (#10205) * [Fixes #10192] Include source into the ExecutionRequest model (#10193) Co-authored-by: Alessio Fabiani * Bump oauthlib from 3.2.1 to 3.2.2 (#10189) Bumps [oauthlib](https://github.com/oauthlib/oauthlib) from 3.2.1 to 3.2.2. - [Release notes](https://github.com/oauthlib/oauthlib/releases) - [Changelog](https://github.com/oauthlib/oauthlib/blob/v3.2.2/CHANGELOG.rst) - [Commits](https://github.com/oauthlib/oauthlib/compare/v3.2.1...v3.2.2) --- updated-dependencies: - dependency-name: oauthlib dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * fix ip whitelisting (#10218) * Update httplib2 requirement from <0.20.5 to <0.21.1 (#10227) Updates the requirements on [httplib2](https://github.com/httplib2/httplib2) to permit the latest version. - [Release notes](https://github.com/httplib2/httplib2/releases) - [Changelog](https://github.com/httplib2/httplib2/blob/master/CHANGELOG) - [Commits](https://github.com/httplib2/httplib2/compare/0.9...v0.21.0) --- updated-dependencies: - dependency-name: httplib2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Bump pillow from 9.1.1 to 9.3.0 (#10229) Bumps [pillow](https://github.com/python-pillow/Pillow) from 9.1.1 to 9.3.0. - [Release notes](https://github.com/python-pillow/Pillow/releases) - [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) - [Commits](https://github.com/python-pillow/Pillow/compare/9.1.1...9.3.0) --- updated-dependencies: - dependency-name: pillow dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump twisted from 22.8.0 to 22.10.0 (#10233) Bumps [twisted](https://github.com/twisted/twisted) from 22.8.0 to 22.10.0. - [Release notes](https://github.com/twisted/twisted/releases) - [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst) - [Commits](https://github.com/twisted/twisted/compare/twisted-22.8.0...twisted-22.10.0) --- updated-dependencies: - dependency-name: twisted dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.24.91 to 1.26.0 (#10235) Bumps [boto3](https://github.com/boto/boto3) from 1.24.91 to 1.26.0. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.24.91...1.26.0) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytz from 2022.4 to 2022.6 (#10234) Bumps [pytz](https://github.com/stub42/pytz) from 2022.4 to 2022.6. - [Release notes](https://github.com/stub42/pytz/releases) - [Commits](https://github.com/stub42/pytz/compare/release_2022.4...release_2022.6) --- updated-dependencies: - dependency-name: pytz dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump ipython from 8.5.0 to 8.6.0 (#10228) Bumps [ipython](https://github.com/ipython/ipython) from 8.5.0 to 8.6.0. - [Release notes](https://github.com/ipython/ipython/releases) - [Commits](https://github.com/ipython/ipython/compare/8.5.0...8.6.0) --- updated-dependencies: - dependency-name: ipython dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump requests-toolbelt from 0.10.0 to 0.10.1 (#10225) Bumps [requests-toolbelt](https://github.com/requests/toolbelt) from 0.10.0 to 0.10.1. - [Release notes](https://github.com/requests/toolbelt/releases) - [Changelog](https://github.com/requests/toolbelt/blob/master/HISTORY.rst) - [Commits](https://github.com/requests/toolbelt/compare/0.10.0...0.10.1) --- updated-dependencies: - dependency-name: requests-toolbelt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytest from 7.1.3 to 7.2.0 (#10224) Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.1.3 to 7.2.0. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/7.1.3...7.2.0) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump django-select2 from 7.10.1 to 7.11.0 (#10223) Bumps [django-select2](https://github.com/codingjoe/django-select2) from 7.10.1 to 7.11.0. - [Release notes](https://github.com/codingjoe/django-select2/releases) - [Commits](https://github.com/codingjoe/django-select2/compare/7.10.1...7.11.0) --- updated-dependencies: - dependency-name: django-select2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump psycopg2 from 2.9.4 to 2.9.5 (#10222) Bumps [psycopg2](https://github.com/psycopg/psycopg2) from 2.9.4 to 2.9.5. - [Release notes](https://github.com/psycopg/psycopg2/releases) - [Changelog](https://github.com/psycopg/psycopg2/blob/master/NEWS) - [Commits](https://github.com/psycopg/psycopg2/commits) --- updated-dependencies: - dependency-name: psycopg2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pyjwt from 2.5.0 to 2.6.0 (#10186) Bumps [pyjwt](https://github.com/jpadilla/pyjwt) from 2.5.0 to 2.6.0. - [Release notes](https://github.com/jpadilla/pyjwt/releases) - [Changelog](https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst) - [Commits](https://github.com/jpadilla/pyjwt/commits) --- updated-dependencies: - dependency-name: pyjwt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump psutil from 5.9.2 to 5.9.3 (#10185) Bumps [psutil](https://github.com/giampaolo/psutil) from 5.9.2 to 5.9.3. - [Release notes](https://github.com/giampaolo/psutil/releases) - [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst) - [Commits](https://github.com/giampaolo/psutil/compare/release-5.9.2...release-5.9.3) --- updated-dependencies: - dependency-name: psutil dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump webdriver-manager from 3.8.3 to 3.8.4 (#10184) Bumps [webdriver-manager](https://github.com/SergeyPirogov/webdriver_manager) from 3.8.3 to 3.8.4. - [Release notes](https://github.com/SergeyPirogov/webdriver_manager/releases) - [Changelog](https://github.com/SergeyPirogov/webdriver_manager/blob/master/CHANGELOG.md) - [Commits](https://github.com/SergeyPirogov/webdriver_manager/compare/v3.8.3...v3.8.4) --- updated-dependencies: - dependency-name: webdriver-manager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: scripts/docker/nginx/Dockerfile to reduce vulnerabilities (#10180) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-ALPINE316-CURL-3011748 - https://snyk.io/vuln/SNYK-ALPINE316-LIBXML2-3040799 - https://snyk.io/vuln/SNYK-ALPINE316-LIBXML2-3050523 - https://snyk.io/vuln/SNYK-ALPINE316-LIBXML2-3050527 - https://snyk.io/vuln/SNYK-ALPINE316-ZLIB-2976176 Co-authored-by: Alessio Fabiani * [Dependencies] Align "setup.cfg" to "requirements.txt" (#10242) * [Fixes #10251] Review geonode management command set_layers_permissions (#10252) * [Fixes #10251] Review geonode management command set_layers_permissions * [Fixes #10251] Review geonode management command set_layers_permissions * [Fixes #10251] Review geonode management command set_layers_permissions * [Fixes #10251] Review geonode management command set_layers_permissions * [Fixes #10251] Review geonode management command set_layers_permissions * [Fixes #10251] Review geonode management command set_layers_permissions * [Fixes #10251] Review geonode management command set_layers_permissions * [Hardening] Prevent migration 0034_maplayer_extra_params_and_current_style to fail abruptly in the case the maplayer has no styles associated with it * [Fixes #10263] non admin user in fresh instance cannot create resources_ (#10264) * [Fixes #10208] Add a custom hook at the end of the permissions assign (#10213) Co-authored-by: Alessio Fabiani * Fix broken test (#10266) * Fix broken test build * Fix broken test build * Bump GeoServer to version 2.20.6 (#10164) * [Fixes #10214] metadata_only filter not working properly (#10215) * [Fixes #10214] metadata_only filter not working properly * [Fixes #10214] metadata_only filter not working properly * [Fixes #10214] metadata_only filter not working properly Co-authored-by: Alessio Fabiani * Bump jsonschema from 4.16.0 to 4.17.0 (#10262) Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.16.0 to 4.17.0. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.16.0...v4.17.0) --- updated-dependencies: - dependency-name: jsonschema dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Bump pip from 22.3 to 22.3.1 (#10261) Bumps [pip](https://github.com/pypa/pip) from 22.3 to 22.3.1. - [Release notes](https://github.com/pypa/pip/releases) - [Changelog](https://github.com/pypa/pip/blob/main/NEWS.rst) - [Commits](https://github.com/pypa/pip/compare/22.3...22.3.1) --- updated-dependencies: - dependency-name: pip dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytest-bdd from 6.0.1 to 6.1.0 (#10260) Bumps [pytest-bdd](https://github.com/pytest-dev/pytest-bdd) from 6.0.1 to 6.1.0. - [Release notes](https://github.com/pytest-dev/pytest-bdd/releases) - [Changelog](https://github.com/pytest-dev/pytest-bdd/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-bdd/compare/6.0.1...6.1.0) --- updated-dependencies: - dependency-name: pytest-bdd dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump django-select2 from 7.11.0 to 8.0.0 (#10259) Bumps [django-select2](https://github.com/codingjoe/django-select2) from 7.11.0 to 8.0.0. - [Release notes](https://github.com/codingjoe/django-select2/releases) - [Commits](https://github.com/codingjoe/django-select2/compare/7.11.0...8.0.0) --- updated-dependencies: - dependency-name: django-select2 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump sqlalchemy from 1.4.42 to 1.4.43 (#10258) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.42 to 1.4.43. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump docker from 6.0.0 to 6.0.1 (#10256) Bumps [docker](https://github.com/docker/docker-py) from 6.0.0 to 6.0.1. - [Release notes](https://github.com/docker/docker-py/releases) - [Commits](https://github.com/docker/docker-py/compare/6.0.0...6.0.1) --- updated-dependencies: - dependency-name: docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump wandb from 0.13.4 to 0.13.5 (#10255) Bumps [wandb](https://github.com/wandb/wandb) from 0.13.4 to 0.13.5. - [Release notes](https://github.com/wandb/wandb/releases) - [Changelog](https://github.com/wandb/wandb/blob/main/CHANGELOG.md) - [Commits](https://github.com/wandb/wandb/compare/v0.13.4...v0.13.5) --- updated-dependencies: - dependency-name: wandb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Fixes #10251] improve feedback to the user and UI experience of batch permisisons assignment (#10281) * [Fixes #10251] improve feedback to the user and UI experience * [Fixes #10251] improve feedback to the user and UI experience * [Fixes #10251] improve feedback to the user and UI experience * Bump boto3 from 1.26.0 to 1.26.4 (#10273) Bumps [boto3](https://github.com/boto/boto3) from 1.26.0 to 1.26.4. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.0...1.26.4) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * [Dependencies] Align setup.cfg to requirements.txt (#10284) * [Fixes #10287] The "set_layer_permissions" management command does not behave correctly with "AnonyousUser" (#10288) * [Fixes #10287] The "set_layer_permissions" management command does not behave correctly with "AnonyousUser" * [Fixes #10270] Document creation via API v2 (#10271) * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 * [Fixes #10270] Document creation via API v2 Co-authored-by: Alessio Fabiani * fix: requirements_tests.txt to reduce vulnerabilities (#10299) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-SETUPTOOLS-3113904 * Bump pytest-bdd from 6.1.0 to 6.1.1 (#10297) Bumps [pytest-bdd](https://github.com/pytest-dev/pytest-bdd) from 6.1.0 to 6.1.1. - [Release notes](https://github.com/pytest-dev/pytest-bdd/releases) - [Changelog](https://github.com/pytest-dev/pytest-bdd/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-bdd/compare/6.1.0...6.1.1) --- updated-dependencies: - dependency-name: pytest-bdd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Fabiani * Bump pymupdf from 1.20.2 to 1.21.0 (#10296) Bumps [pymupdf](https://github.com/pymupdf/pymupdf) from 1.20.2 to 1.21.0. - [Release notes](https://github.com/pymupdf/pymupdf/releases) - [Changelog](https://github.com/pymupdf/PyMuPDF/blob/master/changes.txt) - [Commits](https://github.com/pymupdf/pymupdf/compare/1.20.2...1.21.0) --- updated-dependencies: - dependency-name: pymupdf dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump sqlalchemy from 1.4.43 to 1.4.44 (#10294) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.43 to 1.4.44. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump psutil from 5.9.3 to 5.9.4 (#10293) Bumps [psutil](https://github.com/giampaolo/psutil) from 5.9.3 to 5.9.4. - [Release notes](https://github.com/giampaolo/psutil/releases) - [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst) - [Commits](https://github.com/giampaolo/psutil/compare/release-5.9.3...release-5.9.4) --- updated-dependencies: - dependency-name: psutil dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump dropbox from 11.35.0 to 11.36.0 (#10292) Bumps [dropbox](https://github.com/dropbox/dropbox-sdk-python) from 11.35.0 to 11.36.0. - [Release notes](https://github.com/dropbox/dropbox-sdk-python/releases) - [Commits](https://github.com/dropbox/dropbox-sdk-python/compare/v11.35.0...v11.36.0) --- updated-dependencies: - dependency-name: dropbox dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump google-cloud-storage from 2.5.0 to 2.6.0 (#10291) Bumps [google-cloud-storage](https://github.com/googleapis/python-storage) from 2.5.0 to 2.6.0. - [Release notes](https://github.com/googleapis/python-storage/releases) - [Changelog](https://github.com/googleapis/python-storage/blob/main/CHANGELOG.md) - [Commits](https://github.com/googleapis/python-storage/compare/v2.5.0...v2.6.0) --- updated-dependencies: - dependency-name: google-cloud-storage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.4 to 1.26.11 (#10312) Bumps [boto3](https://github.com/boto/boto3) from 1.26.4 to 1.26.11. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.4...1.26.11) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align setup.cfg with requirements.txt (#10315) * [Fixes #10303] automatic periodic TaskResult removal (#10306) * [Fixes #10303] automatic periodic TaskResult removal * [Fixes #10303] automatic periodic TaskResult removal * [Fixes #10303] automatic periodic TaskResult removal * [Fixes #10303] fix flake8 formatting Co-authored-by: Alessio Fabiani * [Fixes #10302] Incorrect permissions assigned on cloning a resource (#10309) * [Fixes #10302] Incorrect permissions assigned on cloning a resource * [Fixes #10302] Incorrect permissions assigned on cloning a resource * [Fixes #10302] Incorrect permissions assigned on cloning a resource * [Fixes #10302] test fix broken tests * [Fixes #10302] fix flake8 formatting * [Fixes #10302] test fix broken tests * [Fixes #10302] fix flake8 * - Fix test case * [Fixes #10302] fix flake8 Co-authored-by: Alessio Fabiani * Create SECURITY.md (#10285) * Create SECURITY.md * Update SECURITY.md fix minor typo Co-authored-by: Florian Hoedt * Update setuptools requirement from <65.6.0,>=59.1.1 to >=59.1.1,<65.7.0 (#10327) Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v65.5.1...v65.6.0) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump python-slugify from 6.1.2 to 7.0.0 (#10322) Bumps [python-slugify](https://github.com/un33k/python-slugify) from 6.1.2 to 7.0.0. - [Release notes](https://github.com/un33k/python-slugify/releases) - [Changelog](https://github.com/un33k/python-slugify/blob/master/CHANGELOG.md) - [Commits](https://github.com/un33k/python-slugify/compare/v6.1.2...v7.0.0) --- updated-dependencies: - dependency-name: python-slugify dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.11 to 1.26.14 (#10330) Bumps [boto3](https://github.com/boto/boto3) from 1.26.11 to 1.26.14. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.11...1.26.14) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump mako from 1.2.3 to 1.2.4 (#10325) Bumps [mako](https://github.com/sqlalchemy/mako) from 1.2.3 to 1.2.4. - [Release notes](https://github.com/sqlalchemy/mako/releases) - [Changelog](https://github.com/sqlalchemy/mako/blob/main/CHANGES) - [Commits](https://github.com/sqlalchemy/mako/commits) --- updated-dependencies: - dependency-name: mako dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump selenium-requests from 2.0.0 to 2.0.1 (#10324) Bumps [selenium-requests]() from 2.0.0 to 2.0.1. --- updated-dependencies: - dependency-name: selenium-requests dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump webdriver-manager from 3.8.4 to 3.8.5 (#10323) Bumps [webdriver-manager](https://github.com/SergeyPirogov/webdriver_manager) from 3.8.4 to 3.8.5. - [Release notes](https://github.com/SergeyPirogov/webdriver_manager/releases) - [Changelog](https://github.com/SergeyPirogov/webdriver_manager/blob/master/CHANGELOG.md) - [Commits](https://github.com/SergeyPirogov/webdriver_manager/compare/v3.8.4...v3.8.5) --- updated-dependencies: - dependency-name: webdriver-manager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Fixes #9041] Docker NGINX listen on ports 80/443 (#10338) * [Dependencies] Align setup.cfg with requirements.txt (#10339) * Bump django-grappelli from 3.0.3 to 3.0.4 (#10351) Bumps [django-grappelli](https://github.com/sehmaschine/django-grappelli) from 3.0.3 to 3.0.4. - [Release notes](https://github.com/sehmaschine/django-grappelli/releases) - [Changelog](https://github.com/sehmaschine/django-grappelli/blob/master/docs/changelog.rst) - [Commits](https://github.com/sehmaschine/django-grappelli/compare/3.0.3...3.0.4) --- updated-dependencies: - dependency-name: django-grappelli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: requirements_dev.txt to reduce vulnerabilities (#10300) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-SETUPTOOLS-3113904 Co-authored-by: snyk-bot * changed bbox_polygon and llbox_polygone to read only in serializer for #10316 (#10317) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Co-authored-by: Giovanni Allegri * Bump urllib3 from 1.26.12 to 1.26.13 (#10350) Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.12 to 1.26.13. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/1.26.13/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.26.12...1.26.13) --- updated-dependencies: - dependency-name: urllib3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump jsonschema from 4.17.0 to 4.17.1 (#10349) Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.17.0 to 4.17.1. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.17.0...v4.17.1) --- updated-dependencies: - dependency-name: jsonschema dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.14 to 1.26.17 (#10354) Bumps [boto3](https://github.com/boto/boto3) from 1.26.14 to 1.26.17. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.14...1.26.17) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump flake8 from 5.0.4 to 6.0.0 (#10348) Bumps [flake8](https://github.com/pycqa/flake8) from 5.0.4 to 6.0.0. - [Release notes](https://github.com/pycqa/flake8/releases) - [Commits](https://github.com/pycqa/flake8/compare/5.0.4...6.0.0) --- updated-dependencies: - dependency-name: flake8 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align "setup.cfg" to "requirements.txt" (#10363) * [CLA] Add MalteIwanicki to clabot (#10381) * Bump jsonschema from 4.17.1 to 4.17.3 (#10372) Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.17.1 to 4.17.3. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.17.1...v4.17.3) --- updated-dependencies: - dependency-name: jsonschema dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump ipython from 8.6.0 to 8.7.0 (#10371) Bumps [ipython](https://github.com/ipython/ipython) from 8.6.0 to 8.7.0. - [Release notes](https://github.com/ipython/ipython/releases) - [Commits](https://github.com/ipython/ipython/compare/8.6.0...8.7.0) --- updated-dependencies: - dependency-name: ipython dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.17 to 1.26.26 (#10386) Bumps [boto3](https://github.com/boto/boto3) from 1.26.17 to 1.26.26. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.17...1.26.26) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Fixes #10376] Time serie dataset, missing permissions (#10377) * fix: requirements_dev.txt to reduce vulnerabilities (#10369) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-IPYTHON-2348630 - https://snyk.io/vuln/SNYK-PYTHON-PYGMENTS-1086606 - https://snyk.io/vuln/SNYK-PYTHON-PYGMENTS-1088505 - https://snyk.io/vuln/SNYK-PYTHON-SETUPTOOLS-3113904 * fix: upgrade react-hot-loader from 4.13.0 to 4.13.1 (#10370) Snyk has created this PR to upgrade react-hot-loader from 4.13.0 to 4.13.1. See this package in npm: https://www.npmjs.com/package/react-hot-loader See this project in Snyk: https://app.snyk.io/org/afabiani/project/4217120c-f173-454b-b620-3b8eaebc4a07?utm_source=github&utm_medium=referral&page=upgrade-pr * [Dependencies] Align setup.cfg to requirements.txt (#10397) * Bump sqlalchemy from 1.4.44 to 1.4.45 (#10402) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.44 to 1.4.45. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump wandb from 0.13.5 to 0.13.6 (#10399) Bumps [wandb](https://github.com/wandb/wandb) from 0.13.5 to 0.13.6. - [Release notes](https://github.com/wandb/wandb/releases) - [Changelog](https://github.com/wandb/wandb/blob/main/CHANGELOG.md) - [Commits](https://github.com/wandb/wandb/compare/v0.13.5...v0.13.6) --- updated-dependencies: - dependency-name: wandb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump selenium-requests from 2.0.1 to 2.0.2 (#10401) Bumps [selenium-requests]() from 2.0.1 to 2.0.2. --- updated-dependencies: - dependency-name: selenium-requests dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump google-cloud-storage from 2.6.0 to 2.7.0 (#10398) Bumps [google-cloud-storage](https://github.com/googleapis/python-storage) from 2.6.0 to 2.7.0. - [Release notes](https://github.com/googleapis/python-storage/releases) - [Changelog](https://github.com/googleapis/python-storage/blob/main/CHANGELOG.md) - [Commits](https://github.com/googleapis/python-storage/compare/v2.6.0...v2.7.0) --- updated-dependencies: - dependency-name: google-cloud-storage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.26 to 1.26.28 (#10407) Bumps [boto3](https://github.com/boto/boto3) from 1.26.26 to 1.26.28. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.26...1.26.28) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align setup.cfg to requirements.txt (#10417) * [Fixes #10374] UUID resolver endpoint (#10375) * Bump lxml from 4.9.1 to 4.9.2 (#10433) Bumps [lxml](https://github.com/lxml/lxml) from 4.9.1 to 4.9.2. - [Release notes](https://github.com/lxml/lxml/releases) - [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt) - [Commits](https://github.com/lxml/lxml/compare/lxml-4.9.1...lxml-4.9.2) --- updated-dependencies: - dependency-name: lxml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pymupdf from 1.21.0 to 1.21.1 (#10432) Bumps [pymupdf](https://github.com/pymupdf/pymupdf) from 1.21.0 to 1.21.1. - [Release notes](https://github.com/pymupdf/pymupdf/releases) - [Changelog](https://github.com/pymupdf/PyMuPDF/blob/1.21.1/changes.txt) - [Commits](https://github.com/pymupdf/pymupdf/compare/1.21.0...1.21.1) --- updated-dependencies: - dependency-name: pymupdf dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytz from 2022.6 to 2022.7 (#10431) Bumps [pytz](https://github.com/stub42/pytz) from 2022.6 to 2022.7. - [Release notes](https://github.com/stub42/pytz/releases) - [Commits](https://github.com/stub42/pytz/compare/release_2022.6...release_2022.7) --- updated-dependencies: - dependency-name: pytz dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump wandb from 0.13.6 to 0.13.7 (#10430) Bumps [wandb](https://github.com/wandb/wandb) from 0.13.6 to 0.13.7. - [Release notes](https://github.com/wandb/wandb/releases) - [Changelog](https://github.com/wandb/wandb/blob/main/CHANGELOG.md) - [Commits](https://github.com/wandb/wandb/compare/v0.13.6...v0.13.7) --- updated-dependencies: - dependency-name: wandb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump coverage from 6.5.0 to 7.0.0 (#10429) Bumps [coverage](https://github.com/nedbat/coveragepy) from 6.5.0 to 7.0.0. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/6.5.0...7.0.0) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump drf-spectacular from 0.24.2 to 0.25.1 (#10428) Bumps [drf-spectacular](https://github.com/tfranzel/drf-spectacular) from 0.24.2 to 0.25.1. - [Release notes](https://github.com/tfranzel/drf-spectacular/releases) - [Changelog](https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst) - [Commits](https://github.com/tfranzel/drf-spectacular/compare/0.24.2...0.25.1) --- updated-dependencies: - dependency-name: drf-spectacular dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update numpy requirement from ==1.23.* to ==1.24.* (#10427) Updates the requirements on [numpy](https://github.com/numpy/numpy) to permit the latest version. - [Release notes](https://github.com/numpy/numpy/releases) - [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst) - [Commits](https://github.com/numpy/numpy/compare/v1.23.0rc1...v1.24.0) --- updated-dependencies: - dependency-name: numpy dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump dj-database-url from 1.0.0 to 1.2.0 (#10426) Bumps [dj-database-url](https://github.com/jazzband/dj-database-url) from 1.0.0 to 1.2.0. - [Release notes](https://github.com/jazzband/dj-database-url/releases) - [Changelog](https://github.com/jazzband/dj-database-url/blob/master/CHANGELOG.md) - [Commits](https://github.com/jazzband/dj-database-url/compare/v1.0.0...v1.2.0) --- updated-dependencies: - dependency-name: dj-database-url dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.28 to 1.26.32 (#10425) Bumps [boto3](https://github.com/boto/boto3) from 1.26.28 to 1.26.32. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.28...1.26.32) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump smart-open from 6.2.0 to 6.3.0 (#10424) Bumps [smart-open](https://github.com/piskvorky/smart_open) from 6.2.0 to 6.3.0. - [Release notes](https://github.com/piskvorky/smart_open/releases) - [Changelog](https://github.com/RaRe-Technologies/smart_open/blob/develop/CHANGELOG.md) - [Commits](https://github.com/piskvorky/smart_open/compare/v6.2.0...v6.3.0) --- updated-dependencies: - dependency-name: smart-open dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align setup.cfg to requirements.txt (#10444) * Bump GeoNode to version 4.1.0 dev (#10461) * Bump GeoNode to version 4.1.0 dev (cherry picked from commit e6dd1f3e92f070d578a4a9fe29881e0f87abda3b) # Conflicts: # geonode/__init__.py * Bump GeoNode to version 4.1.0 dev (cherry picked from commit e6dd1f3e92f070d578a4a9fe29881e0f87abda3b) # Conflicts: # geonode/__init__.py * [Fixes #10462] GeoNode is vulnerable to an XML External Entity (XXE) injection (#10463) * [Fixes #10464] Fix code scanning alert - Uncontrolled data used in path expression (#10465) * [Fixes #10462] GeoNode is vulnerable to an XML External Entity (XXE) injection * [Fixes #10464] Fix code scanning alert - Uncontrolled data used in path expression * fix: Dockerfile to reduce vulnerabilities (#10470) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-DEBIAN10-DPKG-2847944 - https://snyk.io/vuln/SNYK-DEBIAN10-OPENSSL-2807585 - https://snyk.io/vuln/SNYK-DEBIAN10-OPENSSL-2933515 - https://snyk.io/vuln/SNYK-DEBIAN10-PYTHON37-3090928 - https://snyk.io/vuln/SNYK-DEBIAN10-XZUTILS-2444279 Co-authored-by: snyk-bot * Create codeql.yml * Create pyre.yml * Create pysa.yml * [Fixes #10472] Fix code scanning alert - Polynomial regular expression used on uncontrolled data (#10473) * [Fixes #10472] Fix code scanning alert - Polynomial regular expression used on uncontrolled data * - Get rid of pyre and pysa workflows * Update mock requirement from <5.0.0 to <6.0.0 (#10480) Updates the requirements on [mock](https://github.com/testing-cabal/mock) to permit the latest version. - [Release notes](https://github.com/testing-cabal/mock/releases) - [Changelog](https://github.com/testing-cabal/mock/blob/master/CHANGELOG.rst) - [Commits](https://github.com/testing-cabal/mock/compare/release-0.5.0...5.0.0) --- updated-dependencies: - dependency-name: mock dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump django-storages from 1.13.1 to 1.13.2 (#10477) Bumps [django-storages](https://github.com/jschneier/django-storages) from 1.13.1 to 1.13.2. - [Release notes](https://github.com/jschneier/django-storages/releases) - [Changelog](https://github.com/jschneier/django-storages/blob/master/CHANGELOG.rst) - [Commits](https://github.com/jschneier/django-storages/compare/1.13.1...1.13.2) --- updated-dependencies: - dependency-name: django-storages dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump django-allauth from 0.51.0 to 0.52.0 (#10479) Bumps [django-allauth](https://github.com/pennersr/django-allauth) from 0.51.0 to 0.52.0. - [Release notes](https://github.com/pennersr/django-allauth/releases) - [Changelog](https://github.com/pennersr/django-allauth/blob/master/ChangeLog.rst) - [Commits](https://github.com/pennersr/django-allauth/compare/0.51.0...0.52.0) --- updated-dependencies: - dependency-name: django-allauth dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump whitenoise from 6.2.0 to 6.3.0 (#10496) Bumps [whitenoise](https://github.com/evansd/whitenoise) from 6.2.0 to 6.3.0. - [Release notes](https://github.com/evansd/whitenoise/releases) - [Changelog](https://github.com/evansd/whitenoise/blob/main/docs/changelog.rst) - [Commits](https://github.com/evansd/whitenoise/compare/6.2.0...6.3.0) --- updated-dependencies: - dependency-name: whitenoise dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pyopenssl from 22.1.0 to 23.0.0 (#10489) Bumps [pyopenssl](https://github.com/pyca/pyopenssl) from 22.1.0 to 23.0.0. - [Release notes](https://github.com/pyca/pyopenssl/releases) - [Changelog](https://github.com/pyca/pyopenssl/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/pyopenssl/compare/22.1.0...23.0.0) --- updated-dependencies: - dependency-name: pyopenssl dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pillow from 9.3.0 to 9.4.0 (#10495) Bumps [pillow](https://github.com/python-pillow/Pillow) from 9.3.0 to 9.4.0. - [Release notes](https://github.com/python-pillow/Pillow/releases) - [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) - [Commits](https://github.com/python-pillow/Pillow/compare/9.3.0...9.4.0) --- updated-dependencies: - dependency-name: pillow dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump sqlalchemy from 1.4.45 to 1.4.46 (#10490) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.45 to 1.4.46. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump ipython from 8.7.0 to 8.8.0 (#10491) Bumps [ipython](https://github.com/ipython/ipython) from 8.7.0 to 8.8.0. - [Release notes](https://github.com/ipython/ipython/releases) - [Commits](https://github.com/ipython/ipython/compare/8.7.0...8.8.0) --- updated-dependencies: - dependency-name: ipython dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump django-treebeard from 4.5.1 to 4.6.0 (#10492) Bumps [django-treebeard](https://github.com/django-treebeard/django-treebeard) from 4.5.1 to 4.6.0. - [Release notes](https://github.com/django-treebeard/django-treebeard/releases) - [Changelog](https://github.com/django-treebeard/django-treebeard/blob/master/CHANGES.md) - [Commits](https://github.com/django-treebeard/django-treebeard/compare/4.5.1...4.6.0) --- updated-dependencies: - dependency-name: django-treebeard dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump coverage from 7.0.0 to 7.0.4 (#10493) Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.0.0 to 7.0.4. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.0.0...7.0.4) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.32 to 1.26.45 (#10494) Bumps [boto3](https://github.com/boto/boto3) from 1.26.32 to 1.26.45. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.32...1.26.45) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align "setup.cfg" to "requirements.txt" (#10507) * Update backport.yml * [Fixes #10509] Configure UTF-8 encoding for shapefiles in Geoserver by default (#10510) * [CLA] add 52North staff to .clabot (#10512) * fix: scripts/docker/nginx/Dockerfile to reduce vulnerabilities (#10513) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-ALPINE316-CURL-3179541 - https://snyk.io/vuln/SNYK-ALPINE316-CURL-3179541 - https://snyk.io/vuln/SNYK-ALPINE316-CURL-3179542 - https://snyk.io/vuln/SNYK-ALPINE316-CURL-3179542 * Update README.md * [Fixes #7181] fix ISO 19139 metadata validity (#10488) * Adding "ahmdthr" to .clabot * Bump requests from 2.28.1 to 2.28.2 (#10528) Bumps [requests](https://github.com/psf/requests) from 2.28.1 to 2.28.2. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.28.1...v2.28.2) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update setuptools requirement from <65.7.0,>=59.1.1 to >=59.1.1,<66.1.0 (#10542) Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v65.5.1...v66.0.0) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump urllib3 from 1.26.13 to 1.26.14 (#10531) Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.13 to 1.26.14. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.26.13...1.26.14) --- updated-dependencies: - dependency-name: urllib3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump selenium-requests from 2.0.2 to 2.0.3 (#10536) Bumps [selenium-requests]() from 2.0.2 to 2.0.3. --- updated-dependencies: - dependency-name: selenium-requests dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Fixes #10524] Resource permissions are not returned in the users/groups endpoint (#10544) * [Fixes #10524] Resource permissions are not returned in the users/groups endpoint * [Fixes #10524] Resource permissions are not returned in the users/groups endpoint * [Fixes #10482] Upload ISO-19115 xml metadata via the API (#10483) * ISO-19115 xml metadata file can be uploaded via the API * Small changes for PEP8 compliance * Added tests for checking permissions for metadata upload Co-authored-by: Alessio Fabiani * [Fixes #10525] set/unset batch permissions on groups raise an error (#10526) * [Fixes #10525] set/unset batch permissions on groups raise an error * [Fixes #10525] set/unset batch permissions on groups raise an error * Bump pytz from 2022.7 to 2022.7.1 (#10533) Bumps [pytz](https://github.com/stub42/pytz) from 2022.7 to 2022.7.1. - [Release notes](https://github.com/stub42/pytz/releases) - [Commits](https://github.com/stub42/pytz/compare/release_2022.7...release_2022.7.1) --- updated-dependencies: - dependency-name: pytz dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump wandb from 0.13.7 to 0.13.9 (#10530) Bumps [wandb](https://github.com/wandb/wandb) from 0.13.7 to 0.13.9. - [Release notes](https://github.com/wandb/wandb/releases) - [Changelog](https://github.com/wandb/wandb/blob/main/CHANGELOG.md) - [Commits](https://github.com/wandb/wandb/compare/v0.13.7...v0.13.9) --- updated-dependencies: - dependency-name: wandb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump coverage from 7.0.4 to 7.0.5 (#10529) Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.0.4 to 7.0.5. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.0.4...7.0.5) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pytest from 7.2.0 to 7.2.1 (#10534) Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.2.0 to 7.2.1. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/7.2.0...7.2.1) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.45 to 1.26.50 (#10535) Bumps [boto3](https://github.com/boto/boto3) from 1.26.45 to 1.26.50. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.45...1.26.50) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align "setup.cfg" to "requirements.txt" (#10555) * [Fixes #10537] Improve rules creation using GeoFence batch (#10538) * [Fixes #10537] Improve rules creation using GeoFence batch * - code improvements accordingly to the PR comments * - code improvements accordingly to the PR comments * - Test fixes Co-authored-by: afabiani * Update setuptools requirement from <66.1.0,>=59.1.1 to >=59.1.1,<66.2.0 (#10563) Updates the requirements on [setuptools](https://github.com/pypa/setuptools) to permit the latest version. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v65.5.1...v66.1.1) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump invoke from 1.7.3 to 2.0.0 (#10565) Bumps [invoke](https://github.com/pyinvoke/invoke) from 1.7.3 to 2.0.0. - [Release notes](https://github.com/pyinvoke/invoke/releases) - [Commits](https://github.com/pyinvoke/invoke/compare/1.7.3...2.0.0) --- updated-dependencies: - dependency-name: invoke dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump splinter from 0.18.1 to 0.19.0 (#10564) Bumps [splinter](https://github.com/cobrateam/splinter) from 0.18.1 to 0.19.0. - [Release notes](https://github.com/cobrateam/splinter/releases) - [Changelog](https://github.com/cobrateam/splinter/blob/master/docs/news.rst) - [Commits](https://github.com/cobrateam/splinter/compare/0.18.1...0.19.0) --- updated-dependencies: - dependency-name: splinter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump boto3 from 1.26.50 to 1.26.54 (#10566) Bumps [boto3](https://github.com/boto/boto3) from 1.26.50 to 1.26.54. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.26.50...1.26.54) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Dependencies] Align "setup.cfg" to "requirements.txt" (#10572) * [Fixes #10574] Code formatting with Black (#10575) * auto reformatting by black * relax flake8 * Add black to requirements * Add black to CircleCI * [Fixes #10574] Code formatting with Black (#10575) * auto reformatting by black * relax flake8 * Add black to requirements * Add black to CircleCI (cherry picked from commit e0b7ec94ebb97b0f3eb4fbe5cf82c71f11d0a8d3) # Conflicts: # geonode/base/api/serializers.py # geonode/catalogue/tests.py # geonode/catalogue/urls.py # geonode/catalogue/views.py # geonode/geoserver/manager.py # geonode/geoserver/signals.py * - Upgrade GeoServer to version 2.20.6 Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Emanuele Tajariol Co-authored-by: Giovanni Allegri Co-authored-by: NAGGINDA MARTHA Co-authored-by: Edson Flavio de Souza <44442399+edsonflavio@users.noreply.github.com> Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Co-authored-by: Snyk bot Co-authored-by: mattiagiupponi Co-authored-by: Florian Hoedt Co-authored-by: Francesco Frassinelli Co-authored-by: Malte Iwanicki <45853662+MalteIwanicki@users.noreply.github.com> Co-authored-by: Toni Co-authored-by: Christian Autermann Co-authored-by: matthesrieke Co-authored-by: ahmdthr <116570171+ahmdthr@users.noreply.github.com> --- geonode/base/forms.py | 2 +- geonode/base/views.py | 11 ++++++----- geonode/geoserver/signals.py | 2 +- geonode/security/tests.py | 8 +++++--- geonode/storage/tests.py | 4 ++-- geonode/upload/__init__.py | 13 +++++++------ 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/geonode/base/forms.py b/geonode/base/forms.py index bfceef992f9..f545c6b0323 100644 --- a/geonode/base/forms.py +++ b/geonode/base/forms.py @@ -579,7 +579,7 @@ def __init__(self, *args, **kwargs): if field in ["owner"] and not self.can_change_perms: self.fields[field].disabled = True - if field in ['poc', 'owner'] and not self.can_change_perms: + if field in ["poc", "owner"] and not self.can_change_perms: self.fields[field].disabled = True def disable_keywords_widget_for_non_superuser(self, user): diff --git a/geonode/base/views.py b/geonode/base/views.py index 86a8c1b58a4..2d13abe8ae0 100644 --- a/geonode/base/views.py +++ b/geonode/base/views.py @@ -357,15 +357,16 @@ def get_results(self, context): class DatasetsAutocomplete(SimpleSelect2View): model = Dataset - filter_arg = 'title__icontains' + filter_arg = "title__icontains" def get_results(self, context): return [ { - 'id': self.get_result_value(result), - 'text': self.get_result_label(result.title), - 'selected_text': self.get_selected_result_label(result.title), - } for result in context['object_list'] + "id": self.get_result_value(result), + "text": self.get_result_label(result.title), + "selected_text": self.get_selected_result_label(result.title), + } + for result in context["object_list"] ] diff --git a/geonode/geoserver/signals.py b/geonode/geoserver/signals.py index 591a1e12552..cfe1ad6f85b 100644 --- a/geonode/geoserver/signals.py +++ b/geonode/geoserver/signals.py @@ -42,7 +42,7 @@ geofence_rule_assign = Signal(providing_args=["instance"]) -post_set_permissions = Signal(providing_args=['instance']) +geofence_rule_assign = Signal(providing_args=["instance"]) def geoserver_delete(typename): diff --git a/geonode/security/tests.py b/geonode/security/tests.py index b04dba3b2ae..25f0613d2f3 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -90,11 +90,13 @@ def _log(msg, *args): def get_geofence_rules_count(): from geonode.geoserver.helpers import gf_client + return gf_client.get_rules_count() def get_geofence_rules(): from geonode.geoserver.helpers import gf_client + return gf_client.get_rules() @@ -1758,11 +1760,11 @@ def test_admin_whitelisted_access_middleware(self): self.assertTrue(request.user.is_superuser) # Test valid IP in second element - with self.settings(ADMIN_IP_WHITELIST=['88.88.88.88', '127.0.0.1']): + with self.settings(ADMIN_IP_WHITELIST=["88.88.88.88", "127.0.0.1"]): request = HttpRequest() request.user = admin - request.path = reverse('home') - request.META['REMOTE_ADDR'] = '127.0.0.1' + request.path = reverse("home") + request.META["REMOTE_ADDR"] = "127.0.0.1" middleware.process_request(request) self.assertTrue(request.user.is_superuser) diff --git a/geonode/storage/tests.py b/geonode/storage/tests.py index dedef558e0c..a44d9a460ee 100644 --- a/geonode/storage/tests.py +++ b/geonode/storage/tests.py @@ -420,9 +420,9 @@ def test_storage_manager_copy(self): @override_settings(FILE_UPLOAD_DIRECTORY_PERMISSIONS=0o777) @override_settings(FILE_UPLOAD_PERMISSIONS=0o777) def test_storage_manager_copy(self): - ''' + """ Test that the copy works as expected and the permissions are corerct - ''' + """ dataset = create_single_dataset(name="test_copy") dataset.files = [os.path.join(f"{self.project_root}", "tests/data/test_sld.sld")] dataset.save() diff --git a/geonode/upload/__init__.py b/geonode/upload/__init__.py index f8afdf61568..8be4d76cb36 100644 --- a/geonode/upload/__init__.py +++ b/geonode/upload/__init__.py @@ -52,14 +52,15 @@ def run_setup_hooks(sender, **kwargs): every=1, period="days" ) + daily_interval, _ = IntervalSchedule.objects.get_or_create(every=1, period="days") PeriodicTask.objects.update_or_create( name="clean-up-old-task-result", defaults=dict( task="geonode.upload.tasks.cleanup_celery_task_entries", interval=daily_interval, - args='', - start_time=timezone.now() - ) + args="", + start_time=timezone.now(), + ), ) @@ -73,9 +74,9 @@ def ready(self): "task": "geonode.upload.tasks.cleanup_celery_task_entries", "schedule": 86400.0, } - settings.CELERY_BEAT_SCHEDULE['clean-up-old-task-result'] = { - 'task': 'geonode.upload.tasks.cleanup_celery_task_entries', - 'schedule': 86400.0, + settings.CELERY_BEAT_SCHEDULE["clean-up-old-task-result"] = { + "task": "geonode.upload.tasks.cleanup_celery_task_entries", + "schedule": 86400.0, } From c283f5dc5eb7492f93e54af2a7337b6d2e3e8278 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 26 Jan 2023 17:11:04 +0100 Subject: [PATCH 155/253] =?UTF-8?q?[Fixes=20#10537]=20Improve=20rules=20cr?= =?UTF-8?q?eation=20using=20GeoFence=20batch=20-=20more=20imp=E2=80=A6=20(?= =?UTF-8?q?#10585)=20(#10588)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Code Formatting] Revert formatting on conflicting files * [Fixes #10537] Improve rules creation using GeoFence batch - more improvements * [#10574] Align code formatting with black Co-authored-by: afabiani (cherry picked from commit 36f414d02a054ecd328e3d16358992b0a503cc36) Co-authored-by: Emanuele Tajariol --- geonode/geoserver/helpers.py | 16 +++++++++++++++- geonode/geoserver/manager.py | 1 + geonode/security/tests.py | 12 ------------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index 193b2df05ed..a968dd6136b 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -1874,7 +1874,21 @@ def get_time_info(layer): url, _user, _password, retries=ogc_server_settings.MAX_RETRIES, backoff_factor=ogc_server_settings.BACKOFF_FACTOR ) gs_uploader = Client(url, _user, _password) -gf_client = GeofenceClient(url, _user, _password) + + +def create_geofence_client(): + gs_url = settings.OGC_SERVER["default"]["LOCATION"] + user = settings.OGC_SERVER["default"]["USER"] + passwd = settings.OGC_SERVER["default"]["PASSWORD"] + + gf_rest_url = f'{gs_url.rstrip("/")}/rest/geofence/' + client = GeoFenceClient(gf_rest_url, user, passwd) + client.set_timeout(settings.OGC_SERVER["default"].get("GEOFENCE_TIMEOUT", 60)) + return client + + +geofence = create_geofence_client() +gf_utils = GeoFenceUtils(geofence) def _create_geofence_client(): diff --git a/geonode/geoserver/manager.py b/geonode/geoserver/manager.py index a88b641b71f..01903befc9a 100644 --- a/geonode/geoserver/manager.py +++ b/geonode/geoserver/manager.py @@ -442,6 +442,7 @@ def set_permissions( approval_status_changed: bool = False, group_status_changed: bool = False, ) -> bool: + _resource = instance or ResourceManager._get_instance(uuid) try: diff --git a/geonode/security/tests.py b/geonode/security/tests.py index 25f0613d2f3..861b6a7a9a4 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -88,18 +88,6 @@ def _log(msg, *args): logger.debug(msg, *args) -def get_geofence_rules_count(): - from geonode.geoserver.helpers import gf_client - - return gf_client.get_rules_count() - - -def get_geofence_rules(): - from geonode.geoserver.helpers import gf_client - - return gf_client.get_rules() - - class StreamToLogger: """ Fake file-like stream object that redirects writes to a logger instance. From e0b15526d9b4a7192989bc67db27d0b64247eba5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 27 Jan 2023 09:27:32 +0100 Subject: [PATCH 156/253] [Code Format] Minor refactoring of geofence create options (#10589) (#10596) * [Code Format] Minor refactoring of geofence create options * - fix test cases (cherry picked from commit 118b8e7c40fcfc55bdd01f669fecb14ef6974918) Co-authored-by: Alessio Fabiani --- geonode/geoserver/helpers.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index a968dd6136b..2bd6f3030c7 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -1876,18 +1876,14 @@ def get_time_info(layer): gs_uploader = Client(url, _user, _password) -def create_geofence_client(): - gs_url = settings.OGC_SERVER["default"]["LOCATION"] - user = settings.OGC_SERVER["default"]["USER"] - passwd = settings.OGC_SERVER["default"]["PASSWORD"] - - gf_rest_url = f'{gs_url.rstrip("/")}/rest/geofence/' - client = GeoFenceClient(gf_rest_url, user, passwd) - client.set_timeout(settings.OGC_SERVER["default"].get("GEOFENCE_TIMEOUT", 60)) +def _create_geofence_client(): + gf_rest_url = f'{url.rstrip("/")}/geofence/' + client = GeoFenceClient(gf_rest_url, _user, _password) + client.set_timeout(ogc_server_settings.GEOFENCE_TIMEOUT) return client -geofence = create_geofence_client() +geofence = _create_geofence_client() gf_utils = GeoFenceUtils(geofence) From 9ae6030defd3375e51620d33becd731c7b13177e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 09:27:26 +0100 Subject: [PATCH 157/253] [Dependencies] Align "setup.cfg" to "requirements.txt" (#10623) (#10624) (cherry picked from commit cb8d2aac6dae90ab61a266d902b5b1a38f957431) Co-authored-by: Alessio Fabiani --- setup.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup.cfg b/setup.cfg index 5f5f08158f3..cac1e264a07 100644 --- a/setup.cfg +++ b/setup.cfg @@ -209,6 +209,8 @@ install_requires = wandb==0.13.9 protobuf==3.20.3 mako==1.2.4 + certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability + jwcrypto>=1.4 # not directly required, pinned by Snyk to avoid a vulnerability [options.packages.find] exclude = tests From dfe6596b432ea711632afe6ab6e3aaae231c8458 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 18:34:23 +0100 Subject: [PATCH 158/253] [Dependencies] Align "setup.cfg" to "requirements.txt" (#10642) (#10643) * [Dependencies] Align "setup.cfg" to "requirements.txt" * - Fix black formatting (cherry picked from commit b73cc24226568d010bffb862edef6706ff1c98c5) Co-authored-by: Alessio Fabiani --- geonode/geoserver/manager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/geonode/geoserver/manager.py b/geonode/geoserver/manager.py index 01903befc9a..a88b641b71f 100644 --- a/geonode/geoserver/manager.py +++ b/geonode/geoserver/manager.py @@ -442,7 +442,6 @@ def set_permissions( approval_status_changed: bool = False, group_status_changed: bool = False, ) -> bool: - _resource = instance or ResourceManager._get_instance(uuid) try: From 0ae1d82e91305afd512ea9902e5c0a03e4ee708b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 17:26:02 +0100 Subject: [PATCH 159/253] [Fixes #10521] Make metadata wizard more flexible for custom metadata (#10592) (#10653) * [Fixes: 10521] Make metadata wizard more flexible for custom metadata * add tests for extrametadata query; pep8 format imports * fix map test for metadata response (cherry picked from commit 5ccc0d6a225115ef05c8121cbed6616888f2134c) Co-authored-by: Toni --- geonode/documents/api/tests.py | 1 - geonode/layers/api/serializers.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/documents/api/tests.py b/geonode/documents/api/tests.py index daa8fff413e..32aac59ed91 100644 --- a/geonode/documents/api/tests.py +++ b/geonode/documents/api/tests.py @@ -17,7 +17,6 @@ # ######################################################################### import os -from django.contrib.auth import get_user_model import logging from django.contrib.auth import get_user_model diff --git a/geonode/layers/api/serializers.py b/geonode/layers/api/serializers.py index 304e89467c5..b1506fc79f5 100644 --- a/geonode/layers/api/serializers.py +++ b/geonode/layers/api/serializers.py @@ -181,6 +181,7 @@ class Meta: "subtype", "ptype", "executions", + "metadata", ) name = serializers.CharField(read_only=True) From 4a2d5102e2123a5f6ffb868d6e5c61c09c111738 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 16:57:52 +0100 Subject: [PATCH 160/253] [Dependencies] align "setup.cfg" to "requirements.txt" (#10665) (#10666) (cherry picked from commit 0e89afe806f359a1a0b700c233f292999249af5f) Co-authored-by: Alessio Fabiani --- setup.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index cac1e264a07..d859ea59b85 100644 --- a/setup.cfg +++ b/setup.cfg @@ -205,8 +205,8 @@ install_requires = nh3==0.2.15 # Security and audit - mistune==2.0.4 - wandb==0.13.9 + mistune==2.0.5 + wandb==0.13.10 protobuf==3.20.3 mako==1.2.4 certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability From 1952d3fda17fb851b235bf17f5ab65f999619a81 Mon Sep 17 00:00:00 2001 From: Alessio Fabiani Date: Fri, 17 Mar 2023 11:42:24 +0100 Subject: [PATCH 161/253] [Dependencies] Align setup.cfg to requirements.txt (#10788) (#10789) (cherry picked from commit e7620effb065ca8b4bf9a0e4969adfd454ed36b3) # Conflicts: # setup.cfg --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index d859ea59b85..dc5199bcc79 100644 --- a/setup.cfg +++ b/setup.cfg @@ -206,7 +206,7 @@ install_requires = # Security and audit mistune==2.0.5 - wandb==0.13.10 + wandb==0.13.11 protobuf==3.20.3 mako==1.2.4 certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability From 4d9c1f67106080cd8ca944ca7df06f1d70808d35 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 18 Apr 2023 19:43:45 +0200 Subject: [PATCH 162/253] Sorts files during unzip Ensures that related content are unpacked accordingly in a mixed content case --- geonode/storage/tests.py | 27 ++++++++++++++++++ .../storage/tests/data/data_collection.zip | Bin 0 -> 14261 bytes 2 files changed, 27 insertions(+) create mode 100644 geonode/storage/tests/data/data_collection.zip diff --git a/geonode/storage/tests.py b/geonode/storage/tests.py index a44d9a460ee..094b519647d 100644 --- a/geonode/storage/tests.py +++ b/geonode/storage/tests.py @@ -639,3 +639,30 @@ def test_zip_file_should_correctly_recognize_main_extension_with_shp(self): self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) _files = storage_manager.get_retrieved_paths() self.assertTrue("single_point.shp" in _files.get("base_file")) + + def test_zip_file_should_correctly_relate_mixed_content(self): + zip_file = os.path.join(f"{self.project_root}", "tests/data/data_collection.zip") + storage_manager = self.sut( + remote_files={"base_file": zip_file} + ) + storage_manager.clone_remote_files() + self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) + _files = storage_manager.get_retrieved_paths() + base_file = _files.get("base_file") + + def strip_extension(filename): + return filename.split(".")[0] if filename else filename + + base_name = strip_extension(base_file) + available_files = [ + _files.get("shp_file"), + _files.get("prj_file"), + _files.get("shx_file"), + _files.get("dbf_file") + ] + + def assert_same_base_name(base_name, file_name): + self.assertEqual(base_name, strip_extension(file_name)) + + for file in available_files: + assert_same_base_name(base_name, file) diff --git a/geonode/storage/tests/data/data_collection.zip b/geonode/storage/tests/data/data_collection.zip new file mode 100644 index 0000000000000000000000000000000000000000..0702327be361a2bfda7c9c2a6eb13bd08ca5a9b4 GIT binary patch literal 14261 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 Cq!$1H literal 0 HcmV?d00001 From 54723550e1ee1cbeb59cb9d58c438d7f9e4c1345 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Thu, 11 May 2023 15:21:56 +0200 Subject: [PATCH 163/253] fix: requirements.txt to reduce vulnerabilities (#11029) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-DJANGO-5496950 Co-authored-by: Alessio Fabiani From 6bd24b0ad08cd7fde585e679a5e78cea6df1b5ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 15:40:26 +0200 Subject: [PATCH 164/253] Bump django-autocomplete-light from 3.5.1 to 3.9.7 (#11056) * Bump django-autocomplete-light from 3.5.1 to 3.9.7 Bumps [django-autocomplete-light](https://github.com/yourlabs/django-autocomplete-light) from 3.5.1 to 3.9.7. - [Release notes](https://github.com/yourlabs/django-autocomplete-light/releases) - [Changelog](https://github.com/yourlabs/django-autocomplete-light/blob/master/CHANGELOG) - [Commits](https://github.com/yourlabs/django-autocomplete-light/compare/3.5.1...3.9.7) --- updated-dependencies: - dependency-name: django-autocomplete-light dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * [Dependencies] Align setup.cfg to requirements.txt (#11048) --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 70f7db16c82..205a0178053 100644 --- a/requirements.txt +++ b/requirements.txt @@ -70,7 +70,7 @@ dj-pagination==2.5.0 django-select2==8.1.2 django-floppyforms<1.10.0 django-forms-bootstrap<=3.1.0 -django-autocomplete-light==3.5.1 +django-autocomplete-light==3.9.7 django-invitations<2.0.1 django-recaptcha==3.0.0 diff --git a/setup.cfg b/setup.cfg index dc5199bcc79..9883259771b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -96,7 +96,7 @@ install_requires = django-select2==8.1.2 django-floppyforms<1.10.0 django-forms-bootstrap<=3.1.0 - django-autocomplete-light==3.5.1 + django-autocomplete-light==3.9.7 django-invitations<2.0.1 django-recaptcha==3.0.0 From c8fc0147b43cf7ff1fac6e429e109f8298ecf0bd Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Tue, 16 May 2023 13:02:24 +0200 Subject: [PATCH 165/253] revert django-autocomplete-light upgrade (#11073) --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 205a0178053..70f7db16c82 100644 --- a/requirements.txt +++ b/requirements.txt @@ -70,7 +70,7 @@ dj-pagination==2.5.0 django-select2==8.1.2 django-floppyforms<1.10.0 django-forms-bootstrap<=3.1.0 -django-autocomplete-light==3.9.7 +django-autocomplete-light==3.5.1 django-invitations<2.0.1 django-recaptcha==3.0.0 diff --git a/setup.cfg b/setup.cfg index 9883259771b..dc5199bcc79 100644 --- a/setup.cfg +++ b/setup.cfg @@ -96,7 +96,7 @@ install_requires = django-select2==8.1.2 django-floppyforms<1.10.0 django-forms-bootstrap<=3.1.0 - django-autocomplete-light==3.9.7 + django-autocomplete-light==3.5.1 django-invitations<2.0.1 django-recaptcha==3.0.0 From 2aa029b08feec610bc7d8105e7643456488ce713 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 17:07:05 +0200 Subject: [PATCH 166/253] Remove doc_file and file_path from document serializer (#11117) (#11119) (cherry picked from commit 927a302bb4494a3d7dce5c829d7c6a646247704c) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/documents/api/tests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/geonode/documents/api/tests.py b/geonode/documents/api/tests.py index 32aac59ed91..3f6b4d6bf2e 100644 --- a/geonode/documents/api/tests.py +++ b/geonode/documents/api/tests.py @@ -16,7 +16,6 @@ # along with this program. If not, see . # ######################################################################### -import os import logging from django.contrib.auth import get_user_model From 3979607df910a61a2bcf1d49ac4b3bdfa86c2665 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 11 Sep 2023 14:53:45 +0200 Subject: [PATCH 167/253] Add github workflow files --- .github/workflows/build-and-push.yaml | 62 +++++++++++++++++++++++++ .github/workflows/release.yaml | 66 +++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 .github/workflows/build-and-push.yaml create mode 100644 .github/workflows/release.yaml diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/build-and-push.yaml new file mode 100644 index 00000000000..1ca4e975540 --- /dev/null +++ b/.github/workflows/build-and-push.yaml @@ -0,0 +1,62 @@ +name: Release GeoNode Docker Images + +env: + TITLE: "52°North GeoNode Docker Image" + VENDOR: "52°North GmbH" + AUTHORS: "https://52North.org/" + DESCRIPTION: "Builds and publishes the GeoNode Docker development image for Thuenen" + LICENSE: "GPL-3.0" + +on: + push: + branches: + - "thuenen-dev" + +jobs: + build_and_push_geonode: + runs-on: ubuntu-22.04 + env: + IMAGE: 52north/geonode_thuenen + DEVELOPMENT_VERSION: "4.x" + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.IMAGE }} + labels: | + "org.opencontainers.image.authors=${{ env.AUTHORS }}" + "org.opencontainers.image.vendor=${{ env.VENDOR }}" + "org.opencontainers.image.description=${{ env.DESCRIPTION }}" + "org.opencontainers.image.title=${{ env.TITLE }}" + "org.opencontainers.image.licenses=${{ env.LICENSE }}" + tags: | + latest + ${{ env.DEVELOPMENT_VERSION }} + - + name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Build and push + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache + cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000000..0aeac429729 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,66 @@ +name: Release GeoNode Docker Images + +env: + TITLE: "52°North GeoNode Docker Image" + VENDOR: "52°North GmbH" + AUTHORS: "https://52North.org/" + DESCRIPTION: "Builds and publishes the GeoNode Docker image for Thuenen" + LICENSE: "GPL-3.0" + +on: + push: + tags: + - "v*" + +jobs: + build_and_push_geonode: + runs-on: ubuntu-22.04 + env: + IMAGE: 52north/geonode_thuenen + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Parse semver string + id: semver_parser + uses: booxmedialtd/ws-action-parse-semver@v1 + with: + input_string: "${{github.ref_name}}" + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.IMAGE }} + labels: | + "org.opencontainers.image.authors=${{ env.AUTHORS }}" + "org.opencontainers.image.vendor=${{ env.VENDOR }}" + "org.opencontainers.image.description=${{ env.DESCRIPTION }}" + "org.opencontainers.image.title=${{ env.TITLE }}" + "org.opencontainers.image.licenses=${{ env.LICENSE }}" + tags: | + latest + ${{ steps.semver_parser.outputs.major }} + ${{ steps.semver_parser.outputs.minor }} + ${{ steps.semver_parser.outputs.patch }} + - + name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Build and push + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache + cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max From 4b61e7241bc0461dc17565d58984e52e929e0f4d Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 11 Sep 2023 15:00:26 +0200 Subject: [PATCH 168/253] Update branch to build --- .github/workflows/build-and-push.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/build-and-push.yaml index 1ca4e975540..49797d7ac29 100644 --- a/.github/workflows/build-and-push.yaml +++ b/.github/workflows/build-and-push.yaml @@ -10,7 +10,7 @@ env: on: push: branches: - - "thuenen-dev" + - "thuenen_4.x" jobs: build_and_push_geonode: From 3827df14c069b625ae03282b7cb04b2aba39b2e7 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 11 Sep 2023 15:04:51 +0200 Subject: [PATCH 169/253] Cancels running builds on new push --- .github/workflows/build-and-push.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/build-and-push.yaml index 49797d7ac29..d2283a14dfb 100644 --- a/.github/workflows/build-and-push.yaml +++ b/.github/workflows/build-and-push.yaml @@ -1,4 +1,8 @@ -name: Release GeoNode Docker Images +name: Push GeoNode Docker Images + +concurrency: + group: "geonode_build" + cancel-in-progress: true env: TITLE: "52°North GeoNode Docker Image" From 900051096d85f7e4a5287e0aaa043792f4c63538 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 11 Sep 2023 15:18:23 +0200 Subject: [PATCH 170/253] Push to 52north/geonode and use different versions --- .github/workflows/build-and-push.yaml | 5 ++--- .github/workflows/release.yaml | 11 +++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/build-and-push.yaml index d2283a14dfb..ca75363ac92 100644 --- a/.github/workflows/build-and-push.yaml +++ b/.github/workflows/build-and-push.yaml @@ -20,7 +20,7 @@ jobs: build_and_push_geonode: runs-on: ubuntu-22.04 env: - IMAGE: 52north/geonode_thuenen + IMAGE: 52north/geonode DEVELOPMENT_VERSION: "4.x" steps: - @@ -45,8 +45,7 @@ jobs: "org.opencontainers.image.title=${{ env.TITLE }}" "org.opencontainers.image.licenses=${{ env.LICENSE }}" tags: | - latest - ${{ env.DEVELOPMENT_VERSION }} + ${{ env.DEVELOPMENT_VERSION }}-thuenen - name: Login to Docker Hub uses: docker/login-action@v2 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0aeac429729..18bb9817a11 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -10,13 +10,13 @@ env: on: push: tags: - - "v*" + - "v*-thuenen" jobs: build_and_push_geonode: runs-on: ubuntu-22.04 env: - IMAGE: 52north/geonode_thuenen + IMAGE: 52north/geonode steps: - name: Checkout @@ -43,10 +43,9 @@ jobs: "org.opencontainers.image.title=${{ env.TITLE }}" "org.opencontainers.image.licenses=${{ env.LICENSE }}" tags: | - latest - ${{ steps.semver_parser.outputs.major }} - ${{ steps.semver_parser.outputs.minor }} - ${{ steps.semver_parser.outputs.patch }} + ${{ steps.semver_parser.outputs.major }}-thuenen + ${{ steps.semver_parser.outputs.minor }}-thuenen + ${{ steps.semver_parser.outputs.patch }}-thuenen - name: Login to Docker Hub uses: docker/login-action@v2 From ee7ef2ba6acaf5989f95d83ef8101a947ffe3df5 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 11 Sep 2023 15:33:12 +0200 Subject: [PATCH 171/253] Use dedicated image repository --- .github/workflows/build-and-push.yaml | 9 +++------ .github/workflows/release.yaml | 8 ++++---- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/build-and-push.yaml index ca75363ac92..2785d012047 100644 --- a/.github/workflows/build-and-push.yaml +++ b/.github/workflows/build-and-push.yaml @@ -20,15 +20,12 @@ jobs: build_and_push_geonode: runs-on: ubuntu-22.04 env: - IMAGE: 52north/geonode + IMAGE: 52north/geonode_thuenen DEVELOPMENT_VERSION: "4.x" steps: - name: Checkout uses: actions/checkout@v3 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 @@ -45,7 +42,7 @@ jobs: "org.opencontainers.image.title=${{ env.TITLE }}" "org.opencontainers.image.licenses=${{ env.LICENSE }}" tags: | - ${{ env.DEVELOPMENT_VERSION }}-thuenen + ${{ env.DEVELOPMENT_VERSION }} - name: Login to Docker Hub uses: docker/login-action@v2 @@ -58,7 +55,7 @@ jobs: with: context: . file: ./Dockerfile - push: true + push: false tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 18bb9817a11..ec4e54cdf9e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -16,7 +16,7 @@ jobs: build_and_push_geonode: runs-on: ubuntu-22.04 env: - IMAGE: 52north/geonode + IMAGE: 52north/geonode_thuenen steps: - name: Checkout @@ -43,9 +43,9 @@ jobs: "org.opencontainers.image.title=${{ env.TITLE }}" "org.opencontainers.image.licenses=${{ env.LICENSE }}" tags: | - ${{ steps.semver_parser.outputs.major }}-thuenen - ${{ steps.semver_parser.outputs.minor }}-thuenen - ${{ steps.semver_parser.outputs.patch }}-thuenen + ${{ steps.semver_parser.outputs.major }} + ${{ steps.semver_parser.outputs.minor }} + ${{ steps.semver_parser.outputs.patch }} - name: Login to Docker Hub uses: docker/login-action@v2 From aacbd08d1eeb43d596387f9586590568cf6a1ffd Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 11 Sep 2023 16:37:25 +0200 Subject: [PATCH 172/253] push to registry after build --- .github/workflows/build-and-push.yaml | 2 +- .github/workflows/release.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/build-and-push.yaml index 2785d012047..0cfb52d4174 100644 --- a/.github/workflows/build-and-push.yaml +++ b/.github/workflows/build-and-push.yaml @@ -55,7 +55,7 @@ jobs: with: context: . file: ./Dockerfile - push: false + push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ec4e54cdf9e..bce7da86980 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -44,8 +44,8 @@ jobs: "org.opencontainers.image.licenses=${{ env.LICENSE }}" tags: | ${{ steps.semver_parser.outputs.major }} - ${{ steps.semver_parser.outputs.minor }} - ${{ steps.semver_parser.outputs.patch }} + ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }} + ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }}-${{ steps.semver_parser.outputs.patch }} - name: Login to Docker Hub uses: docker/login-action@v2 From 1d06b04f66bc8a8788264caca1c759bae47f024c Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Wed, 13 Sep 2023 11:16:49 +0200 Subject: [PATCH 173/253] Adjust tag management on built images --- .../{build-and-push.yaml => 52n-build.yaml} | 4 ++-- .../workflows/{release.yaml => 52n-release.yaml} | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) rename .github/workflows/{build-and-push.yaml => 52n-build.yaml} (93%) rename .github/workflows/{release.yaml => 52n-release.yaml} (72%) diff --git a/.github/workflows/build-and-push.yaml b/.github/workflows/52n-build.yaml similarity index 93% rename from .github/workflows/build-and-push.yaml rename to .github/workflows/52n-build.yaml index 0cfb52d4174..df1a12d6259 100644 --- a/.github/workflows/build-and-push.yaml +++ b/.github/workflows/52n-build.yaml @@ -1,4 +1,4 @@ -name: Push GeoNode Docker Images +name: Push Thünen Atlas Docker Image(s) concurrency: group: "geonode_build" @@ -8,7 +8,7 @@ env: TITLE: "52°North GeoNode Docker Image" VENDOR: "52°North GmbH" AUTHORS: "https://52North.org/" - DESCRIPTION: "Builds and publishes the GeoNode Docker development image for Thuenen" + DESCRIPTION: "Builds and publishes Thuenen Atlas GeoNode image(s)" LICENSE: "GPL-3.0" on: diff --git a/.github/workflows/release.yaml b/.github/workflows/52n-release.yaml similarity index 72% rename from .github/workflows/release.yaml rename to .github/workflows/52n-release.yaml index bce7da86980..c98640c39bd 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/52n-release.yaml @@ -34,6 +34,10 @@ jobs: name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@v4 + env: + MAJOR_VERSION: ${{ steps.semver_parser.outputs.major }} + MAJOR_MINOR_VERSION: ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }} + MAJOR_MINOR_PATCH_VERSION: ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }}-${{ steps.semver_parser.outputs.patch }} with: images: ${{ env.IMAGE }} labels: | @@ -43,15 +47,19 @@ jobs: "org.opencontainers.image.title=${{ env.TITLE }}" "org.opencontainers.image.licenses=${{ env.LICENSE }}" tags: | - ${{ steps.semver_parser.outputs.major }} - ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }} - ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }}-${{ steps.semver_parser.outputs.patch }} + latest + ${{ env.MAJOR_VERSION }} + ${{ env.MAJOR_MINOR_VERSION }} + ${{ env.MAJOR_MINOR_PATCH_VERSION }} - name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Fail in case fully tagged version already exists + run: docker manifest inspect ${{ env.IMAGE }}:${{ steps.meta.env.MAJOR_MINOR_PATCH_VERSION }} > /dev/null ; test $? != 0 - name: Build and push uses: docker/build-push-action@v4 From d00812c20879cf9e819a003e208845fa02e3d78d Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 18 Sep 2023 12:06:12 +0200 Subject: [PATCH 174/253] Align with upstream 4.1.x --- geonode/base/forms.py | 3 --- geonode/base/views.py | 15 ------------- geonode/geoserver/helpers.py | 11 ---------- geonode/geoserver/signals.py | 2 -- geonode/layers/api/serializers.py | 1 - geonode/security/tests.py | 9 -------- geonode/storage/tests.py | 20 ++---------------- .../storage/tests/data/data_collection.zip | Bin 14261 -> 0 bytes geonode/upload/__init__.py | 18 ---------------- setup.cfg | 8 ------- 10 files changed, 2 insertions(+), 85 deletions(-) delete mode 100644 geonode/storage/tests/data/data_collection.zip diff --git a/geonode/base/forms.py b/geonode/base/forms.py index f545c6b0323..8152da290e5 100644 --- a/geonode/base/forms.py +++ b/geonode/base/forms.py @@ -579,9 +579,6 @@ def __init__(self, *args, **kwargs): if field in ["owner"] and not self.can_change_perms: self.fields[field].disabled = True - if field in ["poc", "owner"] and not self.can_change_perms: - self.fields[field].disabled = True - def disable_keywords_widget_for_non_superuser(self, user): if settings.FREETEXT_KEYWORDS_READONLY and not user.is_superuser: self["keywords"].field.disabled = True diff --git a/geonode/base/views.py b/geonode/base/views.py index 2d13abe8ae0..ab7359c8b3b 100644 --- a/geonode/base/views.py +++ b/geonode/base/views.py @@ -355,21 +355,6 @@ def get_results(self, context): ] -class DatasetsAutocomplete(SimpleSelect2View): - model = Dataset - filter_arg = "title__icontains" - - def get_results(self, context): - return [ - { - "id": self.get_result_value(result), - "text": self.get_result_label(result.title), - "selected_text": self.get_selected_result_label(result.title), - } - for result in context["object_list"] - ] - - class ThesaurusAvailable(autocomplete.Select2QuerySetView): def get_queryset(self): tid = self.request.GET.get("sysid") diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index 2bd6f3030c7..8067f272adb 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -1876,17 +1876,6 @@ def get_time_info(layer): gs_uploader = Client(url, _user, _password) -def _create_geofence_client(): - gf_rest_url = f'{url.rstrip("/")}/geofence/' - client = GeoFenceClient(gf_rest_url, _user, _password) - client.set_timeout(ogc_server_settings.GEOFENCE_TIMEOUT) - return client - - -geofence = _create_geofence_client() -gf_utils = GeoFenceUtils(geofence) - - def _create_geofence_client(): gf_rest_url = f'{url.rstrip("/")}/geofence/' client = GeoFenceClient(gf_rest_url, _user, _password) diff --git a/geonode/geoserver/signals.py b/geonode/geoserver/signals.py index cfe1ad6f85b..70b96060303 100644 --- a/geonode/geoserver/signals.py +++ b/geonode/geoserver/signals.py @@ -42,8 +42,6 @@ geofence_rule_assign = Signal(providing_args=["instance"]) -geofence_rule_assign = Signal(providing_args=["instance"]) - def geoserver_delete(typename): # cascading_delete should only be called if diff --git a/geonode/layers/api/serializers.py b/geonode/layers/api/serializers.py index b1506fc79f5..304e89467c5 100644 --- a/geonode/layers/api/serializers.py +++ b/geonode/layers/api/serializers.py @@ -181,7 +181,6 @@ class Meta: "subtype", "ptype", "executions", - "metadata", ) name = serializers.CharField(read_only=True) diff --git a/geonode/security/tests.py b/geonode/security/tests.py index 861b6a7a9a4..433f4aa6de7 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -1747,15 +1747,6 @@ def test_admin_whitelisted_access_middleware(self): middleware.process_request(request) self.assertTrue(request.user.is_superuser) - # Test valid IP in second element - with self.settings(ADMIN_IP_WHITELIST=["88.88.88.88", "127.0.0.1"]): - request = HttpRequest() - request.user = admin - request.path = reverse("home") - request.META["REMOTE_ADDR"] = "127.0.0.1" - middleware.process_request(request) - self.assertTrue(request.user.is_superuser) - class SecurityRulesTests(TestCase): """ diff --git a/geonode/storage/tests.py b/geonode/storage/tests.py index 094b519647d..f38c88a58ff 100644 --- a/geonode/storage/tests.py +++ b/geonode/storage/tests.py @@ -417,22 +417,6 @@ def test_storage_manager_copy(self): os.remove(output.get("files")[0]) self.assertFalse(os.path.exists(output.get("files")[0])) - @override_settings(FILE_UPLOAD_DIRECTORY_PERMISSIONS=0o777) - @override_settings(FILE_UPLOAD_PERMISSIONS=0o777) - def test_storage_manager_copy(self): - """ - Test that the copy works as expected and the permissions are corerct - """ - dataset = create_single_dataset(name="test_copy") - dataset.files = [os.path.join(f"{self.project_root}", "tests/data/test_sld.sld")] - dataset.save() - output = self.sut().copy(dataset) - - self.assertTrue(os.path.exists(output.get("files")[0])) - self.assertEqual(os.stat(os.path.exists(output.get("files")[0])).st_mode, 8592) - os.remove(output.get("files")[0]) - self.assertFalse(os.path.exists(output.get("files")[0])) - class TestDataRetriever(TestCase): @classmethod @@ -639,7 +623,7 @@ def test_zip_file_should_correctly_recognize_main_extension_with_shp(self): self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) _files = storage_manager.get_retrieved_paths() self.assertTrue("single_point.shp" in _files.get("base_file")) - + def test_zip_file_should_correctly_relate_mixed_content(self): zip_file = os.path.join(f"{self.project_root}", "tests/data/data_collection.zip") storage_manager = self.sut( @@ -649,7 +633,7 @@ def test_zip_file_should_correctly_relate_mixed_content(self): self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) _files = storage_manager.get_retrieved_paths() base_file = _files.get("base_file") - + def strip_extension(filename): return filename.split(".")[0] if filename else filename diff --git a/geonode/storage/tests/data/data_collection.zip b/geonode/storage/tests/data/data_collection.zip deleted file mode 100644 index 0702327be361a2bfda7c9c2a6eb13bd08ca5a9b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14261 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 Cq!$1H diff --git a/geonode/upload/__init__.py b/geonode/upload/__init__.py index 8be4d76cb36..c3ad74d2b54 100644 --- a/geonode/upload/__init__.py +++ b/geonode/upload/__init__.py @@ -48,20 +48,6 @@ def run_setup_hooks(sender, **kwargs): start_time=timezone.now(), ), ) - daily_interval, _ = IntervalSchedule.objects.get_or_create( - every=1, - period="days" - ) - daily_interval, _ = IntervalSchedule.objects.get_or_create(every=1, period="days") - PeriodicTask.objects.update_or_create( - name="clean-up-old-task-result", - defaults=dict( - task="geonode.upload.tasks.cleanup_celery_task_entries", - interval=daily_interval, - args="", - start_time=timezone.now(), - ), - ) class UploadAppConfig(AppConfig): @@ -74,10 +60,6 @@ def ready(self): "task": "geonode.upload.tasks.cleanup_celery_task_entries", "schedule": 86400.0, } - settings.CELERY_BEAT_SCHEDULE["clean-up-old-task-result"] = { - "task": "geonode.upload.tasks.cleanup_celery_task_entries", - "schedule": 86400.0, - } default_app_config = "geonode.upload.UploadAppConfig" diff --git a/setup.cfg b/setup.cfg index dc5199bcc79..01c83ee8f1f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -204,14 +204,6 @@ install_requires = cryptography>=41.0.0 # not directly required, pinned by Snyk to avoid a vulnerability nh3==0.2.15 - # Security and audit - mistune==2.0.5 - wandb==0.13.11 - protobuf==3.20.3 - mako==1.2.4 - certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability - jwcrypto>=1.4 # not directly required, pinned by Snyk to avoid a vulnerability - [options.packages.find] exclude = tests From a364958c040f6f63b189364081f79f9fe39898e7 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 18 Sep 2023 16:35:46 +0200 Subject: [PATCH 175/253] Add docker hub description --- .github/workflows/52n-build.yaml | 3 +++ .../workflows/52n-dockerhub-description.yaml | 23 +++++++++++++++++++ README_thuenen.md | 8 +++++++ 3 files changed, 34 insertions(+) create mode 100644 .github/workflows/52n-dockerhub-description.yaml create mode 100644 README_thuenen.md diff --git a/.github/workflows/52n-build.yaml b/.github/workflows/52n-build.yaml index df1a12d6259..b30a7643827 100644 --- a/.github/workflows/52n-build.yaml +++ b/.github/workflows/52n-build.yaml @@ -15,6 +15,9 @@ on: push: branches: - "thuenen_4.x" + paths: + - "!./.github/workflows/52n-dockerhub-description.yaml" + - "!./README_thuenen.md" jobs: build_and_push_geonode: diff --git a/.github/workflows/52n-dockerhub-description.yaml b/.github/workflows/52n-dockerhub-description.yaml new file mode 100644 index 00000000000..1bd1b5f84f6 --- /dev/null +++ b/.github/workflows/52n-dockerhub-description.yaml @@ -0,0 +1,23 @@ +name: Update Docker Hub Description +on: + push: + branches: + - thuenen_4.x + paths: + - README_thuenen.md + - .github/workflows/52n-dockerhub-description.yaml +jobs: + dockerHubDescription: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Docker Hub Description + uses: peter-evans/dockerhub-description@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + repository: 52north/geonode + short-description: "Geospatial content management system" + readme-filepath: ./README_thuenen.md + enable-url-completion: true \ No newline at end of file diff --git a/README_thuenen.md b/README_thuenen.md new file mode 100644 index 00000000000..5ebf30dbe77 --- /dev/null +++ b/README_thuenen.md @@ -0,0 +1,8 @@ +# Thünen Atlas Fork of GeoNode + +This image is built from a fork of [Geonode](https://github.com/geonode/geonode). +[Thünen Institute](https://thuenen.de) maintains an own fork of GeoNode in order to make necessary adjustments within projects which are not (yet) part of GeoNode core. + +However, we are interested to stay as close to upstream as possible, to benefit from ongoing development, but also to contribute features and fixes we develop in [Thünen Atlas project](https://atlas.thuenen.de). + +This image (`52north/geonode_thuenen`) is built from the `thuenen_4.x` branch of the [`Thuenen-GeoNode-Development/geonode` repository](https://github.com/Thuenen-GeoNode-Development/geonode/tree/thuenen_4.x). From 1820fa7d0c4c60434cf37f71ac54126ae223782c Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 26 Sep 2023 11:04:10 +0200 Subject: [PATCH 176/253] Fix parsing release version --- .github/workflows/52n-release.yaml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/52n-release.yaml b/.github/workflows/52n-release.yaml index c98640c39bd..3c7aad9527a 100644 --- a/.github/workflows/52n-release.yaml +++ b/.github/workflows/52n-release.yaml @@ -27,6 +27,7 @@ jobs: uses: booxmedialtd/ws-action-parse-semver@v1 with: input_string: "${{github.ref_name}}" + version_extractor_regex: 'v(.*)-thuenen' - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 @@ -37,7 +38,7 @@ jobs: env: MAJOR_VERSION: ${{ steps.semver_parser.outputs.major }} MAJOR_MINOR_VERSION: ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }} - MAJOR_MINOR_PATCH_VERSION: ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }}-${{ steps.semver_parser.outputs.patch }} + MAJOR_MINOR_PATCH_VERSION: ${{ steps.semver_parser.outputs.fullversion }} with: images: ${{ env.IMAGE }} labels: | @@ -59,7 +60,11 @@ jobs: password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Fail in case fully tagged version already exists - run: docker manifest inspect ${{ env.IMAGE }}:${{ steps.meta.env.MAJOR_MINOR_PATCH_VERSION }} > /dev/null ; test $? != 0 + run: | + if docker manifest inspect ${{ env.IMAGE }}:${{ steps.semver_parser.outputs.fullversion }}; then + echo "tag version already exists! Will not override." + exit 1 + fi - name: Build and push uses: docker/build-push-action@v4 From 8d059adc5a05c145f295a65024968eb368598b17 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Thu, 11 May 2023 15:21:56 +0200 Subject: [PATCH 177/253] fix: requirements.txt to reduce vulnerabilities (#11029) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-DJANGO-5496950 Co-authored-by: Alessio Fabiani From 174c5d36754f10cc859456c28abd529d81feb79b Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 19 Sep 2023 17:23:17 +0200 Subject: [PATCH 178/253] Fix target image for docker README --- .github/workflows/52n-dockerhub-description.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/52n-dockerhub-description.yaml b/.github/workflows/52n-dockerhub-description.yaml index 1bd1b5f84f6..6d9a0352a54 100644 --- a/.github/workflows/52n-dockerhub-description.yaml +++ b/.github/workflows/52n-dockerhub-description.yaml @@ -17,7 +17,7 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - repository: 52north/geonode + repository: 52north/geonode_thuenen short-description: "Geospatial content management system" readme-filepath: ./README_thuenen.md enable-url-completion: true \ No newline at end of file From 10a0c3699095b07883ca9a3848a7b30f53d95205 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Wed, 20 Sep 2023 14:46:18 +0200 Subject: [PATCH 179/253] Remove example test Test example is available still from the PR https://github.com/GeoNode/geonode/pull/10842 --- geonode/storage/tests.py | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/geonode/storage/tests.py b/geonode/storage/tests.py index f38c88a58ff..9a96186ab3e 100644 --- a/geonode/storage/tests.py +++ b/geonode/storage/tests.py @@ -623,30 +623,3 @@ def test_zip_file_should_correctly_recognize_main_extension_with_shp(self): self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) _files = storage_manager.get_retrieved_paths() self.assertTrue("single_point.shp" in _files.get("base_file")) - - def test_zip_file_should_correctly_relate_mixed_content(self): - zip_file = os.path.join(f"{self.project_root}", "tests/data/data_collection.zip") - storage_manager = self.sut( - remote_files={"base_file": zip_file} - ) - storage_manager.clone_remote_files() - self.assertIsNotNone(storage_manager.data_retriever.temporary_folder) - _files = storage_manager.get_retrieved_paths() - base_file = _files.get("base_file") - - def strip_extension(filename): - return filename.split(".")[0] if filename else filename - - base_name = strip_extension(base_file) - available_files = [ - _files.get("shp_file"), - _files.get("prj_file"), - _files.get("shx_file"), - _files.get("dbf_file") - ] - - def assert_same_base_name(base_name, file_name): - self.assertEqual(base_name, strip_extension(file_name)) - - for file in available_files: - assert_same_base_name(base_name, file) From 0de91532f99e79d0855e2a026b82fd7b6997bcbe Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Wed, 20 Sep 2023 14:51:31 +0200 Subject: [PATCH 180/253] Reconfigure pipeline regarding ignored paths --- .github/workflows/52n-build.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/52n-build.yaml b/.github/workflows/52n-build.yaml index b30a7643827..18a9b21175f 100644 --- a/.github/workflows/52n-build.yaml +++ b/.github/workflows/52n-build.yaml @@ -15,9 +15,9 @@ on: push: branches: - "thuenen_4.x" - paths: - - "!./.github/workflows/52n-dockerhub-description.yaml" - - "!./README_thuenen.md" + paths-ignore: + - "./.github/workflows/52n-dockerhub-description.yaml" + - "./README_thuenen.md" jobs: build_and_push_geonode: From 9c33fb392b759ef78566313da10b071a927a3757 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Fri, 13 Oct 2023 12:09:37 +0200 Subject: [PATCH 181/253] Rename workflow build --- .github/workflows/52n-build.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/52n-build.yaml b/.github/workflows/52n-build.yaml index 18a9b21175f..cf82d61d0ee 100644 --- a/.github/workflows/52n-build.yaml +++ b/.github/workflows/52n-build.yaml @@ -1,7 +1,7 @@ -name: Push Thünen Atlas Docker Image(s) +name: "[thuenen_4.x -> 4.x] Push Thünen Atlas Docker Image(s)" -concurrency: - group: "geonode_build" +concurrency: + group: "geonode_build_thuenen_4.x" cancel-in-progress: true env: @@ -15,7 +15,7 @@ on: push: branches: - "thuenen_4.x" - paths-ignore: + paths-ignore: - "./.github/workflows/52n-dockerhub-description.yaml" - "./README_thuenen.md" @@ -32,7 +32,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - - + - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@v4 From 888db1a406ed04d5a957085a95578fd263b86799 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Fri, 13 Oct 2023 12:24:05 +0200 Subject: [PATCH 182/253] Rename workflow file --- .github/workflows/{52n-build.yaml => 52n-build-4.x.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{52n-build.yaml => 52n-build-4.x.yaml} (100%) diff --git a/.github/workflows/52n-build.yaml b/.github/workflows/52n-build-4.x.yaml similarity index 100% rename from .github/workflows/52n-build.yaml rename to .github/workflows/52n-build-4.x.yaml From 65cd6ab89619dd6037e490d97e649543eb0008a5 Mon Sep 17 00:00:00 2001 From: Gleb Kilichenko Date: Thu, 23 Nov 2023 20:53:28 +0100 Subject: [PATCH 183/253] overriding update method in dataset serializer class --- geonode/layers/api/serializers.py | 33 ++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/geonode/layers/api/serializers.py b/geonode/layers/api/serializers.py index 304e89467c5..af80ff5bd78 100644 --- a/geonode/layers/api/serializers.py +++ b/geonode/layers/api/serializers.py @@ -17,7 +17,7 @@ # ######################################################################### from rest_framework import serializers - +from rest_framework.exceptions import ValidationError, ParseError from urllib.parse import urlparse from django.conf import settings @@ -195,6 +195,37 @@ class Meta: featureinfo_custom_template = FeatureInfoTemplateField() + def update(self, instance, validated_data): + super().update(instance, validated_data) + + # Handle updates to attribute_set + allowed_fields = ["pk", "description", "attribute_label", "visible", "display_order"] + if "blob" in validated_data and "attribute_set" in validated_data["blob"]: + attributes = validated_data["blob"]["attribute_set"] + + for attribute in attributes: + for field, _ in attribute.items(): + if field not in allowed_fields: + raise ValidationError( + f"{field} is not one of the fields that could be edited directly. \ + Only {str(allowed_fields)} are allowed" + ) + + for attribute in attributes: + try: + if "pk" in attribute: + attribute_instance = Attribute.objects.get(pk=attribute["pk"], dataset=instance) + for field, value in attribute.items(): + setattr(attribute_instance, field, value) + attribute_instance.save() + else: + raise Exception("Primary key of the attribute to be patched not specified") + except Exception as e: + logger.error(e) + raise ParseError(str(e)) + + return instance + class DatasetListSerializer(DatasetSerializer): class Meta(DatasetSerializer.Meta): From 4b1d7bfd8ce7e869420cacfbf5dcbfcac7e081b9 Mon Sep 17 00:00:00 2001 From: ahmdthr <116570171+ahmdthr@users.noreply.github.com> Date: Mon, 18 Dec 2023 10:40:09 +0100 Subject: [PATCH 184/253] Integrates PyCSW v3 to provide DataCite metadata format Integrates pyCSW `v3` (as alpha) to provide DataCite download format on the backend. Relates to PR Thuenen-GeoNode-Development/geonode-mapstore-client#27 which adds a button to download metadata as DataCite format. --- geonode/base/utils.py | 1 + geonode/catalogue/backends/generic.py | 1 + geonode/catalogue/backends/pycsw_http.py | 2 +- geonode/catalogue/backends/pycsw_local.py | 2 +- geonode/catalogue/backends/pycsw_local_mappings.py | 10 +++++++++- geonode/settings.py | 1 + requirements.txt | 2 +- setup.cfg | 2 +- 8 files changed, 16 insertions(+), 5 deletions(-) diff --git a/geonode/base/utils.py b/geonode/base/utils.py index 0afee6192e1..e647c079d5c 100644 --- a/geonode/base/utils.py +++ b/geonode/base/utils.py @@ -60,6 +60,7 @@ "KML", "KMZ", "Atom", + "DataCite", "DIF", "Dublin Core", "ebRIM", diff --git a/geonode/catalogue/backends/generic.py b/geonode/catalogue/backends/generic.py index 848fd9758fe..c1023c17b67 100644 --- a/geonode/catalogue/backends/generic.py +++ b/geonode/catalogue/backends/generic.py @@ -34,6 +34,7 @@ TIMEOUT = 10 METADATA_FORMATS = { "Atom": ("atom:entry", "http://www.w3.org/2005/Atom"), + "DataCite": ("csw:Record", "http://datacite.org/schema/kernel-4"), "DIF": ("dif:DIF", "http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/"), "Dublin Core": ("csw:Record", "http://www.opengis.net/cat/csw/2.0.2"), "ebRIM": ("rim:RegistryObject", "urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0"), diff --git a/geonode/catalogue/backends/pycsw_http.py b/geonode/catalogue/backends/pycsw_http.py index 0058c41359c..4cd5305d0c2 100644 --- a/geonode/catalogue/backends/pycsw_http.py +++ b/geonode/catalogue/backends/pycsw_http.py @@ -26,4 +26,4 @@ class CatalogueBackend(GenericCatalogueBackend): def __init__(self, *args, **kwargs): """initialize pycsw HTTP CSW backend""" GenericCatalogueBackend.__init__(CatalogueBackend, self, *args, **kwargs) - self.catalogue.formats = ["Atom", "DIF", "Dublin Core", "ebRIM", "FGDC", "ISO"] + self.catalogue.formats = ["Atom", "DataCite", "DIF", "Dublin Core", "ebRIM", "FGDC", "ISO"] diff --git a/geonode/catalogue/backends/pycsw_local.py b/geonode/catalogue/backends/pycsw_local.py index 75c66e96498..4be10f9b633 100644 --- a/geonode/catalogue/backends/pycsw_local.py +++ b/geonode/catalogue/backends/pycsw_local.py @@ -65,7 +65,7 @@ class CatalogueBackend(GenericCatalogueBackend): def __init__(self, *args, **kwargs): GenericCatalogueBackend.__init__(CatalogueBackend, self, *args, **kwargs) - self.catalogue.formats = ["Atom", "DIF", "Dublin Core", "ebRIM", "FGDC", "ISO"] + self.catalogue.formats = ["Atom", "DataCite", "DIF", "Dublin Core", "ebRIM", "FGDC", "ISO"] self.catalogue.local = True def remove_record(self, uuid): diff --git a/geonode/catalogue/backends/pycsw_local_mappings.py b/geonode/catalogue/backends/pycsw_local_mappings.py index 4bbb8648b88..d9dd78d7845 100644 --- a/geonode/catalogue/backends/pycsw_local_mappings.py +++ b/geonode/catalogue/backends/pycsw_local_mappings.py @@ -31,6 +31,14 @@ "pycsw:AnyText": "csw_anytext", "pycsw:Language": "language", "pycsw:Title": "title", + "pycsw:Edition": "edition", + "pycsw:Platform": "platform", + "pycsw:Instrument": "instrument", + "pycsw:SensorType": "sensortype", + "pycsw:CloudCover": "cloudcover", + "pycsw:Bands": "bands", + "pycsw:Themes": "themes", + "pycsw:Contacts": "contacts", "pycsw:Abstract": "raw_abstract", "pycsw:Keywords": "keyword_csv", "pycsw:KeywordType": "keywordstype", @@ -78,6 +86,6 @@ "pycsw:Publisher": "publisher", "pycsw:Contributor": "contributor", "pycsw:Relation": "relation", - "pycsw:Links": "download_links", + "pycsw:Links": "download_urls", }, } diff --git a/geonode/settings.py b/geonode/settings.py index 2224bce108f..d3dae712d9e 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -1314,6 +1314,7 @@ # Available download formats DOWNLOAD_FORMATS_METADATA = [ "Atom", + "DataCite", "DIF", "Dublin Core", "ebRIM", diff --git a/requirements.txt b/requirements.txt index 70f7db16c82..9a0e600128d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -55,7 +55,7 @@ pyjwt==2.8.0 # geopython dependencies pyproj<3.7.0 OWSLib==0.29.3 -pycsw==2.6.1 +-e git+https://github.com/geopython/pycsw.git@3.0.0-alpha5#egg=pycsw SQLAlchemy==2.0.21 # required by PyCSW Shapely==1.8.5.post1 mercantile==1.2.1 diff --git a/setup.cfg b/setup.cfg index 01c83ee8f1f..3d47abc0fc5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -81,7 +81,7 @@ install_requires = # geopython dependencies pyproj<3.7.0 OWSLib==0.29.3 - pycsw==2.6.1 + pycsw @ git+https://github.com/geopython/pycsw.git@3.0.0-alpha5 SQLAlchemy==2.0.21 # required by PyCSW Shapely==1.8.5.post1 mercantile==1.2.1 From c2b5a5014e61df4ed38f70bd046795ca89210b4f Mon Sep 17 00:00:00 2001 From: Henning Bredel <881756+ridoo@users.noreply.github.com> Date: Mon, 18 Dec 2023 12:16:48 +0100 Subject: [PATCH 185/253] Allows metadata upload with different UUID Co-authored-by: ahmdthr --- geonode/layers/api/tests.py | 2 +- geonode/layers/api/views.py | 9 ++++----- .../datasets/dataset_metadata_upload.html | 1 + geonode/layers/tests.py | 20 +++++++++---------- geonode/layers/views.py | 11 +++++----- geonode/locale/en/LC_MESSAGES/django.po | 3 +++ geonode/static/geonode/js/upload/LayerInfo.js | 12 +++++++++-- 7 files changed, 35 insertions(+), 23 deletions(-) diff --git a/geonode/layers/api/tests.py b/geonode/layers/api/tests.py index 79b4330977b..ed72c5053a5 100644 --- a/geonode/layers/api/tests.py +++ b/geonode/layers/api/tests.py @@ -660,7 +660,7 @@ def test_valid_metadata_file_with_different_uuid(self): f = open(self.exml_path, "r") put_data = {"metadata_file": f} response = self.client.put(url, data=put_data) - self.assertEqual(500, response.status_code) + self.assertEqual(200, response.status_code) def test_permissions_for_not_permitted_user(self): get_user_model().objects.create_user( diff --git a/geonode/layers/api/views.py b/geonode/layers/api/views.py index 218216a17bd..629367c3440 100644 --- a/geonode/layers/api/views.py +++ b/geonode/layers/api/views.py @@ -141,17 +141,16 @@ def metadata(self, request, pk=None, *args, **kwargs): dataset_uuid, vals, regions, keywords, _ = parse_metadata(open(metadata_file).read()) except Exception: raise InvalidMetadataException(detail="Unsupported metadata format") - if dataset_uuid and dataset.uuid != dataset_uuid: - raise InvalidMetadataException( - detail="The UUID identifier from the XML Metadata, is different from the one saved" - ) try: updated_dataset = update_resource(dataset, metadata_file, regions, keywords, vals) updated_dataset.save() # This also triggers the recreation of the XML metadata file according to the updated values except Exception: raise GeneralDatasetException(detail="Failed to update metadata") out["success"] = True - out["message"] = ["Metadata successfully updated"] + out_message = "Metadata successfully updated" + if dataset_uuid and dataset.uuid != dataset_uuid: + out_message += " The UUID identifier from the XML Metadata is different from the one saved" + out["message"] = [out_message] return Response(out) except Exception as e: raise e diff --git a/geonode/layers/templates/datasets/dataset_metadata_upload.html b/geonode/layers/templates/datasets/dataset_metadata_upload.html index 6ef4d3d2e55..a5a0168e9ef 100644 --- a/geonode/layers/templates/datasets/dataset_metadata_upload.html +++ b/geonode/layers/templates/datasets/dataset_metadata_upload.html @@ -63,6 +63,7 @@

    {% trans "Files to be uploaded" %}

    +
    {% trans "WARNING" %}: {% trans "This will most probably overwrite the current metadata!" %}
    {% trans "Clear" %} {% trans "Upload files" %}
    diff --git a/geonode/layers/tests.py b/geonode/layers/tests.py index bc7d6ff27b6..4ccca2bc8a7 100644 --- a/geonode/layers/tests.py +++ b/geonode/layers/tests.py @@ -1002,9 +1002,10 @@ def test_xml_should_update_the_dataset_with_the_expected_values(self): prev_dataset = Dataset.objects.get(typename="geonode:single_point") self.assertEqual(0, prev_dataset.keywords.count()) resp = self.client.post(reverse("dataset_upload"), params) - self.assertEqual(404, resp.status_code) + self.assertEqual(200, resp.status_code) self.assertEqual( - resp.json()["errors"], "The UUID identifier from the XML Metadata, is different from the one saved" + resp.json()["warning"], + "WARNING: The XML's UUID was ignored while updating this dataset's metadata because that UUID is already present in this system. The rest of the XML's metadata was applied.", ) def test_sld_should_raise_500_if_is_invalid(self): @@ -1052,10 +1053,10 @@ def test_sld_should_update_the_dataset_with_the_expected_values(self): self.assertIsNotNone(updated_dataset.styles.first()) self.assertEqual(layer.styles.first().sld_title, updated_dataset.styles.first().sld_title) - def test_xml_should_raise_an_error_if_the_uuid_is_changed(self): + def test_xml_should_not_raise_an_error_if_the_uuid_is_changed(self): """ If the UUID coming from the XML and the one saved in the DB are different - The system should raise an error + The system should not raise an error, instead it should simply update the values """ params = { "permissions": '{ "users": {"AnonymousUser": ["view_resourcebase"]} , "groups":{}}', @@ -1071,12 +1072,11 @@ def test_xml_should_raise_an_error_if_the_uuid_is_changed(self): prev_dataset = Dataset.objects.get(typename="geonode:single_point") self.assertEqual(0, prev_dataset.keywords.count()) resp = self.client.post(reverse("dataset_upload"), params) - self.assertEqual(404, resp.status_code) - expected = { - "success": False, - "errors": "The UUID identifier from the XML Metadata, is different from the one saved", - } - self.assertDictEqual(expected, resp.json()) + self.assertEqual(200, resp.status_code) + self.assertEqual( + resp.json()["warning"], + "WARNING: The XML's UUID was ignored while updating this dataset's metadata because that UUID is already present in this system. The rest of the XML's metadata was applied.", + ) def test_will_raise_exception_for_replace_vector_dataset_with_raster(self): layer = Dataset.objects.get(name="single_point") diff --git a/geonode/layers/views.py b/geonode/layers/views.py index 8b0c585af9c..32299b048a0 100644 --- a/geonode/layers/views.py +++ b/geonode/layers/views.py @@ -171,10 +171,6 @@ def dataset_upload_metadata(request): ) if layer: dataset_uuid, vals, regions, keywords, _ = parse_metadata(open(base_file).read()) - if dataset_uuid and layer.uuid != dataset_uuid: - out["success"] = False - out["errors"] = "The UUID identifier from the XML Metadata, is different from the one saved" - return HttpResponse(json.dumps(out), content_type="application/json", status=404) updated_dataset = update_resource(layer, base_file, regions, keywords, vals) updated_dataset.save() out["status"] = ["finished"] @@ -186,9 +182,14 @@ def dataset_upload_metadata(request): upload_session = updated_dataset.upload_session upload_session.processed = True upload_session.save() - status_code = 200 out["success"] = True + status_code = 200 + if dataset_uuid and layer.uuid != dataset_uuid: + out[ + "warning" + ] = "WARNING: The XML's UUID was ignored while updating this dataset's metadata because that UUID is already present in this system. The rest of the XML's metadata was applied." return HttpResponse(json.dumps(out), content_type="application/json", status=status_code) + else: out["success"] = False out["errors"] = "Dataset selected does not exists" diff --git a/geonode/locale/en/LC_MESSAGES/django.po b/geonode/locale/en/LC_MESSAGES/django.po index 1e094b47828..8b75867f235 100644 --- a/geonode/locale/en/LC_MESSAGES/django.po +++ b/geonode/locale/en/LC_MESSAGES/django.po @@ -1168,6 +1168,9 @@ msgstr "Files to be uploaded" msgid "Is Upload Metadata XML Form" msgstr "Is Upload Metadata XML Form" +msgid "This will most probably overwrite the current metadata!" +msgstr "This will most probably overwrite the current metadata!" + msgid "Upload files" msgstr "Upload files" diff --git a/geonode/static/geonode/js/upload/LayerInfo.js b/geonode/static/geonode/js/upload/LayerInfo.js index 4d4c4385172..574776a8977 100644 --- a/geonode/static/geonode/js/upload/LayerInfo.js +++ b/geonode/static/geonode/js/upload/LayerInfo.js @@ -458,7 +458,15 @@ define(function (require, exports) { } catch (err) { // pass } - var info_message = gettext('Your ' + resourceType +' was successfully created.'); + var info_message = '' + var level = 'alert-success' + if (resp.warning){ + info_message = resp.warning + level = 'alert-warning' + } + else{ + info_message = gettext('Your ' + resourceType +' was successfully created.'); + } var a = '' + gettext(resourceType.capitalize() + ' Info') + '   '; if(resourceType == 'dataset') { // Only Layers have Metadata and SLD Upload features for the moment @@ -474,7 +482,7 @@ define(function (require, exports) { } self.logStatus({ msg: '

    ' + info_message + '
    ' + msg_col + '
    ' + a + '

    ', - level: 'alert-success', + level: level, empty: 'true' }); }; From d28bdf8763cfb7620f156c1b6c0a39feac5e8a08 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Fri, 23 Feb 2024 08:46:03 +0100 Subject: [PATCH 186/253] Remove artifacts from 52n fork --- .github/workflows/52n-build-4.2.x.yml | 59 ---------------- .github/workflows/52n-release.yml | 78 --------------------- .github/workflows/dockerhub-description.yml | 23 ------ README_52n.md | 38 ---------- 4 files changed, 198 deletions(-) delete mode 100644 .github/workflows/52n-build-4.2.x.yml delete mode 100644 .github/workflows/52n-release.yml delete mode 100644 .github/workflows/dockerhub-description.yml delete mode 100644 README_52n.md diff --git a/.github/workflows/52n-build-4.2.x.yml b/.github/workflows/52n-build-4.2.x.yml deleted file mode 100644 index 13aae68a94a..00000000000 --- a/.github/workflows/52n-build-4.2.x.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: "[52n-4.2.x -> 4.2.x] Builds GeoNode Docker Images" - -concurrency: - group: "geonode_build_master" - cancel-in-progress: true - -env: - TITLE: "52°North GeoNode Docker Image" - VENDOR: "52°North GmbH" - AUTHORS: "https://52North.org/" - DESCRIPTION: "Builds and publishes the Docker images GeoNode, GeoServer, Nginx" - LICENSE: "GPL-3.0" - TAG: 4.2.x - -on: - push: - branches: - - "52n-4.2.x" - -jobs: - build_and_push_geonode: - runs-on: ubuntu-22.04 - env: - IMAGE: 52north/geonode - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.IMAGE }} - labels: | - "org.opencontainers.image.authors=${{ env.AUTHORS }}" - "org.opencontainers.image.vendor=${{ env.VENDOR }}" - "org.opencontainers.image.description=${{ env.DESCRIPTION }}" - "org.opencontainers.image.title=${{ env.TITLE }}" - "org.opencontainers.image.licenses=${{ env.LICENSE }}" - tags: | - latest - ${{ env.TAG }} - - - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN_52N_MASTER }} - - name: Build and push - uses: docker/build-push-action@v4 - with: - context: . - file: ./Dockerfile - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache - cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max diff --git a/.github/workflows/52n-release.yml b/.github/workflows/52n-release.yml deleted file mode 100644 index 983fec64aae..00000000000 --- a/.github/workflows/52n-release.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: Release GeoNode Docker Images - -concurrency: - group: "geonode_build_release" - cancel-in-progress: true - -env: - TITLE: "52°North GeoNode Docker Image" - VENDOR: "52°North GmbH" - AUTHORS: "https://52North.org/" - DESCRIPTION: "Builds and publishes the Docker images GeoNode, GeoServer, Nginx" - LICENSE: "GPL-3.0" - -on: - push: - tags: - - "*-52n" - -jobs: - build_and_push_geonode: - runs-on: ubuntu-22.04 - env: - IMAGE: 52north/geonode - steps: - - - name: Checkout - uses: actions/checkout@v3 - - - name: Parse semver string - id: semver_parser - uses: booxmedialtd/ws-action-parse-semver@v1 - with: - input_string: "${{github.ref_name}}" - version_extractor_regex: '(.*)-52n' - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.IMAGE }} - labels: | - "org.opencontainers.image.authors=${{ env.AUTHORS }}" - "org.opencontainers.image.vendor=${{ env.VENDOR }}" - "org.opencontainers.image.description=${{ env.DESCRIPTION }}" - "org.opencontainers.image.title=${{ env.TITLE }}" - "org.opencontainers.image.licenses=${{ env.LICENSE }}" - tags: | - latest - ${{ steps.semver_parser.outputs.fullversion }} - - - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN_52N_MASTER }} - - - name: Fail in case fully tagged version already exists - run: | - if docker manifest inspect ${{ env.IMAGE }}:${{ steps.semver_parser.outputs.fullversion }}; then - echo "tag version already exists! Will not override." - exit 1 - fi - - - name: Build and push - if: ${{ !github.event.act }} # skip during local actions testing - uses: docker/build-push-action@v4 - with: - context: . - file: ./Dockerfile - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache - cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max - diff --git a/.github/workflows/dockerhub-description.yml b/.github/workflows/dockerhub-description.yml deleted file mode 100644 index 3dbe8fbb583..00000000000 --- a/.github/workflows/dockerhub-description.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Update Docker Hub Description -on: - push: - branches: - - 52n-master - paths: - - README_52n.md - - .github/workflows/dockerhub-description.yml -jobs: - dockerHubDescription: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Docker Hub Description - uses: peter-evans/dockerhub-description@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN_52N_MASTER }} - repository: 52north/geonode - short-description: "Geospatial content management system" - readme-filepath: ./README_52n.md - enable-url-completion: true \ No newline at end of file diff --git a/README_52n.md b/README_52n.md deleted file mode 100644 index 51f68b028c3..00000000000 --- a/README_52n.md +++ /dev/null @@ -1,38 +0,0 @@ -# 52°North Fork of GeoNode - -This image is built from a fork of [Geonode](https://github.com/geonode/geonode). -[52°North GmbH](https://52north.org) maintains an own fork of GeoNode in order to make necessary adjustments within projects which are not part of GeoNode core. - -However, we are interested to stay as close to upstream as possible, to benefit from ongoing development, but also to contribute features and fixes we develop in our projects. - - -Starting from version `4` this image is built from branch `52n-` of the [`52north/geonode` repository](https://github.com/52North/geonode/tree/52n-master). -Please note, that GeoNode depends on other components which are also available as Docker images. -These images, however, are maintained, built and published from a [`52north/geonode-docker` repository](https://github.com/52North/geonode-docker). - -> :bulb: **Note:** -> -> Please note that the versioning schema is different from the upstream project. -> All images are released and tagged using the GeoNode version. - - -You can obtain all images from here: - -* [`52north/geonode`](https://hub.docker.com/r/52north/geonode) (this image) -* [`52north/geonode-geoserver`](https://hub.docker.com/r/52north/geonode-geoserver) -* [`52north/geonode-geoserver_data`](https://hub.docker.com/r/52north/geonode-geoserver_data) -* [`52north/geonode-nginx`](https://hub.docker.com/r/52north/geonode-nginx) -* [`52north/geonode-postgis`](https://hub.docker.com/r/52north/geonode-postgis) - -The Dockerfiles can be found under the [`./scripts/docker` folder](https://github.com/52North/geonode/tree/52n-master/scripts/docker). - -The GeoNode Dockerfile can be found under the [`./scripts/docker` folder](https://github.com/52North/geonode/tree/52n-master/scripts/docker). -The Dockerfiles for the dependent components are available at [the geonode-docker repository](https://github.com/52North/geonode-docker). - - -Depending on our current project contexts we merge regularly from upstream, and create new pull requests based on this fork. - -> **Note on version `3` tags** -> -> Images containing a `3.x` version tag were experimental and do have a different code base. -> These image are considered to be removed in the near future. \ No newline at end of file From 2f0f190807bf24a033b69d45740ef6d7ae3fd5d7 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Thu, 29 Feb 2024 13:53:00 +0100 Subject: [PATCH 187/253] Updates image tags for major and minor version --- .github/workflows/52n-release.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/52n-release.yml b/.github/workflows/52n-release.yml index 983fec64aae..6a72b28abc6 100644 --- a/.github/workflows/52n-release.yml +++ b/.github/workflows/52n-release.yml @@ -39,6 +39,10 @@ jobs: name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@v4 + env: + MAJOR_VERSION: ${{ steps.semver_parser.outputs.major }} + MAJOR_MINOR_VERSION: ${{ steps.semver_parser.outputs.major }}-${{ steps.semver_parser.outputs.minor }} + MAJOR_MINOR_PATCH_VERSION: ${{ steps.semver_parser.outputs.fullversion }} with: images: ${{ env.IMAGE }} labels: | @@ -49,7 +53,9 @@ jobs: "org.opencontainers.image.licenses=${{ env.LICENSE }}" tags: | latest - ${{ steps.semver_parser.outputs.fullversion }} + ${{ env.MAJOR_VERSION }} + ${{ env.MAJOR_MINOR_VERSION }} + ${{ env.MAJOR_MINOR_PATCH_VERSION }} - name: Login to Docker Hub uses: docker/login-action@v2 From 5f0b294201506fdddfaf07d5ed323c52dd12977f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 18:30:39 +0100 Subject: [PATCH 188/253] Upgrade Remote Docker version for CircleCI (#12020) (#12022) (cherry picked from commit cd1ad83e3161c70c912da67d231e7be06dbaf523) Co-authored-by: Giovanni Allegri --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 782732b6ff3..a5524f5ab34 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,7 +21,7 @@ jobs: - checkout - setup_remote_docker: docker_layer_caching: false - version: 20.10.12 + version: docker24 - run: name: Build the stack From 4b8a1696642265ebe5a88cb951f4c3561d67b006 Mon Sep 17 00:00:00 2001 From: Emanuele Tajariol Date: Wed, 6 Mar 2024 11:34:44 +0100 Subject: [PATCH 189/253] [Fixes #11977] B/R should only deal with data (#12006) --- geonode/br/management/commands/backup.py | 125 +---------------- geonode/br/management/commands/restore.py | 161 +++------------------- 2 files changed, 20 insertions(+), 266 deletions(-) diff --git a/geonode/br/management/commands/backup.py b/geonode/br/management/commands/backup.py index 9741d084ccf..1b23dde6915 100644 --- a/geonode/br/management/commands/backup.py +++ b/geonode/br/management/commands/backup.py @@ -156,6 +156,9 @@ def execute_backup(self, **options): # Dump Fixtures logger.info("*** Dumping GeoNode fixtures...") + fixtures_target = os.path.join(target_folder, "fixtures") + os.makedirs(fixtures_target, exist_ok=True) + for app_name, dump_name in zip(config.app_names, config.dump_names): # prevent dumping BackupRestore application if app_name == "br": @@ -163,7 +166,7 @@ def execute_backup(self, **options): logger.info(f" - Dumping '{app_name}' into '{dump_name}.json'") # Point stdout at a file for dumping data to. - with open(os.path.join(target_folder, f"{dump_name}.json"), "w") as output: + with open(os.path.join(fixtures_target, f"{dump_name}.json"), "w") as output: call_command("dumpdata", app_name, format="json", indent=2, stdout=output) # Store Media Root @@ -181,126 +184,6 @@ def execute_backup(self, **options): ) logger.info(f"Saved media files from '{media_root}'") - # Store Static Root - logger.info("*** Dumping GeoNode static folder...") - - static_root = settings.STATIC_ROOT - static_folder = os.path.join(target_folder, utils.STATIC_ROOT) - if not os.path.exists(static_folder): - os.makedirs(static_folder, exist_ok=True) - - copy_tree( - static_root, - static_folder, - ignore=utils.ignore_time(config.gs_data_dt_filter[0], config.gs_data_dt_filter[1]), - ) - logger.info(f"Saved static root from '{static_root}'.") - - # Store Static Folders - logger.info("*** Dumping GeoNode static files...") - - static_folders = settings.STATICFILES_DIRS - static_files_folders = os.path.join(target_folder, utils.STATICFILES_DIRS) - if not os.path.exists(static_files_folders): - os.makedirs(static_files_folders, exist_ok=True) - - for static_files_folder in static_folders: - # skip dumping of static files of apps not located under PROJECT_ROOT path - # (check to prevent saving files from site-packages in project-template based GeoNode projects) - if getattr(settings, "PROJECT_ROOT", None) and not static_files_folder.startswith( - settings.PROJECT_ROOT - ): - logger.info( - f"Skipping static directory: {static_files_folder}. " - f"It's not located under PROJECT_ROOT path: {settings.PROJECT_ROOT}." - ) - continue - - static_folder = os.path.join( - static_files_folders, os.path.basename(os.path.normpath(static_files_folder)) - ) - if not os.path.exists(static_folder): - os.makedirs(static_folder, exist_ok=True) - - copy_tree( - static_files_folder, - static_folder, - ignore=utils.ignore_time(config.gs_data_dt_filter[0], config.gs_data_dt_filter[1]), - ) - logger.info(f"Saved static files from '{static_files_folder}'.") - - # Store Template Folders - logger.info("*** Dumping GeoNode template folders...") - - template_folders = [] - try: - template_folders = settings.TEMPLATE_DIRS - except Exception: - try: - template_folders = settings.TEMPLATES[0]["DIRS"] - except Exception: - pass - template_files_folders = os.path.join(target_folder, utils.TEMPLATE_DIRS) - if not os.path.exists(template_files_folders): - os.makedirs(template_files_folders, exist_ok=True) - - for template_files_folder in template_folders: - # skip dumping of template files of apps not located under PROJECT_ROOT path - # (check to prevent saving files from site-packages in project-template based GeoNode projects) - if getattr(settings, "PROJECT_ROOT", None) and not template_files_folder.startswith( - settings.PROJECT_ROOT - ): - logger.info( - f"Skipping template directory: {template_files_folder}. " - f"It's not located under PROJECT_ROOT path: {settings.PROJECT_ROOT}." - ) - continue - - template_folder = os.path.join( - template_files_folders, os.path.basename(os.path.normpath(template_files_folder)) - ) - if not os.path.exists(template_folder): - os.makedirs(template_folder, exist_ok=True) - - copy_tree( - template_files_folder, - template_folder, - ignore=utils.ignore_time(config.gs_data_dt_filter[0], config.gs_data_dt_filter[1]), - ) - logger.info(f"Saved template files from '{template_files_folder}'.") - - # Store Locale Folders - logger.info("*** Dumping GeoNode locale folders...") - locale_folders = settings.LOCALE_PATHS - locale_files_folders = os.path.join(target_folder, utils.LOCALE_PATHS) - if not os.path.exists(locale_files_folders): - os.makedirs(locale_files_folders, exist_ok=True) - - for locale_files_folder in locale_folders: - # skip dumping of locale files of apps not located under PROJECT_ROOT path - # (check to prevent saving files from site-packages in project-template based GeoNode projects) - if getattr(settings, "PROJECT_ROOT", None) and not locale_files_folder.startswith( - settings.PROJECT_ROOT - ): - logger.info( - f"Skipping locale directory: {locale_files_folder}. " - f"It's not located under PROJECT_ROOT path: {settings.PROJECT_ROOT}." - ) - continue - - locale_folder = os.path.join( - locale_files_folders, os.path.basename(os.path.normpath(locale_files_folder)) - ) - if not os.path.exists(locale_folder): - os.makedirs(locale_folder, exist_ok=True) - - copy_tree( - locale_files_folder, - locale_folder, - ignore=utils.ignore_time(config.gs_data_dt_filter[0], config.gs_data_dt_filter[1]), - ) - logger.info(f"Saved Locale Files from '{locale_files_folder}'.") - # Create Final ZIP Archive logger.info("*** Creating final ZIP archive...") diff --git a/geonode/br/management/commands/restore.py b/geonode/br/management/commands/restore.py index 7544c2215fc..95ee228d955 100755 --- a/geonode/br/management/commands/restore.py +++ b/geonode/br/management/commands/restore.py @@ -59,7 +59,11 @@ def add_arguments(self, parser): # Named (optional) arguments utils.option(parser) - utils.geoserver_option_list(parser) + parser.add_argument( + "--geoserver-data-dir", + dest="gs_data_dir", + default=None, + help="Geoserver data directory") parser.add_argument( "-i", @@ -107,7 +111,7 @@ def add_arguments(self, parser): "--recovery-file", dest="recovery_file", default=None, - help="Backup archive containing GeoNode data to restore.", + help="Archive that shall be used to restore the original content of GeoNode should the restore fail.", ) parser.add_argument( @@ -165,7 +169,7 @@ def handle(self, **options): skip_read_only = options.get("skip_read_only") config = Configuration.load() - # activate read only mode and store it's original config value + # activate read only mode and store its original config value if not skip_read_only: original_read_only_value = config.read_only config.read_only = True @@ -261,21 +265,6 @@ def execute_restore(self, **options): # Write Checks media_root = settings.MEDIA_ROOT media_folder = os.path.join(target_folder, utils.MEDIA_ROOT) - static_root = settings.STATIC_ROOT - static_folder = os.path.join(target_folder, utils.STATIC_ROOT) - static_folders = settings.STATICFILES_DIRS - static_files_folders = os.path.join(target_folder, utils.STATICFILES_DIRS) - template_folders = [] - try: - template_folders = settings.TEMPLATE_DIRS - except Exception: - try: - template_folders = settings.TEMPLATES[0]["DIRS"] - except Exception: - pass - template_files_folders = os.path.join(target_folder, utils.TEMPLATE_DIRS) - locale_folders = settings.LOCALE_PATHS - locale_files_folders = os.path.join(target_folder, utils.LOCALE_PATHS) try: logger.info("*** Performing some checks...") @@ -283,20 +272,6 @@ def execute_restore(self, **options): chmod_tree(restore_folder) logger.info(f"[Sanity Check] Full Write Access to media root: '{media_root}' ...") chmod_tree(media_root) - logger.info(f"[Sanity Check] Full Write Access to static root: '{static_root}' ...") - chmod_tree(static_root) - for folder in static_folders: - if getattr(settings, "PROJECT_ROOT", None) and folder.startswith(settings.PROJECT_ROOT): - logger.info(f"[Sanity Check] Full Write Access to static file folder: '{folder}' ...") - chmod_tree(folder) - for folder in template_folders: - if getattr(settings, "PROJECT_ROOT", None) and folder.startswith(settings.PROJECT_ROOT): - logger.info(f"[Sanity Check] Full Write Access to template folder: '{folder}' ...") - chmod_tree(folder) - for folder in locale_folders: - if getattr(settings, "PROJECT_ROOT", None) and folder.startswith(settings.PROJECT_ROOT): - logger.info(f"[Sanity Check] Full Write Access to locale files folder: '{folder}' ...") - chmod_tree(folder) except Exception as e: if notify: restore_notification.apply_async( @@ -361,14 +336,6 @@ def execute_restore(self, **options): logger.info("*** Align the database schema") # call_command('makemigrations', interactive=False) call_command("migrate", interactive=False) - - # db_name = settings.DATABASES['default']['NAME'] - # db_user = settings.DATABASES['default']['USER'] - # db_port = settings.DATABASES['default']['PORT'] - # db_host = settings.DATABASES['default']['HOST'] - # db_passwd = settings.DATABASES['default']['PASSWORD'] - # - # utils.patch_db(db_name, db_user, db_port, db_host, db_passwd, settings.MONITORING_ENABLED) except Exception as e: logger.warning(f"Error while aligning the db: {e}", exc_info=e) @@ -397,8 +364,15 @@ def execute_restore(self, **options): err_cnt = 0 logger.info("*** Restoring GeoNode fixtures...") + + fixtures_folder = os.path.join(target_folder, "fixtures") + if not os.path.exists(fixtures_folder): + # fixtures folder was introduced on 2024-02; make the restore command lenient about + # dumps created without such a folder (this behaviour may be removed in a short while) + fixtures_folder = target_folder + for app_name, dump_name in zip(config.app_names, config.dump_names): - fixture_file = os.path.join(target_folder, f"{dump_name}.json") + fixture_file = os.path.join(fixtures_folder, f"{dump_name}.json") logger.info(f" - restoring '{fixture_file}'") try: @@ -430,109 +404,6 @@ def execute_restore(self, **options): chmod_tree(media_root) logger.info(f"Media files restored into '{media_root}'.") - # Restore Static Root - logger.info("*** Restore static root...") - if config.gs_data_dt_filter[0] is None: - shutil.rmtree(static_root, ignore_errors=True) - - if not os.path.exists(static_root): - os.makedirs(static_root, exist_ok=True) - - copy_tree(static_folder, static_root) - chmod_tree(static_root) - logger.info(f"Static root restored into '{static_root}'.") - - # Restore Static Folders - logger.info("*** Restore static folders...") - - for folder in static_folders: - logger.info(f"* Restoring {folder}...") - - # skip restoration of static files of apps not located under PROJECT_ROOT path - # (check to prevent overriding files from site-packages - # in project-template based GeoNode projects) - if getattr(settings, "PROJECT_ROOT", None) and not folder.startswith(settings.PROJECT_ROOT): - logger.info( - f"Skipping static directory: {folder}. " - f"It's not located under PROJECT_ROOT path: {settings.PROJECT_ROOT}." - ) - continue - - if config.gs_data_dt_filter[0] is None: - logger.info(f"Cleaning {folder}...") - shutil.rmtree(folder, ignore_errors=True) - - logger.info(f"Restoring {folder}...") - if not os.path.exists(folder): - os.makedirs(folder, exist_ok=True) - - copy_tree( - os.path.join(static_files_folders, os.path.basename(os.path.normpath(folder))), folder - ) - chmod_tree(folder) - logger.info(f"Static files restored into '{folder}'.") - - # Restore Template Folders - logger.info("*** Restore template folders...") - for folder in template_folders: - logger.info(f"* Restoring {folder}...") - - # skip restoration of template files of apps not located under PROJECT_ROOT path - # (check to prevent overriding files from site-packages - # in project-template based GeoNode projects) - if getattr(settings, "PROJECT_ROOT", None) and not folder.startswith(settings.PROJECT_ROOT): - logger.info( - f"Skipping template directory: {folder}. " - f"It's not located under PROJECT_ROOT path: {settings.PROJECT_ROOT}." - ) - continue - - if config.gs_data_dt_filter[0] is None: - logger.info(f"Cleaning {folder}...") - shutil.rmtree(folder, ignore_errors=True) - - logger.info(f"Restoring {folder}...") - if not os.path.exists(folder): - os.makedirs(folder, exist_ok=True) - - copy_tree( - os.path.join(template_files_folders, os.path.basename(os.path.normpath(folder))), folder - ) - chmod_tree(folder) - logger.info(f"Template files restored into '{folder}'.") - - # Restore Locale Folders - logger.info("*** Restore locale folders...") - for folder in locale_folders: - logger.info(f"* Restoring {folder}...") - - # skip restoration of locale files of apps not located under PROJECT_ROOT path - # (check to prevent overriding files from site-packages - # in project-template based GeoNode projects) - if getattr(settings, "PROJECT_ROOT", None) and not folder.startswith(settings.PROJECT_ROOT): - logger.info( - f"Skipping locale directory: {folder}. " - f"It's not located under PROJECT_ROOT path: {settings.PROJECT_ROOT}." - ) - continue - - if config.gs_data_dt_filter[0] is None: - logger.info(f"Cleaning {folder}...") - shutil.rmtree(folder, ignore_errors=True) - - logger.info(f"Restoring {folder}...") - if not os.path.exists(folder): - os.makedirs(folder, exist_ok=True) - - copy_tree( - os.path.join(locale_files_folders, os.path.basename(os.path.normpath(folder))), folder - ) - chmod_tree(folder) - logger.info(f"Locale Files Restored into '{folder}'.") - - logger.info("*** Calling collectstatic...") - call_command("collectstatic", interactive=False) - # store backup info restored_backup = RestoredBackup( name=backup_file.rsplit("/", 1)[-1], @@ -771,7 +642,7 @@ def bstr(x): gs_bk_exec_status = gs_backup["restore"]["execution"]["status"] gs_bk_exec_progress = gs_backup["restore"]["execution"]["progress"] - logger.info(f"Async backup status: {gs_bk_exec_status} - {gs_bk_exec_progress}") + logger.info(f"Async restore status: {gs_bk_exec_status} - {gs_bk_exec_progress}") time.sleep(3) else: raise ValueError(error_backup.format(url, r.status_code, r.text)) From 4bd93cc6b667189fe17971b208f24d351e5d648d Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 14 Mar 2024 19:18:54 +0100 Subject: [PATCH 190/253] [Backport 4.2.x] Upgrade to GeoServer 2.24.2 (#12048) * [Fixes #12039] Upgrade to GeoServer 2.24.2 (#12040) * [Fixes #12039] Upgrade to GeoServer 2.24.2 * Update to Geoserver 2.24.2-latest image --------- Co-authored-by: Giovanni Allegri * fix conflict * fixed image version * fixed typo --------- Co-authored-by: Emanuele Tajariol --- docker-compose-test.yml | 4 ++-- docker-compose.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker-compose-test.yml b/docker-compose-test.yml index a0da45aafa0..2d649b8df67 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -92,7 +92,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.3-v2 + image: geonode/geoserver:2.24.2-latest container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -118,7 +118,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.3-v1 + image: geonode/geoserver_data:2.24.2-latest container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: diff --git a/docker-compose.yml b/docker-compose.yml index d073b1cbbcf..d0529c178f4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -91,7 +91,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.3-v2 + image: geonode/geoserver:2.24.2-latest container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -117,7 +117,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.3-v1 + image: geonode/geoserver_data:2.24.2-latest container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: From 0bc9040417ad97b5dcbd844ca36ec161a6b44be9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 16:39:45 +0100 Subject: [PATCH 191/253] [Fixes #12063] Cannot clone map/geoapp with linked resources (#12064) (#12065) (cherry picked from commit f6a2884582e75ab56f8dbc64e1620fe9ae28e1de) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/resource/manager.py | 4 ++-- geonode/resource/tests.py | 22 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/geonode/resource/manager.py b/geonode/resource/manager.py index 6b2cead54ca..ad64452d6dc 100644 --- a/geonode/resource/manager.py +++ b/geonode/resource/manager.py @@ -513,11 +513,11 @@ def copy( defaults.pop("name") _resource.save() for lr in LinkedResource.get_linked_resources(source=instance.pk, is_internal=False): - LinkedResource.object.get_or_create( + LinkedResource.objects.get_or_create( source_id=_resource.pk, target_id=lr.target.pk, internal=False ) for lr in LinkedResource.get_linked_resources(target=instance.pk, is_internal=False): - LinkedResource.object.get_or_create( + LinkedResource.objects.get_or_create( source_id=lr.source.pk, target_id=_resource.pk, internal=False ) diff --git a/geonode/resource/tests.py b/geonode/resource/tests.py index be7f5428c82..9ef2467a6fc 100644 --- a/geonode/resource/tests.py +++ b/geonode/resource/tests.py @@ -29,7 +29,7 @@ from geonode.base.populate_test_data import create_models from geonode.tests.base import GeoNodeBaseTestSupport from geonode.resource.manager import ResourceManager -from geonode.base.models import ResourceBase +from geonode.base.models import LinkedResource, ResourceBase from geonode.layers.models import Dataset from geonode.services.models import Service from geonode.documents.models import Document @@ -173,6 +173,26 @@ def _copy_assert_resource(res, title): self.assertTrue(isinstance(res, Map)) _copy_assert_resource(res, "A Test Map 2") + def test_resource_copy_with_linked_resources(self): + def _copy_assert_resource(res, title): + dataset_copy = None + try: + dataset_copy = self.rm.copy(res, defaults=dict(title=title)) + self.assertIsNotNone(dataset_copy) + self.assertEqual(dataset_copy.title, title) + finally: + if dataset_copy: + dataset_copy.delete() + self.assertIsNotNone(res) + res.delete() + + # copy with maps + res = create_single_map("A Test Map") + target = ResourceBase.objects.first() + LinkedResource.objects.get_or_create(source_id=res.id, target_id=target.id) + self.assertTrue(isinstance(res, Map)) + _copy_assert_resource(res, "A Test Map 2") + @patch.object(ResourceManager, "_validate_resource") def test_append(self, mock_validator): mock_validator.return_value = True From a2e7e66f0249138254c54026bf52a29cd1789986 Mon Sep 17 00:00:00 2001 From: Henning Bredel <881756+ridoo@users.noreply.github.com> Date: Tue, 19 Mar 2024 16:43:17 +0100 Subject: [PATCH 192/253] Fixes wrong mapping to the download links (#7) Closes: https://github.com/Thuenen-GeoNode-Development/thuenen_atlas/issues/21 See also: https://github.com/GeoNode/geonode-mapstore-client/issues/1703 --- geonode/catalogue/backends/pycsw_local_mappings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/catalogue/backends/pycsw_local_mappings.py b/geonode/catalogue/backends/pycsw_local_mappings.py index d9dd78d7845..0c30b0ef597 100644 --- a/geonode/catalogue/backends/pycsw_local_mappings.py +++ b/geonode/catalogue/backends/pycsw_local_mappings.py @@ -86,6 +86,6 @@ "pycsw:Publisher": "publisher", "pycsw:Contributor": "contributor", "pycsw:Relation": "relation", - "pycsw:Links": "download_urls", + "pycsw:Links": "download_links", }, } From d46e227303cb5b6e35580ab9d80515554bbe088c Mon Sep 17 00:00:00 2001 From: Emanuele Tajariol Date: Wed, 20 Mar 2024 20:16:30 +0100 Subject: [PATCH 193/253] [Fixes #12068][Backport 4.2.x] linked_resources API is slow (#12071) * [Fixes #12068][Backport 4.2.x] linked_resources API is slow * Fix black check --- geonode/base/api/tests.py | 124 ++++++++++++++++++++++++----------- geonode/base/api/views.py | 89 +++++++++++++++---------- geonode/geoserver/signals.py | 6 +- 3 files changed, 146 insertions(+), 73 deletions(-) diff --git a/geonode/base/api/tests.py b/geonode/base/api/tests.py index 4833a955484..bbff21b3267 100644 --- a/geonode/base/api/tests.py +++ b/geonode/base/api/tests.py @@ -1951,10 +1951,10 @@ def test_set_resource_thumbnail(self): self.assertEqual(response.json(), "The url must be of an image with format (png, jpeg or jpg)") # using Base64 data as an ASCII byte string - data[ - "file" - ] = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\ + data["file"] = ( + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\ fAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAANSURBVAiZYzAxMfkPAALYAZzx61+bAAAAAElFTkSuQmCC" + ) with patch("geonode.base.models.is_monochromatic_image") as _mck: _mck.return_value = False response = self.client.put(url, data=data, format="json") @@ -2623,15 +2623,6 @@ def test_linked_resource_for_document(self): # validation self.assertEqual(response.status_code, 200) payload = response.json() - self.assert_linkedres_size(payload, "resources", 2) - self.assert_linkedres_contains( - payload, - "resources", - ( - {"pk": self.map.id, "title": ">>> " + self.map.title}, - {"pk": self.dataset.id, "title": ">>> " + self.dataset.title}, - ), - ) self.assert_linkedres_size(payload, "linked_to", 2) self.assert_linkedres_contains( payload, @@ -2644,7 +2635,11 @@ def test_linked_resource_for_document(self): d.delete() def assert_linkedres_size(self, payload, element: str, expected_size: int): - self.assertEqual(expected_size, len(payload[element]), f"Mismatching payload size of {element}") + self.assertEqual( + expected_size, + len(payload[element]), + f"Mismatching payload size of '{element}': exp:{expected_size} found:{payload[element]}", + ) def assert_linkedres_contains(self, payload, element: str, expected_elements: Iterable): res_list = payload[element] @@ -2684,15 +2679,6 @@ def test_linked_resource_for_maps_mixed(self): self.assertEqual(response.status_code, 200) payload = response.json() - self.assert_linkedres_size(payload, "resources", 2) - self.assert_linkedres_contains( - payload, - "resources", - ( - {"pk": self.doc.id, "title": "<<< " + self.doc.title}, - {"pk": self.dataset.id, "title": ">>> " + self.dataset.title}, - ), - ) self.assert_linkedres_size(payload, "linked_to", 1) self.assert_linkedres_contains( payload, "linked_to", ({"pk": self.dataset.id, "title": self.dataset.title},) @@ -2705,6 +2691,7 @@ def test_linked_resource_for_maps_mixed(self): d.delete() def test_linked_resources_for_maps(self): + _m = None try: # data preparation _m = MapLayer.objects.create( @@ -2723,10 +2710,6 @@ def test_linked_resources_for_maps(self): self.assertEqual(response.status_code, 200) payload = response.json() - self.assert_linkedres_size(payload, "resources", 1) - self.assert_linkedres_contains( - payload, "resources", ({"pk": self.dataset.id, "title": ">>> " + self.dataset.title},) - ) self.assert_linkedres_size(payload, "linked_to", 1) self.assert_linkedres_contains( payload, "linked_to", ({"pk": self.dataset.id, "title": self.dataset.title},) @@ -2757,10 +2740,6 @@ def test_linked_resource_for_dataset(self): self.assertEqual(response.status_code, 200) payload = response.json() - self.assert_linkedres_size(payload, "resources", 1) - self.assert_linkedres_contains( - payload, "resources", ({"pk": self.map.id, "title": "<<< " + self.map.title},) - ) self.assert_linkedres_size(payload, "linked_to", 0) self.assert_linkedres_size(payload, "linked_by", 1) self.assert_linkedres_contains(payload, "linked_by", ({"pk": self.map.id, "title": self.map.title},)) @@ -2791,15 +2770,6 @@ def test_linked_resource_for_datasets_mixed(self): # validation self.assertEqual(response.status_code, 200) payload = response.json() - self.assert_linkedres_size(payload, "resources", 2) - self.assert_linkedres_contains( - payload, - "resources", - ( - {"pk": self.doc.id, "title": "<<< " + self.doc.title}, - {"pk": self.map.id, "title": "<<< " + self.map.title}, - ), - ) self.assert_linkedres_size(payload, "linked_to", 0) self.assert_linkedres_size(payload, "linked_by", 2) self.assert_linkedres_contains( @@ -2848,6 +2818,82 @@ def test_linked_resource_deprecated_pagination(self): for d in _d: d.delete() + def test_linked_resource_filter_one_resource_type(self): + _d = [] + try: + # data preparation + _d.append(LinkedResource.objects.create(source_id=self.doc.id, target_id=self.dataset.id)) + _d.append(LinkedResource.objects.create(source_id=self.doc.id, target_id=self.map.id)) + resource_type_param = "dataset" + # call api with single resource_type param + url = reverse("base-resources-linked_resources", args=[self.doc.id]) + response = self.client.get(f"{url}?resource_type={resource_type_param}") + + # validation + self.assertEqual(response.status_code, 200) + payload = response.json() + + res_types_orig = resource_type_param.split(",") + res_types_payload = [res["resource_type"] for res in payload["linked_to"]] + for r in res_types_payload: + self.assertTrue(r in res_types_orig) + + finally: + for d in _d: + d.delete() + + def test_linked_resource_filter_multiple_resource_type_linktype(self): + _d = [] + try: + # data preparation + _d.append(LinkedResource.objects.create(source_id=self.doc.id, target_id=self.dataset.id)) + _d.append(LinkedResource.objects.create(source_id=self.doc.id, target_id=self.map.id)) + resource_type_param = "map" + link_type = "linked_to" + # call the API w/ both parameters + url = reverse("base-resources-linked_resources", args=[self.doc.id]) + response = self.client.get(f"{url}?resource_type={resource_type_param}&link_type={link_type}") + + # validation + self.assertEqual(response.status_code, 200) + payload = response.json() + + res_types_orig = resource_type_param.split(",") + res_types_payload = [res["resource_type"] for res in payload["linked_to"]] + for type in res_types_payload: + self.assertTrue(type in res_types_orig) + self.assertTrue({"linked_to", "WARNINGS"} == set(payload.keys())) + + finally: + for d in _d: + d.delete() + + def test_linked_resource_filter_multiple_resource_type_without_linktype(self): + _d = [] + try: + # data preparation + _d.append(LinkedResource.objects.create(source_id=self.doc.id, target_id=self.dataset.id)) + _d.append(LinkedResource.objects.create(source_id=self.doc.id, target_id=self.map.id)) + resource_type_param = "dataset,map" + # call the API w/ resource_type + url = reverse("base-resources-linked_resources", args=[self.doc.id]) + response = self.client.get(f"{url}?resource_type={resource_type_param}") + + # validation + self.assertEqual(response.status_code, 200) + payload = response.json() + + res_types_orig = resource_type_param.split(",") + res_types_payload = [res["resource_type"] for res in payload["linked_to"]] + for type in res_types_payload: + self.assertTrue(type in res_types_orig) + payload_keys = {"linked_by", "linked_to", "WARNINGS"} + self.assertTrue(payload_keys == set(payload.keys())) + + finally: + for d in _d: + d.delete() + class TestApiAdditionalBBoxCalculation(GeoNodeBaseTestSupport): @classmethod diff --git a/geonode/base/api/views.py b/geonode/base/api/views.py index 2721fd7c195..6132b54a412 100644 --- a/geonode/base/api/views.py +++ b/geonode/base/api/views.py @@ -17,6 +17,7 @@ # ######################################################################### import ast +import functools import json import re @@ -33,7 +34,7 @@ from django.shortcuts import get_object_or_404 from django.urls import reverse from django.conf import settings -from django.db.models import Subquery +from django.db.models import Subquery, QuerySet from django.http.request import QueryDict from django.contrib.auth import get_user_model @@ -97,7 +98,6 @@ ) from .serializers import ( FavoriteSerializer, - SimpleResourceSerializer, UserSerializer, PermSpecSerialiazer, GroupProfileSerializer, @@ -1493,47 +1493,70 @@ def linked_resources(self, request, pk, *args, **kwargs): def base_linked_resources(instance, user, params): + try: - visibile_resources = get_visible_resources( - ResourceBase.objects, + resource_type = params.get("resource_type") + link_type = params.get("link_type") + type_list = resource_type.split(",") if resource_type else [] + + warnings = {} + + if "page_size" in params or "page" in params: + warnings["PAGINATION"] = "Pagination is not supported on this call" + + ret = {"WARNINGS": warnings} + + get_visible_resources_p = functools.partial( + get_visible_resources, user=user, admin_approval_required=settings.ADMIN_MODERATE_UPLOADS, unpublished_not_visible=settings.RESOURCE_PUBLISHING, private_groups_not_visibile=settings.GROUP_PRIVATE_RESOURCES, - ).order_by("-pk") - visible_ids = [res.id for res in visibile_resources] + ) - linked_resources = [lres for lres in instance.get_linked_resources() if lres.target.id in visible_ids] - linked_by = [lres for lres in instance.get_linked_resources(as_target=True) if lres.source.id in visible_ids] + if not link_type or link_type == "linked_to": + # list of linked resources, probably extended by ResourceBase's child class - may be loopable only once + linked_to_over = instance.get_linked_resources() - warnings = { - "DEPRECATION": "'resources' field is deprecated, please use 'linked_to'", - } + # resolve the ids of linked resources - using either e QuerySet (preferred) or a list + if isinstance(linked_to_over, QuerySet): + linked_to_over_loopable = linked_to_over + linked_to_id_values = linked_to_over.values("target_id") + else: + linked_to_over_loopable = [lr for lr in linked_to_over] + linked_to_id_values = [lr.target_id for lr in linked_to_over_loopable] - if "page_size" in params or "page" in params: - warnings["PAGINATION"] = "Pagination is not supported on this call" + # filter resources by visibility / permissions + linked_to_visib = get_visible_resources_p(ResourceBase.objects.filter(id__in=linked_to_id_values)).order_by( + "-pk" + ) + # optionally filter by resource type + linked_to_visib = linked_to_visib.filter(resource_type__in=type_list) if type_list else linked_to_visib + linked_to_visib_ids = linked_to_visib.values_list("id", flat=True) + linked_to = [lres for lres in linked_to_over_loopable if lres.target.id in linked_to_visib_ids] + + ret["linked_to"] = LinkedResourceSerializer(linked_to, embed=True, many=True).data + + if not link_type or link_type == "linked_by": + linked_by_over = instance.get_linked_resources(as_target=True) + if isinstance(linked_by_over, QuerySet): + linked_by_over_loopable = linked_by_over + linked_by_id_values = linked_by_over.values("source_id") + else: + linked_by_over_loopable = [lr for lr in linked_by_over] + linked_by_id_values = [lr.source_id for lr in linked_by_over_loopable] - # "resources" will be deprecated, so next block is temporary - # "resources" at the moment it's the only element rendered, so we want to add there both the linked_resources and the linked_by - # we want to tell them apart, so we're adding an attr to store this info, that will be used in the SimpleResourceSerializer - resources = [] - for lres in linked_resources: - res = lres.target - setattr(res, "is_target", True) - resources.append(res) - for lres in linked_by: - res = lres.source - setattr(res, "is_target", False) - resources.append(res) - - ret = { - "WARNINGS": warnings, - "resources": SimpleResourceSerializer(resources, embed=True, many=True).data, # deprecated - "linked_to": LinkedResourceSerializer(linked_resources, embed=True, many=True).data, - "linked_by": LinkedResourceSerializer( + linked_by_visib = get_visible_resources_p(ResourceBase.objects.filter(id__in=linked_by_id_values)).order_by( + "-pk" + ) + + linked_by_visib = linked_by_visib.filter(resource_type__in=type_list) if type_list else linked_by_visib + linked_by_visib_ids = linked_by_visib.values_list("id", flat=True) + linked_by = [lres for lres in linked_by_over_loopable if lres.source.id in linked_by_visib_ids] + + ret["linked_by"] = LinkedResourceSerializer( instance=linked_by, serialize_source=True, embed=True, many=True - ).data, - } + ).data return Response(ret) diff --git a/geonode/geoserver/signals.py b/geonode/geoserver/signals.py index 70b96060303..e8b36dcde0f 100644 --- a/geonode/geoserver/signals.py +++ b/geonode/geoserver/signals.py @@ -18,6 +18,7 @@ ######################################################################### import errno import logging +from requests.exceptions import ConnectionError from deprecated import deprecated from geoserver.layer import Layer as GsLayer @@ -90,10 +91,13 @@ def geoserver_pre_save_maplayer(instance, sender, **kwargs): try: instance.local = isinstance(gs_catalog.get_layer(instance.name), GsLayer) + except ConnectionError as e: + logger.warning(f"Could not connect to catalog to verify if layer {instance.name} was local: {e}") except OSError as e: + logger.warning(f"***** OSERROR TYPE:{type(e)} ERR:{e} ERRNO:{e.errno}") if e.errno == errno.ECONNREFUSED: msg = f"Could not connect to catalog to verify if layer {instance.name} was local" - logger.warn(msg) + logger.warning(msg) else: raise e From 650deb4ce1f476db39c7115290a48536b16da266 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 21 Mar 2024 17:08:05 +0100 Subject: [PATCH 194/253] [Backport #12050] [Fixes #12049] Adapt the SLD and XML upload forms to the new progress API (#12075) * [Fixes #12049] Adapt the SLD and XML upload forms to the new progress API (#12050) * Adapt SLD and XML forms to the new API * change source name and delete execution when completed * Fixed LayerInfo.js --- geonode/geoserver/context_processors.py | 1 + .../datasets/dataset_metadata_upload.html | 1 + .../datasets/dataset_style_upload.html | 1 + geonode/settings.py | 4 +- geonode/static/geonode/js/upload/LayerInfo.js | 44 ++++++++++++++++--- 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/geonode/geoserver/context_processors.py b/geonode/geoserver/context_processors.py index 464cfffa772..572a02469a1 100644 --- a/geonode/geoserver/context_processors.py +++ b/geonode/geoserver/context_processors.py @@ -30,6 +30,7 @@ def geoserver_urls(request): GEOSERVER_BASE_URL=ogc_server_settings.public_url, UPLOADER_URL=reverse("importer_upload"), LAYER_ANCILLARY_FILES_UPLOAD_URL=reverse("importer_upload"), + EXECUTION_STATUS_ENDPOINT=reverse("executionrequest-list"), MAPFISH_PRINT_ENABLED=getattr(ogc_server_settings, "MAPFISH_PRINT_ENABLED", False), PRINT_NG_ENABLED=getattr(ogc_server_settings, "PRINT_NG_ENABLED", False), GEONODE_SECURITY_ENABLED=getattr(ogc_server_settings, "GEONODE_SECURITY_ENABLED", False), diff --git a/geonode/layers/templates/datasets/dataset_metadata_upload.html b/geonode/layers/templates/datasets/dataset_metadata_upload.html index 6ef4d3d2e55..b5238bdf372 100644 --- a/geonode/layers/templates/datasets/dataset_metadata_upload.html +++ b/geonode/layers/templates/datasets/dataset_metadata_upload.html @@ -80,6 +80,7 @@

    {% trans "Files to be uploaded" %}

    csrf_token = "{{ csrf_token }}", form_target = "{{ LAYER_ANCILLARY_FILES_UPLOAD_URL }}", + executions_status_endpoint = "{{EXECUTION_STATUS_ENDPOINT}}", time_enabled = false, mosaic_enabled = false, userLookup = "{% url "account_ajax_lookup" %}" diff --git a/geonode/layers/templates/datasets/dataset_style_upload.html b/geonode/layers/templates/datasets/dataset_style_upload.html index 6b873fab6c4..ac90cbd9d34 100644 --- a/geonode/layers/templates/datasets/dataset_style_upload.html +++ b/geonode/layers/templates/datasets/dataset_style_upload.html @@ -81,6 +81,7 @@

    {% trans "Files to be uploaded" %}

    csrf_token = "{{ csrf_token }}", form_target = "{{ LAYER_ANCILLARY_FILES_UPLOAD_URL }}", + executions_status_endpoint = "{{EXECUTION_STATUS_ENDPOINT}}", time_enabled = false, mosaic_enabled = false, userLookup = "{% url "account_ajax_lookup" %}" diff --git a/geonode/settings.py b/geonode/settings.py index 2224bce108f..d42d330a2cf 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -2347,7 +2347,9 @@ def get_geonode_catalogue_service(): 'importer.handlers.shapefile.handler.ShapeFileHandler',\ 'importer.handlers.kml.handler.KMLFileHandler',\ 'importer.handlers.csv.handler.CSVFileHandler',\ - 'importer.handlers.geotiff.handler.GeoTiffFileHandler'\ + 'importer.handlers.geotiff.handler.GeoTiffFileHandler',\ + 'importer.handlers.xml.handler.XMLFileHandler',\ + 'importer.handlers.sld.handler.SLDFileHandler',\ ]", ) ) diff --git a/geonode/static/geonode/js/upload/LayerInfo.js b/geonode/static/geonode/js/upload/LayerInfo.js index 4d4c4385172..cb6500cb0ab 100644 --- a/geonode/static/geonode/js/upload/LayerInfo.js +++ b/geonode/static/geonode/js/upload/LayerInfo.js @@ -404,6 +404,14 @@ define(function (require, exports) { }); }; + LayerInfo.prototype.markEnd = function () { + this.logStatus({ + msg: 'Your upload was succesfull!', + level: 'alert-success', + empty: 'true' + }); + }; + LayerInfo.prototype.doResume = function (event) { $(this).text(gettext('Finalizing')).attr('disabled', 'disabled').after(''); var id = (new Date()).getTime(); @@ -479,13 +487,36 @@ define(function (require, exports) { }); }; - LayerInfo.prototype.startPolling = function() { + LayerInfo.prototype.startPolling = function(execution_id) { var self = this; + const baseUrl = executions_status_endpoint; if (self.polling) { - $.ajax({ url: updateUrl(siteUrl + "upload/progress", 'id', self.id), type: 'GET', success: function(data){ + $.ajax({ + url: baseUrl + "?import&filter{source}=resource_file_upload&page=1&page_size=99999", type: 'GET', success: function(data){ // TODO: Not sure we need to do anything here? //console.log('polling'); - }, dataType: "json", complete: setTimeout(function() {self.startPolling()}, 3000), timeout: 30000 }); + }, + dataType: "json", + success: function(resp, code) { + if (resp.requests && resp.requests.length>0) { + const execution_data = resp.requests.find((req) => req.exec_id === execution_id); + if (execution_data.status == 'finished'){ + self.polling = false; + self.markEnd(); + $.ajax({url: baseUrl + "/" + execution_id, type: "DELETE"}); + if (execution_data.output_params && execution_data.output_params['detail_url']) { + const detail_url = execution_data.output_params['detail_url']; + if (detail_url != '') { + window.location = detail_url; + } + } + + } + } + setTimeout(function() {self.startPolling(execution_id)}, 3000) + }, + timeout: 30000 + }) } }; @@ -675,8 +706,6 @@ define(function (require, exports) { }, beforeSend: function () { self.markStart(); - self.polling = true; - self.startPolling(); }, error: function (jqXHR) { self.polling = false; @@ -713,13 +742,16 @@ define(function (require, exports) { callback(array); }, success: function (resp, status) { - self.logStatus({ + /*self.logStatus({ msg: '

    ' + gettext('Layer files uploaded, configuring in GeoServer') + '

    ', level: 'alert-success', empty: 'true' }); self.id = resp.id; self.doStep(resp, callback, array); + */ + self.polling = true; + self.startPolling(resp.execution_id); } }); }; From d5d7b6e8cf13620f35b76e842cfba46c43b9d85d Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 27 Mar 2024 12:30:43 +0100 Subject: [PATCH 195/253] Release 4.2.3 (#12093) --- docker-compose-dev.yml | 4 ++-- docker-compose-test.yml | 4 ++-- docker-compose.yml | 9 +++------ geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 19b81b0985a..b1973f64aab 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -79,7 +79,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.3-v2 + image: geonode/geoserver:2.24.2-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -105,7 +105,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.3-v1 + image: geonode/geoserver_data:2.24.2-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 2d649b8df67..7b085c5e6d0 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -92,7 +92,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.24.2-latest + image: geonode/geoserver:2.24.2-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -118,7 +118,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.24.2-latest + image: geonode/geoserver_data:2.24.2-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: diff --git a/docker-compose.yml b/docker-compose.yml index d0529c178f4..ca203e8c858 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:4.2.x + image: geonode/geonode:4.2.3 restart: unless-stopped env_file: - .env @@ -22,9 +22,6 @@ services: # Our custom django application. It includes Geonode. django: << : *default-common-django - build: - context: ./ - dockerfile: Dockerfile container_name: django4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://django:8000/" @@ -91,7 +88,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.24.2-latest + image: geonode/geoserver:2.24.2-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -117,7 +114,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.24.2-latest + image: geonode/geoserver_data:2.24.2-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: diff --git a/geonode/__init__.py b/geonode/__init__.py index 9b1e32fbb4d..08d6c164079 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 0, "dev", 0) +__version__ = (4, 2, 3, "final", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 70f7db16c82..25559512627 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. --e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.2.0 +geonode-importer==1.0.8 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 01c83ee8f1f..99d74f19ed4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.1.1,<5.0.0 - geonode-importer>=1.0.6 + django-geonode-mapstore-client==4.2.0 + geonode-importer==1.0.8 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 567191c620136f84286abb7bad9ce0dc00cbcfb2 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 11 Apr 2024 10:57:35 +0200 Subject: [PATCH 196/253] Use the Docker build on master (#12149) * Use the Docker build on master * also for celery * use local builds also for the other composes --- docker-compose-dev.yml | 6 +++--- docker-compose-test.yml | 6 +++--- docker-compose.yml | 3 +++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index b1973f64aab..1b408d1c6f0 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -4,6 +4,9 @@ version: '3.9' x-common-django: &default-common-django image: geonode/geonode:local + build: + context: ./ + dockerfile: Dockerfile restart: unless-stopped env_file: - .env @@ -23,9 +26,6 @@ services: # Our custom django application. It includes Geonode. django: << : *default-common-django - build: - context: ./ - dockerfile: Dockerfile container_name: django4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://django:8000/" diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 7b085c5e6d0..8edc8b2194b 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -4,6 +4,9 @@ version: '3.9' x-common-django: &default-common-django image: geonode/geonode:local + build: + context: ./ + dockerfile: Dockerfile restart: unless-stopped env_file: - .env_test @@ -23,9 +26,6 @@ services: # Our custom django application. It includes Geonode. django: << : *default-common-django - build: - context: ./ - dockerfile: Dockerfile container_name: django4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://django:8000/" diff --git a/docker-compose.yml b/docker-compose.yml index ca203e8c858..7adb4337403 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,6 +4,9 @@ version: '3.9' x-common-django: &default-common-django image: geonode/geonode:4.2.3 + build: + context: ./ + dockerfile: Dockerfile restart: unless-stopped env_file: - .env From 57e5841f8b6f3b5e89e4d233be2363681f9c758b Mon Sep 17 00:00:00 2001 From: mwallschlaeger Date: Thu, 18 Apr 2024 08:52:42 +0200 Subject: [PATCH 197/253] [Fixes #12170] unable to set advanced contact roles in metadata editor --- geonode/base/widgets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/base/widgets.py b/geonode/base/widgets.py index b1281de7dd7..5c1f2d16726 100644 --- a/geonode/base/widgets.py +++ b/geonode/base/widgets.py @@ -33,7 +33,7 @@ def value_from_datadict(self, data, files, name) -> List[str]: returns list of selected elements """ try: - ret_list = data[name] + ret_list = data.getlist(name) except KeyError: ret_list = [] finally: From c846db55a3bd1af11d334ee322b236e07450f003 Mon Sep 17 00:00:00 2001 From: mwallschlaeger Date: Fri, 19 Apr 2024 08:42:48 +0200 Subject: [PATCH 198/253] [Fixes #12170] unable to set advanced contact roles in metadata editor --- geonode/base/models.py | 3 +-- geonode/base/widgets.py | 13 +++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/geonode/base/models.py b/geonode/base/models.py index 5768df93281..4141c44bd18 100644 --- a/geonode/base/models.py +++ b/geonode/base/models.py @@ -1707,8 +1707,7 @@ def set_contact_roles_from_metadata_edit(self, resource_base_form) -> bool: failed = False for role in self.get_multivalue_role_property_names(): try: - if resource_base_form.cleaned_data[role].exists(): - self.__setattr__(role, resource_base_form.cleaned_data[role]) + self.__setattr__(role, resource_base_form.cleaned_data[role]) except AttributeError: logger.warning(f"unable to set contact role {role} for {self} ...") failed = True diff --git a/geonode/base/widgets.py b/geonode/base/widgets.py index 5c1f2d16726..87b17b523ad 100644 --- a/geonode/base/widgets.py +++ b/geonode/base/widgets.py @@ -1,6 +1,7 @@ from typing import List from dal_select2_taggit.widgets import TaggitSelect2 +from django.http.request import QueryDict class TaggitSelect2Custom(TaggitSelect2): @@ -32,9 +33,9 @@ def value_from_datadict(self, data, files, name) -> List[str]: returns list of selected elements """ - try: - ret_list = data.getlist(name) - except KeyError: - ret_list = [] - finally: - return ret_list + if type(data) is dict and "name" in data: + return data["name"] + elif type(data) is QueryDict: + print("QUERYDICT") + return data.getlist(name) + return [] From 4cef45237d837d3aa477cae13ca44216ffada485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Wallschl=C3=A4ger?= Date: Fri, 19 Apr 2024 09:49:03 +0200 Subject: [PATCH 199/253] [Fixes #12170] unable to set advanced contact roles in metadata editor --- geonode/base/widgets.py | 1 - 1 file changed, 1 deletion(-) diff --git a/geonode/base/widgets.py b/geonode/base/widgets.py index 87b17b523ad..17e3e3c4b17 100644 --- a/geonode/base/widgets.py +++ b/geonode/base/widgets.py @@ -36,6 +36,5 @@ def value_from_datadict(self, data, files, name) -> List[str]: if type(data) is dict and "name" in data: return data["name"] elif type(data) is QueryDict: - print("QUERYDICT") return data.getlist(name) return [] From 087ba427bb1ea41fbb57fddf63be97a4653c58cc Mon Sep 17 00:00:00 2001 From: mwallschlaeger Date: Fri, 19 Apr 2024 12:52:31 +0200 Subject: [PATCH 200/253] [Fixes #12170] unable to set advanced contact roles in metadata editor --- geonode/base/models.py | 8 ++++++-- geonode/base/widgets.py | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/geonode/base/models.py b/geonode/base/models.py index 4141c44bd18..c75918c755e 100644 --- a/geonode/base/models.py +++ b/geonode/base/models.py @@ -1752,9 +1752,13 @@ def __create_role__( ContactRole.objects.filter(role=role, resource=self).delete() return __create_role__(self, role, user_profile) - elif isinstance(user_profile, list) and all(isinstance(x, get_user_model()) for x in user_profile): + elif isinstance(user_profile, list) and all( + get_user_model().objects.filter(username=x).exists() for x in user_profile + ): ContactRole.objects.filter(role=role, resource=self).delete() - return [__create_role__(self, role, profile) for profile in user_profile] + return [ + __create_role__(self, role, user) for user in get_user_model().objects.filter(username__in=user_profile) + ] elif user_profile is None: ContactRole.objects.filter(role=role, resource=self).delete() diff --git a/geonode/base/widgets.py b/geonode/base/widgets.py index 17e3e3c4b17..a4e32bb94d4 100644 --- a/geonode/base/widgets.py +++ b/geonode/base/widgets.py @@ -33,8 +33,8 @@ def value_from_datadict(self, data, files, name) -> List[str]: returns list of selected elements """ - if type(data) is dict and "name" in data: - return data["name"] + if type(data) is dict and name in data: + return data[name] elif type(data) is QueryDict: return data.getlist(name) return [] From 10d2d7993ff7fa1cdae329b3f133f01ee51fd006 Mon Sep 17 00:00:00 2001 From: mwallschlaeger Date: Wed, 24 Apr 2024 11:08:18 +0200 Subject: [PATCH 201/253] [Fixes #12170] unable to set advanced contact roles in metadata editor --- .../documents/templates/layouts/doc_panels.html | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/geonode/documents/templates/layouts/doc_panels.html b/geonode/documents/templates/layouts/doc_panels.html index d354531d314..c6eebcb6723 100644 --- a/geonode/documents/templates/layouts/doc_panels.html +++ b/geonode/documents/templates/layouts/doc_panels.html @@ -596,22 +596,6 @@
    {% endblock document_more_contact_roles %} - -
    -
    {% trans "Responsible and Permissions" %}
    -
    -
    - - - {{ document_form.owner }} -
    -
    - - - {{ document_form.metadata_author }} -
    -
    -
    From 792a151a15129320c9d46ff4b08c99875c162e34 Mon Sep 17 00:00:00 2001 From: Marcel Wallschlaeger Date: Tue, 30 Apr 2024 20:44:40 +0200 Subject: [PATCH 202/253] [Fixes #12170] unable to set advanced contact roles in metadata editor --- geonode/base/api/tests.py | 6 +++--- geonode/base/api/views.py | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/geonode/base/api/tests.py b/geonode/base/api/tests.py index bbff21b3267..94dae413cd5 100644 --- a/geonode/base/api/tests.py +++ b/geonode/base/api/tests.py @@ -1951,10 +1951,10 @@ def test_set_resource_thumbnail(self): self.assertEqual(response.json(), "The url must be of an image with format (png, jpeg or jpg)") # using Base64 data as an ASCII byte string - data["file"] = ( - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\ + data[ + "file" + ] = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\ fAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAANSURBVAiZYzAxMfkPAALYAZzx61+bAAAAAElFTkSuQmCC" - ) with patch("geonode.base.models.is_monochromatic_image") as _mck: _mck.return_value = False response = self.client.put(url, data=data, format="json") diff --git a/geonode/base/api/views.py b/geonode/base/api/views.py index 6132b54a412..31891c6ad14 100644 --- a/geonode/base/api/views.py +++ b/geonode/base/api/views.py @@ -1493,7 +1493,6 @@ def linked_resources(self, request, pk, *args, **kwargs): def base_linked_resources(instance, user, params): - try: resource_type = params.get("resource_type") link_type = params.get("link_type") From 9913230bd3dbfcddd994c1ba5880280e999f803b Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Mon, 6 May 2024 12:40:31 +0200 Subject: [PATCH 203/253] Use dev deps on stable dev branch --- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 25559512627..70f7db16c82 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -django-geonode-mapstore-client==4.2.0 -geonode-importer==1.0.8 +-e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client +-e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 99d74f19ed4..01c83ee8f1f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client==4.2.0 - geonode-importer==1.0.8 + django-geonode-mapstore-client>=4.1.1,<5.0.0 + geonode-importer>=1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 1a5a48aba901647ee30861a52ce0950921d62806 Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Tue, 7 May 2024 10:42:33 +0200 Subject: [PATCH 204/253] Upgrade Geoserver datadir --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 7adb4337403..d0173dd5109 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -117,7 +117,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.24.2-v1 + image: geonode/geoserver_data:2.24.2-v2 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: From e45d32bc93bd72485b928880ccfa950bcff85bdf Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Wed, 8 May 2024 11:36:46 +0200 Subject: [PATCH 205/253] Release 4.2.4 --- docker-compose.yml | 5 +---- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index d0173dd5109..5359007392d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,10 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:4.2.3 - build: - context: ./ - dockerfile: Dockerfile + image: geonode/geonode:4.2.4 restart: unless-stopped env_file: - .env diff --git a/geonode/__init__.py b/geonode/__init__.py index 08d6c164079..256f61ef1db 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 3, "final", 0) +__version__ = (4, 2, 4, "final", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 70f7db16c82..25559512627 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. --e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.2.0 +geonode-importer==1.0.8 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 01c83ee8f1f..99d74f19ed4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.1.1,<5.0.0 - geonode-importer>=1.0.6 + django-geonode-mapstore-client==4.2.0 + geonode-importer==1.0.8 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From ea34af01fff334cc2e716380711bc60e39824389 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Fri, 10 May 2024 10:50:24 +0200 Subject: [PATCH 206/253] Bump 4.2.x to dev (#12212) * Bump to dev * Bump version * Bump client minimum version --- docker-compose.yml | 3 +++ geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 5359007392d..50f5147d522 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,6 +4,9 @@ version: '3.9' x-common-django: &default-common-django image: geonode/geonode:4.2.4 + build: + context: ./ + dockerfile: Dockerfile restart: unless-stopped env_file: - .env diff --git a/geonode/__init__.py b/geonode/__init__.py index 256f61ef1db..dc6d49f1968 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 4, "final", 0) +__version__ = (4, 2, 5, "dev", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 25559512627..70f7db16c82 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -django-geonode-mapstore-client==4.2.0 -geonode-importer==1.0.8 +-e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client +-e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 99d74f19ed4..1e9bdb2e87c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client==4.2.0 - geonode-importer==1.0.8 + django-geonode-mapstore-client>=4.2.0,<5.0.0 + geonode-importer>=1.0.8 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 1fe021d0b5c8a5118cc1be3bec0d27b782e3b977 Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Fri, 10 May 2024 12:45:12 +0200 Subject: [PATCH 207/253] dev branch 4.3.x creation --- geonode/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/__init__.py b/geonode/__init__.py index 4c56c53ace5..177ce1f12df 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 4, 0, "dev", 0) +__version__ = (4, 3, 0, "dev", 0) def get_version(): From 25a4e700e15f631bc13837e0784fcc4b92694f02 Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Fri, 10 May 2024 12:54:33 +0200 Subject: [PATCH 208/253] Bump minimum dev dependencies --- requirements.txt | 2 +- setup.cfg | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index e2c38442d45..1e80b79c5d8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -86,7 +86,7 @@ git+https://github.com/GeoNode/pinax-notifications.git@django_upgrade#egg=pinax- # GeoNode org maintained apps. # django-geonode-mapstore-client==4.0.5 -git+https://github.com/GeoNode/geonode-mapstore-client.git@master#egg=django_geonode_mapstore_client +git+https://github.com/GeoNode/geonode-mapstore-client.git@4.3.x#egg=django_geonode_mapstore_client git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer django-avatar==8.0.0 git+https://github.com/GeoNode/geonode-oauth-toolkit.git@openid-connect#egg=geonode-oauth-toolkit diff --git a/setup.cfg b/setup.cfg index 1c67a897dc2..14695a6fbd3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -111,8 +111,8 @@ install_requires = pinax-notifications @ git+https://github.com/GeoNode/pinax-notifications.git@django_upgrade#egg=pinax-notifications # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.0.5,<5.0.0 - geonode-importer>=1.0.2 + django-geonode-mapstore-client>=4.3.0,<5.0.0 + geonode-importer>=1.0.8 django-avatar==8.0.0 geonode-oauth-toolkit @ git+https://github.com/GeoNode/geonode-oauth-toolkit.git@openid-connect#egg=geonode-oauth-toolkit geonode-user-messages @ git+https://github.com/GeoNode/geonode-user-messages.git@django_upgrade#egg=geonode-user-messages From 632689d3bb5557fae971195c2f939cd9dc062360 Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Fri, 10 May 2024 13:29:13 +0200 Subject: [PATCH 209/253] revert minimum version of client --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 14695a6fbd3..51facc35024 100644 --- a/setup.cfg +++ b/setup.cfg @@ -111,7 +111,7 @@ install_requires = pinax-notifications @ git+https://github.com/GeoNode/pinax-notifications.git@django_upgrade#egg=pinax-notifications # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.3.0,<5.0.0 + django-geonode-mapstore-client>=4.2.0,<5.0.0 geonode-importer>=1.0.8 django-avatar==8.0.0 geonode-oauth-toolkit @ git+https://github.com/GeoNode/geonode-oauth-toolkit.git@openid-connect#egg=geonode-oauth-toolkit From b85334c42d83f73171f62826ebfaacb062527568 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 15 May 2024 17:52:39 +0200 Subject: [PATCH 210/253] tinymce is not visible after the upgrade to v4 (#12231) --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 1e80b79c5d8..ba8fb45a038 100644 --- a/requirements.txt +++ b/requirements.txt @@ -42,7 +42,7 @@ django-guardian<2.4.1 django-downloadview==2.3.0 django-polymorphic==3.1.0 django-tastypie<0.15.0 -django-tinymce==4.0.0 +django-tinymce==3.7.1 django-grappelli==3.0.8 django-uuid-upload-path==1.0.0 django-widget-tweaks==1.5.0 diff --git a/setup.cfg b/setup.cfg index 51facc35024..6f307884a2e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -68,7 +68,7 @@ install_requires = django-downloadview==2.3.0 django-polymorphic==3.1.0 django-tastypie<0.15.0 - django-tinymce==4.0.0 + django-tinymce==3.7.1 django-grappelli==3.0.8 django-uuid-upload-path==1.0.0 django-widget-tweaks==1.5.0 From eab593fbfe23f230fb4d084d6b99b61a8fd0e720 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 22:17:44 +0200 Subject: [PATCH 211/253] fix workflow (#12238) (#12239) (cherry picked from commit 684a1f3572a39b6ab8ba5a6ce7ea4d96fc739c8c) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/resource/manager.py | 14 +++++++++-- geonode/security/models.py | 14 +++++++++-- geonode/security/tests.py | 48 +++++++++++++++++++++++++++++++++++++ geonode/security/utils.py | 3 +-- 4 files changed, 73 insertions(+), 6 deletions(-) diff --git a/geonode/resource/manager.py b/geonode/resource/manager.py index d10266e60ee..d4c94a1bc66 100644 --- a/geonode/resource/manager.py +++ b/geonode/resource/manager.py @@ -849,7 +849,12 @@ def _safe_assign_perm(perm, user_or_group, obj=None): ) else: for user_group in get_user_groups(_owner): - if not skip_registered_members_common_group(user_group): + # if AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() is False, + # means that at least one config of the advanced workflow is set, which means that users group get view_permissions + if ( + not skip_registered_members_common_group(user_group) + and not AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() + ): _safe_assign_perm("view_resourcebase", user_group, _resource.get_self_resource()) _prev_perm = ( _perm_spec["groups"].get(user_group, []) if "groups" in _perm_spec else [] @@ -873,7 +878,12 @@ def _safe_assign_perm(perm, user_or_group, obj=None): ) else: for user_group in get_user_groups(_owner): - if not skip_registered_members_common_group(user_group): + # if AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() is False, + # means that at least one config of the advanced workflow is set, which means that users group get view_permissions + if ( + not skip_registered_members_common_group(user_group) + and not AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() + ): _safe_assign_perm( "download_resourcebase", user_group, _resource.get_self_resource() ) diff --git a/geonode/security/models.py b/geonode/security/models.py index 2a878368827..de9ece62f6d 100644 --- a/geonode/security/models.py +++ b/geonode/security/models.py @@ -201,7 +201,12 @@ def set_default_permissions(self, owner=None, created=False): perm_spec["groups"][anonymous_group] = ["view_resourcebase"] else: for user_group in user_groups: - if not skip_registered_members_common_group(user_group): + # if aswm.is_auto_publishing_workflow() is False, means that at least one config of the advanced workflow + # is set, which means that users group get view_permissions + if ( + not skip_registered_members_common_group(user_group) + and not AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() + ): perm_spec["groups"][user_group] = ["view_resourcebase"] anonymous_can_download = settings.DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION @@ -209,7 +214,12 @@ def set_default_permissions(self, owner=None, created=False): perm_spec["groups"][anonymous_group] = ["view_resourcebase", "download_resourcebase"] else: for user_group in user_groups: - if not skip_registered_members_common_group(user_group): + # if aswm.is_auto_publishing_workflow() is False, means that at least one config of the advanced workflow + # is set, which means that users group get view_permissions + if ( + not skip_registered_members_common_group(user_group) + and not AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() + ): perm_spec["groups"][user_group] = ["view_resourcebase", "download_resourcebase"] AdvancedSecurityWorkflowManager.handle_moderated_uploads(self.uuid, instance=self) diff --git a/geonode/security/tests.py b/geonode/security/tests.py index 1d0f829b234..5ae00733cf4 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -20,6 +20,7 @@ import json import base64 import logging +import uuid import requests import importlib import mock @@ -2234,6 +2235,53 @@ def test_permissions_on_user_role_promote_to_manager_only_RESOURCE_PUBLISHING_ac set(expected_perms), set(perms_got), msg=f"use case #0 - user: {authorized_subject.username}" ) + @override_settings(DEFAULT_ANONYMOUS_VIEW_PERMISSION=False) + def test_if_anonymoys_default_perms_is_false_should_not_assign_perms_to_user_group(self): + """ + if DEFAULT_ANONYMOUS_VIEW_PERMISSION is False, the user's group should not get any permission + """ + + resource = resource_manager.create(str(uuid.uuid4), Dataset, defaults={"owner": self.group_member}) + self.assertFalse(self.group_profile.group in resource.get_all_level_info()["groups"].keys()) + + @override_settings(DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION=False) + def test_if_anonymoys_default_download_perms_is_false_should_not_assign_perms_to_user_group(self): + """ + if DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION is False, the user's group should not get any permission + """ + + resource = resource_manager.create(str(uuid.uuid4), Dataset, defaults={"owner": self.group_member}) + self.assertFalse(self.group_profile.group in resource.get_all_level_info()["groups"].keys()) + + @override_settings(DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION=False) + @override_settings(RESOURCE_PUBLISHING=True) + def test_if_anonymoys_default_perms_is_false_should_assign_perms_to_user_group_if_advanced_workflow_is_on(self): + """ + if DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION is False and the advanced workflow is activate + the user's group should get the view and download permission + """ + + resource = resource_manager.create(str(uuid.uuid4), Dataset, defaults={"owner": self.group_member}) + self.assertTrue(self.group_profile.group in resource.get_all_level_info()["groups"].keys()) + group_val = resource.get_all_level_info()["groups"][self.group_profile.group] + self.assertSetEqual({"view_resourcebase", "download_resourcebase"}, set(group_val)) + + @override_settings(DEFAULT_ANONYMOUS_VIEW_PERMISSION=False) + @override_settings(ADMIN_MODERATE_UPLOADS=True) + def test_if_anonymoys_default_perms_is_false_should_assign_perms_to_user_group_if_advanced_workflow_is_on_moderate( + self, + ): + """ + if DEFAULT_ANONYMOUS_VIEW_PERMISSION is False and the advanced workflow is activate + the user's group should get the view and download permission + """ + + resource = resource_manager.create(str(uuid.uuid4), Dataset, defaults={"owner": self.group_member}) + + self.assertTrue(self.group_profile.group in resource.get_all_level_info()["groups"].keys()) + group_val = resource.get_all_level_info()["groups"][self.group_profile.group] + self.assertSetEqual({"view_resourcebase", "download_resourcebase"}, set(group_val)) + @override_settings(RESOURCE_PUBLISHING=True) @override_settings(ADMIN_MODERATE_UPLOADS=True) diff --git a/geonode/security/utils.py b/geonode/security/utils.py index 7ed61f199e2..98f13ab1395 100644 --- a/geonode/security/utils.py +++ b/geonode/security/utils.py @@ -224,8 +224,7 @@ def get_geoapp_subtypes(): def skip_registered_members_common_group(user_group): - _members_group_name = groups_settings.REGISTERED_MEMBERS_GROUP_NAME - if (settings.RESOURCE_PUBLISHING or settings.ADMIN_MODERATE_UPLOADS) and _members_group_name == user_group.name: + if groups_settings.REGISTERED_MEMBERS_GROUP_NAME == user_group.name: return True return False From 2117bbd2246734dfce882ec5bd4f8f9ea5c4c6fc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 12:02:44 +0200 Subject: [PATCH 212/253] [Fixes #12250] Add missing migration (#12251) (#12252) (cherry picked from commit 0a7644180aa0b1a6634430d4ef2c3f04be2fb5cb) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- .../0091_alter_hierarchicalkeyword_slug.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 geonode/base/migrations/0091_alter_hierarchicalkeyword_slug.py diff --git a/geonode/base/migrations/0091_alter_hierarchicalkeyword_slug.py b/geonode/base/migrations/0091_alter_hierarchicalkeyword_slug.py new file mode 100644 index 00000000000..e884c56b26a --- /dev/null +++ b/geonode/base/migrations/0091_alter_hierarchicalkeyword_slug.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.9 on 2024-05-21 08:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("base", "0090_alter_resourcebase_polymorphic_ctype"), + ] + + operations = [ + migrations.AlterField( + model_name="hierarchicalkeyword", + name="slug", + field=models.SlugField(allow_unicode=True, max_length=100, unique=True, verbose_name="slug"), + ), + ] From 004c205a385d7606b38c06a16827b3bd949657be Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 22 May 2024 18:55:14 +0200 Subject: [PATCH 213/253] [Fixes #12253] Improvements to the proxy view (#12254) (#12257) * Some improvements to the proxy view * Implemented proxy allowed hosts registry and signal handler for services * Moved signals inside proxy view * Moved proxy registry initialization to app setup stage * Initialize proxy registry only once Services have been configured * flake fixes * fixed typo * Avoid cycling the services inside the view * Restore reading from PROXY_ALLOWED_HOSTS * Simplify error message * do not cache hostnames passing needels validation * Reinit proxy registry when service is deleted * Fixed hotname passing needle test not being validated * avoid calling get_proxy_allowed_hosts again * A few more optimizations (cherry picked from commit 5e249744ce1c722e9f11bf0a4381c89956dd4734) Co-authored-by: Giovanni Allegri --- geonode/proxy/apps.py | 15 ++++++ geonode/proxy/tests.py | 102 ++++++++++++++++++++++++++----------- geonode/proxy/utils.py | 41 +++++++++++++++ geonode/proxy/views.py | 88 ++++++++++++-------------------- geonode/services/models.py | 1 + geonode/settings.py | 5 ++ geonode/utils.py | 7 +-- 7 files changed, 172 insertions(+), 87 deletions(-) create mode 100644 geonode/proxy/utils.py diff --git a/geonode/proxy/apps.py b/geonode/proxy/apps.py index 9901d333798..3b0174a8473 100644 --- a/geonode/proxy/apps.py +++ b/geonode/proxy/apps.py @@ -17,8 +17,23 @@ # ######################################################################### from django.apps import AppConfig +from django.db.models.signals import post_migrate + +from .utils import proxy_urls_registry + + +def run_setup_hooks(*args, **kwargs): + proxy_urls_registry.initialize() class GeoNodeProxyAppConfig(AppConfig): name = "geonode.proxy" verbose_name = "GeoNode Proxy" + + def ready(self): + super().ready() + try: + run_setup_hooks() + except Exception: + # This is in case the Service table doesn't exist yet + post_migrate.connect(run_setup_hooks, sender=self) diff --git a/geonode/proxy/tests.py b/geonode/proxy/tests.py index 5ffdf239ce1..2f094488ee0 100644 --- a/geonode/proxy/tests.py +++ b/geonode/proxy/tests.py @@ -52,6 +52,7 @@ from geonode.decorators import on_ogc_backend from geonode.tests.base import GeoNodeBaseTestSupport from geonode.base.populate_test_data import create_models, create_single_dataset +from geonode.proxy.utils import ProxyUrlsRegistry TEST_DOMAIN = ".github.com" TEST_URL = f"https://help{TEST_DOMAIN}/" @@ -67,36 +68,46 @@ def setUp(self): self.proxy_url = "/proxy/" self.url = TEST_URL - @override_settings(DEBUG=True, PROXY_ALLOWED_HOSTS=()) - def test_validate_host_disabled_in_debug(self): - """If PROXY_ALLOWED_HOSTS is empty and DEBUG is True, all hosts pass the proxy.""" - response = self.client.get(f"{self.proxy_url}?url={self.url}") - if response.status_code != 404: # 404 - NOT FOUND - self.assertTrue(response.status_code in (200, 301), response.status_code) - - @override_settings(DEBUG=False, PROXY_ALLOWED_HOSTS=()) - def test_validate_host_disabled_not_in_debug(self): - """If PROXY_ALLOWED_HOSTS is empty and DEBUG is False requests should return 403.""" - response = self.client.get(f"{self.proxy_url}?url={self.url}") - if response.status_code != 404: # 404 - NOT FOUND - self.assertEqual(response.status_code, 403, response.status_code) - - @override_settings(DEBUG=False, PROXY_ALLOWED_HOSTS=(TEST_DOMAIN,)) + @patch("geonode.proxy.views.proxy_urls_registry", ProxyUrlsRegistry().set([TEST_DOMAIN])) def test_proxy_allowed_host(self): """If PROXY_ALLOWED_HOSTS is not empty and DEBUG is False requests should return no error.""" self.client.login(username="admin", password="admin") response = self.client.get(f"{self.proxy_url}?url={self.url}") - if response.status_code != 404: # 404 - NOT FOUND - self.assertEqual(response.status_code, 200, response.status_code) - - @override_settings(DEBUG=False, PROXY_ALLOWED_HOSTS=()) + self.assertNotEqual(response.status_code, 403, response.status_code) + + @override_settings(PROXY_ALLOWED_PARAMS_NEEDLES=("request=GetCapabilities",)) + @patch("geonode.proxy.views.proxy_urls_registry", ProxyUrlsRegistry().clear()) + def test_proxy_allowed_params(self): + response = self.client.get(f"{self.proxy_url}?url=https://example.com?request=GetCapabilities") + self.assertNotEqual(response.status_code, 403, response.status_code) + + @override_settings(PROXY_ALLOWED_PARAMS_NEEDLES=("request=GetCapabilities",)) + @patch("geonode.proxy.views.proxy_urls_registry", ProxyUrlsRegistry().clear()) + def test_proxy_not_allowed_params(self): + response = self.client.get(f"{self.proxy_url}?url=http://example.com?param=any") + self.assertEqual(response.status_code, 403, response.status_code) + + @override_settings(PROXY_ALLOWED_PATH_NEEDLES=("tms",)) + @patch("geonode.proxy.views.proxy_urls_registry", ProxyUrlsRegistry().clear()) + def test_proxy_allowed_path(self): + response = self.client.get(f"{self.proxy_url}?url=https://example.com/tms/") + self.assertNotEqual(response.status_code, 403, response.status_code) + + @override_settings(PROXY_ALLOWED_PATH_NEEDLES=("tms",)) + @patch("geonode.proxy.views.proxy_urls_registry", ProxyUrlsRegistry().clear()) + def test_proxy_not_allowed_path(self): + response = self.client.get(f"{self.proxy_url}?url=http://example.com/xyz") + self.assertEqual(response.status_code, 403, response.status_code) + + @override_settings(PROXY_ALLOWED_PARAMS_NEEDLES=(), PROXY_ALLOWED_PATH_NEEDLES=()) + @patch("geonode.proxy.views.proxy_urls_registry", ProxyUrlsRegistry().clear()) def test_validate_remote_services_hosts(self): """If PROXY_ALLOWED_HOSTS is empty and DEBUG is False requests should return 200 for Remote Services hosts.""" from geonode.services.models import Service from geonode.services.enumerations import WMS, INDEXED - Service.objects.get_or_create( + service, _ = Service.objects.get_or_create( type=WMS, name="Bogus", title="Pocus", @@ -104,11 +115,44 @@ def test_validate_remote_services_hosts(self): method=INDEXED, base_url="http://bogus.pocus.com/ows", ) - response = self.client.get(f"{self.proxy_url}?url=http://bogus.pocus.com/ows/wms?request=GetCapabilities") - # 200 - FOUND - self.assertTrue(response.status_code in (200, 301)) + response = self.client.get(f"{self.proxy_url}?url=http://bogus.pocus.com/ows") + self.assertNotEqual(response.status_code, 403, response.status_code) + + # The service should be removed from the proxy registry + service.delete() + response = self.client.get(f"{self.proxy_url}?url=http://bogus.pocus.com/ows") + self.assertEqual(response.status_code, 403, response.status_code) - @override_settings(DEBUG=False, PROXY_ALLOWED_HOSTS=(".example.org",)) + # Two services with the same hostname are added to the proxy registry + service, _ = Service.objects.get_or_create( + type=WMS, + name="Bogus", + title="Pocus", + owner=self.admin, + method=INDEXED, + base_url="http://bogus.pocus.com/ows", + ) + Service.objects.get_or_create( + type=WMS, + name="Bogus2", + title="Pocus", + owner=self.admin, + method=INDEXED, + base_url="http://bogus.pocus.com/wms", + ) + response = self.client.get(f"{self.proxy_url}?url=http://bogus.pocus.com/ows") + self.assertNotEqual(response.status_code, 403, response.status_code) + response = self.client.get(f"{self.proxy_url}?url=http://bogus.pocus.com/wms") + self.assertNotEqual(response.status_code, 403, response.status_code) + + service.delete() + response = self.client.get(f"{self.proxy_url}?url=http://bogus.pocus.com/wfs") + # The request passes because the same hostname is still registered for the other serrice + self.assertNotEqual(response.status_code, 403, response.status_code) + response = self.client.get(f"{self.proxy_url}?url=http://bogus.pocus.com/wcs") + self.assertNotEqual(response.status_code, 403, response.status_code) + + @patch("geonode.proxy.views.proxy_urls_registry", ProxyUrlsRegistry().set([".example.org"])) def test_relative_urls(self): """Proxying to a URL with a relative path element should normalise the path into an absolute path before calling the remote URL.""" @@ -128,6 +172,7 @@ class Response: self.client.get(f"{self.proxy_url}?url={url}") assert request_mock.call_args[0][0] == "http://example.org/index.html" + @patch("geonode.proxy.views.proxy_urls_registry", ProxyUrlsRegistry().set(["example.org"])) def test_proxy_preserve_headers(self): """The GeoNode Proxy should preserve the original request headers.""" import geonode.proxy.views @@ -164,23 +209,22 @@ class Response: response = self.client.get(f"{self.proxy_url}?url={url}") self.assertDictContainsSubset( - dict(response.headers.copy()), { - "Content-Type": "text/plain", + "Content-Type": "image/tiff", "Vary": "Authorization, Accept-Language, Cookie, origin", "X-Content-Type-Options": "nosniff", "X-XSS-Protection": "1; mode=block", "Referrer-Policy": "same-origin", "Cross-Origin-Opener-Policy": "same-origin", "X-Frame-Options": "SAMEORIGIN", - "Content-Language": "en-us", - "Content-Length": "119", + "Content-Language": "en", + "Content-Length": "11", "Content-Disposition": 'attachment; filename="filename.tif"', }, + dict(response.headers.copy()), ) def test_proxy_url_forgery(self): - """The GeoNode Proxy should preserve the original request headers.""" import geonode.proxy.views from urllib.parse import urlsplit diff --git a/geonode/proxy/utils.py b/geonode/proxy/utils.py new file mode 100644 index 00000000000..e2c80a001d5 --- /dev/null +++ b/geonode/proxy/utils.py @@ -0,0 +1,41 @@ +from urllib.parse import urlsplit + +from django.conf import settings + + +site_url = urlsplit(settings.SITEURL) + + +class ProxyUrlsRegistry: + def initialize(self): + from geonode.geoserver.helpers import ogc_server_settings + from geonode.services.models import Service + + self.proxy_allowed_hosts = set([site_url.hostname] + list(getattr(settings, "PROXY_ALLOWED_HOSTS", ()))) + + if ogc_server_settings: + self.proxy_allowed_hosts.add(ogc_server_settings.hostname) + + for _s in Service.objects.all(): + _remote_host = urlsplit(_s.base_url).hostname + self.proxy_allowed_hosts.add(_remote_host) + + def set(self, hosts): + self.proxy_allowed_hosts = set(hosts) + return self + + def clear(self): + self.proxy_allowed_hosts = set() + return self + + def register_host(self, host): + self.proxy_allowed_hosts.add(host) + + def unregister_host(self, host): + self.proxy_allowed_hosts.remove(host) + + def get_proxy_allowed_hosts(self): + return self.proxy_allowed_hosts + + +proxy_urls_registry = ProxyUrlsRegistry() diff --git a/geonode/proxy/views.py b/geonode/proxy/views.py index 2ea1c29841b..b7bca6ee5b9 100644 --- a/geonode/proxy/views.py +++ b/geonode/proxy/views.py @@ -30,8 +30,8 @@ from django.conf import settings from django.template import loader from django.http import HttpResponse, StreamingHttpResponse +from django.db.models import signals from django.views.generic import View -from distutils.version import StrictVersion from django.http.request import validate_host from django.utils.translation import gettext_lazy as _ from django.views.decorators.csrf import requires_csrf_token @@ -39,6 +39,7 @@ from geonode.layers.models import Dataset from geonode.upload.models import Upload from geonode.base.models import ResourceBase +from geonode.services.models import Service from geonode.storage.manager import storage_manager from geonode.utils import ( resolve_object, @@ -53,17 +54,17 @@ from geonode import geoserver # noqa from geonode.base import register_event from geonode.base.auth import get_auth_user, get_token_from_auth_header +from geonode.geoserver.helpers import ogc_server_settings -BUFFER_CHUNK_SIZE = 64 * 1024 - -TIMEOUT = 30 - -LINK_TYPES = [L for L in _LT if L.startswith("OGC:")] +from .utils import proxy_urls_registry logger = logging.getLogger(__name__) +BUFFER_CHUNK_SIZE = 64 * 1024 +TIMEOUT = 30 +LINK_TYPES = [L for L in _LT if L.startswith("OGC:")] -ows_regexp = re.compile(r"^(?i)(version)=(\d\.\d\.\d)(?i)&(?i)request=(?i)(GetCapabilities)&(?i)service=(?i)(\w\w\w)$") +site_url = urlsplit(settings.SITEURL) @requires_csrf_token @@ -72,23 +73,19 @@ def proxy( url=None, response_callback=None, sec_chk_hosts=True, - sec_chk_rules=True, timeout=None, allowed_hosts=[], headers=None, access_token=None, **kwargs, ): - # Request default timeout - from geonode.geoserver.helpers import ogc_server_settings if not timeout: timeout = getattr(ogc_server_settings, "TIMEOUT", TIMEOUT) - # Security rules and settings - PROXY_ALLOWED_HOSTS = getattr(settings, "PROXY_ALLOWED_HOSTS", ()) + PROXY_ALLOWED_PARAMS_NEEDLES = getattr(settings, "PROXY_ALLOWED_PARAMS_NEEDLES", ()) + PROXY_ALLOWED_PATH_NEEDLES = getattr(settings, "PROXY_ALLOWED_PATH_NEEDLES", ()) - # Sanity url checks if "url" not in request.GET and not url: return HttpResponse( "The proxy service requires a URL-encoded URL as a parameter.", status=400, content_type="text/plain" @@ -104,52 +101,20 @@ def proxy( if url.fragment != "": locator += f"#{url.fragment}" - # White-Black Listing Hosts - site_url = urlsplit(settings.SITEURL) - if sec_chk_hosts and not settings.DEBUG: - # Attach current SITEURL - if site_url.hostname not in PROXY_ALLOWED_HOSTS: - PROXY_ALLOWED_HOSTS += (site_url.hostname,) - - # Attach current hostname - hostname = (ogc_server_settings.hostname,) if ogc_server_settings else () - if hostname not in PROXY_ALLOWED_HOSTS: - PROXY_ALLOWED_HOSTS += hostname - - # Check OWS regexp - if url.query and ows_regexp.match(url.query): - ows_tokens = ows_regexp.match(url.query).groups() - if ( - len(ows_tokens) == 4 - and "version" == ows_tokens[0] - and StrictVersion(ows_tokens[1]) >= StrictVersion("1.0.0") - and StrictVersion(ows_tokens[1]) <= StrictVersion("3.0.0") - and ows_tokens[2].lower() in ("getcapabilities") - and ows_tokens[3].upper() in ("OWS", "WCS", "WFS", "WMS", "WPS", "CSW") - ): - if url.hostname not in PROXY_ALLOWED_HOSTS: - PROXY_ALLOWED_HOSTS += (url.hostname,) - - # Check Remote Services base_urls - from geonode.services.models import Service - - for _s in Service.objects.all(): - _remote_host = urlsplit(_s.base_url).hostname - PROXY_ALLOWED_HOSTS += (_remote_host,) - - if not validate_host(extract_ip_or_domain(raw_url), PROXY_ALLOWED_HOSTS): + proxy_allowed_hosts = list(proxy_urls_registry.get_proxy_allowed_hosts()) + if sec_chk_hosts: + if any(needle.lower() in url.query.lower() for needle in PROXY_ALLOWED_PARAMS_NEEDLES) or any( + needle.lower() in url.path.lower() for needle in PROXY_ALLOWED_PATH_NEEDLES + ): + proxy_allowed_hosts.append(url.hostname) + + if not validate_host(extract_ip_or_domain(raw_url), proxy_allowed_hosts): return HttpResponse( - "DEBUG is set to False but the host of the path provided to the proxy service" - " is not in the PROXY_ALLOWED_HOSTS setting.", + "The url provided to the proxy service is not a valid hostname.", status=403, content_type="text/plain", ) - # Security checks based on rules; allow only specific requests - if sec_chk_rules: - # TODO: Not yet implemented - pass - # Collecting headers and cookies if not headers: headers, access_token = get_headers(request, url, raw_url, allowed_hosts=allowed_hosts) @@ -186,7 +151,6 @@ def proxy( # Avoid translating local geoserver calls into external ones if check_ogc_backend(geoserver.BACKEND_PACKAGE): - from geonode.geoserver.helpers import ogc_server_settings _url = _url.replace(f"{settings.SITEURL}geoserver", ogc_server_settings.LOCATION.rstrip("/")) _data = _data.replace(f"{settings.SITEURL}geoserver", ogc_server_settings.LOCATION.rstrip("/")) @@ -439,3 +403,17 @@ def fetch_response_headers(response, response_headers): ]: response._headers[_header] = (_header, response_headers.get(_header)) return response + + +def service_post_save(instance, sender, **kwargs): + service_hostname = urlsplit(instance.base_url).hostname + proxy_urls_registry.register_host(service_hostname) + + +def service_post_delete(instance, sender, **kwargs): + # We reinitialize the registry otherwise we might delete a host requested by another service with the same hostanme + proxy_urls_registry.initialize() + + +signals.post_save.connect(service_post_save, sender=Service) +signals.post_delete.connect(service_post_delete, sender=Service) diff --git a/geonode/services/models.py b/geonode/services/models.py index e52d8e53d15..24355b411ca 100644 --- a/geonode/services/models.py +++ b/geonode/services/models.py @@ -22,6 +22,7 @@ from django.db import models from django.conf import settings + from django.utils.translation import gettext_lazy as _ from geonode.base.models import ResourceBase diff --git a/geonode/settings.py b/geonode/settings.py index 2da7b84278a..2ca11ae13ff 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -1289,6 +1289,11 @@ else re.split(r" *[,|:;] *", os.getenv("PROXY_ALLOWED_HOSTS")) ) +# Tuple with valid strings to be matched inside the request querystring to let it pass through the proxy +PROXY_ALLOWED_PARAMS_NEEDLES = ast.literal_eval(os.getenv("PROXY_ALLOWED_PARAMS_NEEDLES", "()")) +# Tuple with valid strings to be matched inside the request path to let it pass through the proxy +PROXY_ALLOWED_PATH_NEEDLES = ast.literal_eval(os.getenv("PROXY_ALLOWED_PATH_NEEDLES", "()")) + # The proxy to use when making cross origin requests. PROXY_URL = os.environ.get("PROXY_URL", "/proxy/?url=") diff --git a/geonode/utils.py b/geonode/utils.py index 97cb3ff5723..c93b61d7cf7 100755 --- a/geonode/utils.py +++ b/geonode/utils.py @@ -1919,13 +1919,14 @@ def remove_credentials_from_url(url): return cleaned_url +ip_regex = re.compile("^(?:http://|https://)(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})") +domain_regex = re.compile("^(?:http://|https://)([a-zA-Z0-9.-]+)") + + def extract_ip_or_domain(url): # Decode the URL to handle percent-encoded characters _url = remove_credentials_from_url(unquote(url)) - ip_regex = re.compile("^(?:http://|https://)(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})") - domain_regex = re.compile("^(?:http://|https://)([a-zA-Z0-9.-]+)") - match = ip_regex.findall(_url) if len(match): ip_address = match[0] From 04367650b88b12cefd234acedf63900c5dcf7c45 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 23 May 2024 12:10:31 +0200 Subject: [PATCH 214/253] [Fixes #12255] Harvester is not deleted when its Service is deleted (#12258) (#12259) (cherry picked from commit 33ea4b90d7b239560738601206e95dfc6bd7757c) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/services/tests.py | 28 ++++++++++++++++++++++++++++ geonode/services/views.py | 3 ++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/geonode/services/tests.py b/geonode/services/tests.py index 00d4fa9690e..1da5649bc08 100644 --- a/geonode/services/tests.py +++ b/geonode/services/tests.py @@ -18,6 +18,7 @@ ######################################################################### from unittest.mock import MagicMock +from uuid import uuid4 import mock import logging @@ -38,6 +39,7 @@ from owslib.map.wms111 import ContentMetadata +from geonode.harvesting.models import Harvester from geonode.layers.models import Dataset from geonode.tests.base import GeoNodeBaseTestSupport from geonode.resource.manager import resource_manager @@ -774,6 +776,32 @@ def test_local_user_cant_delete_service(self): response = self.client.post(reverse("remove_service", args=(s.id,))) self.assertEqual(len(Service.objects.all()), 0) + def test_removing_the_service_delete_also_the_harvester(self): + """ + If the user delete the service, the corrisponding harvester object should be deleted too + """ + owner = get_user_model().objects.get(username="admin") + # creating the service + dummy_service = Service.objects.create( + uuid=str(uuid4()), owner=owner, title="test service removing", is_approved=True + ) + # creating the harvester + harvester = Harvester.objects.create( + remote_url="http://fake1.com", + name="harvester1", + default_owner=owner, + harvester_type="geonode.harvesting.harvesters.geonodeharvester.GeonodeUnifiedHarvesterWorker", + ) + dummy_service.harvester = harvester + dummy_service.save() + + self.client.login(username="admin", password="admin") + + response = self.client.post(reverse("remove_service", args=(dummy_service.id,))) + self.assertEqual(302, response.status_code) + self.assertFalse(Service.objects.filter(id=dummy_service.id).exists()) + self.assertFalse(Harvester.objects.filter(id=harvester.id).exists()) + @flaky(max_runs=3) def test_add_duplicate_remote_service_url(self): form_data = { diff --git a/geonode/services/views.py b/geonode/services/views.py index 305fdff5e93..3eb4e66a778 100644 --- a/geonode/services/views.py +++ b/geonode/services/views.py @@ -351,6 +351,7 @@ def remove_service(request, service_id): return render(request, "services/service_remove.html", {"service": service}) elif request.method == "POST": service.dataset_set.all().delete() - service.delete() + # by deleting the harvester we delete also the service + service.harvester.delete() messages.add_message(request, messages.INFO, _(f"Service {service.title} has been deleted")) return HttpResponseRedirect(reverse("services")) From 2ad8442795ed885f0b2903c45d29bad7fa129af9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 24 May 2024 17:27:11 +0200 Subject: [PATCH 215/253] [Fixes #12261] Current user is assigned as owner on geoapp update (#12262) (#12263) (cherry picked from commit 012ca34838435068a679414145aca6bc8122574a) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/geoapps/api/serializers.py | 6 ---- geonode/geoapps/api/tests.py | 45 ++++++++++++++++++++++++++++++ geonode/geoapps/api/views.py | 8 ++++++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/geonode/geoapps/api/serializers.py b/geonode/geoapps/api/serializers.py index c511b7e1a37..c89440ccddc 100644 --- a/geonode/geoapps/api/serializers.py +++ b/geonode/geoapps/api/serializers.py @@ -61,12 +61,6 @@ def extra_create_checks(self, validated_data): self.extra_update_checks(validated_data) - def validate(self, data): - request = self.context.get("request") - if request: - data["owner"] = request.user - return data - def _sanitize_validated_data(self, validated_data, instance=None): # Extract users' profiles _user_profiles = {} diff --git a/geonode/geoapps/api/tests.py b/geonode/geoapps/api/tests.py index 210d8256d76..fc409095972 100644 --- a/geonode/geoapps/api/tests.py +++ b/geonode/geoapps/api/tests.py @@ -238,3 +238,48 @@ def test_create_checks_duplicated(self): self.assertEqual(exp.exception.category, "geoapp_api") self.assertEqual(exp.exception.default_code, "geoapp_exception") self.assertEqual(str(exp.exception.detail), "A GeoApp with the same 'name' already exists!") + + def test_geoapp_creation_owner_is_mantained(self): + """ + https://github.com/GeoNode/geonode/issues/12261 + The geoapp owner should be mantained even if another + user save the instance. + """ + + url = f"{reverse('geoapps-list')}?include[]=data" + data = { + "name": "Test Create", + "title": "Test Create", + "resource_type": "geostory", + "extent": {"coords": [1123692.0, 5338214.0, 1339852.0, 5482615.0], "srid": "EPSG:3857"}, + } + + self.assertTrue(self.client.login(username="norman", password="norman")) + + response = self.client.post(url, data=data, format="json") + + self.assertEqual(201, response.status_code) + # let's check that the owner is the request one + self.assertEqual("norman", response.json()["geoapp"]["owner"]["username"]) + + # let's change the user of the request + self.assertTrue(self.client.login(username="admin", password="admin")) + + sut = GeoApp.objects.get(pk=response.json()["geoapp"]["pk"]) + # Update: PATCH + # we ensure that norman is the resource owner + self.assertEqual("norman", sut.owner.username) + + url = reverse("geoapps-detail", kwargs={"pk": sut.pk}) + data = {"blob": {"test_data": {"test": ["test_4", "test_5", "test_6"]}}} + # sending the update of the geoapp + response = self.client.patch(url, data=json.dumps(data), content_type="application/json") + + self.assertEqual(response.status_code, 200) + + # ensure that the value of the owner is not changed + sut.refresh_from_db() + self.assertEqual("norman", sut.owner.username) + + # cleanup + sut.delete() diff --git a/geonode/geoapps/api/views.py b/geonode/geoapps/api/views.py index e13d5814713..57136b9e771 100644 --- a/geonode/geoapps/api/views.py +++ b/geonode/geoapps/api/views.py @@ -59,3 +59,11 @@ class GeoAppViewSet(ApiPresetsInitializer, DynamicModelViewSet, AdvertisedListMi queryset = GeoApp.objects.all().order_by("-created") serializer_class = GeoAppSerializer pagination_class = GeoNodeApiPagination + + def perform_create(self, serializer): + """ + The owner is not passed from the FE + so we force the request.user to be the owner + in creation + """ + return serializer.save(owner=self.request.user) From 111ee9f06615738c825a5099e7bf420b47b16f15 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 24 May 2024 18:07:58 +0200 Subject: [PATCH 216/253] fix workflow (#12238) (#12264) (cherry picked from commit 684a1f3572a39b6ab8ba5a6ce7ea4d96fc739c8c) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/resource/manager.py | 14 +++++++++-- geonode/security/models.py | 14 +++++++++-- geonode/security/tests.py | 48 +++++++++++++++++++++++++++++++++++++ geonode/security/utils.py | 3 +-- 4 files changed, 73 insertions(+), 6 deletions(-) diff --git a/geonode/resource/manager.py b/geonode/resource/manager.py index ad64452d6dc..5673409488e 100644 --- a/geonode/resource/manager.py +++ b/geonode/resource/manager.py @@ -859,7 +859,12 @@ def _safe_assign_perm(perm, user_or_group, obj=None): ) else: for user_group in get_user_groups(_owner): - if not skip_registered_members_common_group(user_group): + # if AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() is False, + # means that at least one config of the advanced workflow is set, which means that users group get view_permissions + if ( + not skip_registered_members_common_group(user_group) + and not AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() + ): _safe_assign_perm("view_resourcebase", user_group, _resource.get_self_resource()) _prev_perm = ( _perm_spec["groups"].get(user_group, []) if "groups" in _perm_spec else [] @@ -883,7 +888,12 @@ def _safe_assign_perm(perm, user_or_group, obj=None): ) else: for user_group in get_user_groups(_owner): - if not skip_registered_members_common_group(user_group): + # if AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() is False, + # means that at least one config of the advanced workflow is set, which means that users group get view_permissions + if ( + not skip_registered_members_common_group(user_group) + and not AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() + ): _safe_assign_perm( "download_resourcebase", user_group, _resource.get_self_resource() ) diff --git a/geonode/security/models.py b/geonode/security/models.py index 2a878368827..de9ece62f6d 100644 --- a/geonode/security/models.py +++ b/geonode/security/models.py @@ -201,7 +201,12 @@ def set_default_permissions(self, owner=None, created=False): perm_spec["groups"][anonymous_group] = ["view_resourcebase"] else: for user_group in user_groups: - if not skip_registered_members_common_group(user_group): + # if aswm.is_auto_publishing_workflow() is False, means that at least one config of the advanced workflow + # is set, which means that users group get view_permissions + if ( + not skip_registered_members_common_group(user_group) + and not AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() + ): perm_spec["groups"][user_group] = ["view_resourcebase"] anonymous_can_download = settings.DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION @@ -209,7 +214,12 @@ def set_default_permissions(self, owner=None, created=False): perm_spec["groups"][anonymous_group] = ["view_resourcebase", "download_resourcebase"] else: for user_group in user_groups: - if not skip_registered_members_common_group(user_group): + # if aswm.is_auto_publishing_workflow() is False, means that at least one config of the advanced workflow + # is set, which means that users group get view_permissions + if ( + not skip_registered_members_common_group(user_group) + and not AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() + ): perm_spec["groups"][user_group] = ["view_resourcebase", "download_resourcebase"] AdvancedSecurityWorkflowManager.handle_moderated_uploads(self.uuid, instance=self) diff --git a/geonode/security/tests.py b/geonode/security/tests.py index 433f4aa6de7..d621a77a13d 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -20,6 +20,7 @@ import json import base64 import logging +import uuid import requests import importlib import mock @@ -2267,6 +2268,53 @@ def test_permissions_on_user_role_promote_to_manager_only_RESOURCE_PUBLISHING_ac set(expected_perms), set(perms_got), msg=f"use case #0 - user: {authorized_subject.username}" ) + @override_settings(DEFAULT_ANONYMOUS_VIEW_PERMISSION=False) + def test_if_anonymoys_default_perms_is_false_should_not_assign_perms_to_user_group(self): + """ + if DEFAULT_ANONYMOUS_VIEW_PERMISSION is False, the user's group should not get any permission + """ + + resource = resource_manager.create(str(uuid.uuid4), Dataset, defaults={"owner": self.group_member}) + self.assertFalse(self.group_profile.group in resource.get_all_level_info()["groups"].keys()) + + @override_settings(DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION=False) + def test_if_anonymoys_default_download_perms_is_false_should_not_assign_perms_to_user_group(self): + """ + if DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION is False, the user's group should not get any permission + """ + + resource = resource_manager.create(str(uuid.uuid4), Dataset, defaults={"owner": self.group_member}) + self.assertFalse(self.group_profile.group in resource.get_all_level_info()["groups"].keys()) + + @override_settings(DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION=False) + @override_settings(RESOURCE_PUBLISHING=True) + def test_if_anonymoys_default_perms_is_false_should_assign_perms_to_user_group_if_advanced_workflow_is_on(self): + """ + if DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION is False and the advanced workflow is activate + the user's group should get the view and download permission + """ + + resource = resource_manager.create(str(uuid.uuid4), Dataset, defaults={"owner": self.group_member}) + self.assertTrue(self.group_profile.group in resource.get_all_level_info()["groups"].keys()) + group_val = resource.get_all_level_info()["groups"][self.group_profile.group] + self.assertSetEqual({"view_resourcebase", "download_resourcebase"}, set(group_val)) + + @override_settings(DEFAULT_ANONYMOUS_VIEW_PERMISSION=False) + @override_settings(ADMIN_MODERATE_UPLOADS=True) + def test_if_anonymoys_default_perms_is_false_should_assign_perms_to_user_group_if_advanced_workflow_is_on_moderate( + self, + ): + """ + if DEFAULT_ANONYMOUS_VIEW_PERMISSION is False and the advanced workflow is activate + the user's group should get the view and download permission + """ + + resource = resource_manager.create(str(uuid.uuid4), Dataset, defaults={"owner": self.group_member}) + + self.assertTrue(self.group_profile.group in resource.get_all_level_info()["groups"].keys()) + group_val = resource.get_all_level_info()["groups"][self.group_profile.group] + self.assertSetEqual({"view_resourcebase", "download_resourcebase"}, set(group_val)) + @override_settings(RESOURCE_PUBLISHING=True) @override_settings(ADMIN_MODERATE_UPLOADS=True) diff --git a/geonode/security/utils.py b/geonode/security/utils.py index 91b567562de..312c2a417fb 100644 --- a/geonode/security/utils.py +++ b/geonode/security/utils.py @@ -221,8 +221,7 @@ def get_geoapp_subtypes(): def skip_registered_members_common_group(user_group): - _members_group_name = groups_settings.REGISTERED_MEMBERS_GROUP_NAME - if (settings.RESOURCE_PUBLISHING or settings.ADMIN_MODERATE_UPLOADS) and _members_group_name == user_group.name: + if groups_settings.REGISTERED_MEMBERS_GROUP_NAME == user_group.name: return True return False From 99e60ad6b54a5f8d665f5e9ecd4a904d217334e5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 24 May 2024 18:08:14 +0200 Subject: [PATCH 217/253] [Fixes #12261] Current user is assigned as owner on geoapp update (#12262) (#12265) (cherry picked from commit 012ca34838435068a679414145aca6bc8122574a) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/geoapps/api/serializers.py | 6 ---- geonode/geoapps/api/tests.py | 45 ++++++++++++++++++++++++++++++ geonode/geoapps/api/views.py | 8 ++++++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/geonode/geoapps/api/serializers.py b/geonode/geoapps/api/serializers.py index 1a1e42e7c8a..c9fde60158d 100644 --- a/geonode/geoapps/api/serializers.py +++ b/geonode/geoapps/api/serializers.py @@ -61,12 +61,6 @@ def extra_create_checks(self, validated_data): self.extra_update_checks(validated_data) - def validate(self, data): - request = self.context.get("request") - if request: - data["owner"] = request.user - return data - def _sanitize_validated_data(self, validated_data, instance=None): # Extract users' profiles _user_profiles = {} diff --git a/geonode/geoapps/api/tests.py b/geonode/geoapps/api/tests.py index 4b3a545f182..4d38680e743 100644 --- a/geonode/geoapps/api/tests.py +++ b/geonode/geoapps/api/tests.py @@ -205,3 +205,48 @@ def test_create_checks_duplicated(self): self.assertEqual(exp.exception.category, "geoapp_api") self.assertEqual(exp.exception.default_code, "geoapp_exception") self.assertEqual(str(exp.exception.detail), "A GeoApp with the same 'name' already exists!") + + def test_geoapp_creation_owner_is_mantained(self): + """ + https://github.com/GeoNode/geonode/issues/12261 + The geoapp owner should be mantained even if another + user save the instance. + """ + + url = f"{reverse('geoapps-list')}?include[]=data" + data = { + "name": "Test Create", + "title": "Test Create", + "resource_type": "geostory", + "extent": {"coords": [1123692.0, 5338214.0, 1339852.0, 5482615.0], "srid": "EPSG:3857"}, + } + + self.assertTrue(self.client.login(username="norman", password="norman")) + + response = self.client.post(url, data=data, format="json") + + self.assertEqual(201, response.status_code) + # let's check that the owner is the request one + self.assertEqual("norman", response.json()["geoapp"]["owner"]["username"]) + + # let's change the user of the request + self.assertTrue(self.client.login(username="admin", password="admin")) + + sut = GeoApp.objects.get(pk=response.json()["geoapp"]["pk"]) + # Update: PATCH + # we ensure that norman is the resource owner + self.assertEqual("norman", sut.owner.username) + + url = reverse("geoapps-detail", kwargs={"pk": sut.pk}) + data = {"blob": {"test_data": {"test": ["test_4", "test_5", "test_6"]}}} + # sending the update of the geoapp + response = self.client.patch(url, data=json.dumps(data), content_type="application/json") + + self.assertEqual(response.status_code, 200) + + # ensure that the value of the owner is not changed + sut.refresh_from_db() + self.assertEqual("norman", sut.owner.username) + + # cleanup + sut.delete() diff --git a/geonode/geoapps/api/views.py b/geonode/geoapps/api/views.py index d5cd99eabcb..272bbaebdcf 100644 --- a/geonode/geoapps/api/views.py +++ b/geonode/geoapps/api/views.py @@ -57,3 +57,11 @@ class GeoAppViewSet(DynamicModelViewSet): queryset = GeoApp.objects.all().order_by("-created") serializer_class = GeoAppSerializer pagination_class = GeoNodeApiPagination + + def perform_create(self, serializer): + """ + The owner is not passed from the FE + so we force the request.user to be the owner + in creation + """ + return serializer.save(owner=self.request.user) From c11ddee830626141178ebf91b0bc0ab27e857d6c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 29 May 2024 11:58:51 +0200 Subject: [PATCH 218/253] fix to tests counting 'Featured' words (#12281) (#12282) (cherry picked from commit 2f7486e81a94738f8a620f30e06ae3d99e79b3e3) Co-authored-by: Giovanni Allegri --- geonode/layers/tests.py | 2 +- geonode/maps/tests.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/geonode/layers/tests.py b/geonode/layers/tests.py index 00d2e5cca1d..d11ad69ec5f 100644 --- a/geonode/layers/tests.py +++ b/geonode/layers/tests.py @@ -151,7 +151,7 @@ def test_describe_data_3(self): self.assertEqual(response.status_code, 200) self.assertContains(response, "Approved", count=1, status_code=200, msg_prefix="", html=False) self.assertContains(response, "Published", count=1, status_code=200, msg_prefix="", html=False) - self.assertContains(response, "Featured", count=3, status_code=200, msg_prefix="", html=False) + self.assertContains(response, "Featured", count=1, status_code=200, msg_prefix="", html=False) self.assertContains(response, "
    Group
    ", count=0, status_code=200, msg_prefix="", html=False) # ... now assigning a Group to the Dataset diff --git a/geonode/maps/tests.py b/geonode/maps/tests.py index 5ae30a5b258..88514ffc33c 100644 --- a/geonode/maps/tests.py +++ b/geonode/maps/tests.py @@ -189,7 +189,7 @@ def test_describe_map(self, thumbnail_mock): self.assertEqual(response.status_code, 200) self.assertContains(response, "Approved", count=1, status_code=200, msg_prefix="", html=False) self.assertContains(response, "Published", count=1, status_code=200, msg_prefix="", html=False) - self.assertContains(response, "Featured", count=3, status_code=200, msg_prefix="", html=False) + self.assertContains(response, "Featured", count=1, status_code=200, msg_prefix="", html=False) self.assertContains(response, "
    Group
    ", count=0, status_code=200, msg_prefix="", html=False) # ... now assigning a Group to the map From 89cab20159a3d7bcf1ed079011a0cc3deb121d2b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 29 May 2024 13:05:01 +0200 Subject: [PATCH 219/253] [Fixes #12277] Remove the MS catalog service configuration (#12278) (#12284) * Removed MS catalog service configuration * fixed formatting * Fixed test that was expected to fail (?) * Fixed test that was expected to fail 2 (?) (cherry picked from commit 0bc2fe2e62083f773e0808e81f6d6b41a3564024) Co-authored-by: Giovanni Allegri --- geonode/local_settings.py.geoserver.sample | 10 ---------- geonode/settings.py | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/geonode/local_settings.py.geoserver.sample b/geonode/local_settings.py.geoserver.sample index 59ac574511b..d7ea4c9bc9d 100644 --- a/geonode/local_settings.py.geoserver.sample +++ b/geonode/local_settings.py.geoserver.sample @@ -286,16 +286,6 @@ if GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY == "mapstore": GEONODE_CATALOGUE_SERVICE = get_geonode_catalogue_service() - MAPSTORE_CATALOGUE_SERVICES = {} - - MAPSTORE_CATALOGUE_SELECTED_SERVICE = "" - - if GEONODE_CATALOGUE_SERVICE: - MAPSTORE_CATALOGUE_SERVICES[list(GEONODE_CATALOGUE_SERVICE.keys())[0]] = GEONODE_CATALOGUE_SERVICE[ - list(GEONODE_CATALOGUE_SERVICE.keys())[0] - ] - MAPSTORE_CATALOGUE_SELECTED_SERVICE = list(GEONODE_CATALOGUE_SERVICE.keys())[0] - DEFAULT_MS2_BACKGROUNDS = [ { "type": "tileprovider", diff --git a/geonode/settings.py b/geonode/settings.py index 2ca11ae13ff..c2a2660a4f3 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -1467,16 +1467,6 @@ def get_geonode_catalogue_service(): GEONODE_CATALOGUE_SERVICE = get_geonode_catalogue_service() - MAPSTORE_CATALOGUE_SERVICES = {} - - MAPSTORE_CATALOGUE_SELECTED_SERVICE = "" - - if GEONODE_CATALOGUE_SERVICE: - MAPSTORE_CATALOGUE_SERVICES[list(list(GEONODE_CATALOGUE_SERVICE.keys()))[0]] = GEONODE_CATALOGUE_SERVICE[ - list(list(GEONODE_CATALOGUE_SERVICE.keys()))[0] - ] # noqa - MAPSTORE_CATALOGUE_SELECTED_SERVICE = list(list(GEONODE_CATALOGUE_SERVICE.keys()))[0] - DEFAULT_MS2_BACKGROUNDS = [ { "type": "osm", From 6cb3aafa0ace7052337633599e24a202cf3bcc9f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 29 May 2024 17:50:34 +0200 Subject: [PATCH 220/253] Fixes to metadata detail URL inside metadata page (#12286) (#12287) (cherry picked from commit 5ec22818838899cd838de5a3937c65f27e8510ea) Co-authored-by: Giovanni Allegri --- .../templates/documents/document_metadata_detail.html | 7 +++++-- geonode/geoapps/templates/apps/app_metadata_detail.html | 7 ++++++- .../layers/templates/datasets/dataset_metadata_detail.html | 7 ++++++- geonode/maps/templates/maps/map_metadata_detail.html | 7 ++++++- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/geonode/documents/templates/documents/document_metadata_detail.html b/geonode/documents/templates/documents/document_metadata_detail.html index a455e09d8d6..6e889f84f3d 100644 --- a/geonode/documents/templates/documents/document_metadata_detail.html +++ b/geonode/documents/templates/documents/document_metadata_detail.html @@ -1,11 +1,14 @@ {% extends "metadata_detail.html" %} - +{% load i18n %} {% block header %} {% if 'preview' not in request.GET %} {% include 'geonode-mapstore-client/snippets/header.html' %} {% endif %} {% endblock %} - +{% block metaget_absolute_url %} +
    {% trans "Metadata Page" %}
    +
    {% url "document_metadata_detail" resource.id %}
    +{% endblock metaget_absolute_url %} {% block footer %} {% if 'preview' not in request.GET %} {% include 'geonode-mapstore-client/snippets/footer.html' %} diff --git a/geonode/geoapps/templates/apps/app_metadata_detail.html b/geonode/geoapps/templates/apps/app_metadata_detail.html index f320e00ff13..83004edeacb 100644 --- a/geonode/geoapps/templates/apps/app_metadata_detail.html +++ b/geonode/geoapps/templates/apps/app_metadata_detail.html @@ -1 +1,6 @@ -{% extends "metadata_detail.html" %} \ No newline at end of file +{% extends "metadata_detail.html" %} +{% load i18n %} +{% block metaget_absolute_url %} +
    {% trans "Metadata Page" %}
    +
    {% url "geoapp_metadata_detail" resource.id %}
    +{% endblock metaget_absolute_url %} \ No newline at end of file diff --git a/geonode/layers/templates/datasets/dataset_metadata_detail.html b/geonode/layers/templates/datasets/dataset_metadata_detail.html index f320e00ff13..340824f86d6 100644 --- a/geonode/layers/templates/datasets/dataset_metadata_detail.html +++ b/geonode/layers/templates/datasets/dataset_metadata_detail.html @@ -1 +1,6 @@ -{% extends "metadata_detail.html" %} \ No newline at end of file +{% extends "metadata_detail.html" %} +{% load i18n %} +{% block metaget_absolute_url %} +
    {% trans "Metadata Page" %}
    +
    {% url "dataset_metadata_detail" resource.alternate %}
    +{% endblock metaget_absolute_url %} \ No newline at end of file diff --git a/geonode/maps/templates/maps/map_metadata_detail.html b/geonode/maps/templates/maps/map_metadata_detail.html index f320e00ff13..ea1b5bb4a95 100644 --- a/geonode/maps/templates/maps/map_metadata_detail.html +++ b/geonode/maps/templates/maps/map_metadata_detail.html @@ -1 +1,6 @@ -{% extends "metadata_detail.html" %} \ No newline at end of file +{% extends "metadata_detail.html" %} +{% load i18n %} +{% block metaget_absolute_url %} +
    {% trans "Metadata Page" %}
    +
    {% url "map_metadata_detail" resource.id %}
    +{% endblock metaget_absolute_url %} \ No newline at end of file From 4bfc52285902ffad44457718bedd89f5a3cd3160 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 30 May 2024 12:15:13 +0200 Subject: [PATCH 221/253] Release 4.3.0 (#12288) --- CHANGELOG.md | 95 ++++++++++++++++++++++++++++++++++++++++- docker-compose-dev.yml | 4 +- docker-compose-test.yml | 6 +-- docker-compose.yml | 12 +++--- geonode/__init__.py | 2 +- requirements.txt | 5 +-- setup.cfg | 4 +- 7 files changed, 110 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee54d4a6d2e..6007ff65a41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,97 @@ -# Change Log +# Changelogs + +## [4.3.0](https://github.com/GeoNode/geonode/releases/tag/4.3.0) (2024-05-30) +### New features and improvements + +- **3D and MapSore catalog plugins available for maps**: This release includes a major upgrade of the MapStore framework upon which the GeoNode client is built. One of the key benefits brought by the alignment to the latest MapStore versions, is the integration of new plugins powered by MapStore. Two of these plugins have been enabled by default for maps: **3D view**, powered by Cesium and the [**Catalog tool**](https://docs.mapstore.geosolutionsgroup.com/en/latest/user-guide/catalog/) which gives users the option to include external layers (from WMS, TMS, CSW, etc. services) directly into a map. The 3D view is the first step toward the publishing of 3D content with GeoNode. Meanwhile external 3D Tiles sources can already be viewed inside a GeoNode map thanks to the [Catalog service for 3D Tiles](https://docs.mapstore.geosolutionsgroup.com/en/v2023.02.01/user-guide/catalog/#3d-tiles-catalog). +- **Map Viewers**: Thanks again to the work done to extend the integration with MapStore, its concept of Application Contexts have been adapted and integrated in GeoNode under the the name "Map Viewers". With a Map Viewer the list of tools and plugins available in a map can be configured. Map Viewers can be created from a map (the feature is available under the Edit menu) and they can be used by multiple maps. With Map Viewers all the plugins offered by MapStore can be used inside GeoNode maps. +- **Hiding resources from catalog listing**: There are cases where a resource is created only to be used within other resources. Images uploaded to be included in a geostory, datasets only meant to be viewed inside maps, are examples. Sometimes we don't want these resoruces to be visibile inside the catalog list, or inside search results. For these cases a new "Advertized" attribute is available under the Settings tab of the Metadata editor. When this flag is turned off the resource will only be listed to its owner. This doesn't affect the permissions on the resource. Users with view permissions can still visualize the resource, but it won't be listed in the catalog to them. +- **Extended Users API**: The User API has been extended to support the full management of GeoNode accounts. This API makes GeoNode compliant with the Data policies that request to give users the option to delete their account and their data from apps. The new APIs also support the transfer of resource ownership to another user and the ability to step down from the Group Manager role for a user. +- **Groups facet**: A new facet (filter) has been added to the filters panel for filtering resources by Group. + +### Other minor improvements and fixes + + - **Backup/Restore**: Several improvements that make the B/R service more robust and performant. Code customizations (layouts, etc.) are excluded now from projects backups. + - **Owner was update when geoapp were saved**: This fixes a problem with geoapps (geostories and dashboards) where the current user was assigned as owner when the resource was saved. + - **Fixed textara for rich HTML metadata fields**: It wasn't editable due to a regression introduced in previous versions. + - **Metadata and SLD file uploads**: Fixed a problem with the legacy code that prevented the upload of XML and SLD metadata files for an existing resource. + + ### Software upgrades: + - Django 4.2.9 + - Geoserver 2.24.3 + - MapStore 2024.01.00 + +The full list of changes [here](https://github.com/GeoNode/geonode/milestone/43?closed=1) + +## [4.2.0](https://github.com/GeoNode/geonode/releases/tag/4.2.0) (2024-01-10) + +### New features and improvements + +- **Enhanced faceted filtering**: Filtering of resources has undergone a deep refactoring with the goal of improving its performance and implement proper (cascaded) faceted filtering. The resoruces, and their counting, are calculated from the intersection of the topics selected between different filters (AND logic) and the union of the optics selected from the same filter (OR logic). An improvement is planned for a future version to let users select additional topics from the same filter that happen to be hidden because not cointained in the current results. +- **Location view and management**: A new "Location" tab is available inside the information side panel, where the bounding box of the resoruce and its centroid are displayed. The location for spatial resources (datasets and maps) are automatically retrieved by the data itself. For non-spatial resources the same panel gives editors the tools to set the bounding bos and the position of the resource. +- **Linked resources**: The options to link resources has been extended to any type of resource. It's possible to related any resource with any other resource (one or many), and the relationship is disaplyed inside the new "Lined resources" tab inside the information side panel. The direction of the relationship is also visible, since linked resources are disaplyed under two distinct groups "Linked from" and "Lined to". + +### Other minor improvements + - Implemented a generic and pluggable OIDC SocialAccount Provider, which extends and improves the one provided by the `allauth` module already available in GeoNode + - Documents from remote URLs can be created from the client + - Regions are not assigned to new resources automatically anymore. A pluggable and configurable option lets administrators implement specific logic for the automatic assignmenet if required + - Option to configure a WMTS service to generate thumbnail backgrounds + - The rendering of thumbnails for the maps now take into account ordering and opacity + - Implemented the option to do not register new users as contributors automatically (default behaviour) + +### Software upgrades: + - Django 3.2.23 + - Geoserver 2.23.3 + - PostgreSQL 15.3 / PostGIS 3.3 + - Nginx 1.25.3 + +The full list of changes [here](https://github.com/GeoNode/geonode/milestone/37?closed=1) + +## [4.1.0](https://github.com/GeoNode/geonode/releases/tag/4.1.0) (2023-06-05) + +### New upload engine +GeoNode integrates a brand new importer module based on [GDAL/OGR](https://gdal.org/), which offers increased robustness and reliability to the upload UI and API services. GeoPackage (vector), GeoJSON, KML/KMZ formats and a new CSV handler have been implemented. + +### Thesaurus faceting and date filtering +If thesaurus and thesaurus keywords are configured and assigned to resources, they will be available inside the filters panel, along with the number of associated resources. +Date filtering (from/top) has also been added. + +### Time series configurable after the upload +The configuration of (potential) time series at upload time was confusing for users, and not very robust. +With the new importer, the optional configuration of vector time series can be done afterward, through the Settings tab inside the Metadata editing page +Only vector fomats that provide date(time) fields natively are supported. Conversion from string fields is not implemented. + +### Linked resources +This restore a functionality available in previous versions of GeoNode. +A tab inside the info panel has been added where relationships between datasets, maps and documents are reported. + +### Vector dataset attributes +A tab inside the info panel has been added showing the attributes of vector datasets + +### Remote documents +The API has been extended to permit the creation of document resources referencing remote URLs + +### ISO-19115 XML upload via API +The API now supports the upload of a metadata XML file along with the resource data + +### Software upgrades + + - [Geoserver 2.23.0](https://geoserver.org/announcements/2023/04/05/geoserver-2-23-0-released.html) is now the reference version. This version includes Geofence WPS rules which are employed by GeoNode to strengthen the security of the OGC/WPS processes. +- [MapStore 2022.02.xx](https://github.com/geosolutions-it/MapStore2/tree/2022.02.xx) +- [Django 3.2.19](https://docs.djangoproject.com/en/4.2/releases/3.2.19/) +- PostgreSQL 13 and PostGIS 3.3.3 + + +### Security and Bug Fixes +- [CVE-2023-26043](https://github.com/GeoNode/geonode/security/advisories/GHSA-mcmc-c59m-pqq8) +Fixed a vulnerability to XML External Entity (XXE) injection +- [CVE-2023-28442](https://github.com/GeoNode/geonode/security/advisories/GHSA-87mh-vw7c-5v6w) +Fixed information leak + +You can see the **full list of closed issues [here](https://github.com/GeoNode/geonode/compare/4.1.0...4.0.3)**. + +## System requirements +Python >3.9 is required to run GeoNode 4.1.0, since many of its dependencies have dropped support for older versions. ## [4.0.2](https://github.com/GeoNode/geonode/tree/4.0.2) (2022-12-20) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 3f496a6445b..fb4aac94f86 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -79,7 +79,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.24.3-latest + image: geonode/geoserver:2.24.3-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -105,7 +105,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.24.3-latest + image: geonode/geoserver_data:2.24.3-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 1a162f8cf4f..5f1ea57d6ab 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:latest-ubuntu-22.04 + image: geonode/geonode:4.3.0 build: context: ./ dockerfile: Dockerfile @@ -92,7 +92,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.24.3-latest + image: geonode/geoserver:2.24.3-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -118,7 +118,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.24.3-latest + image: geonode/geoserver_data:2.24.3-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: diff --git a/docker-compose.yml b/docker-compose.yml index fb0e0190a00..3e3ca03578a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,10 +3,10 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:latest-ubuntu-22.04 - build: - context: ./ - dockerfile: Dockerfile + image: geonode/geonode:4.3.0 + #build: + # context: ./ + # dockerfile: Dockerfile restart: unless-stopped env_file: - .env @@ -91,7 +91,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.24.3-latest + image: geonode/geoserver:2.24.3-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -117,7 +117,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.24.3-latest + image: geonode/geoserver_data:2.24.3-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: diff --git a/geonode/__init__.py b/geonode/__init__.py index 177ce1f12df..e6892414338 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 3, 0, "dev", 0) +__version__ = (4, 3, 0, "final", 0) def get_version(): diff --git a/requirements.txt b/requirements.txt index ba8fb45a038..2928b1033b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -85,9 +85,8 @@ Markdown==3.6 git+https://github.com/GeoNode/pinax-notifications.git@django_upgrade#egg=pinax-notifications # GeoNode org maintained apps. -# django-geonode-mapstore-client==4.0.5 -git+https://github.com/GeoNode/geonode-mapstore-client.git@4.3.x#egg=django_geonode_mapstore_client -git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.3.0 +geonode-importer==1.0.9 django-avatar==8.0.0 git+https://github.com/GeoNode/geonode-oauth-toolkit.git@openid-connect#egg=geonode-oauth-toolkit git+https://github.com/GeoNode/geonode-user-messages.git@django_upgrade#egg=geonode-user-messages diff --git a/setup.cfg b/setup.cfg index 6f307884a2e..a316545b9cc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -111,8 +111,8 @@ install_requires = pinax-notifications @ git+https://github.com/GeoNode/pinax-notifications.git@django_upgrade#egg=pinax-notifications # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.2.0,<5.0.0 - geonode-importer>=1.0.8 + django-geonode-mapstore-client==4.3.0 + geonode-importer==1.0.9 django-avatar==8.0.0 geonode-oauth-toolkit @ git+https://github.com/GeoNode/geonode-oauth-toolkit.git@openid-connect#egg=geonode-oauth-toolkit geonode-user-messages @ git+https://github.com/GeoNode/geonode-user-messages.git@django_upgrade#egg=geonode-user-messages From face3652ea0edbdbc0e60d777a638460a65d083b Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 30 May 2024 12:15:47 +0200 Subject: [PATCH 222/253] Release 4.2.5 (#12289) --- docker-compose-test.yml | 2 +- docker-compose.yml | 8 ++++---- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 8edc8b2194b..28738fa28b6 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:local + image: geonode/geonode:4.2.5 build: context: ./ dockerfile: Dockerfile diff --git a/docker-compose.yml b/docker-compose.yml index 50f5147d522..65386e71e96 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,10 +3,10 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:4.2.4 - build: - context: ./ - dockerfile: Dockerfile + image: geonode/geonode:4.2.5 + #build: + # context: ./ + # dockerfile: Dockerfile restart: unless-stopped env_file: - .env diff --git a/geonode/__init__.py b/geonode/__init__.py index dc6d49f1968..13a7dc840e7 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 5, "dev", 0) +__version__ = (4, 2, 5, "final", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 70f7db16c82..ba2d0e67168 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. --e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.2.0 +geonode-importer==1.0.9 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 1e9bdb2e87c..835ea9d092e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.2.0,<5.0.0 - geonode-importer>=1.0.8 + django-geonode-mapstore-client==4.2.0 + geonode-importer==1.0.9 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 99de4674bcc3474b27e65c581cd54520987dd29e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 12:53:00 +0200 Subject: [PATCH 223/253] Update dynamic-rest to 2.3.0 (#12292) (#12293) * Update setup.cfg * Update requirements.txt (cherry picked from commit 582392ea88b38beb2243360f03c013309247d4f2) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 2928b1033b4..1b3144dcff6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -79,7 +79,7 @@ djangorestframework-guardian==0.3.0 drf-extensions==0.7.1 drf-writable-nested==0.7.0 drf-spectacular==0.27.2 -git+https://github.com/AltSchool/dynamic-rest.git@v2.2.0#egg=dynamic_rest +dynamic-rest==2.3.0 Markdown==3.6 git+https://github.com/GeoNode/pinax-notifications.git@django_upgrade#egg=pinax-notifications diff --git a/setup.cfg b/setup.cfg index a316545b9cc..54eac342add 100644 --- a/setup.cfg +++ b/setup.cfg @@ -105,7 +105,7 @@ install_requires = drf-extensions==0.7.1 drf-writable-nested==0.7.0 drf-spectacular==0.27.2 - dynamic-rest @ git+https://github.com/AltSchool/dynamic-rest.git@v2.2.0#egg=dynamic_rest + dynamic-rest==2.3.0 Markdown==3.6 pinax-notifications @ git+https://github.com/GeoNode/pinax-notifications.git@django_upgrade#egg=pinax-notifications From 23d8faf1f3f2af9a7b7d90544279045b44b12267 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 15:24:49 +0200 Subject: [PATCH 224/253] Use published PyPi modules (#12295) (#12296) (cherry picked from commit 9882a795f355435bcce80ed09a56628f1adfc5f7) Co-authored-by: Giovanni Allegri --- requirements.txt | 8 ++++---- setup.cfg | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/requirements.txt b/requirements.txt index 1b3144dcff6..963c190eaa6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -82,15 +82,15 @@ drf-spectacular==0.27.2 dynamic-rest==2.3.0 Markdown==3.6 -git+https://github.com/GeoNode/pinax-notifications.git@django_upgrade#egg=pinax-notifications +geonode-pinax-notifications==6.0.0.2 # GeoNode org maintained apps. django-geonode-mapstore-client==4.3.0 geonode-importer==1.0.9 django-avatar==8.0.0 -git+https://github.com/GeoNode/geonode-oauth-toolkit.git@openid-connect#egg=geonode-oauth-toolkit -git+https://github.com/GeoNode/geonode-user-messages.git@django_upgrade#egg=geonode-user-messages -git+https://github.com/GeoNode/geonode-announcements.git@django_upgrade#egg=geonode-announcements +geonode-oauth-toolkit==2.2.2.2 +geonode-user-messages==2.0.2.2 +geonode-announcements==2.0.2.2 django-activity-stream==2.0.0 gn-arcrest==10.5.6 geoserver-restconfig~=2.0.11 diff --git a/setup.cfg b/setup.cfg index 54eac342add..7c337939658 100644 --- a/setup.cfg +++ b/setup.cfg @@ -108,15 +108,15 @@ install_requires = dynamic-rest==2.3.0 Markdown==3.6 - pinax-notifications @ git+https://github.com/GeoNode/pinax-notifications.git@django_upgrade#egg=pinax-notifications + geonode-pinax-notifications==6.0.0.2 # GeoNode org maintained apps. django-geonode-mapstore-client==4.3.0 geonode-importer==1.0.9 django-avatar==8.0.0 - geonode-oauth-toolkit @ git+https://github.com/GeoNode/geonode-oauth-toolkit.git@openid-connect#egg=geonode-oauth-toolkit - geonode-user-messages @ git+https://github.com/GeoNode/geonode-user-messages.git@django_upgrade#egg=geonode-user-messages - geonode-announcements @ git+https://github.com/GeoNode/geonode-announcements.git@django_upgrade#egg=geonode-announcements + geonode-oauth-toolkit==2.2.2.2 + geonode-user-messages==2.0.2.2 + geonode-announcements==2.0.2.2 django-activity-stream==2.0.0 gn-arcrest==10.5.6 geoserver-restconfig~=2.0.11 From 4df0b6428af33c283a9717c450e4237c31867c4f Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 30 May 2024 19:17:52 +0200 Subject: [PATCH 225/253] Bump to dev deps (#12299) * Bump to dev deps * build local docker --- docker-compose.yml | 6 +++--- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 3e3ca03578a..0b283f82bdf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,9 +4,9 @@ version: '3.9' x-common-django: &default-common-django image: geonode/geonode:4.3.0 - #build: - # context: ./ - # dockerfile: Dockerfile + build: + context: ./ + dockerfile: Dockerfile restart: unless-stopped env_file: - .env diff --git a/geonode/__init__.py b/geonode/__init__.py index e6892414338..54866022b5b 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 3, 0, "final", 0) +__version__ = (4, 3, 1, "dev", 0) def get_version(): diff --git a/requirements.txt b/requirements.txt index 963c190eaa6..16237c7484d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -85,8 +85,8 @@ Markdown==3.6 geonode-pinax-notifications==6.0.0.2 # GeoNode org maintained apps. -django-geonode-mapstore-client==4.3.0 -geonode-importer==1.0.9 +git+https://github.com/GeoNode/geonode-mapstore-client.git@4.3.x#egg=django_geonode_mapstore_client +git+https://github.com/GeoNode/geonode-importer.git@1.0.x#egg=geonode-importer django-avatar==8.0.0 geonode-oauth-toolkit==2.2.2.2 geonode-user-messages==2.0.2.2 diff --git a/setup.cfg b/setup.cfg index 7c337939658..3b077344d45 100644 --- a/setup.cfg +++ b/setup.cfg @@ -111,8 +111,8 @@ install_requires = geonode-pinax-notifications==6.0.0.2 # GeoNode org maintained apps. - django-geonode-mapstore-client==4.3.0 - geonode-importer==1.0.9 + django-geonode-mapstore-client>=4.3.0,<5.0.0 + geonode-importer>=1.0.9 django-avatar==8.0.0 geonode-oauth-toolkit==2.2.2.2 geonode-user-messages==2.0.2.2 From 0854a4ea2a74df0ad025710f18d2ef99df161282 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 31 May 2024 14:59:30 +0200 Subject: [PATCH 226/253] Fixes missing __init__.py inside people/api (#12300) (#12301) (cherry picked from commit eb9bfe0d98080ceb48c34b21dfe8059031474c3e) Co-authored-by: Giovanni Allegri --- geonode/people/api/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 geonode/people/api/__init__.py diff --git a/geonode/people/api/__init__.py b/geonode/people/api/__init__.py new file mode 100644 index 00000000000..e69de29bb2d From f1841f2bba57ab8265455c7a753d7f05d82de3d8 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Fri, 31 May 2024 15:03:03 +0200 Subject: [PATCH 227/253] Prepare tagging for fixed 4.3.0.post1 release (#12302) --- docker-compose.yml | 6 +++--- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 0b283f82bdf..3e3ca03578a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,9 +4,9 @@ version: '3.9' x-common-django: &default-common-django image: geonode/geonode:4.3.0 - build: - context: ./ - dockerfile: Dockerfile + #build: + # context: ./ + # dockerfile: Dockerfile restart: unless-stopped env_file: - .env diff --git a/geonode/__init__.py b/geonode/__init__.py index 54866022b5b..d8d6c353488 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 3, 1, "dev", 0) +__version__ = (4, 3, 0, "post", 1) def get_version(): diff --git a/requirements.txt b/requirements.txt index 16237c7484d..963c190eaa6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -85,8 +85,8 @@ Markdown==3.6 geonode-pinax-notifications==6.0.0.2 # GeoNode org maintained apps. -git+https://github.com/GeoNode/geonode-mapstore-client.git@4.3.x#egg=django_geonode_mapstore_client -git+https://github.com/GeoNode/geonode-importer.git@1.0.x#egg=geonode-importer +django-geonode-mapstore-client==4.3.0 +geonode-importer==1.0.9 django-avatar==8.0.0 geonode-oauth-toolkit==2.2.2.2 geonode-user-messages==2.0.2.2 diff --git a/setup.cfg b/setup.cfg index 3b077344d45..7c337939658 100644 --- a/setup.cfg +++ b/setup.cfg @@ -111,8 +111,8 @@ install_requires = geonode-pinax-notifications==6.0.0.2 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.3.0,<5.0.0 - geonode-importer>=1.0.9 + django-geonode-mapstore-client==4.3.0 + geonode-importer==1.0.9 django-avatar==8.0.0 geonode-oauth-toolkit==2.2.2.2 geonode-user-messages==2.0.2.2 From d296f7a8e20e3c3d34300011aa05b31e66c351da Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Fri, 31 May 2024 15:06:36 +0200 Subject: [PATCH 228/253] Bump to dev deps (#12303) --- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/geonode/__init__.py b/geonode/__init__.py index d8d6c353488..54866022b5b 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 3, 0, "post", 1) +__version__ = (4, 3, 1, "dev", 0) def get_version(): diff --git a/requirements.txt b/requirements.txt index 963c190eaa6..16237c7484d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -85,8 +85,8 @@ Markdown==3.6 geonode-pinax-notifications==6.0.0.2 # GeoNode org maintained apps. -django-geonode-mapstore-client==4.3.0 -geonode-importer==1.0.9 +git+https://github.com/GeoNode/geonode-mapstore-client.git@4.3.x#egg=django_geonode_mapstore_client +git+https://github.com/GeoNode/geonode-importer.git@1.0.x#egg=geonode-importer django-avatar==8.0.0 geonode-oauth-toolkit==2.2.2.2 geonode-user-messages==2.0.2.2 diff --git a/setup.cfg b/setup.cfg index 7c337939658..3b077344d45 100644 --- a/setup.cfg +++ b/setup.cfg @@ -111,8 +111,8 @@ install_requires = geonode-pinax-notifications==6.0.0.2 # GeoNode org maintained apps. - django-geonode-mapstore-client==4.3.0 - geonode-importer==1.0.9 + django-geonode-mapstore-client>=4.3.0,<5.0.0 + geonode-importer>=1.0.9 django-avatar==8.0.0 geonode-oauth-toolkit==2.2.2.2 geonode-user-messages==2.0.2.2 From a4589253a14e0c4fd7a34f5172ba2a6b619d08fc Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Fri, 7 Jun 2024 16:25:02 +0200 Subject: [PATCH 229/253] Add WFS links to tabular datasets --- geonode/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/utils.py b/geonode/utils.py index c93b61d7cf7..44d67cc39f8 100755 --- a/geonode/utils.py +++ b/geonode/utils.py @@ -1665,7 +1665,7 @@ def set_resource_default_links(instance, layer, prune=False, **kwargs): ), ) - if instance.subtype == "vector": + if instance.subtype == "vector" or instance.subtype == "tabular": ogc_wfs_url = instance.ows_url or urljoin(ogc_server_settings.public_url, "ows") ogc_wfs_name = f"OGC WFS: {instance.workspace} Service" if ( From 6739068a1a1219ebe9bb0a2c03811c609241f535 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Fri, 14 Jun 2024 12:51:45 +0000 Subject: [PATCH 230/253] Add proper download_url for tabular data See https://github.com/GeoNodeUserGroup-DE/geonode-dev-datapackage/issues/16 --- geonode/geoserver/helpers.py | 17 +++++++++++------ geonode/layers/download_handler.py | 4 +++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index 56d5696ae76..c85e6b6ad9b 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -103,6 +103,7 @@ ("application/wfs-collection-1.1", "vector"), ("application/zip", "vector"), ("text/csv", "vector"), + ("text/csv", "tabular"), ] DEFAULT_STYLE_NAME = ["generic", "line", "point", "polygon", "raster"] @@ -1126,14 +1127,18 @@ def clean_styles(layer, gs_catalog: Catalog): style = None gs_catalog.reset() gs_dataset = get_dataset(layer, gs_catalog) - if gs_dataset is not None: + if gs_dataset is None: + if gs_dataset.default_style is None: + # ignore dataset without style + pass + logger.debug(f'clean_styles: Retrieving style "{gs_dataset.default_style.name}" for cleanup') style = gs_catalog.get_style(name=gs_dataset.default_style.name, workspace=None, recursive=True) - if style: - gs_catalog.delete(style, purge=True, recurse=False) - logger.debug(f"clean_styles: Style removed: {gs_dataset.default_style.name}") - else: - logger.debug(f"clean_styles: Style does not exist: {gs_dataset.default_style.name}") + if style: + gs_catalog.delete(style, purge=True, recurse=False) + logger.debug(f"clean_styles: Style removed: {gs_dataset.default_style.name}") + else: + logger.debug(f"clean_styles: Style does not exist: {gs_dataset.default_style.name}") except Exception as e: logger.warning(f"Could not clean style for layer {layer.name}", exc_info=e) logger.debug(f"Could not clean style for layer {layer.name} - STACK INFO", stack_info=True) diff --git a/geonode/layers/download_handler.py b/geonode/layers/download_handler.py index 7f154a6f30d..dcdfecba1ec 100644 --- a/geonode/layers/download_handler.py +++ b/geonode/layers/download_handler.py @@ -75,7 +75,7 @@ def download_url(self): resource = self.get_resource() if not resource: return None - if resource.subtype not in ["vector", "raster", "vector_time"]: + if resource.subtype not in ["vector", "raster", "vector_time", "tabular"]: logger.info("Download URL is available only for datasets that have been harvested and copied locally") return None @@ -118,6 +118,8 @@ def process_dowload(self, resource=None): return JsonResponse({"error": "The format provided is not valid for the selected resource"}, status=500) _format = "application/zip" if resource.is_vector() else "image/tiff" + if resource.subtype == "tabular": + _format = "text/csv" # getting default payload tpl = get_template("geoserver/dataset_download.xml") ctx = {"alternate": resource.alternate, "download_format": download_format or _format} From b74f1cb4294630d832ee6c35a91e756c416d0a63 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Fri, 14 Jun 2024 15:23:49 +0000 Subject: [PATCH 231/253] Fix singular case of download_url See https://github.com/GeoNodeUserGroup-DE/geonode-dev-datapackage/issues/16 --- geonode/layers/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/layers/models.py b/geonode/layers/models.py index 016597dcb44..3188cdd2837 100644 --- a/geonode/layers/models.py +++ b/geonode/layers/models.py @@ -328,7 +328,7 @@ def get_linked_resources(self, as_target: bool = False): @property def download_url(self): - if self.subtype not in ["vector", "raster", "vector_time"]: + if self.subtype not in ["vector", "raster", "vector_time", "tabular"]: logger.info("Download URL is available only for datasets that have been harvested and copied locally") return None return build_absolute_uri(reverse("dataset_download", args=(self.alternate,))) From a40184803cc49462c30edcbbd19a9d8d9bad6691 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 18 Jun 2024 11:32:47 +0200 Subject: [PATCH 232/253] Keep tabular subtype when syncing with geoserver Fixes: https://github.com/GeoNodeUserGroup-DE/importer-datapackage/issues/4 --- geonode/geoserver/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index c85e6b6ad9b..645e79a23a4 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -1571,7 +1571,7 @@ def fetch_gs_resource(instance, values, tries): else: values = {} - _subtype = gs_resource.store.resource_type + _subtype = "tabular" if instance.subtype == "tabular" else gs_resource.store.resource_type if ( getattr(gs_resource, "metadata", None) and gs_resource.metadata.get("time", False) From 8c9fbe467ec9367e676d87c95d980c5230b0ed3c Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 18 Jun 2024 15:32:27 +0200 Subject: [PATCH 233/253] Create attributes_set for tabular datasets too See https://github.com/GeoNodeUserGroup-DE/geonode-dev-datapackage/issues/3 --- geonode/geoserver/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index 645e79a23a4..d6c0964cd6f 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -1015,7 +1015,7 @@ def set_attributes_from_geoserver(layer, overwrite=False): tb = traceback.format_exc() logger.debug(tb) attribute_map = [] - elif layer.subtype in {"vector", "tileStore", "remote", "wmsStore", "vector_time"}: + elif layer.subtype in {"vector", "tileStore", "remote", "wmsStore", "vector_time", "tabular"}: typename = layer.alternate if layer.alternate else layer.typename dft_url_path = re.sub(r"\/wms\/?$", "/", server_url) dft_query = urlencode( From ec426922575475661654abd89940a2e887dd454c Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 25 Jun 2024 14:36:11 +0200 Subject: [PATCH 234/253] Do not create image links for tabular data Closes https://github.com/GeoNodeUserGroup-DE/geonode-dev-datapackage/issues/19 --- geonode/geoserver/helpers.py | 2 +- geonode/utils.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index d6c0964cd6f..71a2d3411fa 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -1218,7 +1218,7 @@ def set_styles(layer, gs_catalog: Catalog): layer.default_style, ] ): - if style: + if style and layer.subtype != "tabular": style_name = os.path.basename(urlparse(style.sld_url).path).split(".")[0] legend_url = get_legend_url(layer, style_name) if dataset_legends.filter(resource=layer.resourcebase_ptr, name="Legend", url=legend_url).count() < 2: diff --git a/geonode/utils.py b/geonode/utils.py index 44d67cc39f8..ed6e23e83ed 100755 --- a/geonode/utils.py +++ b/geonode/utils.py @@ -1486,7 +1486,7 @@ def set_resource_default_links(instance, layer, prune=False, **kwargs): # Set download links for WMS, WCS or WFS and KML logger.debug(" -- Resource Links[Set download links for WMS, WCS or WFS and KML]...") instance_ows_url = f"{instance.ows_url}?" if instance.ows_url else f"{ogc_server_settings.public_url}ows?" - links = wms_links(instance_ows_url, instance.alternate, bbox, srid, height, width) + links = wms_links(instance_ows_url, instance.alternate, bbox, srid, height, width) if instance.subtype != "tabular" else [] for ext, name, mime, wms_url in links: try: @@ -1506,7 +1506,7 @@ def set_resource_default_links(instance, layer, prune=False, **kwargs): resource=instance.resourcebase_ptr, name=gettext_lazy(name), link_type="image" ).update(**_d) - if instance.subtype == "vector": + if instance.subtype == "vector" or instance.subtype == "tabular": links = wfs_links( instance_ows_url, instance.alternate, @@ -1592,7 +1592,7 @@ def set_resource_default_links(instance, layer, prune=False, **kwargs): instance.default_style, ] ): - if style: + if style and instance.subtype != "tabular": style_name = os.path.basename(urlparse(style.sld_url).path).split(".")[0] legend_url = get_legend_url(instance, style_name) if Link.objects.filter(resource=instance.resourcebase_ptr, url=legend_url).count() < 2: @@ -1650,6 +1650,7 @@ def set_resource_default_links(instance, layer, prune=False, **kwargs): ogc_wms_url = instance.ows_url or urljoin(ogc_server_settings.public_url, "ows") ogc_wms_name = f"OGC WMS: {instance.workspace} Service" if ( + instance.subtype != "tabular" and Link.objects.filter(resource=instance.resourcebase_ptr, name=ogc_wms_name, url=ogc_wms_url).count() < 2 ): From fdefb0d8070a2faab07d1b4b44f355db295c4419 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 25 Jun 2024 14:59:12 +0200 Subject: [PATCH 235/253] Avoid calls to GWC for non-spatial data See https://github.com/GeoNodeUserGroup-DE/geonode-dev-datapackage/issues/14 --- .../br/management/commands/create_tile_layers.py | 2 +- geonode/geoserver/helpers.py | 15 ++++++++------- .../management/commands/set_default_gridsets.py | 2 +- geonode/geoserver/manager.py | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/geonode/br/management/commands/create_tile_layers.py b/geonode/br/management/commands/create_tile_layers.py index 57b81d805aa..231b1a52e95 100644 --- a/geonode/br/management/commands/create_tile_layers.py +++ b/geonode/br/management/commands/create_tile_layers.py @@ -116,7 +116,7 @@ def handle(self, **options): curl -v -u admin:geoserver -XGET \ "http://:/geoserver/gwc/rest/layers/geonode:tasmania_roads.xml" """ - layers = Dataset.objects.all() + layers = Dataset.objects.filter(subtype__not="tabular") tot = len(layers) logger.info(f"Total layers in GeoNode: {tot}") i = 0 diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index 71a2d3411fa..0145bf26830 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -1779,7 +1779,7 @@ def style_update(request, url, workspace=None): # Invalidate GeoWebCache so it doesn't retain old style in tiles try: - if dataset_name: + if dataset_name and layer.subtype != "tabular": _stylefilterparams_geowebcache_dataset(dataset_name) _invalidate_geowebcache_dataset(dataset_name) except Exception: @@ -2186,12 +2186,13 @@ def sync_instance_with_geoserver(instance_id, *args, **kwargs): except Exception as e: logger.warning(e) - # Invalidate GeoWebCache for the updated resource - try: - _stylefilterparams_geowebcache_dataset(instance.alternate) - _invalidate_geowebcache_dataset(instance.alternate) - except Exception as e: - logger.warning(e) + if instance.subtype != "tabular": + # Invalidate GeoWebCache for the updated resource + try: + _stylefilterparams_geowebcache_dataset(instance.alternate) + _invalidate_geowebcache_dataset(instance.alternate) + except Exception as e: + logger.warning(e) # Refreshing dataset links logger.debug(f"... Creating Default Resource Links for Dataset {instance.title}") diff --git a/geonode/geoserver/management/commands/set_default_gridsets.py b/geonode/geoserver/management/commands/set_default_gridsets.py index 0826b744e57..5bdac07eefd 100644 --- a/geonode/geoserver/management/commands/set_default_gridsets.py +++ b/geonode/geoserver/management/commands/set_default_gridsets.py @@ -43,7 +43,7 @@ def handle(self, **options): curl -v -u admin:geoserver -XGET \ "http://:/geoserver/gwc/rest/layers/geonode:tasmania_roads.xml" """ - layers = Dataset.objects.all() + layers = Dataset.objects.filter(subtype__not="tabular") print(f"Total layers to be updated: {layers.count()}") for layer in layers: print(f"Processing layer: {layer.typename}") diff --git a/geonode/geoserver/manager.py b/geonode/geoserver/manager.py index a88b641b71f..0cc7c83c607 100644 --- a/geonode/geoserver/manager.py +++ b/geonode/geoserver/manager.py @@ -532,7 +532,7 @@ def set_permissions( create_geofence_rules(_resource, DOWNLOAD_PERMISSIONS, None, None, batch) exist_geolimits = exist_geolimits or has_geolimits(_resource, None, None) - if exist_geolimits is not None: + if exist_geolimits is not None and _resource.subtype != "tabular": filters, formats = _get_gwc_filters_and_formats(exist_geolimits) try: _dataset_workspace = get_dataset_workspace(_resource) From 4c05cbd3d487b35a3a5b8d0238506c29393dc8fc Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Thu, 4 Jul 2024 18:11:03 +0200 Subject: [PATCH 236/253] Relax contraint on column description As datapackage descriptions can easily take more than 255 characters it makes sense to relax the contraints here. In this case we just set no constraints at all. Fixes https://github.com/GeoNodeUserGroup-DE/geonode-dev-datapackage/issues/23 --- .../0045_alter_attribute_description.py | 23 +++++++++++++++++++ geonode/layers/models.py | 3 +-- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 geonode/layers/migrations/0045_alter_attribute_description.py diff --git a/geonode/layers/migrations/0045_alter_attribute_description.py b/geonode/layers/migrations/0045_alter_attribute_description.py new file mode 100644 index 00000000000..6d988f30d33 --- /dev/null +++ b/geonode/layers/migrations/0045_alter_attribute_description.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.9 on 2024-07-04 16:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("layers", "0044_alter_dataset_unique_together"), + ] + + operations = [ + migrations.AlterField( + model_name="attribute", + name="description", + field=models.TextField( + blank=True, + help_text="description of attribute to be used in metadata", + null=True, + verbose_name="attribute description", + ), + ), + ] diff --git a/geonode/layers/models.py b/geonode/layers/models.py index 3188cdd2837..a15eec68c8c 100644 --- a/geonode/layers/models.py +++ b/geonode/layers/models.py @@ -400,10 +400,9 @@ class Attribute(models.Model): null=True, unique=False, ) - description = models.CharField( + description = models.TextField( _("attribute description"), help_text=_("description of attribute to be used in metadata"), - max_length=255, blank=True, null=True, ) From 7197e76e905ad2ead4e790889cd72e87f999338c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 13:55:11 +0200 Subject: [PATCH 237/253] [Fixes #12361] Fix captcha field visualization in signup page (#12392) (#12393) * Fix captcha field visualization in signup page * fix formatting (cherry picked from commit d3686f86aee56cb3be5b71601237a5542fed7bdb) Co-authored-by: Giovanni Allegri --- geonode/people/forms.py | 2 +- geonode/people/views.py | 4 ++++ geonode/templates/account/signup.html | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/geonode/people/forms.py b/geonode/people/forms.py index b158ae74136..9fbdf4ae638 100644 --- a/geonode/people/forms.py +++ b/geonode/people/forms.py @@ -34,7 +34,7 @@ class AllauthReCaptchaSignupForm(forms.Form): - captcha = ReCaptchaField() + captcha = ReCaptchaField(label=False) def signup(self, request, user): """Required, or else it thorws deprecation warnings""" diff --git a/geonode/people/views.py b/geonode/people/views.py index f7f68a027e9..3abfae18fcf 100644 --- a/geonode/people/views.py +++ b/geonode/people/views.py @@ -50,6 +50,10 @@ class CustomSignupView(SignupView): def get_context_data(self, **kwargs): ret = super().get_context_data(**kwargs) ret.update({"account_geonode_local_signup": settings.SOCIALACCOUNT_WITH_GEONODE_LOCAL_SINGUP}) + # Push captcha field at the end + form = ret["form"] + form.field_order = [f for f in form.fields.keys() if f != "captcha"] + ["captcha"] + form.order_fields(form.field_order) return ret diff --git a/geonode/templates/account/signup.html b/geonode/templates/account/signup.html index 7d897580cdd..f0752becf6e 100644 --- a/geonode/templates/account/signup.html +++ b/geonode/templates/account/signup.html @@ -44,6 +44,7 @@

    {% trans "Sign up" %}

    {% endblock %} From 5ebe7fc45d60b3471ae1055cfe54a1c6d4c8918b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 15:06:10 +0200 Subject: [PATCH 238/253] Move create_tile_layers to backup.sh (#12394) (#12395) (cherry picked from commit 7a99ec8fec9fe54f4bf7ebeb48d8d8732540ca90) Co-authored-by: Giovanni Allegri --- geonode/br/management/commands/restore.py | 1 - 1 file changed, 1 deletion(-) diff --git a/geonode/br/management/commands/restore.py b/geonode/br/management/commands/restore.py index 95ee228d955..e8b48ba8287 100755 --- a/geonode/br/management/commands/restore.py +++ b/geonode/br/management/commands/restore.py @@ -304,7 +304,6 @@ def execute_restore(self, **options): self.restore_geoserver_vector_data(config, settings, target_folder, soft_reset) self.restore_geoserver_externals(config, settings, target_folder) logger.info("*** Recreate GWC tile layers") - call_command("create_tile_layers") except Exception as e: logger.warning(f"*** GeoServer Restore failed: {e}", exc_info=e) if recovery_file: From 750457b995ad10fe9985eb14e91fdc50fdeacb0a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:56:12 +0200 Subject: [PATCH 239/253] [Fixes #12369] Create a command to regenerate the XML metadata (#12396) (#12401) (cherry picked from commit cc3816da2d332a1eda338706c94585209b28802f) Co-authored-by: Emanuele Tajariol --- geonode/base/management/command_utils.py | 34 +++++ geonode/catalogue/management/__init__.py | 0 .../catalogue/management/commands/__init__.py | 0 .../management/commands/regenerate_xml.py | 126 ++++++++++++++++++ geonode/catalogue/models.py | 7 +- 5 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 geonode/base/management/command_utils.py create mode 100644 geonode/catalogue/management/__init__.py create mode 100644 geonode/catalogue/management/commands/__init__.py create mode 100644 geonode/catalogue/management/commands/regenerate_xml.py diff --git a/geonode/base/management/command_utils.py b/geonode/base/management/command_utils.py new file mode 100644 index 00000000000..9d70f22d49e --- /dev/null +++ b/geonode/base/management/command_utils.py @@ -0,0 +1,34 @@ +import logging +from django.conf import settings + +DEFAULT_COMMAND_LOGGER_NAME = "geonode.commands" + + +def setup_logger(logger_name=DEFAULT_COMMAND_LOGGER_NAME, formatter_name="command", handler_name="command"): + if logger_name not in settings.LOGGING["loggers"]: + format = "%(levelname)-7s %(asctime)s %(message)s" + + settings.LOGGING["formatters"][formatter_name] = { + "format": format + } + settings.LOGGING["handlers"][handler_name] = { + "level": "DEBUG", + "class": "logging.StreamHandler", + "formatter": formatter_name + } + settings.LOGGING["loggers"][logger_name] = { + "handlers": [handler_name], + "level": "INFO", + "propagate": False + } + + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter(fmt=format)) + handler.setLevel(logging.DEBUG) + + logger = logging.getLogger(logger_name) + logger.addHandler(handler) + logger.setLevel(logging.INFO) + logger.propagate = False + + return logger diff --git a/geonode/catalogue/management/__init__.py b/geonode/catalogue/management/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/geonode/catalogue/management/commands/__init__.py b/geonode/catalogue/management/commands/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/geonode/catalogue/management/commands/regenerate_xml.py b/geonode/catalogue/management/commands/regenerate_xml.py new file mode 100644 index 00000000000..ce89abdaaa7 --- /dev/null +++ b/geonode/catalogue/management/commands/regenerate_xml.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +######################################################################### +# +# Copyright (C) 2023 OSGeo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +######################################################################### + +import logging + +from django.core.management.base import BaseCommand + +from geonode.base.management import command_utils +from geonode.base.models import ResourceBase +from geonode.layers.models import Dataset + + +logger = logging.getLogger(__name__) + + +class Command(BaseCommand): + help = "Re-create XML metadata documents" + + def add_arguments(self, parser): + parser.add_argument( + '-l', + '--layer', + dest="layers", + action='append', + help="Only process specified layers ") + + parser.add_argument( + "--skip-logger-setup", + action="store_false", + dest="setup_logger", + help='Skips setup of the "geonode.br" logger, "br" handler and "br" format if not present in settings', + ) + parser.add_argument( + '-d', + '--dry-run', + dest="dry-run", + action='store_true', + help="Do not actually perform any change") + + def handle(self, **options): + requested_layers = options.get('layers') + dry_run = options.get('dry-run') + + if options.get("setup_logger"): + logger = command_utils.setup_logger() + + logger.info(f"==== Running command {__name__}") + logger.info(f"{self.help}") + logger.info("") + + logger.debug(f"DRY-RUN is {dry_run}") + logger.debug(f"LAYERS is {requested_layers}") + + try: + + layers = Dataset.objects.all() + tot = len(layers) + logger.info(f"Total layers in GeoNode: {tot}") + i = 0 + cnt_ok = 0 + cnt_bad = 0 + cnt_skip = 0 + + instance: ResourceBase + for instance in layers: + i += 1 + logger.info(f"- {i}/{tot} Processing layer {instance.id} [{instance.typename}] '{instance.title}'") + + if requested_layers and instance.typename not in requested_layers: + logger.info(" - Layer filtered out by args") + cnt_skip += 1 + continue + + if instance.metadata_uploaded and instance.metadata_uploaded_preserve: + logger.info(" - Layer filtered out since it uses custom XML") + cnt_skip += 1 + continue + + try: + good = None + if not dry_run: + try: + try: + # the save() method triggers the metadata regeneration + instance.save() + good = True + except Exception as e: + logger.error(f"Error saving instance '{instance.title}': {e}") + raise e + + except Exception as e: + logger.exception(f"Error processing '{instance.title}': {e}", e) + + if dry_run or good: + logger.info(f" - Done {instance.name}") + cnt_ok += 1 + else: + logger.warning(f"Metadata couldn't be regenerated for instance '{instance.title}' ") + cnt_bad += 1 + + except Exception as e: + raise e + except Exception as e: + raise e + + logger.info("Work completed" + (" [DRYRUN]" if dry_run else "")) + logger.info(f"- Metadata regenerated : {cnt_ok}") + logger.info(f"- Metadata in error : {cnt_bad}") + logger.info(f"- Resources skipped : {cnt_skip}") diff --git a/geonode/catalogue/models.py b/geonode/catalogue/models.py index caebd2fe42e..e575be179e6 100644 --- a/geonode/catalogue/models.py +++ b/geonode/catalogue/models.py @@ -80,11 +80,14 @@ def catalogue_post_save(instance, sender, **kwargs): resource=resources.get(), url=metadata_url, extension="xml", link_type="metadata" ).update(**_d) - # generate an XML document (GeoNode's default is ISO) if instance.metadata_uploaded and instance.metadata_uploaded_preserve: md_doc = etree.tostring(dlxml.fromstring(instance.metadata_xml)) else: - md_doc = catalogue.catalogue.csw_gen_xml(instance, settings.CATALOG_METADATA_TEMPLATE) + # generate an XML document (GeoNode's default is ISO) + raw_xml = catalogue.catalogue.csw_gen_xml(instance, settings.CATALOG_METADATA_TEMPLATE) + md_obj = dlxml.fromstring(raw_xml, parser=etree.XMLParser(remove_blank_text=True)) + md_doc = etree.tostring(md_obj, pretty_print=True, encoding="unicode") + try: csw_anytext = catalogue.catalogue.csw_gen_anytext(md_doc) except Exception as e: From 5ac36014f5505f55897f4ef97aa4a06ff4af3422 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 21:29:47 +0200 Subject: [PATCH 240/253] [Fixes #12402] Adopt strict-origin-when-cross-origin Referrer Policy as default (#12403) (#12404) * Referre poicy strict-origin-when-cross-origin as default * adapt proxy tests to adapt to new referrer policy (cherry picked from commit 8bb5eda741b4ec6e5a3c5ed652ffff97a72fde03) Co-authored-by: Giovanni Allegri --- geonode/proxy/tests.py | 4 ++-- geonode/settings.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/geonode/proxy/tests.py b/geonode/proxy/tests.py index 2f094488ee0..ce2c966dc00 100644 --- a/geonode/proxy/tests.py +++ b/geonode/proxy/tests.py @@ -214,7 +214,7 @@ class Response: "Vary": "Authorization, Accept-Language, Cookie, origin", "X-Content-Type-Options": "nosniff", "X-XSS-Protection": "1; mode=block", - "Referrer-Policy": "same-origin", + "Referrer-Policy": "strict-origin-when-cross-origin", "Cross-Origin-Opener-Policy": "same-origin", "X-Frame-Options": "SAMEORIGIN", "Content-Language": "en", @@ -236,7 +236,7 @@ class Response: "Vary": "Authorization, Accept-Language, Cookie, origin", "X-Content-Type-Options": "nosniff", "X-XSS-Protection": "1; mode=block", - "Referrer-Policy": "same-origin", + "Referrer-Policy": "strict-origin-when-cross-origin", "X-Frame-Options": "SAMEORIGIN", "Content-Language": "en-us", "Content-Length": "119", diff --git a/geonode/settings.py b/geonode/settings.py index c2a2660a4f3..70651fb21ba 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -848,6 +848,7 @@ SECURE_SSL_REDIRECT = ast.literal_eval(os.environ.get("SECURE_SSL_REDIRECT", "False")) SECURE_HSTS_SECONDS = int(os.getenv("SECURE_HSTS_SECONDS", "3600")) SECURE_HSTS_INCLUDE_SUBDOMAINS = ast.literal_eval(os.environ.get("SECURE_HSTS_INCLUDE_SUBDOMAINS", "True")) +SECURE_REFERRER_POLICY = os.environ.get("SECURE_REFERRER_POLICY", "strict-origin-when-cross-origin") # Replacement of the default authentication backend in order to support # permissions per object. From bb7827548039c16c83d483bc99702a99b58a4602 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 11 Jul 2024 14:57:33 +0200 Subject: [PATCH 241/253] Add missing "m" in "Request permission" (#12266) (#12410) Add missing "m" in "Request permission" (cherry picked from commit dd0000612fbf0d022707cf74949c09be660418e9) Co-authored-by: Sylvain POULAIN --- geonode/templates/owner_rights_request.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geonode/templates/owner_rights_request.html b/geonode/templates/owner_rights_request.html index feb09faafd4..00e2ed189f6 100644 --- a/geonode/templates/owner_rights_request.html +++ b/geonode/templates/owner_rights_request.html @@ -3,7 +3,7 @@ {% load i18n %} {% load bootstrap_tags %} -{% block title %}{% trans "Request perission" %} {% endblock %} +{% block title %}{% trans "Request permission" %} {% endblock %} {% block body %}

    {% trans "Request editing for resource: " %} {{ resource.title }}

    {% trans "Back to resource" %} @@ -16,4 +16,4 @@

    {% trans "Request editing for resource: " %} {{ resource.title }}

    -{% endblock %} \ No newline at end of file +{% endblock %} From 8a2eaa5d3930b33dfbfd6b4095a268b3d031ee4c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 17:46:00 +0200 Subject: [PATCH 242/253] [Fixes #12413] Group filter autocomplete does not work (#12414) (#12415) (cherry picked from commit 0c827f565336e8f0a60d76a44fa0b218b1f6a574) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/facets/providers/group.py | 3 +++ geonode/facets/tests.py | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/geonode/facets/providers/group.py b/geonode/facets/providers/group.py index d93404337f4..c8de489b461 100644 --- a/geonode/facets/providers/group.py +++ b/geonode/facets/providers/group.py @@ -62,6 +62,9 @@ def get_facet_items( logger.debug("Filtering by keys %r", keys) filters["group__id__in"] = keys + if topic_contains: + filters["group__name__icontains"] = topic_contains + visible_groups = get_user_visible_groups(user=kwargs["user"]) q = ( diff --git a/geonode/facets/tests.py b/geonode/facets/tests.py index 9bce8fc6a96..5cd6cba1b57 100644 --- a/geonode/facets/tests.py +++ b/geonode/facets/tests.py @@ -669,3 +669,28 @@ def test_group_facet_api_call(self): self.assertDictEqual(expected_response_filtered, response_dict_filtered) self.assertDictEqual(expected_response_base, response_dict_base) + + def test_group_facets_are_filtered_by_words(self): + # there are some groups and the facets return them + url = f"{reverse('get_facet',args=['group'])}" + + response = self.client.get(url) + self.assertEqual(200, response.status_code, response.json()) + + self.assertTrue(response.json().get("topics", {}).get("total", 0) > 0) + + # topic_contains with real name should return 1 + url = f"{reverse('get_facet',args=['group'])}?topic_contains=UserAdmin" + response = self.client.get(url) + + self.assertEqual(200, response.status_code, response.json()) + + self.assertEqual(1, response.json().get("topics", {}).get("total", 0)) + + # topic_contains with a random string to be searched for should be 0 + url = f"{reverse('get_facet',args=['group'])}?topic_contains=abc123scfuqbrwefbasascgiu" + response = self.client.get(url) + + self.assertEqual(200, response.status_code, response.json()) + + self.assertEqual(0, response.json().get("topics", {}).get("total", 0)) From 2dc0df0b13cdf740a7dae230a04c5db0e962b169 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Fri, 19 Jul 2024 16:26:35 +0200 Subject: [PATCH 243/253] Upgrade to Geoserver 2.24.4 (#12426) --- docker-compose-dev.yml | 4 ++-- docker-compose-test.yml | 4 ++-- docker-compose.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index fb4aac94f86..65c1c9b2b36 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -79,7 +79,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.24.3-v1 + image: geonode/geoserver:2.24.4-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -105,7 +105,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.24.3-v1 + image: geonode/geoserver_data:2.24.4-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 5f1ea57d6ab..0194bcb559a 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -92,7 +92,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.24.3-v1 + image: geonode/geoserver:2.24.4-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -118,7 +118,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.24.3-v1 + image: geonode/geoserver_data:2.24.4-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: diff --git a/docker-compose.yml b/docker-compose.yml index 3e3ca03578a..709ddc3b147 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -91,7 +91,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.24.3-v1 + image: geonode/geoserver:2.24.4-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -117,7 +117,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.24.3-v1 + image: geonode/geoserver_data:2.24.4-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: From 46f27dc5b52daa5d8dffa81afa4b9100fd7246e5 Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Fri, 19 Jul 2024 16:27:57 +0200 Subject: [PATCH 244/253] Bump to 4.3.1 --- docker-compose.yml | 2 +- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 709ddc3b147..354010dcff6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:4.3.0 + image: geonode/geonode:4.3.1 #build: # context: ./ # dockerfile: Dockerfile diff --git a/geonode/__init__.py b/geonode/__init__.py index 54866022b5b..52dca5d04bd 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 3, 1, "dev", 0) +__version__ = (4, 3, 1, 'final', 0) def get_version(): diff --git a/requirements.txt b/requirements.txt index 16237c7484d..e56405e86ae 100644 --- a/requirements.txt +++ b/requirements.txt @@ -85,8 +85,8 @@ Markdown==3.6 geonode-pinax-notifications==6.0.0.2 # GeoNode org maintained apps. -git+https://github.com/GeoNode/geonode-mapstore-client.git@4.3.x#egg=django_geonode_mapstore_client -git+https://github.com/GeoNode/geonode-importer.git@1.0.x#egg=geonode-importer +django-geonode-mapstore-client==4.3.1 +geonode-importer==1.0.10 django-avatar==8.0.0 geonode-oauth-toolkit==2.2.2.2 geonode-user-messages==2.0.2.2 diff --git a/setup.cfg b/setup.cfg index 3b077344d45..c7c7d0555eb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -111,8 +111,8 @@ install_requires = geonode-pinax-notifications==6.0.0.2 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.3.0,<5.0.0 - geonode-importer>=1.0.9 + django-geonode-mapstore-client==4.3.1 + geonode-importer==1.0.10 django-avatar==8.0.0 geonode-oauth-toolkit==2.2.2.2 geonode-user-messages==2.0.2.2 From fbdfe7353199881c3e8ca80e156b42aa2e182d28 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 13 Aug 2024 18:33:25 +0200 Subject: [PATCH 245/253] Use WFS link for tabular datasets Some URL needs to be available for download. --- geonode/base/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/base/models.py b/geonode/base/models.py index 0c83f340898..643aad67f43 100644 --- a/geonode/base/models.py +++ b/geonode/base/models.py @@ -1510,7 +1510,7 @@ def get_legend_url(self, style_name=None): def get_ows_url(self): """Return URL for OGC WMS server None if it does not exist.""" try: - ows_link = self.link_set.get(name="OGC:WMS") + ows_link = self.link_set.get(name="OGC:WMS") or self.link_set.get(name="OGC:WFS") except Link.DoesNotExist: return None else: From ac4a3e9d0cb288429cf2c84774accccd4c8aecb4 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 13 Aug 2024 18:38:10 +0200 Subject: [PATCH 246/253] Store map subtype for tabular collections --- geonode/maps/api/views.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/geonode/maps/api/views.py b/geonode/maps/api/views.py index 6ad3febe547..ec4e6b5ffb1 100644 --- a/geonode/maps/api/views.py +++ b/geonode/maps/api/views.py @@ -117,10 +117,13 @@ def datasets(self, request, pk=None, *args, **kwargs): def perform_create(self, serializer): # Thumbnail will be handled later post_creation_data = {"thumbnail": serializer.validated_data.pop("thumbnail_url", "")} + map_layers = serializer.validated_data.pop("maplayers", []) + tabular_collection = all(("tabular" in layer.dataset.subtype) for layer in map_layers) instance = serializer.save( owner=self.request.user, resource_type="map", + subtype="tabular-collection" if tabular_collection else None, uuid=str(uuid4()), ) @@ -148,8 +151,13 @@ def perform_update(self, serializer): "thumbnail": serializer.validated_data.pop("thumbnail_url", ""), "dataset_names_before_changes": [lyr.alternate for lyr in instance.datasets], } + + map_layers = serializer.validated_data.pop("maplayers", []) + tabular_collection = all(("tabular" in layer.dataset.subtype) for layer in map_layers) - instance = serializer.save() + instance = serializer.save( + subtype="tabular-collection" if tabular_collection else None, + ) # thumbnail, events and resouce routines self._post_change_routines( From 3c9f5ad23a0a4dd277d4c1d1c68f406a5ab3628a Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Tue, 13 Aug 2024 21:30:04 +0200 Subject: [PATCH 247/253] Fix storing maplayers --- geonode/maps/api/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/geonode/maps/api/views.py b/geonode/maps/api/views.py index ec4e6b5ffb1..d28276e881a 100644 --- a/geonode/maps/api/views.py +++ b/geonode/maps/api/views.py @@ -117,7 +117,7 @@ def datasets(self, request, pk=None, *args, **kwargs): def perform_create(self, serializer): # Thumbnail will be handled later post_creation_data = {"thumbnail": serializer.validated_data.pop("thumbnail_url", "")} - map_layers = serializer.validated_data.pop("maplayers", []) + map_layers = serializer.validated_data.get("maplayers", []) tabular_collection = all(("tabular" in layer.dataset.subtype) for layer in map_layers) instance = serializer.save( @@ -151,8 +151,8 @@ def perform_update(self, serializer): "thumbnail": serializer.validated_data.pop("thumbnail_url", ""), "dataset_names_before_changes": [lyr.alternate for lyr in instance.datasets], } - - map_layers = serializer.validated_data.pop("maplayers", []) + + map_layers = serializer.validated_data.get("maplayers", []) tabular_collection = all(("tabular" in layer.dataset.subtype) for layer in map_layers) instance = serializer.save( From 98d786da42fa37ec4c68f23cbf2b4f43ad960f00 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Fri, 23 Aug 2024 14:28:55 +0200 Subject: [PATCH 248/253] Tabular datasets (datapackage upload) --- geonode/base/models.py | 2 +- .../management/commands/create_tile_layers.py | 31 +++++------- geonode/geoserver/helpers.py | 38 ++++++++------- .../commands/set_default_gridsets.py | 48 +++++++++++-------- geonode/geoserver/manager.py | 2 +- geonode/layers/download_handler.py | 4 +- geonode/layers/models.py | 5 +- geonode/maps/api/views.py | 10 +++- geonode/utils.py | 17 +++++-- 9 files changed, 90 insertions(+), 67 deletions(-) diff --git a/geonode/base/models.py b/geonode/base/models.py index 0c83f340898..643aad67f43 100644 --- a/geonode/base/models.py +++ b/geonode/base/models.py @@ -1510,7 +1510,7 @@ def get_legend_url(self, style_name=None): def get_ows_url(self): """Return URL for OGC WMS server None if it does not exist.""" try: - ows_link = self.link_set.get(name="OGC:WMS") + ows_link = self.link_set.get(name="OGC:WMS") or self.link_set.get(name="OGC:WFS") except Link.DoesNotExist: return None else: diff --git a/geonode/br/management/commands/create_tile_layers.py b/geonode/br/management/commands/create_tile_layers.py index 57b81d805aa..466f9bb41d4 100644 --- a/geonode/br/management/commands/create_tile_layers.py +++ b/geonode/br/management/commands/create_tile_layers.py @@ -79,30 +79,23 @@ class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument( - '-f', - '--force', + "-f", + "--force", dest="force", - action='store_true', - help="Force tile layer re-creation also if it already exists in GWC") + action="store_true", + help="Force tile layer re-creation also if it already exists in GWC", + ) - parser.add_argument( - '-l', - '--layer', - dest="layers", - action='append', - help="Only process specified layers ") + parser.add_argument("-l", "--layer", dest="layers", action="append", help="Only process specified layers ") parser.add_argument( - '-d', - '--dry-run', - dest="dry-run", - action='store_true', - help="Do not actually perform any change on GWC") + "-d", "--dry-run", dest="dry-run", action="store_true", help="Do not actually perform any change on GWC" + ) def handle(self, **options): - force = options.get('force') - requested_layers = options.get('layers') - dry_run = options.get('dry-run') + force = options.get("force") + requested_layers = options.get("layers") + dry_run = options.get("dry-run") logger.debug(f"FORCE is {force}") logger.debug(f"DRY-RUN is {dry_run}") @@ -116,7 +109,7 @@ def handle(self, **options): curl -v -u admin:geoserver -XGET \ "http://:/geoserver/gwc/rest/layers/geonode:tasmania_roads.xml" """ - layers = Dataset.objects.all() + layers = Dataset.objects.filter(subtype__not="tabular") tot = len(layers) logger.info(f"Total layers in GeoNode: {tot}") i = 0 diff --git a/geonode/geoserver/helpers.py b/geonode/geoserver/helpers.py index 56d5696ae76..57299a6edf9 100755 --- a/geonode/geoserver/helpers.py +++ b/geonode/geoserver/helpers.py @@ -103,6 +103,7 @@ ("application/wfs-collection-1.1", "vector"), ("application/zip", "vector"), ("text/csv", "vector"), + ("text/csv", "tabular"), ] DEFAULT_STYLE_NAME = ["generic", "line", "point", "polygon", "raster"] @@ -1014,7 +1015,7 @@ def set_attributes_from_geoserver(layer, overwrite=False): tb = traceback.format_exc() logger.debug(tb) attribute_map = [] - elif layer.subtype in {"vector", "tileStore", "remote", "wmsStore", "vector_time"}: + elif layer.subtype in {"vector", "tileStore", "remote", "wmsStore", "vector_time", "tabular"}: typename = layer.alternate if layer.alternate else layer.typename dft_url_path = re.sub(r"\/wms\/?$", "/", server_url) dft_query = urlencode( @@ -1126,14 +1127,18 @@ def clean_styles(layer, gs_catalog: Catalog): style = None gs_catalog.reset() gs_dataset = get_dataset(layer, gs_catalog) - if gs_dataset is not None: + if gs_dataset is None: + if gs_dataset.default_style is None: + # ignore dataset without style + pass + logger.debug(f'clean_styles: Retrieving style "{gs_dataset.default_style.name}" for cleanup') style = gs_catalog.get_style(name=gs_dataset.default_style.name, workspace=None, recursive=True) - if style: - gs_catalog.delete(style, purge=True, recurse=False) - logger.debug(f"clean_styles: Style removed: {gs_dataset.default_style.name}") - else: - logger.debug(f"clean_styles: Style does not exist: {gs_dataset.default_style.name}") + if style: + gs_catalog.delete(style, purge=True, recurse=False) + logger.debug(f"clean_styles: Style removed: {gs_dataset.default_style.name}") + else: + logger.debug(f"clean_styles: Style does not exist: {gs_dataset.default_style.name}") except Exception as e: logger.warning(f"Could not clean style for layer {layer.name}", exc_info=e) logger.debug(f"Could not clean style for layer {layer.name} - STACK INFO", stack_info=True) @@ -1213,7 +1218,7 @@ def set_styles(layer, gs_catalog: Catalog): layer.default_style, ] ): - if style: + if style and layer.subtype != "tabular": style_name = os.path.basename(urlparse(style.sld_url).path).split(".")[0] legend_url = get_legend_url(layer, style_name) if dataset_legends.filter(resource=layer.resourcebase_ptr, name="Legend", url=legend_url).count() < 2: @@ -1566,7 +1571,7 @@ def fetch_gs_resource(instance, values, tries): else: values = {} - _subtype = gs_resource.store.resource_type + _subtype = "tabular" if instance.subtype == "tabular" else gs_resource.store.resource_type if ( getattr(gs_resource, "metadata", None) and gs_resource.metadata.get("time", False) @@ -1774,7 +1779,7 @@ def style_update(request, url, workspace=None): # Invalidate GeoWebCache so it doesn't retain old style in tiles try: - if dataset_name: + if dataset_name and layer.subtype != "tabular": _stylefilterparams_geowebcache_dataset(dataset_name) _invalidate_geowebcache_dataset(dataset_name) except Exception: @@ -2181,12 +2186,13 @@ def sync_instance_with_geoserver(instance_id, *args, **kwargs): except Exception as e: logger.warning(e) - # Invalidate GeoWebCache for the updated resource - try: - _stylefilterparams_geowebcache_dataset(instance.alternate) - _invalidate_geowebcache_dataset(instance.alternate) - except Exception as e: - logger.warning(e) + if instance.subtype != "tabular": + # Invalidate GeoWebCache for the updated resource + try: + _stylefilterparams_geowebcache_dataset(instance.alternate) + _invalidate_geowebcache_dataset(instance.alternate) + except Exception as e: + logger.warning(e) # Refreshing dataset links logger.debug(f"... Creating Default Resource Links for Dataset {instance.title}") diff --git a/geonode/geoserver/management/commands/set_default_gridsets.py b/geonode/geoserver/management/commands/set_default_gridsets.py index 0826b744e57..abf26e47de0 100644 --- a/geonode/geoserver/management/commands/set_default_gridsets.py +++ b/geonode/geoserver/management/commands/set_default_gridsets.py @@ -29,46 +29,52 @@ class Command(BaseCommand): - help = 'Assign all the default values to GeoServer Gridsets' + help = "Assign all the default values to GeoServer Gridsets" def add_arguments(self, parser): pass def handle(self, **options): try: - url = settings.OGC_SERVER['default']['LOCATION'] - user = settings.OGC_SERVER['default']['USER'] - passwd = settings.OGC_SERVER['default']['PASSWORD'] + url = settings.OGC_SERVER["default"]["LOCATION"] + user = settings.OGC_SERVER["default"]["USER"] + passwd = settings.OGC_SERVER["default"]["PASSWORD"] """ curl -v -u admin:geoserver -XGET \ "http://:/geoserver/gwc/rest/layers/geonode:tasmania_roads.xml" """ - layers = Dataset.objects.all() + layers = Dataset.objects.filter(subtype__not="tabular") print(f"Total layers to be updated: {layers.count()}") for layer in layers: print(f"Processing layer: {layer.typename}") - r = requests.get(f'{url}gwc/rest/layers/{layer.typename}.xml', - auth=HTTPBasicAuth(user, passwd)) + r = requests.get(f"{url}gwc/rest/layers/{layer.typename}.xml", auth=HTTPBasicAuth(user, passwd)) - if (r.status_code < 200 or r.status_code > 201): + if r.status_code < 200 or r.status_code > 201: print(f"Dataset does not exists on geoserver: {layer.name}") continue try: xml_content = r.content tree = dlxml.fromstring(xml_content) - gwc_id = tree.find('id') + gwc_id = tree.find("id") tree.remove(gwc_id) - gwc_gridSubsets = tree.find('gridSubsets') + gwc_gridSubsets = tree.find("gridSubsets") if len(gwc_gridSubsets) == 6: continue tree.remove(gwc_gridSubsets) - gwc_gridSubsets = etree.Element('gridSubsets') - for gridSubset in ('EPSG:3857', 'EPSG:3857x2', 'EPSG:4326', 'EPSG:4326x2', 'EPSG:900913', 'EPSG:900913x2'): - gwc_gridSubset = etree.Element('gridSubset') - gwc_gridSetName = etree.Element('gridSetName') + gwc_gridSubsets = etree.Element("gridSubsets") + for gridSubset in ( + "EPSG:3857", + "EPSG:3857x2", + "EPSG:4326", + "EPSG:4326x2", + "EPSG:900913", + "EPSG:900913x2", + ): + gwc_gridSubset = etree.Element("gridSubset") + gwc_gridSetName = etree.Element("gridSetName") gwc_gridSetName.text = gridSubset gwc_gridSubset.append(gwc_gridSetName) gwc_gridSubsets.append(gwc_gridSubset) @@ -80,13 +86,15 @@ def handle(self, **options): -H "Content-type: text/xml" -d @poi.xml \ "http://localhost:8080/geoserver/gwc/rest/layers/tiger:poi.xml" """ - headers = {'Content-type': 'text/xml'} + headers = {"Content-type": "text/xml"} payload = ET.tostring(tree) - r = requests.post(f'{url}gwc/rest/layers/{layer.typename}.xml', - headers=headers, - data=payload, - auth=HTTPBasicAuth(user, passwd)) - if (r.status_code < 200 or r.status_code > 201): + r = requests.post( + f"{url}gwc/rest/layers/{layer.typename}.xml", + headers=headers, + data=payload, + auth=HTTPBasicAuth(user, passwd), + ) + if r.status_code < 200 or r.status_code > 201: print(f"Error during update of layer in geoserver: {layer.name} {r.content}") continue except Exception as e: diff --git a/geonode/geoserver/manager.py b/geonode/geoserver/manager.py index a88b641b71f..0cc7c83c607 100644 --- a/geonode/geoserver/manager.py +++ b/geonode/geoserver/manager.py @@ -532,7 +532,7 @@ def set_permissions( create_geofence_rules(_resource, DOWNLOAD_PERMISSIONS, None, None, batch) exist_geolimits = exist_geolimits or has_geolimits(_resource, None, None) - if exist_geolimits is not None: + if exist_geolimits is not None and _resource.subtype != "tabular": filters, formats = _get_gwc_filters_and_formats(exist_geolimits) try: _dataset_workspace = get_dataset_workspace(_resource) diff --git a/geonode/layers/download_handler.py b/geonode/layers/download_handler.py index 7f154a6f30d..dcdfecba1ec 100644 --- a/geonode/layers/download_handler.py +++ b/geonode/layers/download_handler.py @@ -75,7 +75,7 @@ def download_url(self): resource = self.get_resource() if not resource: return None - if resource.subtype not in ["vector", "raster", "vector_time"]: + if resource.subtype not in ["vector", "raster", "vector_time", "tabular"]: logger.info("Download URL is available only for datasets that have been harvested and copied locally") return None @@ -118,6 +118,8 @@ def process_dowload(self, resource=None): return JsonResponse({"error": "The format provided is not valid for the selected resource"}, status=500) _format = "application/zip" if resource.is_vector() else "image/tiff" + if resource.subtype == "tabular": + _format = "text/csv" # getting default payload tpl = get_template("geoserver/dataset_download.xml") ctx = {"alternate": resource.alternate, "download_format": download_format or _format} diff --git a/geonode/layers/models.py b/geonode/layers/models.py index 016597dcb44..a15eec68c8c 100644 --- a/geonode/layers/models.py +++ b/geonode/layers/models.py @@ -328,7 +328,7 @@ def get_linked_resources(self, as_target: bool = False): @property def download_url(self): - if self.subtype not in ["vector", "raster", "vector_time"]: + if self.subtype not in ["vector", "raster", "vector_time", "tabular"]: logger.info("Download URL is available only for datasets that have been harvested and copied locally") return None return build_absolute_uri(reverse("dataset_download", args=(self.alternate,))) @@ -400,10 +400,9 @@ class Attribute(models.Model): null=True, unique=False, ) - description = models.CharField( + description = models.TextField( _("attribute description"), help_text=_("description of attribute to be used in metadata"), - max_length=255, blank=True, null=True, ) diff --git a/geonode/maps/api/views.py b/geonode/maps/api/views.py index 6ad3febe547..d28276e881a 100644 --- a/geonode/maps/api/views.py +++ b/geonode/maps/api/views.py @@ -117,10 +117,13 @@ def datasets(self, request, pk=None, *args, **kwargs): def perform_create(self, serializer): # Thumbnail will be handled later post_creation_data = {"thumbnail": serializer.validated_data.pop("thumbnail_url", "")} + map_layers = serializer.validated_data.get("maplayers", []) + tabular_collection = all(("tabular" in layer.dataset.subtype) for layer in map_layers) instance = serializer.save( owner=self.request.user, resource_type="map", + subtype="tabular-collection" if tabular_collection else None, uuid=str(uuid4()), ) @@ -149,7 +152,12 @@ def perform_update(self, serializer): "dataset_names_before_changes": [lyr.alternate for lyr in instance.datasets], } - instance = serializer.save() + map_layers = serializer.validated_data.get("maplayers", []) + tabular_collection = all(("tabular" in layer.dataset.subtype) for layer in map_layers) + + instance = serializer.save( + subtype="tabular-collection" if tabular_collection else None, + ) # thumbnail, events and resouce routines self._post_change_routines( diff --git a/geonode/utils.py b/geonode/utils.py index c93b61d7cf7..1b7f30216f7 100755 --- a/geonode/utils.py +++ b/geonode/utils.py @@ -1486,7 +1486,11 @@ def set_resource_default_links(instance, layer, prune=False, **kwargs): # Set download links for WMS, WCS or WFS and KML logger.debug(" -- Resource Links[Set download links for WMS, WCS or WFS and KML]...") instance_ows_url = f"{instance.ows_url}?" if instance.ows_url else f"{ogc_server_settings.public_url}ows?" - links = wms_links(instance_ows_url, instance.alternate, bbox, srid, height, width) + links = ( + wms_links(instance_ows_url, instance.alternate, bbox, srid, height, width) + if instance.subtype != "tabular" + else [] + ) for ext, name, mime, wms_url in links: try: @@ -1506,7 +1510,7 @@ def set_resource_default_links(instance, layer, prune=False, **kwargs): resource=instance.resourcebase_ptr, name=gettext_lazy(name), link_type="image" ).update(**_d) - if instance.subtype == "vector": + if instance.subtype == "vector" or instance.subtype == "tabular": links = wfs_links( instance_ows_url, instance.alternate, @@ -1592,7 +1596,7 @@ def set_resource_default_links(instance, layer, prune=False, **kwargs): instance.default_style, ] ): - if style: + if style and instance.subtype != "tabular": style_name = os.path.basename(urlparse(style.sld_url).path).split(".")[0] legend_url = get_legend_url(instance, style_name) if Link.objects.filter(resource=instance.resourcebase_ptr, url=legend_url).count() < 2: @@ -1650,7 +1654,10 @@ def set_resource_default_links(instance, layer, prune=False, **kwargs): ogc_wms_url = instance.ows_url or urljoin(ogc_server_settings.public_url, "ows") ogc_wms_name = f"OGC WMS: {instance.workspace} Service" if ( - Link.objects.filter(resource=instance.resourcebase_ptr, name=ogc_wms_name, url=ogc_wms_url).count() + instance.subtype != "tabular" + and Link.objects.filter( + resource=instance.resourcebase_ptr, name=ogc_wms_name, url=ogc_wms_url + ).count() < 2 ): Link.objects.get_or_create( @@ -1665,7 +1672,7 @@ def set_resource_default_links(instance, layer, prune=False, **kwargs): ), ) - if instance.subtype == "vector": + if instance.subtype == "vector" or instance.subtype == "tabular": ogc_wfs_url = instance.ows_url or urljoin(ogc_server_settings.public_url, "ows") ogc_wfs_name = f"OGC WFS: {instance.workspace} Service" if ( From ba1696f336cfba69c4ac75c1977a1babee7590cd Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Fri, 23 Aug 2024 17:34:08 +0200 Subject: [PATCH 249/253] Handle None case of MapLayer --- geonode/maps/api/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/maps/api/views.py b/geonode/maps/api/views.py index d28276e881a..d110d9195a0 100644 --- a/geonode/maps/api/views.py +++ b/geonode/maps/api/views.py @@ -118,7 +118,7 @@ def perform_create(self, serializer): # Thumbnail will be handled later post_creation_data = {"thumbnail": serializer.validated_data.pop("thumbnail_url", "")} map_layers = serializer.validated_data.get("maplayers", []) - tabular_collection = all(("tabular" in layer.dataset.subtype) for layer in map_layers) + tabular_collection = all(layer.dataset and ("tabular" in layer.dataset.subtype) for layer in map_layers) instance = serializer.save( owner=self.request.user, From 4c9c33325e8da99b1a5dc03931b3d2fb2c12d880 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 26 Aug 2024 09:13:16 +0200 Subject: [PATCH 250/253] Handler Non case of MapLayer --- geonode/maps/api/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/maps/api/views.py b/geonode/maps/api/views.py index d28276e881a..d110d9195a0 100644 --- a/geonode/maps/api/views.py +++ b/geonode/maps/api/views.py @@ -118,7 +118,7 @@ def perform_create(self, serializer): # Thumbnail will be handled later post_creation_data = {"thumbnail": serializer.validated_data.pop("thumbnail_url", "")} map_layers = serializer.validated_data.get("maplayers", []) - tabular_collection = all(("tabular" in layer.dataset.subtype) for layer in map_layers) + tabular_collection = all(layer.dataset and ("tabular" in layer.dataset.subtype) for layer in map_layers) instance = serializer.save( owner=self.request.user, From 520099d8271f53d56ea51005c0566bf3264bba7b Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 26 Aug 2024 09:20:58 +0200 Subject: [PATCH 251/253] Do not change subtype of empty maps --- geonode/maps/api/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/geonode/maps/api/views.py b/geonode/maps/api/views.py index d110d9195a0..64385b314cc 100644 --- a/geonode/maps/api/views.py +++ b/geonode/maps/api/views.py @@ -119,11 +119,12 @@ def perform_create(self, serializer): post_creation_data = {"thumbnail": serializer.validated_data.pop("thumbnail_url", "")} map_layers = serializer.validated_data.get("maplayers", []) tabular_collection = all(layer.dataset and ("tabular" in layer.dataset.subtype) for layer in map_layers) + subtype = "tabular-collection" if len(map_layers) > 0 and tabular_collection else None instance = serializer.save( owner=self.request.user, resource_type="map", - subtype="tabular-collection" if tabular_collection else None, + subtype=subtype, uuid=str(uuid4()), ) From 0398af79fc1d57a5bc85ed20272f51831cb34e16 Mon Sep 17 00:00:00 2001 From: Henning Bredel Date: Mon, 26 Aug 2024 09:17:50 +0200 Subject: [PATCH 252/253] Do not change subtype of empty maps --- geonode/maps/api/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/geonode/maps/api/views.py b/geonode/maps/api/views.py index d110d9195a0..64385b314cc 100644 --- a/geonode/maps/api/views.py +++ b/geonode/maps/api/views.py @@ -119,11 +119,12 @@ def perform_create(self, serializer): post_creation_data = {"thumbnail": serializer.validated_data.pop("thumbnail_url", "")} map_layers = serializer.validated_data.get("maplayers", []) tabular_collection = all(layer.dataset and ("tabular" in layer.dataset.subtype) for layer in map_layers) + subtype = "tabular-collection" if len(map_layers) > 0 and tabular_collection else None instance = serializer.save( owner=self.request.user, resource_type="map", - subtype="tabular-collection" if tabular_collection else None, + subtype=subtype, uuid=str(uuid4()), ) From 661f6d3bda89064e64bcf58f3dd31848ef571fb7 Mon Sep 17 00:00:00 2001 From: Hlib Kilichenko Date: Wed, 6 Nov 2024 15:36:59 +0100 Subject: [PATCH 253/253] fix api permissions --- geonode/documents/api/views.py | 2 +- geonode/documents/views.py | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/geonode/documents/api/views.py b/geonode/documents/api/views.py index d8fe1ca2395..26f96c45674 100644 --- a/geonode/documents/api/views.py +++ b/geonode/documents/api/views.py @@ -131,7 +131,7 @@ def perform_create(self, serializer): resource.set_missing_info() resourcebase_post_save(resource.get_real_instance()) - resource_manager.set_permissions(None, instance=resource, permissions=None, created=True) + resource.set_default_permissions(owner=self.request.user) resource.handle_moderated_uploads() resource_manager.set_thumbnail(resource.uuid, instance=resource, overwrite=False) return resource diff --git a/geonode/documents/views.py b/geonode/documents/views.py index 545fd715647..8ec7bf80e5d 100644 --- a/geonode/documents/views.py +++ b/geonode/documents/views.py @@ -189,9 +189,6 @@ def form_valid(self, form): ) self.object.handle_moderated_uploads() - resource_manager.set_permissions( - None, instance=self.object, permissions=form.cleaned_data["permissions"], created=True - ) abstract = None date = None