From 8d2c7e4f07685b4da65a7d4f1a51421a5305ad6b Mon Sep 17 00:00:00 2001 From: Mattia Date: Mon, 26 May 2025 16:24:09 +0200 Subject: [PATCH 01/26] Upgrade to django5 --- requirements.txt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/requirements.txt b/requirements.txt index 97101d973f8..b45d2bfc43a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ Pillow==10.4.0 lxml==5.2.1 psycopg2==2.9.9 -Django==4.2.21 +Django==5.2.1 # Other beautifulsoup4==4.12.3 @@ -60,7 +60,9 @@ numpy==1.26.* dj-database-url==2.1.0 dj-pagination==2.5.0 django-select2==8.1.2 -django-floppyforms<1.10.0 +#django-floppyforms<1.10.0 +git+https://github.com/jazzband/django-floppyforms@master#egg=django-floppyforms + django-forms-bootstrap<=3.1.0 django-autocomplete-light==3.11.0 django-invitations<2.1.1 @@ -72,13 +74,16 @@ djangorestframework-gis==1.0 djangorestframework-guardian==0.3.0 drf-extensions==0.7.1 drf-spectacular==0.27.2 -dynamic-rest==2.3.0 +#dynamic-rest==2.3.0 +git+https://github.com/GeoNode/dynamic-rest@master#egg=dynamic-rest + -geonode-pinax-notifications==6.0.0.2 +#geonode-pinax-notifications==6.0.0.2 +git+https://github.com/GeoNode/pinax-notifications@master#egg=geonode-pinax-notifications # 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@django_upgrade#egg=django_geonode_mapstore_client django-avatar==8.0.0 geonode-oauth-toolkit==2.2.2.2 geonode-announcements==2.0.2.2 @@ -90,7 +95,7 @@ gisdata==0.5.4 # importer dependencies setuptools>=59 -gdal<=3.4.3 +gdal<=3.6.4 pdok-geopackage-validator==0.8.5 geonode-django-dynamic-model==0.4.0 @@ -103,6 +108,7 @@ django-storages==1.14.3 dropbox==11.36.2 google-cloud-storage==2.16.0 boto3==1.34.103 +botocore==1.34.162 # Django Caches whitenoise==6.6.0 From 605922fc7f851d79bb6b05c2c4f0eab35722895c Mon Sep 17 00:00:00 2001 From: Mattia Date: Mon, 26 May 2025 16:30:40 +0200 Subject: [PATCH 02/26] Upgrade to django5 --- geonode/layers/admin.py | 2 +- geonode/resource/processing/admin.py | 2 +- geonode/settings.py | 2 +- geonode/templates/metadata_base.html | 242 ------ geonode/templates/metadata_detail.html | 955 ----------------------- geonode/templates/metadata_form_js.html | 963 ------------------------ requirements.txt | 3 +- setup.cfg | 2 +- 8 files changed, 5 insertions(+), 2166 deletions(-) delete mode 100644 geonode/templates/metadata_base.html delete mode 100644 geonode/templates/metadata_detail.html delete mode 100644 geonode/templates/metadata_form_js.html diff --git a/geonode/layers/admin.py b/geonode/layers/admin.py index 5afa8e52042..ee17db8b9c9 100644 --- a/geonode/layers/admin.py +++ b/geonode/layers/admin.py @@ -66,7 +66,7 @@ class DatasetAdmin(TabbedTranslationAdmin): "dirty_state", ) search_fields = ("alternate", "title", "abstract", "purpose", "is_approved", "is_published", "state") - filter_horizontal = ("contacts",) + #filter_horizontal = ("contacts",) date_hierarchy = "date" readonly_fields = ("uuid", "alternate", "workspace", "geographic_bounding_box") inlines = [AttributeInline] diff --git a/geonode/resource/processing/admin.py b/geonode/resource/processing/admin.py index 1f13d86269e..3cd3cffb504 100644 --- a/geonode/resource/processing/admin.py +++ b/geonode/resource/processing/admin.py @@ -32,7 +32,7 @@ class ProcessingWorkflowAdmin(admin.ModelAdmin): "id", "name", ) - filter_horizontal = ("processing_tasks",) + #filter_horizontal = ("processing_tasks",) inlines = [ProcessingWorkflowTasksInline] diff --git a/geonode/settings.py b/geonode/settings.py index 7234d8afd7f..f32433d8383 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -470,7 +470,7 @@ "django_filters", "mptt", "storages", - "floppyforms", + #"floppyforms", "tinymce", "widget_tweaks", "django_celery_results", diff --git a/geonode/templates/metadata_base.html b/geonode/templates/metadata_base.html deleted file mode 100644 index bdcbfeaf009..00000000000 --- a/geonode/templates/metadata_base.html +++ /dev/null @@ -1,242 +0,0 @@ -{% extends "geonode_base.html" %} -{% load i18n %} -{% load bootstrap_tags %} -{% load base_tags %} -{% load guardian_tags %} -{% load floppyforms %} -{% load static %} - -{% block head %} - - - - - -{{ block.super }} -{% endblock head %} - -{% block title %} {{ block.super }} {% endblock %} - -{% block body_class %}data{% endblock body_class %} - -{% block body_outer %} - - - - - - - - - - {% block body %}{% endblock body %} - {% block sidebar %}{% endblock sidebar %} -{% endblock body_outer %} - -{% block extra_script %} -{{ block.super }} - {% include 'metadata_form_js.html' %} - - - - - - - - -{% endblock extra_script %} diff --git a/geonode/templates/metadata_detail.html b/geonode/templates/metadata_detail.html deleted file mode 100644 index f09b341eecd..00000000000 --- a/geonode/templates/metadata_detail.html +++ /dev/null @@ -1,955 +0,0 @@ -{% extends "geonode_base.html" %} -{% load i18n %} -{% load bootstrap_tags %} -{% load thesaurus %} -{% load client_lib_tags %} -{% load sanitize_html %} - -{% block title %}{{ resource.title }} — {{ block.super }}{% endblock %} - -{% block body_class %}data{% endblock %} - -{% block body_outer %} - - - - - - - - -
- - {% trans "Identification" %} -

-
- {% block resource_title %} - {% if resource.title %} -
{% trans "Title" %}
-
{{ resource.title|truncatechars:80 }}
- {% endif %} - {% endblock resource_title %} - - {% block abstract %} - {% if resource.abstract %} -
{% trans "Abstract" %}
-
{{ resource.abstract|sanitize_html|safe }}
- {% endif %} - {% endblock abstract %} - -
- -
- - {% block license %} - {% if LICENSES_ENABLED and LICENSES_DETAIL == 'above' and resource.license %} -
{% trans "License" %}
-
{{ resource.license.name_long }}
- {% endif %} -
- {% for bullet in resource.license.description_bullets %} - {{ bullet }}

- {% endfor %} - {% if resource.license.url %} - + {% trans "For more info see" %} {{ resource.license.url }}. - {% endif %} -
- - {% endblock license %} - - {% block date %} - {% if resource.date %} -
{% trans resource.date_type|title %} {% trans "Date" %}
-
{{ resource.date }}
- {% endif %} - {% endblock date %} - - {% block display_type %} - {% if resource.display_type %} -
{% trans "Type" %}
-
{{ resource.display_type }}
- {% endif %} - {% endblock display_type %} - - {% block keyword_list %} - {% if resource.keywords.count > 0 or resource.tkeywords.count > 0 %} -
{% trans "Keywords" %}
-
-
    - {% for keyword in resource.keywords.all %} -
  • - - {{ keyword.name|sanitize_html|safe }} - -
  • - {% endfor %} - {% for tid in resource.tkeywords.all|get_unique_thesaurus_set %} -
  • {{ tid|get_thesaurus_translation_by_id }} - {% for tkeywords in resource.tkeywords.all %} -
      - {% if tid == tkeywords.thesaurus.id %} -
    • {{tkeywords|get_thesaurus_localized_label}}
    • - {% endif %} -
    - {% endfor %} -
  • - {% endfor %} -
-
- {% endif %} - {% endblock keyword_list %} - - {% block category %} - {% if resource.category %} -
{% trans "Category" %}
-
{{ resource.category }} {% if resource.category.description %}{% endif %}
- {% if resource.category.description %} -
- {{ resource.category.description }} -
- {% endif %} - {% endif %} - {% endblock category %} - - {% block regions %} - {% if resource.regions.all %} -
{% trans "Regions" %}
-
{{ resource.regions.all|join:", " }}
- {% endif %} - {% endblock regions %} - - {% block is_approved %} -
{% trans "Approved" %}
-
{% if resource.is_approved %} {% trans "Yes" %} {% else %} {% trans "No" %} {% endif %}
- {% endblock is_approved %} - - {% block is_published %} -
{% trans "Published" %}
-
{% if resource.is_published %} {% trans "Yes" %} {% else %} {% trans "No" %} {% endif %}
- {% endblock is_published %} - - {% block featured %} -
{% trans "Featured" %}
-
{% if resource.featured %} {% trans "Yes" %} {% else %} {% trans "No" %} {% endif %}
- {% endblock featured %} - - {% block group %} - {% if resource.group %} -
{% trans "Group" %}
-
{{ group }}
- {% endif %} - {% endblock group %} - - {% block doi %} -
{% trans "DOI" %}
-
{{ resource.doi }}
- {% endblock doi %} - - {% block attribution %} -
{% trans "Attribution" %}
-
{{ resource.attribution }}
- {% endblock attribution %} - - {% block extra_tag %}{% endblock extra_tag %} -
- - - {% trans "Responsible" %} -

- -
- - {% if resource.owner %} - {% with resource.owner as poc %} - - {% block name_long %} -
{% trans "Name" %}
-
{{ poc.name_long }}
- {% endblock name_long %} - - {% block email %} -
{% trans "email" %}
-
{{ poc.email }}
- {% endblock email %} - - {% block position %} -
{% trans "Position" %}
-
{{ poc.position }}
- {% endblock position %} - - {% block organization %} -
{% trans "Organization" %}
-
{{ poc.organization }}
- {% endblock organization %} - - {% block location %} -
{% trans "Location" %}
-
{{ poc.location }}
- {% endblock location %} - - {% block voice %} -
{% trans "Voice" %}
-
{{ poc.voice }}
- {% endblock voice %} - - {% block fax %} -
{% trans "Fax" %}
-
{{ poc.fax }}
- {% endblock fax %} - - {% block poc_keyword_list %} - {% if poc.keyword_list %} -
{% trans "Keywords" %}
-
{% for keyword in poc.keyword_list %} - {{ keyword }} - {% endfor %}
- {% endif %} - {% endblock poc_keyword_list %} - - {% endwith %} - {% endif %} - -
- - {% trans "Information" %} -

- -
- -
{% trans "Identification Image" %}
-
- -
- -
- -
- - {% block scale %} -
{% trans "Spatial Extent" %}
-
{% if resource.scale %} {{ resource.scale }} {% else %} --- {% endif %}
- {% endblock scale %} - - {% block srid %} -
{% trans "Projection System" %}
-
{{ resource.srid }}
- {% endblock srid %} - -
{% trans "Extension x0" %}
- - {% block bbox_x0 %} -
{{resource.bbox_x0}}
- {% endblock bbox_x0 %} - -
{% trans "Extension x1" %}
- {% block bbox_x1 %} -
{{resource.bbox_x1}}
- {% endblock bbox_x1 %} - -
{% trans "Extension y0" %}
- {% block bbox_y0 %} -
{{resource.bbox_y0}}
- {% endblock bbox_y0 %} - -
{% trans "Extension y1" %}
- {% block bbox_y1 %} -
{{resource.bbox_y1}}
- {% endblock bbox_y1 %} -
- - {% trans "Features" %} -

- -
- - {% block license2 %} - {% if LICENSES_ENABLED and LICENSES_DETAIL == 'below' and resource.license %} -
{% trans "License" %}
-
{{ resource.license.name_long }}
-
- {% for bullet in resource.license.description_bullets %} - {{ bullet }}

- {% endfor %} - {% if resource.license.url %} - + {% trans "For more info see" %} {{ resource.license.url }}. - {% endif %} -
- {% endif %} - {% endblock license2 %} - {% block maintenance_frequency %} - {% if resource.maintenance_frequency %} -
{% trans "Maintenance Frequency" %}
-
{{ resource.maintenance_frequency_title }}
- {% endif %} - {% endblock maintenance_frequency %} - - {% block restriction_code_type %} - {% if resource.restriction_code_type or resource.constraints_other %} -
{% trans "Restrictions" %}
-
{% if resource.constraints_other %} - {{ resource.constraints_other|sanitize_html|safe }} - {% else %} - {{ resource.restriction_code_type }} - {% endif %}
- {% endif %} - {% endblock restriction_code_type %} - - {% block edition %} - {% if resource.edition %} -
{% trans "Edition" %}
-
{{ resource.edition}}
- {% endif %} - {% endblock edition %} - - {% block purpose %} - {% if resource.purpose %} -
{% trans "Purpose" %}
-
{{ resource.purpose|sanitize_html|safe }}
- {% endif %} - {% endblock purpose %} - - {% block language %} - {% if resource.language %} -
{% trans "Language" %}
-
{{ resource.language_title }}
- {% endif %} - {% endblock language %} - - {% block temporal_extent_start %} - {% if resource.temporal_extent_start and resource.temporal_extent_end %} -
{% trans "Temporal Extent" %}
-
{{ resource.temporal_extent_start }} - {{ resource.temporal_extent_end }}
- {% endif %} - {% endblock temporal_extent_start %} - - {% block data_quality_statement %} - {% if resource.data_quality_statement %} -
{% trans "Data Quality" %}
-
{{ 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|sanitize_html|safe }}
- {% endif %} - {% endblock supplemental_information %} - - {% block extra_metadata %} - {% endblock extra_metadata %} - - {% block spatial_representation_type %} - {% if resource.spatial_representation_type %} -
{% trans "Spatial Representation Type" %}
-
{{ resource.spatial_representation_type }}
- {% endif %} - {% endblock spatial_representation_type %} - -
- - {% if resource.poc %} - {% trans "Contact Points" %} -

- {% for poc in resource.poc%} -
- {% block poc_name_long %} -
{% trans "Name" %}
-
{{ poc.name_long }}
- {% endblock poc_name_long %} - - {% block poc_email %} -
{% trans "email" %}
-
{{ poc.email }}
- {% endblock poc_email %} - - {% block poc_position %} -
{% trans "Position" %}
-
{{ poc.position }}
- {% endblock poc_position %} - - {% block poc_organization %} -
{% trans "Organization" %}
-
{{ poc.organization }}
- {% endblock poc_organization %} - - {% block poc_location %} -
{% trans "Location" %}
-
{{ poc.location }}
- {% endblock poc_location %} - - {% block poc_voice %} -
{% trans "Voice" %}
-
{{ poc.voice }}
- {% endblock poc_voice %} - - {% block poc_fax %} -
{% trans "Fax" %}
-
{{ poc.fax }}
- {% endblock poc_fax %} - - {% block poc_keyword %} - {% if poc.keyword_list %} -
{% trans "Keywords" %}
-
{% for keyword in poc.keyword_list %} - {{ keyword }} - {% endfor %}
- {% endif %} - {% endblock poc_keyword %} -
-
- {% endfor %} - {% endif %} - - {% trans "References" %} -

- -
- - {% block get_absolute_url %} -
{% trans "Link Online" %}
-
{{ resource.get_absolute_url }}
- {% endblock get_absolute_url %} - - {% block metaget_absolute_url %} -
{% trans "Metadata Page" %}
-
{{ resource.get_absolute_url }}/metadata_detail
- {% endblock metaget_absolute_url %} - - {% block doc_file %} - {% if resource.doc_file %} -
{% trans "Online Link" %}
-
{{ resource.get_absolute_url }}/download
- {% endif %} - {% endblock doc_file %} -
- - {% if "download_resourcebase" in perms_list %} - {% for link in resource.link_set.download %} -
{{link.name}}
-
{{resource.title}}.{{link.extension}}
- {% endfor %} -
- {% endif %} - - {% for link in resource.link_set.ows %} -
{{link.name}}
-
Geoservice {{link.link_type}}
- {% endfor %} - -
- - {% comment %} Contact Role: Metadata Author {% endcomment %} - {% if resource.metadata_author %} - - {% trans "Metadata Author" %} -

- - {% for metadata_author in resource.metadata_author %} -
- {% block metadata_author_doc_file %} -
{% trans "Name" %}
-
{{ metadata_author.name_long }}
- {% endblock metadata_author_doc_file %} - - {% block metadata_author_email %} -
{% trans "email" %}
-
{{ metadata_author.email }}
- {% endblock metadata_author_email %} - - {% block metadata_author_position %} -
{% trans "Position" %}
-
{{ metadata_author.position }}
- {% endblock metadata_author_position %} - - {% block metadata_author_organization %} -
{% trans "Organization" %}
-
{{ metadata_author.organization }}
- {% endblock metadata_author_organization %} - - {% block metadata_author_location %} -
{% trans "Location" %}
-
{{ metadata_author.location }}
- {% endblock metadata_author_location %} - - {% block metadata_author_voice %} -
{% trans "Voice" %}
-
{{ metadata_author.voice }}
- {% endblock metadata_author_voice %} - - {% block metadata_author_fax %} -
{% trans "Fax" %}
-
{{ metadata_author.fax }}
- {% endblock metadata_author_fax %} - - {% block metadata_author_keyword_list %} - {% if metadata_author.keyword_list %} -
{% trans "Keywords" %}
-
{% for keyword in metadata_author.keyword_list %} - {{ keyword }} - {% endfor %}
- {% endif %} - {% endblock metadata_author_keyword_list %} -
- {% endfor%} - {% endif %} - - - {% comment %} Contact Role: Processor {% endcomment %} - {% if resource.processor %} - - {% trans "Processor" %} -

- - {% for processor in resource.processor %} -
- {% block processor_doc_file %} -
{% trans "Name" %}
-
{{ processor.name_long }}
- {% endblock processor_doc_file %} - - {% block processor_email %} -
{% trans "email" %}
-
{{ processor.email }}
- {% endblock processor_email %} - - {% block processor_position %} -
{% trans "Position" %}
-
{{ processor.position }}
- {% endblock processor_position %} - - {% block processor_organization %} -
{% trans "Organization" %}
-
{{ processor.organization }}
- {% endblock processor_organization %} - - {% block processor_location %} -
{% trans "Location" %}
-
{{ processor.location }}
- {% endblock processor_location %} - - {% block processor_voice %} -
{% trans "Voice" %}
-
{{ processor.voice }}
- {% endblock processor_voice %} - - {% block processor_fax %} -
{% trans "Fax" %}
-
{{ processor.fax }}
- {% endblock processor_fax %} - - {% block processor_keyword_list %} - {% if processor.keyword_list %} -
{% trans "Keywords" %}
-
{% for keyword in processor.keyword_list %} - {{ keyword }} - {% endfor %}
- {% endif %} - {% endblock processor_keyword_list %} -
- {% endfor%} - {% endif %} - - {% comment %} Contact Role: Publisher {% endcomment %} - {% if resource.publisher %} - - {% trans "Publisher" %} -

- - {% for publisher in resource.publisher %} -
- {% block publisher_doc_file %} -
{% trans "Name" %}
-
{{ publisher.name_long }}
- {% endblock publisher_doc_file %} - - {% block publisher_email %} -
{% trans "email" %}
-
{{ publisher.email }}
- {% endblock publisher_email %} - - {% block publisher_position %} -
{% trans "Position" %}
-
{{ publisher.position }}
- {% endblock publisher_position %} - - {% block publisher_organization %} -
{% trans "Organization" %}
-
{{ publisher.organization }}
- {% endblock publisher_organization %} - - {% block publisher_location %} -
{% trans "Location" %}
-
{{ publisher.location }}
- {% endblock publisher_location %} - - {% block publisher_voice %} -
{% trans "Voice" %}
-
{{ publisher.voice }}
- {% endblock publisher_voice %} - - {% block publisher_fax %} -
{% trans "Fax" %}
-
{{ publisher.fax }}
- {% endblock publisher_fax %} - - {% block publisher_keyword_list %} - {% if publisher.keyword_list %} -
{% trans "Keywords" %}
-
{% for keyword in publisher.keyword_list %} - {{ keyword }} - {% endfor %}
- {% endif %} - {% endblock publisher_keyword_list %} -
- {% endfor%} - {% endif %} - - {% comment %} Contact Role: Custodian {% endcomment %} - {% if resource.custodian %} - - {% trans "Custodian" %} -

- - {% for custodian in resource.custodian %} -
- {% block custodian_doc_file %} -
{% trans "Name" %}
-
{{ custodian.name_long }}
- {% endblock custodian_doc_file %} - - {% block custodian_email %} -
{% trans "email" %}
-
{{ custodian.email }}
- {% endblock custodian_email %} - - {% block custodian_position %} -
{% trans "Position" %}
-
{{ custodian.position }}
- {% endblock custodian_position %} - - {% block custodian_organization %} -
{% trans "Organization" %}
-
{{ custodian.organization }}
- {% endblock custodian_organization %} - - {% block custodian_location %} -
{% trans "Location" %}
-
{{ custodian.location }}
- {% endblock custodian_location %} - - {% block custodian_voice %} -
{% trans "Voice" %}
-
{{ custodian.voice }}
- {% endblock custodian_voice %} - - {% block custodian_fax %} -
{% trans "Fax" %}
-
{{ custodian.fax }}
- {% endblock custodian_fax %} - - {% block custodian_keyword_list %} - {% if custodian.keyword_list %} -
{% trans "Keywords" %}
-
{% for keyword in custodian.keyword_list %} - {{ keyword }} - {% endfor %}
- {% endif %} - {% endblock custodian_keyword_list %} -
- {% endfor%} - {% endif %} - - {% comment %} Contact Role: Distributor {% endcomment %} - {% if resource.distributor %} - - {% trans "Distributor" %} -

- - {% for distributor in resource.distributor %} -
- {% block distributor_doc_file %} -
{% trans "Name" %}
-
{{ distributor.name_long }}
- {% endblock distributor_doc_file %} - - {% block distributor_email %} -
{% trans "email" %}
-
{{ distributor.email }}
- {% endblock distributor_email %} - - {% block distributor_position %} -
{% trans "Position" %}
-
{{ distributor.position }}
- {% endblock distributor_position %} - - {% block distributor_organization %} -
{% trans "Organization" %}
-
{{ distributor.organization }}
- {% endblock distributor_organization %} - - {% block distributor_location %} -
{% trans "Location" %}
-
{{ distributor.location }}
- {% endblock distributor_location %} - - {% block distributor_voice %} -
{% trans "Voice" %}
-
{{ distributor.voice }}
- {% endblock distributor_voice %} - - {% block distributor_fax %} -
{% trans "Fax" %}
-
{{ distributor.fax }}
- {% endblock distributor_fax %} - - {% block distributor_keyword_list %} - {% if distributor.keyword_list %} -
{% trans "Keywords" %}
-
{% for keyword in distributor.keyword_list %} - {{ keyword }} - {% endfor %}
- {% endif %} - {% endblock distributor_keyword_list %} -
- {% endfor%} - {% endif %} - - - {% comment %} Contact Role: User {% endcomment %} - {% if resource.resource_user %} - - {% trans "User" %} -

- - {% for resource_user in resource.resource_user %} -
- {% block resource_user_doc_file %} -
{% trans "Name" %}
-
{{ resource_user.name_long }}
- {% endblock resource_user_doc_file %} - - {% block resource_user_email %} -
{% trans "email" %}
-
{{ resource_user.email }}
- {% endblock resource_user_email %} - - {% block resource_user_position %} -
{% trans "Position" %}
-
{{ resource_user.position }}
- {% endblock resource_user_position %} - - {% block resource_user_organization %} -
{% trans "Organization" %}
-
{{ resource_user.organization }}
- {% endblock resource_user_organization %} - - {% block resource_user_location %} -
{% trans "Location" %}
-
{{ resource_user.location }}
- {% endblock resource_user_location %} - - {% block resource_user_voice %} -
{% trans "Voice" %}
-
{{ resource_user.voice }}
- {% endblock resource_user_voice %} - - {% block resource_user_fax %} -
{% trans "Fax" %}
-
{{ resource_user.fax }}
- {% endblock resource_user_fax %} - - {% block resource_user_keyword_list %} - {% if resource_user.keyword_list %} -
{% trans "Keywords" %}
-
{% for keyword in resource_user.keyword_list %} - {{ keyword }} - {% endfor %}
- {% endif %} - {% endblock resource_user_keyword_list %} -
- {% endfor%} - {% endif %} - - {% comment %} Contact Role: Resource Provider {% endcomment %} - {% if resource.resource_provider %} - - {% trans "Resource Provider" %} -

- - {% for resource_provider in resource.resource_provider %} -
- {% block resource_provider_doc_file %} -
{% trans "Name" %}
-
{{ resource_provider.name_long }}
- {% endblock resource_provider_doc_file %} - - {% block resource_provider_email %} -
{% trans "email" %}
-
{{ resource_provider.email }}
- {% endblock resource_provider_email %} - - {% block resource_provider_position %} -
{% trans "Position" %}
-
{{ resource_provider.position }}
- {% endblock resource_provider_position %} - - {% block resource_provider_organization %} -
{% trans "Organization" %}
-
{{ resource_provider.organization }}
- {% endblock resource_provider_organization %} - - {% block resource_provider_location %} -
{% trans "Location" %}
-
{{ resource_provider.location }}
- {% endblock resource_provider_location %} - - {% block resource_provider_voice %} -
{% trans "Voice" %}
-
{{ resource_provider.voice }}
- {% endblock resource_provider_voice %} - - {% block resource_provider_fax %} -
{% trans "Fax" %}
-
{{ resource_provider.fax }}
- {% endblock resource_provider_fax %} - - {% block resource_provider_keyword_list %} - {% if resource_provider.keyword_list %} -
{% trans "Keywords" %}
-
{% for keyword in resource_provider.keyword_list %} - {{ keyword }} - {% endfor %}
- {% endif %} - {% endblock resource_provider_keyword_list %} -
- {% endfor%} - {% endif %} - - - {% comment %} Contact Role: Originator {% endcomment %} - {% if resource.originator %} - - {% trans "Resource Provider" %} -

- - {% for originator in resource.originator %} -
- {% block originator_doc_file %} -
{% trans "Name" %}
-
{{ originator.name_long }}
- {% endblock originator_doc_file %} - - {% block originator_email %} -
{% trans "email" %}
-
{{ originator.email }}
- {% endblock originator_email %} - - {% block originator_position %} -
{% trans "Position" %}
-
{{ originator.position }}
- {% endblock originator_position %} - - {% block originator_organization %} -
{% trans "Organization" %}
-
{{ originator.organization }}
- {% endblock originator_organization %} - - {% block originator_location %} -
{% trans "Location" %}
-
{{ originator.location }}
- {% endblock originator_location %} - - {% block originator_voice %} -
{% trans "Voice" %}
-
{{ originator.voice }}
- {% endblock originator_voice %} - - {% block originator_fax %} -
{% trans "Fax" %}
-
{{ originator.fax }}
- {% endblock originator_fax %} - - {% block originator_keyword_list %} - {% if originator.keyword_list %} -
{% trans "Keywords" %}
-
{% for keyword in originator.keyword_list %} - {{ keyword }} - {% endfor %}
- {% endif %} - {% endblock originator_keyword_list %} -
- {% endfor%} - {% endif %} - - - {% comment %} Contact Role: Resource Provider {% endcomment %} - {% if resource.principal_investigator %} - - {% trans "Principal Investigator" %} -

- - {% for principal_investigator in resource.principal_investigator %} -
- {% block principal_investigator_doc_file %} -
{% trans "Name" %}
-
{{ principal_investigator.name_long }}
- {% endblock principal_investigator_doc_file %} - - {% block principal_investigator_email %} -
{% trans "email" %}
-
{{ principal_investigator.email }}
- {% endblock principal_investigator_email %} - - {% block principal_investigator_position %} -
{% trans "Position" %}
-
{{ principal_investigator.position }}
- {% endblock principal_investigator_position %} - - {% block principal_investigator_organization %} -
{% trans "Organization" %}
-
{{ principal_investigator.organization }}
- {% endblock principal_investigator_organization %} - - {% block principal_investigator_location %} -
{% trans "Location" %}
-
{{ principal_investigator.location }}
- {% endblock principal_investigator_location %} - - {% block principal_investigator_voice %} -
{% trans "Voice" %}
-
{{ principal_investigator.voice }}
- {% endblock principal_investigator_voice %} - - {% block principal_investigator_fax %} -
{% trans "Fax" %}
-
{{ principal_investigator.fax }}
- {% endblock principal_investigator_fax %} - - {% block principal_investigator_keyword_list %} - {% if principal_investigator.keyword_list %} -
{% trans "Keywords" %}
-
{% for keyword in principal_investigator.keyword_list %} - {{ keyword }} - {% endfor %}
- {% endif %} - {% endblock principal_investigator_keyword_list %} -
- {% endfor%} - {% endif %} - -
-{% endblock %} diff --git a/geonode/templates/metadata_form_js.html b/geonode/templates/metadata_form_js.html deleted file mode 100644 index efab2de91b2..00000000000 --- a/geonode/templates/metadata_form_js.html +++ /dev/null @@ -1,963 +0,0 @@ -{% load i18n %} -{% load static %} - \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 414ccee5de1..33751ccce70 100644 --- a/requirements.txt +++ b/requirements.txt @@ -62,7 +62,6 @@ dj-database-url==2.1.0 dj-pagination==2.5.0 django-select2==8.1.2 #django-floppyforms<1.10.0 -git+https://github.com/jazzband/django-floppyforms@master#egg=django-floppyforms django-forms-bootstrap<=3.1.0 django-autocomplete-light==3.11.0 @@ -85,7 +84,7 @@ git+https://github.com/GeoNode/pinax-notifications@master#egg=geonode-pinax-noti # GeoNode org maintained apps. # django-geonode-mapstore-client==4.0.5 #git+https://github.com/GeoNode/geonode-mapstore-client.git@django_upgrade#egg=django_geonode_mapstore_client -django-avatar==8.0.0 +django-avatar==8.0.1 geonode-oauth-toolkit==2.2.2.2 geonode-announcements==2.0.2.2 django-activity-stream==2.0.0 diff --git a/setup.cfg b/setup.cfg index 8577a074d83..81620d508c6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -87,7 +87,7 @@ install_requires = dj-database-url==2.1.0 dj-pagination==2.5.0 django-select2==8.1.2 - django-floppyforms<1.10.0 + #django-floppyforms<1.10.0 django-forms-bootstrap<=3.1.0 django-autocomplete-light==3.11.0 django-invitations<2.1.1 From 0d115a4f8d9c6009c019d43a63743b4cf3353722 Mon Sep 17 00:00:00 2001 From: Mattia Date: Mon, 26 May 2025 16:38:42 +0200 Subject: [PATCH 03/26] Upgrade to django5 --- geonode/security/middleware.py | 1 + geonode/settings.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/geonode/security/middleware.py b/geonode/security/middleware.py index da7001f8ac0..5d1f2512e8f 100644 --- a/geonode/security/middleware.py +++ b/geonode/security/middleware.py @@ -112,6 +112,7 @@ class SessionControlMiddleware(MiddlewareMixin): """ Middleware that checks if session variables have been correctly set. """ + async_mode = False redirect_to = getattr(settings, "LOGIN_URL", reverse("account_login")) diff --git a/geonode/settings.py b/geonode/settings.py index f32433d8383..b69f68d0c15 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -831,7 +831,7 @@ MESSAGE_STORAGE = "django.contrib.messages.storage.cookie.CookieStorage" # Sessions -SESSION_SERIALIZER = "django.contrib.sessions.serializers.PickleSerializer" +SESSION_SERIALIZER = "django.contrib.sessions.serializers.JSONSerializer" SESSION_ENGINE = os.environ.get("SESSION_ENGINE", "django.contrib.sessions.backends.db") if SESSION_ENGINE in ("django.contrib.sessions.backends.cached_db", "django.contrib.sessions.backends.cache"): SESSION_CACHE_ALIAS = "memcached" # use memcached cache if a cached backend is requested From f1fefe5a7a051ba718974a38e89ec5ead311cb5d Mon Sep 17 00:00:00 2001 From: Mattia Date: Tue, 27 May 2025 11:24:06 +0200 Subject: [PATCH 04/26] Upgrade to django5 --- geonode/layers/admin.py | 2 +- geonode/resource/processing/admin.py | 2 +- geonode/security/middleware.py | 1 + geonode/settings.py | 6 +++--- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/geonode/layers/admin.py b/geonode/layers/admin.py index ee17db8b9c9..7bd63557c89 100644 --- a/geonode/layers/admin.py +++ b/geonode/layers/admin.py @@ -66,7 +66,7 @@ class DatasetAdmin(TabbedTranslationAdmin): "dirty_state", ) search_fields = ("alternate", "title", "abstract", "purpose", "is_approved", "is_published", "state") - #filter_horizontal = ("contacts",) + # filter_horizontal = ("contacts",) date_hierarchy = "date" readonly_fields = ("uuid", "alternate", "workspace", "geographic_bounding_box") inlines = [AttributeInline] diff --git a/geonode/resource/processing/admin.py b/geonode/resource/processing/admin.py index 3cd3cffb504..b2bd0c8ea1f 100644 --- a/geonode/resource/processing/admin.py +++ b/geonode/resource/processing/admin.py @@ -32,7 +32,7 @@ class ProcessingWorkflowAdmin(admin.ModelAdmin): "id", "name", ) - #filter_horizontal = ("processing_tasks",) + # filter_horizontal = ("processing_tasks",) inlines = [ProcessingWorkflowTasksInline] diff --git a/geonode/security/middleware.py b/geonode/security/middleware.py index 5d1f2512e8f..2e1df5a2365 100644 --- a/geonode/security/middleware.py +++ b/geonode/security/middleware.py @@ -112,6 +112,7 @@ class SessionControlMiddleware(MiddlewareMixin): """ Middleware that checks if session variables have been correctly set. """ + async_mode = False redirect_to = getattr(settings, "LOGIN_URL", reverse("account_login")) diff --git a/geonode/settings.py b/geonode/settings.py index b69f68d0c15..92c333fa0a6 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -250,9 +250,9 @@ AUTH_USER_MODEL = os.getenv("AUTH_USER_MODEL", "people.Profile") PASSWORD_HASHERS = [ - "django.contrib.auth.hashers.SHA1PasswordHasher", - "django.contrib.auth.hashers.PBKDF2PasswordHasher", + #"django.contrib.auth.hashers.SHA1PasswordHasher", "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher", + "django.contrib.auth.hashers.PBKDF2PasswordHasher", # 'django.contrib.auth.hashers.Argon2PasswordHasher', # 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', # 'django.contrib.auth.hashers.BCryptPasswordHasher', @@ -470,7 +470,7 @@ "django_filters", "mptt", "storages", - #"floppyforms", + # "floppyforms", "tinymce", "widget_tweaks", "django_celery_results", From ea629c8d8f4e9766a486b6eaf7a0aba154fe581f Mon Sep 17 00:00:00 2001 From: Mattia Date: Tue, 27 May 2025 13:09:56 +0200 Subject: [PATCH 05/26] Upgrade to django5 --- .devcontainer/.env | 86 +++++++++++++++++------------- .devcontainer/devcontainer.json | 49 +++++++++-------- .devcontainer/docker-compose.yml | 91 +++++--------------------------- .env_dev | 8 +-- geonode/base/apps.py | 1 + geonode/base/models.py | 9 ++-- geonode/documents/apps.py | 1 + geonode/geoapps/apps.py | 2 +- geonode/layers/apps.py | 1 + geonode/maps/apps.py | 1 + geonode/settings.py | 2 +- 11 files changed, 103 insertions(+), 148 deletions(-) diff --git a/.devcontainer/.env b/.devcontainer/.env index 98923e8ed11..e12de6a4f30 100644 --- a/.devcontainer/.env +++ b/.devcontainer/.env @@ -1,5 +1,6 @@ COMPOSE_PROJECT_NAME=geonode -DOCKER_HOST_IP= +# See https://github.com/containers/podman/issues/13889 +# DOCKER_BUILDKIT=0 DOCKER_ENV=production # See https://github.com/geosolutions-it/geonode-generic/issues/28 # to see why we force API version to 1.24 @@ -10,35 +11,35 @@ C_FORCE_ROOT=1 FORCE_REINIT=false INVOKE_LOG_STDOUT=true -# LANGUAGE_CODE=pt -# LANGUAGES=(('en','English'),('pt','Portuguese')) +# LANGUAGE_CODE=it-it +# LANGUAGES=(('en-us','English'),('it-it','Italiano')) DJANGO_SETTINGS_MODULE=geonode.settings GEONODE_INSTANCE_NAME=geonode -GEONODE_LB_HOST_IP= -GEONODE_LB_PORT= # ################# # backend # ################# POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres -GEONODE_DATABASE=geonode +GEONODE_DATABASE=gn +GEONODE_DATABASE_USER=geonode GEONODE_DATABASE_PASSWORD=geonode -GEONODE_GEODATABASE=geonode_data -GEONODE_GEODATABASE_PASSWORD=geonode_data +GEONODE_GEODATABASE=gn5_data +GEONODE_GEODATABASE_USER=geonode +GEONODE_GEODATABASE_PASSWORD=geonode GEONODE_DATABASE_SCHEMA=public GEONODE_GEODATABASE_SCHEMA=public -DATABASE_HOST=db +DATABASE_HOST=localhost DATABASE_PORT=5432 -DATABASE_URL=postgis://geonode:geonode@db:5432/geonode -GEODATABASE_URL=postgis://geonode_data:geonode_data@db:5432/geonode_data +DATABASE_URL=postgis://geonode:geonode@localhost:5432/gn5 +GEODATABASE_URL=postgis://geonode:geonode@localhost:5432/gn5_data GEONODE_DB_CONN_MAX_AGE=0 GEONODE_DB_CONN_TOUT=5 DEFAULT_BACKEND_DATASTORE=datastore -BROKER_URL=amqp://guest:guest@rabbitmq:5672/ +BROKER_URL=amqp://admin:admin@localhost:5672// CELERY_BEAT_SCHEDULER=celery.beat:PersistentScheduler -ASYNC_SIGNALS=True +ASYNC_SIGNALS=False SITEURL=http://localhost:8000/ @@ -48,17 +49,16 @@ ALLOWED_HOSTS="['django', '*']" DEFAULT_BACKEND_UPLOADER=geonode.importer TIME_ENABLED=True MOSAIC_ENABLED=False -HAYSTACK_SEARCH=False -HAYSTACK_ENGINE_URL=http://elasticsearch:9200/ -HAYSTACK_ENGINE_INDEX_NAME=haystack -HAYSTACK_SEARCH_RESULTS_PER_PAGE=200 # ################# # nginx # HTTPD Server # ################# -GEONODE_LB_HOST_IP=localhost -GEONODE_LB_PORT=80 +GEONODE_LB_HOST_IP=django +GEONODE_LB_PORT=8000 +GEOSERVER_LB_HOST_IP=geoserver +GEOSERVER_LB_PORT=8080 +NGINX_BASE_URL=http://localhost # IP or domain name and port where the server can be reached on HTTPS (leave HOST empty if you want to use HTTP only) # port where the server can be reached on HTTPS @@ -84,7 +84,7 @@ RESOLVER=127.0.0.11 # ################# GEOSERVER_WEB_UI_LOCATION=http://localhost:8080/geoserver/ GEOSERVER_PUBLIC_LOCATION=http://localhost:8080/geoserver/ -GEOSERVER_LOCATION=http://geoserver:8080/geoserver/ +GEOSERVER_LOCATION=http://localhost:8080/geoserver/ GEOSERVER_ADMIN_USER=admin GEOSERVER_ADMIN_PASSWORD=geoserver @@ -97,7 +97,7 @@ OGC_REQUEST_POOL_CONNECTIONS=10 # Java Options & Memory ENABLE_JSONP=true outFormat=text/javascript -GEOSERVER_JAVA_OPTS="-Djava.awt.headless=true -Xms2G -Xmx4G -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:PerfDataSamplingInterval=500 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:-UseGCOverheadLimit -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 -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=http://localhost:8080/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 @@ -126,12 +126,17 @@ DEFAULT_FROM_EMAIL='GeoNode ' # Session/Access Control LOCKDOWN_GEONODE=False -CORS_ALLOW_ALL_ORIGINS=True X_FRAME_OPTIONS="SAMEORIGIN" SESSION_EXPIRED_CONTROL_ENABLED=True DEFAULT_ANONYMOUS_VIEW_PERMISSION=True DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION=True +CORS_ALLOW_ALL_ORIGINS=True +GEOSERVER_CORS_ENABLED=True +GEOSERVER_CORS_ALLOWED_ORIGINS=* +GEOSERVER_CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE,HEAD,OPTIONS +GEOSERVER_CORS_ALLOWED_HEADERS=* + # Users Registration ACCOUNT_OPEN_SIGNUP=True ACCOUNT_EMAIL_REQUIRED=True @@ -140,6 +145,7 @@ ACCOUNT_CONFIRM_EMAIL_ON_GET=False ACCOUNT_EMAIL_VERIFICATION=none ACCOUNT_AUTHENTICATION_METHOD=username_email AUTO_ASSIGN_REGISTERED_MEMBERS_TO_REGISTERED_MEMBERS_GROUP_NAME=True +AUTO_ASSIGN_REGISTERED_MEMBERS_TO_CONTRIBUTORS=True # OAuth2 OAUTH2_API_KEY= @@ -155,13 +161,9 @@ TASTYPIE_APIKEY= # Monitoring # ################# DEBUG=True -DEBUG_STATIC=True SECRET_KEY='myv-y4#7j-d*p-__@j#*3z@!y24fz8%^z2v6atuy4bo9vqr1_a' -# STATIC_ROOT=/mnt/volumes/statics/static/ -# MEDIA_ROOT=/mnt/volumes/statics/uploaded/ -# GEOIP_PATH=/mnt/volumes/statics/geoip.db CACHE_BUSTING_STATIC_ENABLED=False @@ -170,8 +172,12 @@ MEMCACHED_BACKEND=django.core.cache.backends.memcached.PyLibMCCache MEMCACHED_LOCATION=127.0.0.1:11211 MEMCACHED_LOCK_EXPIRE=3600 MEMCACHED_LOCK_TIMEOUT=10 +# +# Options for memcached binary, e.g. -vvv to log all requests and cache hits +# +MEMCACHED_OPTIONS= -MAX_DOCUMENT_SIZE=2 +MAX_DOCUMENT_SIZE=200 CLIENT_RESULTS_LIMIT=5 API_LIMIT_PER_PAGE=1000 @@ -181,18 +187,24 @@ MAPBOX_ACCESS_TOKEN= BING_API_KEY= GOOGLE_API_KEY= -# Monitoring -MONITORING_ENABLED=False -MONITORING_DATA_TTL=365 -USER_ANALYTICS_ENABLED=True -USER_ANALYTICS_GZIP=True -CENTRALIZED_DASHBOARD_ENABLED=False -MONITORING_SERVICE_NAME=local-geonode -MONITORING_HOST_NAME=geonode - # Other Options/Contribs MODIFY_TOPICCATEGORY=True AVATAR_GRAVATAR_SSL=True EXIF_ENABLED=True CREATE_LAYER=True -FAVORITE_ENABLED=True \ No newline at end of file +FAVORITE_ENABLED=True + +# Advanced Workflow +RESOURCE_PUBLISHING=False +ADMIN_MODERATE_UPLOADS=False + +# PostgreSQL +POSTGRESQL_MAX_CONNECTIONS=200 + +# Common containers restart policy +RESTART_POLICY_CONDITION="on-failure" +RESTART_POLICY_DELAY="5s" +RESTART_POLICY_MAX_ATTEMPTS="3" +RESTART_POLICY_WINDOW=120s + +DEFAULT_MAX_PARALLEL_UPLOADS_PER_USER=5 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 8ae2150784a..dd6975c8401 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,3 +1,4 @@ + // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: // https://github.com/microsoft/vscode-dev-containers/tree/v0.194.0/containers/docker-existing-docker-compose // If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml. @@ -17,29 +18,33 @@ // The optional 'workspaceFolder' property is the path VS Code should open by default when // connected. This is typically a file mount in .devcontainer/docker-compose.yml - "workspaceFolder": "/usr/src/geonode/", + "workspaceFolder": "/usr/src", // Set *default* container specific settings.json values on container create. - "settings": { - "terminal.integrated.profiles.linux": { - "/bin/bash": { - "path": "/bin/bash", - "args": [ - "-l" - ] - } - }, - "terminal.integrated.defaultProfile.linux": "/bin/bash" - }, - - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "ms-python.python", - "batisteo.vscode-django", - "mrorz.language-gettext", - "eamodio.gitlens", // Note: User preference - "bigonesystems.django" // Note: User preference - ], + "customizations": { + "vscode": { + "settings": { + "terminal.integrated.profiles.linux": { + "/bin/bash": { + "path": "/bin/bash", + "args": [ + "-l" + ] + } + }, + "terminal.integrated.defaultProfile.linux": "bash" + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-python.python", + "batisteo.vscode-django", + "mrorz.language-gettext", + "eamodio.gitlens", // Note: User preference + "bigonesystems.django" // Note: User preference + ] + } + }, // Use 'forwardPorts' to make a list of ports inside the container available locally. "forwardPorts": [ @@ -60,4 +65,4 @@ // Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root. // "remoteUser": "vscode" -} +} \ No newline at end of file diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 3a303d3b066..87481986052 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -1,82 +1,19 @@ -version: '3.4' -services: - # Update this to the name of the service you want to work with in your docker-compose.yml file - django: - # If you want add a non-root user to your Dockerfile, you can use the "remoteUser" - # property in devcontainer.json to cause VS Code its sub-processes (terminals, tasks, - # debugging) to execute as the user. Uncomment the next line if you want the entire - # container to run as this user instead. Note that, on Linux, you may need to - # ensure the UID and GID of the container user you create matches your local user. - # See https://aka.ms/vscode-remote/containers/non-root for details. - # - # user: vscode - - # Uncomment if you want to override the service's Dockerfile to one in the .devcontainer - # folder. Note that the path of the Dockerfile and context is relative to the *primary* - # docker-compose.yml file (the first in the devcontainer.json "dockerComposeFile" - # array). The sample below assumes your primary file is in the root of your project. - - # build: - # context: . - # dockerfile: .devcontainer/Dockerfile - - restart: "no" - - healthcheck: - test: "echo \"I'm alive.\"" - - env_file: - - .devcontainer/.env - volumes: - # Update this to wherever you want VS Code to mount the folder of your project - - '.:/usr/src/geonode' - # Uncomment the next line to use Docker from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker-compose for details. - # - /var/run/docker.sock:/var/run/docker.sock +services: + django: ports: - "8000:8000" - - "5678:5678" - - entrypoint: ["/usr/src/geonode/entrypoint.sh"] - - # Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust. - # cap_add: - # - SYS_PTRACE - # security_opt: - # - seccomp:unconfined - - # Overrides default command so things don't shut down after the process ends. - command: sleep infinity - - celery: - restart: "no" - env_file: - - .devcontainer/.env - volumes: - - '.:/usr/src/geonode' - - geonode: - restart: "no" - - # Removes letsencrypt when developing - letsencrypt: - deploy: - replicas: 0 - - geoserver: - restart: "no" - ports: - - "8080:8080" - - data-dir-conf: - restart: "no" - - db: - restart: "no" - ports: - - "5432:5432" - - rabbitmq: - restart: "no" + - './src:/usr/src/${COMPOSE_PROJECT_NAME}' + - './geonode-mapstore-client:/usr/src/geonode-mapstore-client' + - './.devcontainer/.vscode:/usr/src/.vscode' + - statics:/mnt/volumes/statics + - geoserver-data-dir:/geoserver_data/data + - backup-restore:/backup_restore + - data:/data + - tmp:/tmp + healthcheck: + test: "echo 'Alive'" + entrypoint: ["/usr/src/${COMPOSE_PROJECT_NAME}/entrypoint.sh"] + command: sleep infinity diff --git a/.env_dev b/.env_dev index aae9c72f7cc..e12de6a4f30 100644 --- a/.env_dev +++ b/.env_dev @@ -22,18 +22,18 @@ GEONODE_INSTANCE_NAME=geonode # ################# POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres -GEONODE_DATABASE=geonode +GEONODE_DATABASE=gn GEONODE_DATABASE_USER=geonode GEONODE_DATABASE_PASSWORD=geonode -GEONODE_GEODATABASE=geonode_data +GEONODE_GEODATABASE=gn5_data GEONODE_GEODATABASE_USER=geonode GEONODE_GEODATABASE_PASSWORD=geonode GEONODE_DATABASE_SCHEMA=public GEONODE_GEODATABASE_SCHEMA=public DATABASE_HOST=localhost DATABASE_PORT=5432 -DATABASE_URL=postgis://geonode:geonode@localhost:5432/geonode -GEODATABASE_URL=postgis://geonode:geonode@localhost:5432/geonode_data +DATABASE_URL=postgis://geonode:geonode@localhost:5432/gn5 +GEODATABASE_URL=postgis://geonode:geonode@localhost:5432/gn5_data GEONODE_DB_CONN_MAX_AGE=0 GEONODE_DB_CONN_TOUT=5 DEFAULT_BACKEND_DATASTORE=datastore diff --git a/geonode/base/apps.py b/geonode/base/apps.py index 4b24947e52a..e633659110e 100644 --- a/geonode/base/apps.py +++ b/geonode/base/apps.py @@ -24,6 +24,7 @@ class BaseAppConfig(NotificationsAppConfigBase, AppConfig): name = "geonode.base" + default_auto_field = "django.db.models.BigAutoField" NOTIFICATIONS = ( ( "request_download_resourcebase", diff --git a/geonode/base/models.py b/geonode/base/models.py index 875f6847179..2b1e41b02b1 100644 --- a/geonode/base/models.py +++ b/geonode/base/models.py @@ -31,7 +31,6 @@ from django.db import transaction from django.db import models -from django.db.models import Max from django.conf import settings from django.utils.html import escape from django.utils.timezone import now @@ -1031,11 +1030,9 @@ def save(self, notify=False, *args, **kwargs): send_notification(recipients, notice_type_label, {"resource": self}) if self.pk is None: - _initial_value = ResourceBase.objects.aggregate(Max("pk"))["pk__max"] - if not _initial_value: - _initial_value = 1 - else: - _initial_value += 1 + # behaviour changed with Djagno 5.2 + base = ResourceBase.objects + _initial_value = 1 if not base.exists() else base.last().id + 1 _next_value = get_next_value("ResourceBase", initial_value=_initial_value) # type(self).__name__, if _initial_value > _next_value: Sequence.objects.filter(name="ResourceBase").update(last=_initial_value) diff --git a/geonode/documents/apps.py b/geonode/documents/apps.py index 72e2ad96375..27707aed711 100644 --- a/geonode/documents/apps.py +++ b/geonode/documents/apps.py @@ -24,6 +24,7 @@ class DocumentsAppConfig(NotificationsAppConfigBase, AppConfig): name = "geonode.documents" + default_auto_field = "django.db.models.BigAutoField" NOTIFICATIONS = ( ( "document_created", diff --git a/geonode/geoapps/apps.py b/geonode/geoapps/apps.py index 3985e342070..01d59734453 100644 --- a/geonode/geoapps/apps.py +++ b/geonode/geoapps/apps.py @@ -24,7 +24,7 @@ class GeoNodeAppsConfig(NotificationsAppConfigBase, AppConfig): name = "geonode.geoapps" type = "GEONODE_APP" - + default_auto_field = "django.db.models.BigAutoField" NOTIFICATIONS = ( ( "geoapp_created", diff --git a/geonode/layers/apps.py b/geonode/layers/apps.py index f7c503179a0..789dd690693 100644 --- a/geonode/layers/apps.py +++ b/geonode/layers/apps.py @@ -26,6 +26,7 @@ class DatasetAppConfig(NotificationsAppConfigBase, AppConfig): name = "geonode.layers" verbose_name = "Dataset" verbose_name_plural = "Datasets" + default_auto_field = "django.db.models.BigAutoField" NOTIFICATIONS = ( ( "dataset_created", diff --git a/geonode/maps/apps.py b/geonode/maps/apps.py index 762c6743ec4..b8f6e573a4d 100644 --- a/geonode/maps/apps.py +++ b/geonode/maps/apps.py @@ -25,6 +25,7 @@ class MapsAppConfig(NotificationsAppConfigBase, AppConfig): name = "geonode.maps" + default_auto_field = "django.db.models.BigAutoField" NOTIFICATIONS = ( ( "map_created", diff --git a/geonode/settings.py b/geonode/settings.py index 92c333fa0a6..a16047810fc 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -250,7 +250,7 @@ AUTH_USER_MODEL = os.getenv("AUTH_USER_MODEL", "people.Profile") PASSWORD_HASHERS = [ - #"django.contrib.auth.hashers.SHA1PasswordHasher", + # "django.contrib.auth.hashers.SHA1PasswordHasher", "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher", "django.contrib.auth.hashers.PBKDF2PasswordHasher", # 'django.contrib.auth.hashers.Argon2PasswordHasher', From c642e17d79f1ad25c17026481cb8028e15e5e99f Mon Sep 17 00:00:00 2001 From: Mattia Date: Tue, 27 May 2025 13:10:08 +0200 Subject: [PATCH 06/26] Upgrade to django5 --- .env_dev | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.env_dev b/.env_dev index e12de6a4f30..aae9c72f7cc 100644 --- a/.env_dev +++ b/.env_dev @@ -22,18 +22,18 @@ GEONODE_INSTANCE_NAME=geonode # ################# POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres -GEONODE_DATABASE=gn +GEONODE_DATABASE=geonode GEONODE_DATABASE_USER=geonode GEONODE_DATABASE_PASSWORD=geonode -GEONODE_GEODATABASE=gn5_data +GEONODE_GEODATABASE=geonode_data GEONODE_GEODATABASE_USER=geonode GEONODE_GEODATABASE_PASSWORD=geonode GEONODE_DATABASE_SCHEMA=public GEONODE_GEODATABASE_SCHEMA=public DATABASE_HOST=localhost DATABASE_PORT=5432 -DATABASE_URL=postgis://geonode:geonode@localhost:5432/gn5 -GEODATABASE_URL=postgis://geonode:geonode@localhost:5432/gn5_data +DATABASE_URL=postgis://geonode:geonode@localhost:5432/geonode +GEODATABASE_URL=postgis://geonode:geonode@localhost:5432/geonode_data GEONODE_DB_CONN_MAX_AGE=0 GEONODE_DB_CONN_TOUT=5 DEFAULT_BACKEND_DATASTORE=datastore From 79d822fda16d7fe0af23bbeb2dadde3da4b1f06a Mon Sep 17 00:00:00 2001 From: Mattia Date: Tue, 27 May 2025 14:40:24 +0200 Subject: [PATCH 07/26] Upgrade to django5 --- .env_dev | 8 ++++---- requirements.txt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.env_dev b/.env_dev index aae9c72f7cc..e12de6a4f30 100644 --- a/.env_dev +++ b/.env_dev @@ -22,18 +22,18 @@ GEONODE_INSTANCE_NAME=geonode # ################# POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres -GEONODE_DATABASE=geonode +GEONODE_DATABASE=gn GEONODE_DATABASE_USER=geonode GEONODE_DATABASE_PASSWORD=geonode -GEONODE_GEODATABASE=geonode_data +GEONODE_GEODATABASE=gn5_data GEONODE_GEODATABASE_USER=geonode GEONODE_GEODATABASE_PASSWORD=geonode GEONODE_DATABASE_SCHEMA=public GEONODE_GEODATABASE_SCHEMA=public DATABASE_HOST=localhost DATABASE_PORT=5432 -DATABASE_URL=postgis://geonode:geonode@localhost:5432/geonode -GEODATABASE_URL=postgis://geonode:geonode@localhost:5432/geonode_data +DATABASE_URL=postgis://geonode:geonode@localhost:5432/gn5 +GEODATABASE_URL=postgis://geonode:geonode@localhost:5432/gn5_data GEONODE_DB_CONN_MAX_AGE=0 GEONODE_DB_CONN_TOUT=5 DEFAULT_BACKEND_DATASTORE=datastore diff --git a/requirements.txt b/requirements.txt index 33751ccce70..93516fa1105 100644 --- a/requirements.txt +++ b/requirements.txt @@ -83,7 +83,7 @@ git+https://github.com/GeoNode/pinax-notifications@master#egg=geonode-pinax-noti # GeoNode org maintained apps. # django-geonode-mapstore-client==4.0.5 -#git+https://github.com/GeoNode/geonode-mapstore-client.git@django_upgrade#egg=django_geonode_mapstore_client +-e git+https://github.com/GeoNode/geonode-mapstore-client.git@django_upgrade#egg=django_geonode_mapstore_client django-avatar==8.0.1 geonode-oauth-toolkit==2.2.2.2 geonode-announcements==2.0.2.2 From b809bed04f2708fe97ea552a83e1c74f73be94a8 Mon Sep 17 00:00:00 2001 From: Mattia Date: Tue, 27 May 2025 17:13:11 +0200 Subject: [PATCH 08/26] Upgrade to django5 --- .devcontainer/.env | 16 ++++++++-------- requirements.txt | 4 ++-- setup.cfg | 16 ++++++++++------ 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/.devcontainer/.env b/.devcontainer/.env index e12de6a4f30..6cc1be3fe8c 100644 --- a/.devcontainer/.env +++ b/.devcontainer/.env @@ -22,24 +22,24 @@ GEONODE_INSTANCE_NAME=geonode # ################# POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres -GEONODE_DATABASE=gn +GEONODE_DATABASE=geonode GEONODE_DATABASE_USER=geonode GEONODE_DATABASE_PASSWORD=geonode -GEONODE_GEODATABASE=gn5_data +GEONODE_GEODATABASE=geonode_data GEONODE_GEODATABASE_USER=geonode GEONODE_GEODATABASE_PASSWORD=geonode GEONODE_DATABASE_SCHEMA=public GEONODE_GEODATABASE_SCHEMA=public DATABASE_HOST=localhost DATABASE_PORT=5432 -DATABASE_URL=postgis://geonode:geonode@localhost:5432/gn5 -GEODATABASE_URL=postgis://geonode:geonode@localhost:5432/gn5_data +DATABASE_URL=postgis://geonode:geonode@db:5432/geonode +GEODATABASE_URL=postgis://geonode:geonode@db:5432/geonode_data GEONODE_DB_CONN_MAX_AGE=0 GEONODE_DB_CONN_TOUT=5 DEFAULT_BACKEND_DATASTORE=datastore -BROKER_URL=amqp://admin:admin@localhost:5672// +BROKER_URL=amqp://guest:guest@rabbitmq:5672/ CELERY_BEAT_SCHEDULER=celery.beat:PersistentScheduler -ASYNC_SIGNALS=False +ASYNC_SIGNALS=True SITEURL=http://localhost:8000/ @@ -84,7 +84,7 @@ RESOLVER=127.0.0.11 # ################# GEOSERVER_WEB_UI_LOCATION=http://localhost:8080/geoserver/ GEOSERVER_PUBLIC_LOCATION=http://localhost:8080/geoserver/ -GEOSERVER_LOCATION=http://localhost:8080/geoserver/ +GEOSERVER_LOCATION=http://geoserver:8080/geoserver/ GEOSERVER_ADMIN_USER=admin GEOSERVER_ADMIN_PASSWORD=geoserver @@ -97,7 +97,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=http://localhost:8080/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 -Xms2G -Xmx4G -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:PerfDataSamplingInterval=500 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:-UseGCOverheadLimit -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 -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 diff --git a/requirements.txt b/requirements.txt index 93516fa1105..f62048ee5a8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ Pillow==10.4.0 lxml==5.2.1 psycopg2==2.9.9 -Django==5.2.1 +Django==5.2 # Other beautifulsoup4==4.12.3 @@ -31,7 +31,7 @@ django-imagekit==5.0.0 django-taggit==5.0.1 django-markdownify==0.9.5 django-mptt==0.16.0 -django-modeltranslation>=0.11,<0.19.0 +django-modeltranslation==0.18.13 django-treebeard==4.7.1 django-guardian<2.4.1 django-downloadview==2.3.0 diff --git a/setup.cfg b/setup.cfg index 3055ca6b837..7d400553de7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,7 +28,7 @@ install_requires = Pillow==10.4.0 lxml==5.2.1 psycopg2==2.9.9 - Django==4.2.21 + Django==5.2 # Other beautifulsoup4==4.12.3 @@ -57,7 +57,7 @@ install_requires = django-taggit==5.0.1 django-markdownify==0.9.5 django-mptt==0.16.0 - django-modeltranslation>=0.11,<0.19.0 + django-modeltranslation==0.18.13 django-treebeard==4.7.1 django-guardian<2.4.1 django-downloadview==2.3.0 @@ -99,13 +99,17 @@ install_requires = djangorestframework-guardian==0.3.0 drf-extensions==0.7.1 drf-spectacular==0.27.2 - dynamic-rest==2.3.0 + dynamic-rest @ git+https://github.com/GeoNode/dynamic-rest@master#egg=dynamic-rest geonode-pinax-notifications==6.0.0.2 + #geonode-pinax-notifications==6.0.0.2 + geonode-pinax-notifications @ git+https://github.com/GeoNode/pinax-notifications@master#egg=geonode-pinax-notifications # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.0.5,<5.1.0 - django-avatar==8.0.0 + # django-geonode-mapstore-client==4.0.5 + django-geonode-mapstore-client @ git+https://github.com/GeoNode/geonode-mapstore-client.git@django_upgrade#egg=django_geonode_mapstore_client + + django-avatar==8.0.1 geonode-oauth-toolkit==2.2.2.2 geonode-announcements==2.0.2.2 django-activity-stream==2.0.0 @@ -116,7 +120,7 @@ install_requires = # importer dependencies setuptools>=59 - gdal<=3.4.3 + gdal<=3.6.4 pdok-geopackage-validator==0.8.5 geonode-django-dynamic-model==0.4.0 From c1023018df6524b23c1ceb91017ca0eddf41a4ac Mon Sep 17 00:00:00 2001 From: Mattia Date: Thu, 12 Jun 2025 10:37:37 +0200 Subject: [PATCH 09/26] Upgrade to django5 --- geonode/base/models.py | 16 ++++++++-------- geonode/security/tests.py | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/geonode/base/models.py b/geonode/base/models.py index f3de7f4c8f8..c47fcf4ff5b 100644 --- a/geonode/base/models.py +++ b/geonode/base/models.py @@ -990,14 +990,14 @@ def save(self, notify=False, *args, **kwargs): _approval_status_changed = False if hasattr(self, "class_name") and (self.pk is None or notify): - if self.pk is None and (self.title or getattr(self, "name", None)): - # Resource Created - if not self.title and getattr(self, "name", None): - self.title = getattr(self, "name", None) - notice_type_label = f"{self.class_name.lower()}_created" - recipients = get_notification_recipients(notice_type_label, resource=self) - send_notification(recipients, notice_type_label, {"resource": self}) - elif self.pk: + # if self.pk is None and (self.title or getattr(self, "name", None)): + # # Resource Created + # if not self.title and getattr(self, "name", None): + # self.title = getattr(self, "name", None) + # notice_type_label = f"{self.class_name.lower()}_created" + # recipients = get_notification_recipients(notice_type_label, resource=self) + # send_notification(recipients, notice_type_label, {"resource": self}) + if self.pk: # Group has changed _group_status_changed = self.group != ResourceBase.objects.get(pk=self.get_self_resource().pk).group diff --git a/geonode/security/tests.py b/geonode/security/tests.py index 70bddfec88f..c8ae40a17d3 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -275,7 +275,7 @@ def test_session_ctrl_middleware(self): request = HttpRequest() request.user = admin request.session = engine.SessionStore() - request.session["access_token"] = get_or_create_token(admin) + request.session["access_token"] = str(get_or_create_token(admin)) request.session.save() middleware.process_request(request) self.assertFalse(request.session.is_empty()) From b888984a408615ed5039c984b2bbd7bf30da23b7 Mon Sep 17 00:00:00 2001 From: Mattia Date: Thu, 12 Jun 2025 16:25:59 +0200 Subject: [PATCH 10/26] Upgrade to django5 --- geonode/base/models.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/geonode/base/models.py b/geonode/base/models.py index c47fcf4ff5b..758b51be0c3 100644 --- a/geonode/base/models.py +++ b/geonode/base/models.py @@ -988,7 +988,7 @@ def save(self, notify=False, *args, **kwargs): _notification_sent = False _group_status_changed = False _approval_status_changed = False - + send_create_notification = False if hasattr(self, "class_name") and (self.pk is None or notify): # if self.pk is None and (self.title or getattr(self, "name", None)): # # Resource Created @@ -1037,6 +1037,7 @@ def save(self, notify=False, *args, **kwargs): if _initial_value > _next_value: Sequence.objects.filter(name="ResourceBase").update(last=_initial_value) _next_value = _initial_value + send_create_notification = True self.pk = self.id = _next_value @@ -1046,6 +1047,12 @@ def save(self, notify=False, *args, **kwargs): self.uuid = str(uuid.uuid4()) super().save(*args, **kwargs) + if send_create_notification: + # changed in Django 5.2, the we can get the title via the assets only if the resource is saved + self.title = getattr(self, "name", None) + notice_type_label = f"{self.class_name.lower()}_created" + recipients = get_notification_recipients(notice_type_label, resource=self) + send_notification(recipients, notice_type_label, {"resource": self}) # Update workflow permissions if _approval_status_changed or _group_status_changed: self.set_permissions( From 33fbda1438db5690b691966e9fb3e58ae98c0353 Mon Sep 17 00:00:00 2001 From: Mattia Date: Fri, 13 Jun 2025 17:56:08 +0200 Subject: [PATCH 11/26] merge with master --- setup.cfg | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/setup.cfg b/setup.cfg index a9c944036e1..7cb3c367ee1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,11 +28,7 @@ install_requires = Pillow==10.4.0 lxml==5.2.1 psycopg2==2.9.9 -<<<<<<< HEAD - Django==5.2 -======= - Django==4.2.22 ->>>>>>> d6ec87183f86703dd930bdedddf6ef0b614253d9 + Django==5.2.1 # Other beautifulsoup4==4.12.3 From 411046265def65ec72191958090a4cc3308d4ba2 Mon Sep 17 00:00:00 2001 From: Mattia Date: Fri, 13 Jun 2025 18:06:22 +0200 Subject: [PATCH 12/26] merge with master --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 52d3e68af5b..f62048ee5a8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ Pillow==10.4.0 lxml==5.2.1 psycopg2==2.9.9 -Django==5.2.1 +Django==5.2 # Other beautifulsoup4==4.12.3 diff --git a/setup.cfg b/setup.cfg index 7cb3c367ee1..7d400553de7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,7 +28,7 @@ install_requires = Pillow==10.4.0 lxml==5.2.1 psycopg2==2.9.9 - Django==5.2.1 + Django==5.2 # Other beautifulsoup4==4.12.3 From 6ffdf01de7672457adcc538053d00c444d7df6c8 Mon Sep 17 00:00:00 2001 From: Mattia Date: Tue, 17 Jun 2025 14:39:33 +0200 Subject: [PATCH 13/26] Fixes #13122 django5 upgrade --- geonode/base/models.py | 2 +- requirements.txt | 2 +- setup.cfg | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/geonode/base/models.py b/geonode/base/models.py index 758b51be0c3..2029042511e 100644 --- a/geonode/base/models.py +++ b/geonode/base/models.py @@ -1050,7 +1050,7 @@ def save(self, notify=False, *args, **kwargs): if send_create_notification: # changed in Django 5.2, the we can get the title via the assets only if the resource is saved self.title = getattr(self, "name", None) - notice_type_label = f"{self.class_name.lower()}_created" + notice_type_label = f"{self.__class__.__name__.lower()}_created" recipients = get_notification_recipients(notice_type_label, resource=self) send_notification(recipients, notice_type_label, {"resource": self}) # Update workflow permissions diff --git a/requirements.txt b/requirements.txt index f62048ee5a8..02aa7689fd2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -94,7 +94,7 @@ gn-gsimporter==2.0.4 gisdata==0.5.4 # importer dependencies -setuptools>=59 +setuptools>=59,<81 gdal<=3.6.4 pdok-geopackage-validator==0.8.5 geonode-django-dynamic-model==0.4.0 diff --git a/setup.cfg b/setup.cfg index 7d400553de7..1751fd71c14 100644 --- a/setup.cfg +++ b/setup.cfg @@ -119,7 +119,7 @@ install_requires = gisdata==0.5.4 # importer dependencies - setuptools>=59 + setuptools>=59,<81 gdal<=3.6.4 pdok-geopackage-validator==0.8.5 geonode-django-dynamic-model==0.4.0 From 394af2e5e85f05e664758b3dd30c344c28096510 Mon Sep 17 00:00:00 2001 From: sijandh35 Date: Thu, 10 Jul 2025 20:26:12 +0545 Subject: [PATCH 14/26] Fixes #13122: Added Pbk2sha1 hasher migration from sha1 --- geonode/people/hashers.py | 83 +++++++++++++++++++ .../migrations/0037_migrate_sha1_passwords.py | 23 +++++ geonode/settings.py | 2 +- 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 geonode/people/hashers.py create mode 100644 geonode/people/migrations/0037_migrate_sha1_passwords.py diff --git a/geonode/people/hashers.py b/geonode/people/hashers.py new file mode 100644 index 00000000000..a183e592a55 --- /dev/null +++ b/geonode/people/hashers.py @@ -0,0 +1,83 @@ +import hashlib +import math +from django.utils.translation import gettext_noop as _ +from django.utils.crypto import ( + RANDOM_STRING_CHARS, + constant_time_compare, +) +from django.contrib.auth.hashers import PBKDF2SHA1PasswordHasher, BasePasswordHasher + + +def mask_hash(hash, show=6, char="*"): + """ + Return the given hash, with only the first ``show`` number shown. The + rest are masked with ``char`` for security reasons. + """ + masked = hash[:show] + masked += char * len(hash[show:]) + return masked + + +def must_update_salt(salt, expected_entropy): + # Each character in the salt provides log_2(len(alphabet)) bits of entropy. + return len(salt) * math.log2(len(RANDOM_STRING_CHARS)) < expected_entropy + + +class SHA1PasswordHasher(BasePasswordHasher): + """ + This is the legecy SHA1 password hasher which will be removed in future releases. + """ + + algorithm = "sha1" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def encode(self, password, salt): + self._check_encode_args(password, salt) + hash = hashlib.sha1((salt + password).encode()).hexdigest() + return "%s$%s$%s" % (self.algorithm, salt, hash) + + def decode(self, encoded): + algorithm, salt, hash = encoded.split("$", 2) + assert algorithm == self.algorithm + return { + "algorithm": algorithm, + "hash": hash, + "salt": salt, + } + + def verify(self, password, encoded): + decoded = self.decode(encoded) + encoded_2 = self.encode(password, decoded["salt"]) + return constant_time_compare(encoded, encoded_2) + + def safe_summary(self, encoded): + decoded = self.decode(encoded) + return { + _("algorithm"): decoded["algorithm"], + _("salt"): mask_hash(decoded["salt"], show=2), + _("hash"): mask_hash(decoded["hash"]), + } + + def must_update(self, encoded): + decoded = self.decode(encoded) + return must_update_salt(decoded["salt"], self.salt_entropy) + + def harden_runtime(self, password, encoded): + pass + + +class PBKDF2SHA1WrappedSHA1PasswordHasher(PBKDF2SHA1PasswordHasher): + """ + A password hasher that wraps SHA1 hashes in a PBKDF2SHA1 hash. + """ + + algorithm = "pbkdf2sha1_wrapped_sha1" + + def encode_sha1_hash(self, sha1_hash, salt, iterations=None): + return super().encode(sha1_hash, salt, iterations) + + def encode(self, password, salt, iterations=None): + _, _, sha1_hash = SHA1PasswordHasher().encode(password, salt).split("$", 2) + return self.encode_sha1_hash(sha1_hash, salt, iterations) diff --git a/geonode/people/migrations/0037_migrate_sha1_passwords.py b/geonode/people/migrations/0037_migrate_sha1_passwords.py new file mode 100644 index 00000000000..cadff4f88ea --- /dev/null +++ b/geonode/people/migrations/0037_migrate_sha1_passwords.py @@ -0,0 +1,23 @@ +from django.db import migrations + +from geonode.people.hashers import PBKDF2SHA1WrappedSHA1PasswordHasher + + +def forwards_func(apps, schema_editor): + User = apps.get_model("people", "Profile") + users = User.objects.filter(password__startswith="sha1$") + hasher = PBKDF2SHA1WrappedSHA1PasswordHasher() + for user in users: + algorithm, salt, sha1_hash = user.password.split("$", 2) + user.password = hasher.encode_sha1_hash(sha1_hash, salt) + user.save(update_fields=["password"]) + + +class Migration(migrations.Migration): + dependencies = [ + ("people", "0036_merge_20210706_0951"), + ] + + operations = [ + migrations.RunPython(forwards_func), + ] diff --git a/geonode/settings.py b/geonode/settings.py index 5c2d3f4d6f6..1d3f0257dd9 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -250,9 +250,9 @@ AUTH_USER_MODEL = os.getenv("AUTH_USER_MODEL", "people.Profile") PASSWORD_HASHERS = [ - # "django.contrib.auth.hashers.SHA1PasswordHasher", "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher", "django.contrib.auth.hashers.PBKDF2PasswordHasher", + "geonode.people.hashers.PBKDF2SHA1WrappedSHA1PasswordHasher", # Wrapped Hasher # 'django.contrib.auth.hashers.Argon2PasswordHasher', # 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', # 'django.contrib.auth.hashers.BCryptPasswordHasher', From ff7847db3655304ba4a4229682cb019e39810fe2 Mon Sep 17 00:00:00 2001 From: sijandh35 Date: Wed, 16 Jul 2025 18:50:28 +0545 Subject: [PATCH 15/26] Fixes #13122: solved not null voilation on test case fail due to null in title of ResourceBase --- geonode/base/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/geonode/base/models.py b/geonode/base/models.py index 2029042511e..0c89173f632 100644 --- a/geonode/base/models.py +++ b/geonode/base/models.py @@ -1049,7 +1049,8 @@ def save(self, notify=False, *args, **kwargs): if send_create_notification: # changed in Django 5.2, the we can get the title via the assets only if the resource is saved - self.title = getattr(self, "name", None) + if not self.title and hasattr(self, "name") and getattr(self, "name", None): + self.title = getattr(self, "name", None) notice_type_label = f"{self.__class__.__name__.lower()}_created" recipients = get_notification_recipients(notice_type_label, resource=self) send_notification(recipients, notice_type_label, {"resource": self}) From cd1bb936d612e57c16227f926fcc40802eb02d1a Mon Sep 17 00:00:00 2001 From: sijandh35 Date: Wed, 16 Jul 2025 20:33:26 +0545 Subject: [PATCH 16/26] Fixes #13122: changes from assertQuerysetEqual to assertQuerySetEqual --- geonode/metadata/tests/test_handlers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/metadata/tests/test_handlers.py b/geonode/metadata/tests/test_handlers.py index 4fccb1d1e5d..00fb82d0f27 100644 --- a/geonode/metadata/tests/test_handlers.py +++ b/geonode/metadata/tests/test_handlers.py @@ -1692,7 +1692,7 @@ def test_tkeywords_handler_update_resource(self): about__in=["http://example.com/keyword1", "http://example.com/keyword2"] ) - self.assertQuerysetEqual( + self.assertQuerySetEqual( updated_keywords.order_by("id"), expected_keywords.order_by("id"), transform=lambda x: x ) From bdc09f393c56a1efb2c18bad1a5b950e0fb6a5a6 Mon Sep 17 00:00:00 2001 From: sijandh35 Date: Thu, 17 Jul 2025 16:24:18 +0545 Subject: [PATCH 17/26] Fixes #13122: disable the session serialization for service handler with fetch directly --- geonode/services/views.py | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/geonode/services/views.py b/geonode/services/views.py index 3341fb7fcc1..5959306e5e4 100644 --- a/geonode/services/views.py +++ b/geonode/services/views.py @@ -72,8 +72,9 @@ def register_service(request): if service_handler.indexing_method == enumerations.CASCADED: service_handler.create_cascaded_store(service) service_handler.geonode_service_id = service.id - request.session[service_handler.url] = service_handler - logger.debug("Added handler to the session") + # commented out due to jsonserializer error, will be replaced with cache + # request.session[service_handler.url] = service_handler + # logger.debug("Added handler to the session") messages.add_message(request, messages.SUCCESS, _("Service registered successfully")) result = HttpResponseRedirect(reverse("harvest_resources", kwargs={"service_id": service.id})) else: @@ -95,8 +96,9 @@ def _get_service_handler(request, service): service_handler = get_service_handler(service.service_url, service.type, service.id) if not service_handler.geonode_service_id: service_handler.geonode_service_id = service.id - request.session[service.service_url] = service_handler - logger.debug("Added handler to the session") + # commented out due to jsonserializer error, will be replaced with cache + # request.session[service.service_url] = service_handler + # logger.debug("Added handler to the session") return service_handler @@ -185,14 +187,15 @@ def harvest_resources_handle_post(request, service, handler): @login_required def harvest_resources(request, service_id): service = get_object_or_404(Service, pk=service_id) - try: - handler = request.session[service.service_url] - if not handler.geonode_service_id: - handler.geonode_service_id = service_id - except KeyError: # handler is not saved on the session, recreate it - handler = _get_service_handler(request, service) - if not handler.geonode_service_id: - handler.geonode_service_id = service_id + # commented out due to jsonserializer error, will be replaced with cache + # try: + # handler = request.session[service.service_url] + # if not handler.geonode_service_id: + # handler.geonode_service_id = service_id + # except KeyError: # handler is not saved on the session, recreate it + handler = _get_service_handler(request, service) + if not handler.geonode_service_id: + handler.geonode_service_id = service_id if request.method == "GET": return harvest_resources_handle_get(request, service, handler) elif request.method == "POST": @@ -281,10 +284,11 @@ def service_detail(request, service_id): # speed up the register/harvest resources flow. However, for services # with many resources, keeping the handler in the session leads to degraded # performance - try: - request.session.pop(service.service_url) - except KeyError: - pass + # commented out due to jsonserializer error, will be replaced with cache + # try: + # request.session.pop(service.service_url) + # except KeyError: + # pass return render( request, From c526ca6f3c2714323901f7e3cc2cb436d50cc2e5 Mon Sep 17 00:00:00 2001 From: sijandh35 Date: Thu, 17 Jul 2025 18:32:12 +0545 Subject: [PATCH 18/26] Fixes #13122: test case for migrations of sha password --- geonode/people/tests.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/geonode/people/tests.py b/geonode/people/tests.py index 0183c3834b1..8bea76afbfc 100644 --- a/geonode/people/tests.py +++ b/geonode/people/tests.py @@ -37,6 +37,8 @@ from geonode.base.populate_test_data import all_public, create_models, create_single_dataset, remove_models from geonode.security.registry import permissions_registry +from geonode.people.hashers import SHA1PasswordHasher +from geonode.people.hashers import PBKDF2SHA1WrappedSHA1PasswordHasher class PeopleAndProfileTests(GeoNodeBaseTestSupport): @@ -1298,3 +1300,25 @@ def test_transfer_resource_subset(self): # since the payload say "default" self.assertTrue(resource_to_transfer.owner == new_owner) self.assertTrue(second_resource.owner == new_owner) + + def test_migrate_sha1_passwords(self): + User = get_user_model() + user = User.objects.create_user(username="sha1user", password="password") + # Manually hash the password using SHA1 and save it directly to the database + hasher = SHA1PasswordHasher() + encoded_password = hasher.encode("password", "salt") + User.objects.filter(pk=user.pk).update(password=encoded_password) + user.refresh_from_db() + self.assertTrue(user.password.startswith("sha1")) + # forward function logic on migration to pbkdf2sha1_wrapped_sha1 + new_hasher = PBKDF2SHA1WrappedSHA1PasswordHasher() + algorithm, salt, sha1_hash = user.password.split("$", 2) + user.password = new_hasher.encode_sha1_hash(sha1_hash, salt) + user.save(update_fields=["password"]) + user.refresh_from_db() + self.assertFalse(user.password.startswith("sha1")) + self.assertTrue(user.password.startswith("pbkdf2sha1_wrapped_sha1")) + # Check that the user can still log in with their original password + self.assertTrue(user.check_password("password")) + # after checking it should be migrated to default hash + self.assertTrue(user.password.startswith("pbkdf2_sha1")) From 58c0da922bd3723f004775193fc3add5e5ef88cc Mon Sep 17 00:00:00 2001 From: sijandh35 Date: Thu, 17 Jul 2025 20:51:00 +0545 Subject: [PATCH 19/26] Fixes #13122: boto3 back to previous --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d3695526c4d..b6e50813800 100644 --- a/requirements.txt +++ b/requirements.txt @@ -107,7 +107,8 @@ django-bootstrap3-datetimepicker-2==2.8.3 django-storages==1.14.3 dropbox==11.36.2 google-cloud-storage==2.16.0 -boto3==1.39.3 +boto3==1.34.103 +botocore==1.34.162 # Django Caches whitenoise==6.6.0 From d26724fa2789ce85194b7b00c725cf9282a0884e Mon Sep 17 00:00:00 2001 From: sijandh35 Date: Thu, 17 Jul 2025 23:39:39 +0545 Subject: [PATCH 20/26] Fixes #13122: solves 'LoginRequiredMiddleware' object has no attribute 'async_mode' as django 5 requires call method --- geonode/security/middleware.py | 10 ++++++++++ requirements.txt | 3 +-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/geonode/security/middleware.py b/geonode/security/middleware.py index 4e7dfb42e9b..61cace90f73 100644 --- a/geonode/security/middleware.py +++ b/geonode/security/middleware.py @@ -67,7 +67,9 @@ white_list = [compile(x) for x in white_list_paths + getattr(settings, "AUTH_EXEMPT_URLS", ())] +from django.utils.decorators import sync_and_async_middleware +@sync_and_async_middleware class LoginRequiredMiddleware(MiddlewareMixin): """ Requires a user to be logged in to access any page that is not white-listed. @@ -86,6 +88,14 @@ class LoginRequiredMiddleware(MiddlewareMixin): def __init__(self, get_response): self.get_response = get_response + def __call__(self, request): + #call method is required for django 5 as old style middleware is deprecated + response = self.process_request(request) + if response: + return response + response = self.get_response(request) + return response + def process_request(self, request): if request.user and (not request.user.is_authenticated or request.user.is_anonymous): if not any(path.match(request.path) for path in white_list): diff --git a/requirements.txt b/requirements.txt index b6e50813800..d3695526c4d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -107,8 +107,7 @@ django-bootstrap3-datetimepicker-2==2.8.3 django-storages==1.14.3 dropbox==11.36.2 google-cloud-storage==2.16.0 -boto3==1.34.103 -botocore==1.34.162 +boto3==1.39.3 # Django Caches whitenoise==6.6.0 From a0df6dc10edae9b2313f3c77af72f985d30accb0 Mon Sep 17 00:00:00 2001 From: sijandh35 Date: Thu, 17 Jul 2025 23:41:29 +0545 Subject: [PATCH 21/26] Fixes #13122: solves 'LoginRequiredMiddleware' object has no attribute 'async_mode' as django 5 requires call method formated --- geonode/security/middleware.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/geonode/security/middleware.py b/geonode/security/middleware.py index 61cace90f73..14ce87d2ecd 100644 --- a/geonode/security/middleware.py +++ b/geonode/security/middleware.py @@ -69,6 +69,7 @@ from django.utils.decorators import sync_and_async_middleware + @sync_and_async_middleware class LoginRequiredMiddleware(MiddlewareMixin): """ @@ -89,7 +90,7 @@ def __init__(self, get_response): self.get_response = get_response def __call__(self, request): - #call method is required for django 5 as old style middleware is deprecated + # call method is required for django 5 as old style middleware is deprecated response = self.process_request(request) if response: return response From 467450bd7f5ba1497e6854ce434a303ef28c0c50 Mon Sep 17 00:00:00 2001 From: sijandh35 Date: Thu, 17 Jul 2025 23:44:06 +0545 Subject: [PATCH 22/26] Fixes #13122: remove unnecessary import --- geonode/security/middleware.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/geonode/security/middleware.py b/geonode/security/middleware.py index 14ce87d2ecd..b8433b4f3ad 100644 --- a/geonode/security/middleware.py +++ b/geonode/security/middleware.py @@ -67,10 +67,7 @@ white_list = [compile(x) for x in white_list_paths + getattr(settings, "AUTH_EXEMPT_URLS", ())] -from django.utils.decorators import sync_and_async_middleware - -@sync_and_async_middleware class LoginRequiredMiddleware(MiddlewareMixin): """ Requires a user to be logged in to access any page that is not white-listed. From a1320d9699b9c17d8461153b78143d29ad8b5620 Mon Sep 17 00:00:00 2001 From: sijandh35 Date: Fri, 18 Jul 2025 00:50:35 +0545 Subject: [PATCH 23/26] Fixes #13122: commented reason on middlewaremixin for test case fail solution --- geonode/security/middleware.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/security/middleware.py b/geonode/security/middleware.py index b8433b4f3ad..ada570947d3 100644 --- a/geonode/security/middleware.py +++ b/geonode/security/middleware.py @@ -87,7 +87,7 @@ def __init__(self, get_response): self.get_response = get_response def __call__(self, request): - # call method is required for django 5 as old style middleware is deprecated + # call method is added for test request calls that throws async_mode error called from newer tests response = self.process_request(request) if response: return response From ef715a0d4b869f01c9738df238c685697ff300c9 Mon Sep 17 00:00:00 2001 From: sijandh35 Date: Fri, 18 Jul 2025 19:11:09 +0545 Subject: [PATCH 24/26] Fixes #13122: add super call to resolve ansync issue on MiddlewareMixin --- geonode/security/middleware.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/geonode/security/middleware.py b/geonode/security/middleware.py index ada570947d3..3aa172ae9a7 100644 --- a/geonode/security/middleware.py +++ b/geonode/security/middleware.py @@ -84,16 +84,9 @@ class LoginRequiredMiddleware(MiddlewareMixin): redirect_to = login_url def __init__(self, get_response): + super().__init__(get_response=get_response) self.get_response = get_response - def __call__(self, request): - # call method is added for test request calls that throws async_mode error called from newer tests - response = self.process_request(request) - if response: - return response - response = self.get_response(request) - return response - def process_request(self, request): if request.user and (not request.user.is_authenticated or request.user.is_anonymous): if not any(path.match(request.path) for path in white_list): From 226f788c25c1cbadda16ba3b83f23837e5e5999e Mon Sep 17 00:00:00 2001 From: sijandh35 Date: Fri, 18 Jul 2025 19:50:11 +0545 Subject: [PATCH 25/26] Fixes #13122: add super call to resolve ansync issue on MiddlewareMixin --- geonode/security/middleware.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/geonode/security/middleware.py b/geonode/security/middleware.py index 3aa172ae9a7..38a1296dfc9 100644 --- a/geonode/security/middleware.py +++ b/geonode/security/middleware.py @@ -84,7 +84,8 @@ class LoginRequiredMiddleware(MiddlewareMixin): redirect_to = login_url def __init__(self, get_response): - super().__init__(get_response=get_response) + if get_response: + super().__init__(get_response) self.get_response = get_response def process_request(self, request): From 80fb10ebc728f3a299dff2eb20a46811b90c0c7b Mon Sep 17 00:00:00 2001 From: Mattia Date: Mon, 21 Jul 2025 12:35:02 +0200 Subject: [PATCH 26/26] [Fixes #13122] Fix unwanted changes --- .devcontainer/.env | 70 ++++++++++-------------- .devcontainer/devcontainer.json | 47 ++++++++--------- .devcontainer/docker-compose.yml | 91 +++++++++++++++++++++++++++----- .env_dev | 8 +-- 4 files changed, 131 insertions(+), 85 deletions(-) diff --git a/.devcontainer/.env b/.devcontainer/.env index 6cc1be3fe8c..a3c8523037a 100644 --- a/.devcontainer/.env +++ b/.devcontainer/.env @@ -1,6 +1,5 @@ COMPOSE_PROJECT_NAME=geonode -# See https://github.com/containers/podman/issues/13889 -# DOCKER_BUILDKIT=0 +DOCKER_HOST_IP= DOCKER_ENV=production # See https://github.com/geosolutions-it/geonode-generic/issues/28 # to see why we force API version to 1.24 @@ -11,11 +10,13 @@ C_FORCE_ROOT=1 FORCE_REINIT=false INVOKE_LOG_STDOUT=true -# LANGUAGE_CODE=it-it -# LANGUAGES=(('en-us','English'),('it-it','Italiano')) +# LANGUAGE_CODE=pt +# LANGUAGES=(('en','English'),('pt','Portuguese')) DJANGO_SETTINGS_MODULE=geonode.settings GEONODE_INSTANCE_NAME=geonode +GEONODE_LB_HOST_IP= +GEONODE_LB_PORT= # ################# # backend @@ -23,17 +24,15 @@ GEONODE_INSTANCE_NAME=geonode POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres GEONODE_DATABASE=geonode -GEONODE_DATABASE_USER=geonode GEONODE_DATABASE_PASSWORD=geonode GEONODE_GEODATABASE=geonode_data -GEONODE_GEODATABASE_USER=geonode -GEONODE_GEODATABASE_PASSWORD=geonode +GEONODE_GEODATABASE_PASSWORD=geonode_data GEONODE_DATABASE_SCHEMA=public GEONODE_GEODATABASE_SCHEMA=public -DATABASE_HOST=localhost +DATABASE_HOST=db DATABASE_PORT=5432 DATABASE_URL=postgis://geonode:geonode@db:5432/geonode -GEODATABASE_URL=postgis://geonode:geonode@db:5432/geonode_data +GEODATABASE_URL=postgis://geonode_data:geonode_data@db:5432/geonode_data GEONODE_DB_CONN_MAX_AGE=0 GEONODE_DB_CONN_TOUT=5 DEFAULT_BACKEND_DATASTORE=datastore @@ -49,16 +48,17 @@ ALLOWED_HOSTS="['django', '*']" DEFAULT_BACKEND_UPLOADER=geonode.importer TIME_ENABLED=True MOSAIC_ENABLED=False +HAYSTACK_SEARCH=False +HAYSTACK_ENGINE_URL=http://elasticsearch:9200/ +HAYSTACK_ENGINE_INDEX_NAME=haystack +HAYSTACK_SEARCH_RESULTS_PER_PAGE=200 # ################# # nginx # HTTPD Server # ################# -GEONODE_LB_HOST_IP=django -GEONODE_LB_PORT=8000 -GEOSERVER_LB_HOST_IP=geoserver -GEOSERVER_LB_PORT=8080 -NGINX_BASE_URL=http://localhost +GEONODE_LB_HOST_IP=localhost +GEONODE_LB_PORT=80 # IP or domain name and port where the server can be reached on HTTPS (leave HOST empty if you want to use HTTP only) # port where the server can be reached on HTTPS @@ -126,17 +126,12 @@ DEFAULT_FROM_EMAIL='GeoNode ' # Session/Access Control LOCKDOWN_GEONODE=False +CORS_ALLOW_ALL_ORIGINS=True X_FRAME_OPTIONS="SAMEORIGIN" SESSION_EXPIRED_CONTROL_ENABLED=True DEFAULT_ANONYMOUS_VIEW_PERMISSION=True DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION=True -CORS_ALLOW_ALL_ORIGINS=True -GEOSERVER_CORS_ENABLED=True -GEOSERVER_CORS_ALLOWED_ORIGINS=* -GEOSERVER_CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE,HEAD,OPTIONS -GEOSERVER_CORS_ALLOWED_HEADERS=* - # Users Registration ACCOUNT_OPEN_SIGNUP=True ACCOUNT_EMAIL_REQUIRED=True @@ -145,7 +140,6 @@ ACCOUNT_CONFIRM_EMAIL_ON_GET=False ACCOUNT_EMAIL_VERIFICATION=none ACCOUNT_AUTHENTICATION_METHOD=username_email AUTO_ASSIGN_REGISTERED_MEMBERS_TO_REGISTERED_MEMBERS_GROUP_NAME=True -AUTO_ASSIGN_REGISTERED_MEMBERS_TO_CONTRIBUTORS=True # OAuth2 OAUTH2_API_KEY= @@ -161,9 +155,13 @@ TASTYPIE_APIKEY= # Monitoring # ################# DEBUG=True +DEBUG_STATIC=True SECRET_KEY='myv-y4#7j-d*p-__@j#*3z@!y24fz8%^z2v6atuy4bo9vqr1_a' +# STATIC_ROOT=/mnt/volumes/statics/static/ +# MEDIA_ROOT=/mnt/volumes/statics/uploaded/ +# GEOIP_PATH=/mnt/volumes/statics/geoip.db CACHE_BUSTING_STATIC_ENABLED=False @@ -172,12 +170,8 @@ MEMCACHED_BACKEND=django.core.cache.backends.memcached.PyLibMCCache MEMCACHED_LOCATION=127.0.0.1:11211 MEMCACHED_LOCK_EXPIRE=3600 MEMCACHED_LOCK_TIMEOUT=10 -# -# Options for memcached binary, e.g. -vvv to log all requests and cache hits -# -MEMCACHED_OPTIONS= -MAX_DOCUMENT_SIZE=200 +MAX_DOCUMENT_SIZE=2 CLIENT_RESULTS_LIMIT=5 API_LIMIT_PER_PAGE=1000 @@ -187,24 +181,18 @@ MAPBOX_ACCESS_TOKEN= BING_API_KEY= GOOGLE_API_KEY= +# Monitoring +MONITORING_ENABLED=False +MONITORING_DATA_TTL=365 +USER_ANALYTICS_ENABLED=True +USER_ANALYTICS_GZIP=True +CENTRALIZED_DASHBOARD_ENABLED=False +MONITORING_SERVICE_NAME=local-geonode +MONITORING_HOST_NAME=geonode + # Other Options/Contribs MODIFY_TOPICCATEGORY=True AVATAR_GRAVATAR_SSL=True EXIF_ENABLED=True CREATE_LAYER=True FAVORITE_ENABLED=True - -# Advanced Workflow -RESOURCE_PUBLISHING=False -ADMIN_MODERATE_UPLOADS=False - -# PostgreSQL -POSTGRESQL_MAX_CONNECTIONS=200 - -# Common containers restart policy -RESTART_POLICY_CONDITION="on-failure" -RESTART_POLICY_DELAY="5s" -RESTART_POLICY_MAX_ATTEMPTS="3" -RESTART_POLICY_WINDOW=120s - -DEFAULT_MAX_PARALLEL_UPLOADS_PER_USER=5 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index dd6975c8401..aedbf448d49 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,4 +1,3 @@ - // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: // https://github.com/microsoft/vscode-dev-containers/tree/v0.194.0/containers/docker-existing-docker-compose // If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml. @@ -18,33 +17,29 @@ // The optional 'workspaceFolder' property is the path VS Code should open by default when // connected. This is typically a file mount in .devcontainer/docker-compose.yml - "workspaceFolder": "/usr/src", + "workspaceFolder": "/usr/src/geonode/", // Set *default* container specific settings.json values on container create. - "customizations": { - "vscode": { - "settings": { - "terminal.integrated.profiles.linux": { - "/bin/bash": { - "path": "/bin/bash", - "args": [ - "-l" - ] - } - }, - "terminal.integrated.defaultProfile.linux": "bash" - }, - - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "ms-python.python", - "batisteo.vscode-django", - "mrorz.language-gettext", - "eamodio.gitlens", // Note: User preference - "bigonesystems.django" // Note: User preference - ] - } - }, + "settings": { + "terminal.integrated.profiles.linux": { + "/bin/bash": { + "path": "/bin/bash", + "args": [ + "-l" + ] + } + }, + "terminal.integrated.defaultProfile.linux": "/bin/bash" + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-python.python", + "batisteo.vscode-django", + "mrorz.language-gettext", + "eamodio.gitlens", // Note: User preference + "bigonesystems.django" // Note: User preference + ], // Use 'forwardPorts' to make a list of ports inside the container available locally. "forwardPorts": [ diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 87481986052..3a303d3b066 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -1,19 +1,82 @@ - +version: '3.4' services: - + # Update this to the name of the service you want to work with in your docker-compose.yml file django: + # If you want add a non-root user to your Dockerfile, you can use the "remoteUser" + # property in devcontainer.json to cause VS Code its sub-processes (terminals, tasks, + # debugging) to execute as the user. Uncomment the next line if you want the entire + # container to run as this user instead. Note that, on Linux, you may need to + # ensure the UID and GID of the container user you create matches your local user. + # See https://aka.ms/vscode-remote/containers/non-root for details. + # + # user: vscode + + # Uncomment if you want to override the service's Dockerfile to one in the .devcontainer + # folder. Note that the path of the Dockerfile and context is relative to the *primary* + # docker-compose.yml file (the first in the devcontainer.json "dockerComposeFile" + # array). The sample below assumes your primary file is in the root of your project. + + # build: + # context: . + # dockerfile: .devcontainer/Dockerfile + + restart: "no" + + healthcheck: + test: "echo \"I'm alive.\"" + + env_file: + - .devcontainer/.env + + volumes: + # Update this to wherever you want VS Code to mount the folder of your project + - '.:/usr/src/geonode' + # Uncomment the next line to use Docker from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker-compose for details. + # - /var/run/docker.sock:/var/run/docker.sock + ports: - "8000:8000" - volumes: - - './src:/usr/src/${COMPOSE_PROJECT_NAME}' - - './geonode-mapstore-client:/usr/src/geonode-mapstore-client' - - './.devcontainer/.vscode:/usr/src/.vscode' - - statics:/mnt/volumes/statics - - geoserver-data-dir:/geoserver_data/data - - backup-restore:/backup_restore - - data:/data - - tmp:/tmp - healthcheck: - test: "echo 'Alive'" - entrypoint: ["/usr/src/${COMPOSE_PROJECT_NAME}/entrypoint.sh"] + - "5678:5678" + + entrypoint: ["/usr/src/geonode/entrypoint.sh"] + + # Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust. + # cap_add: + # - SYS_PTRACE + # security_opt: + # - seccomp:unconfined + + # Overrides default command so things don't shut down after the process ends. command: sleep infinity + + celery: + restart: "no" + env_file: + - .devcontainer/.env + + volumes: + - '.:/usr/src/geonode' + + geonode: + restart: "no" + + # Removes letsencrypt when developing + letsencrypt: + deploy: + replicas: 0 + + geoserver: + restart: "no" + ports: + - "8080:8080" + + data-dir-conf: + restart: "no" + + db: + restart: "no" + ports: + - "5432:5432" + + rabbitmq: + restart: "no" diff --git a/.env_dev b/.env_dev index e12de6a4f30..aae9c72f7cc 100644 --- a/.env_dev +++ b/.env_dev @@ -22,18 +22,18 @@ GEONODE_INSTANCE_NAME=geonode # ################# POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres -GEONODE_DATABASE=gn +GEONODE_DATABASE=geonode GEONODE_DATABASE_USER=geonode GEONODE_DATABASE_PASSWORD=geonode -GEONODE_GEODATABASE=gn5_data +GEONODE_GEODATABASE=geonode_data GEONODE_GEODATABASE_USER=geonode GEONODE_GEODATABASE_PASSWORD=geonode GEONODE_DATABASE_SCHEMA=public GEONODE_GEODATABASE_SCHEMA=public DATABASE_HOST=localhost DATABASE_PORT=5432 -DATABASE_URL=postgis://geonode:geonode@localhost:5432/gn5 -GEODATABASE_URL=postgis://geonode:geonode@localhost:5432/gn5_data +DATABASE_URL=postgis://geonode:geonode@localhost:5432/geonode +GEODATABASE_URL=postgis://geonode:geonode@localhost:5432/geonode_data GEONODE_DB_CONN_MAX_AGE=0 GEONODE_DB_CONN_TOUT=5 DEFAULT_BACKEND_DATASTORE=datastore