From 75d8fda8f9f9555d2a9a77026f1977189111e05a Mon Sep 17 00:00:00 2001 From: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Date: Wed, 25 Oct 2023 10:55:07 +0200 Subject: [PATCH 01/47] Fixes #11578: align geoapp metadata update to other resources (#11624) * Fixes #11578: align geoapp metadata update to other resources * Fixes #11578: align geoapp metadata update to other resources * Fixes #11578: align geoapp metadata update to other resources * Fixes #11578: fix broken tests * fix black format --- geonode/geoapps/views.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/geonode/geoapps/views.py b/geonode/geoapps/views.py index 6a2dd3b3344..f83457ae67e 100644 --- a/geonode/geoapps/views.py +++ b/geonode/geoapps/views.py @@ -280,11 +280,11 @@ def geoapp_metadata( new_category = TopicCategory.objects.get(id=int(category_form.cleaned_data["category_choice_field"])) geoapp_form.cleaned_data.pop("ptype") + geoapp_obj = geoapp_form.instance # update contact roles geoapp_obj.set_contact_roles_from_metadata_edit(geoapp_form) - geoapp_obj.save() - additional_vals = dict(category=new_category) + vals = dict(category=new_category) geoapp_form.cleaned_data.pop("metadata") extra_metadata = geoapp_form.cleaned_data.pop("extra_metadata") @@ -292,21 +292,7 @@ def geoapp_metadata( geoapp_form.save_linked_resources() geoapp_form.cleaned_data.pop("linked_resources") - geoapp_obj = geoapp_form.instance - - _vals = dict(**geoapp_form.cleaned_data, **additional_vals) - _vals.update({"resource_type": resource_type, "sourcetype": SOURCE_TYPE_LOCAL}) - - resource_manager.update( - geoapp_obj.uuid, - instance=geoapp_obj, - keywords=new_keywords, - regions=new_regions, - vals=_vals, - notify=True, - extra_metadata=json.loads(extra_metadata), - ) - resource_manager.set_thumbnail(geoapp_obj.uuid, instance=geoapp_obj, overwrite=False) + vals.update({"resource_type": resource_type, "sourcetype": SOURCE_TYPE_LOCAL}) register_event(request, EventType.EVENT_CHANGE_METADATA, geoapp_obj) if not ajax: @@ -333,13 +319,27 @@ def geoapp_metadata( tb = traceback.format_exc() logger.error(tb) - vals = {} if "group" in geoapp_form.changed_data: vals["group"] = geoapp_form.cleaned_data.get("group") if any([x in geoapp_form.changed_data for x in ["is_approved", "is_published"]]): vals["is_approved"] = geoapp_form.cleaned_data.get("is_approved", geoapp_obj.is_approved) vals["is_published"] = geoapp_form.cleaned_data.get("is_published", geoapp_obj.is_published) - resource_manager.update(geoapp_obj.uuid, instance=geoapp_obj, notify=True, vals=vals) + else: + vals.pop("is_approved", None) + vals.pop("is_published", None) + + resource_manager.update( + geoapp_obj.uuid, + instance=geoapp_obj, + keywords=new_keywords, + regions=new_regions, + notify=True, + vals=vals, + extra_metadata=json.loads(extra_metadata), + ) + + resource_manager.set_thumbnail(geoapp_obj.uuid, instance=geoapp_obj, overwrite=False) + return HttpResponse(json.dumps({"message": message})) elif request.method == "POST" and ( not geoapp_form.is_valid() or not category_form.is_valid() or not tkeywords_form.is_valid() From ec457bcd4b04247a4639857d829be91c2b99e6b6 Mon Sep 17 00:00:00 2001 From: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Date: Thu, 26 Oct 2023 16:44:33 +0200 Subject: [PATCH 02/47] Add missing init for facets module (#11638) --- geonode/facets/providers/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 geonode/facets/providers/__init__.py diff --git a/geonode/facets/providers/__init__.py b/geonode/facets/providers/__init__.py new file mode 100644 index 00000000000..e69de29bb2d From 6a8a202565759ec3a07401271ac5cafb37854cf8 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Mon, 30 Oct 2023 10:05:08 +0100 Subject: [PATCH 03/47] thesaurus topics should only return its own keys (#11644) --- geonode/facets/providers/thesaurus.py | 2 +- geonode/facets/tests.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/geonode/facets/providers/thesaurus.py b/geonode/facets/providers/thesaurus.py index 047ac9b82ea..cec04f7ad16 100644 --- a/geonode/facets/providers/thesaurus.py +++ b/geonode/facets/providers/thesaurus.py @@ -111,7 +111,7 @@ def get_facet_items( def get_topics(self, keys: list, lang="en", **kwargs) -> list: q = ( - ThesaurusKeyword.objects.filter(id__in=keys) + ThesaurusKeyword.objects.filter(id__in=keys, thesaurus__identifier=self.name) .values("id", "alt_label") .annotate( localized_label=Subquery( diff --git a/geonode/facets/tests.py b/geonode/facets/tests.py index 8b4812a110f..22a9e18e929 100644 --- a/geonode/facets/tests.py +++ b/geonode/facets/tests.py @@ -498,6 +498,7 @@ def t(tk): {regfilter: "R0", t0filter: t("0_1"), "key": [t("1_1"), t("1_0")]}, {t("1_0"): None, t("1_1"): None}, ), + ("t_1", {"key": [t("0_1")]}, {}), # regions (regname, {t1filter: t("1_1")}, {"R1": 1}), (regname, {t1filter: t("1_1"), "key": ["R0", "R1"]}, {"R1": 1, "R0": None}), From c937f5e42ead119bdfcd709a4ea23d3db37f5e7b Mon Sep 17 00:00:00 2001 From: Emanuele Tajariol Date: Mon, 6 Nov 2023 10:21:09 +0100 Subject: [PATCH 04/47] [Fixes #11652] Facets: wrong count on multiple tkeywords filtering (#11655) * [Fixes #11652] Facets: wrong count on multiple tkeywords filtering - tkeywords * [Fixes #11652] Facets: wrong count on multiple tkeywords filtering - category * [Fixes #11652] Facets: wrong count on multiple tkeywords filtering - region * [Fixes #11652] Facets: wrong count on multiple tkeywords filtering - keywords --- geonode/facets/providers/category.py | 24 ++--- geonode/facets/providers/keyword.py | 16 ++-- geonode/facets/providers/region.py | 18 ++-- geonode/facets/providers/thesaurus.py | 28 +++--- geonode/facets/tests.py | 124 ++++++++++++++++---------- 5 files changed, 120 insertions(+), 90 deletions(-) diff --git a/geonode/facets/providers/category.py b/geonode/facets/providers/category.py index 6b7dc331768..488d5ab2e41 100644 --- a/geonode/facets/providers/category.py +++ b/geonode/facets/providers/category.py @@ -39,14 +39,14 @@ def name(self) -> str: def get_info(self, lang="en", **kwargs) -> dict: return { "name": self.name, - "filter": "filter{category.identifier}", + "filter": "filter{category.identifier.in}", "label": "Category", "type": FACET_TYPE_CATEGORY, } def get_facet_items( self, - queryset=None, + queryset, start: int = 0, end: int = DEFAULT_FACET_PAGE_SIZE, lang="en", @@ -56,22 +56,26 @@ def get_facet_items( ) -> (int, list): logger.debug("Retrieving facets for %s", self.name) - filters = {"category__isnull": False} + filters = {"resourcebase__in": queryset} if topic_contains: - filters["category__gn_description"] = topic_contains + filters["gn_description__icontains"] = topic_contains if keys: logger.debug("Filtering by keys %r", keys) - filters["category__identifier__in"] = keys + filters["identifier__in"] = keys q = ( - queryset.values("category__identifier", "category__gn_description", "category__fa_class") + TopicCategory.objects.values("identifier", "gn_description", "fa_class") .filter(**filters) - .annotate(count=Count("owner")) + .annotate(count=Count("resourcebase")) .order_by("-count") ) + logger.debug(" PREFILTERED QUERY ---> %s\n\n", queryset.query) + logger.debug(" ADDITIONAL FILTERS ---> %s\n\n", filters) + logger.debug(" FINAL QUERY ---> %s\n\n", q.query) + cnt = q.count() logger.info("Found %d facets for %s", cnt, self.name) @@ -80,10 +84,10 @@ def get_facet_items( topics = [ { - "key": r["category__identifier"], - "label": r["category__gn_description"], + "key": r["identifier"], + "label": r["gn_description"], "count": r["count"], - "fa_class": r["category__fa_class"], + "fa_class": r["fa_class"], } for r in q[start:end].all() ] diff --git a/geonode/facets/providers/keyword.py b/geonode/facets/providers/keyword.py index 41c4a470cfa..476031f9e31 100644 --- a/geonode/facets/providers/keyword.py +++ b/geonode/facets/providers/keyword.py @@ -56,18 +56,18 @@ def get_facet_items( ) -> (int, list): logger.debug("Retrieving facets for %s", self.name) - filters = {"keywords__isnull": False} + filters = {"resourcebase__in": queryset} if topic_contains: - filters["keywords__name__icontains"] = topic_contains + filters["name__icontains"] = topic_contains if keys: logger.debug("Filtering by keys %r", keys) - filters["keywords__slug__in"] = keys + filters["slug__in"] = keys q = ( - queryset.filter(**filters) - .values("keywords__slug", "keywords__name") - .annotate(count=Count("keywords__slug")) + HierarchicalKeyword.objects.filter(**filters) + .values("slug", "name") + .annotate(count=Count("resourcebase")) .order_by("-count") ) @@ -79,8 +79,8 @@ def get_facet_items( topics = [ { - "key": r["keywords__slug"], - "label": r["keywords__name"], + "key": r["slug"], + "label": r["name"], "count": r["count"], } for r in q[start:end].all() diff --git a/geonode/facets/providers/region.py b/geonode/facets/providers/region.py index bd912ab8693..73a7e578d37 100644 --- a/geonode/facets/providers/region.py +++ b/geonode/facets/providers/region.py @@ -46,7 +46,7 @@ def get_info(self, lang="en", **kwargs) -> dict: def get_facet_items( self, - queryset=None, + queryset, start: int = 0, end: int = DEFAULT_FACET_PAGE_SIZE, lang="en", @@ -56,19 +56,19 @@ def get_facet_items( ) -> (int, list): logger.debug("Retrieving facets for %s", self.name) - filters = {"regions__isnull": False} + filters = {"resourcebase__in": queryset} if topic_contains: - filters["regions__name"] = topic_contains + filters["name__icontains"] = topic_contains if keys: logger.debug("Filtering by keys %r", keys) - filters["regions__code__in"] = keys + filters["code__in"] = keys q = ( - queryset.filter(**filters) - .values("regions__code", "regions__name") - .annotate(count=Count("regions__code")) + Region.objects.filter(**filters) + .values("code", "name") + .annotate(count=Count("resourcebase")) .order_by("-count") ) @@ -80,8 +80,8 @@ def get_facet_items( topics = [ { - "key": r["regions__code"], - "label": r["regions__name"], + "key": r["code"], + "label": r["name"], "count": r["count"], } for r in q[start:end].all() diff --git a/geonode/facets/providers/thesaurus.py b/geonode/facets/providers/thesaurus.py index cec04f7ad16..92621340394 100644 --- a/geonode/facets/providers/thesaurus.py +++ b/geonode/facets/providers/thesaurus.py @@ -56,7 +56,7 @@ def get_info(self, lang="en", **kwargs) -> dict: def get_facet_items( self, - queryset=None, + queryset, start: int = 0, end: int = DEFAULT_FACET_PAGE_SIZE, lang="en", @@ -66,30 +66,30 @@ def get_facet_items( ) -> (int, list): logger.debug("Retrieving facets for %s", self._name) - filter = { - "tkeywords__thesaurus__identifier": self._name, - } + filter = {"thesaurus__identifier": self._name, "resourcebase__in": queryset} if topic_contains: - filter["tkeywords__keyword__label__icontains"] = topic_contains + filter["label__icontains"] = topic_contains if keys: logger.debug("Filtering by keys %r\n", keys) - filter["tkeywords__in"] = keys + filter["id__in"] = keys q = ( - queryset.filter(**filter) - .values("tkeywords", "tkeywords__alt_label", "tkeywords__image") - .annotate(count=Count("tkeywords")) + ThesaurusKeyword.objects.filter(**filter) + .values("id", "alt_label", "image") + .annotate(count=Count("resourcebase")) .annotate( localized_label=Subquery( - ThesaurusKeywordLabel.objects.filter(keyword=OuterRef("tkeywords"), lang=lang).values("label") + ThesaurusKeywordLabel.objects.filter(keyword=OuterRef("id"), lang=lang).values("label") ) ) .order_by("-count") ) - logger.debug(" ---> %s\n\n", q.query) + logger.debug(" PREFILTERED QUERY ---> %s\n\n", queryset.query) + logger.debug(" ADDITIONAL FILTERS ---> %s\n\n", filter) + logger.debug(" FINAL QUERY ---> %s\n\n", q.query) cnt = q.count() @@ -98,11 +98,11 @@ def get_facet_items( topics = [ { - "key": r["tkeywords"], - "label": r["localized_label"] or r["tkeywords__alt_label"], + "key": r["id"], + "label": r["localized_label"] or r["alt_label"], "is_localized": r["localized_label"] is not None, "count": r["count"], - "image": r["tkeywords__image"], + "image": r["image"], } for r in q[start:end].all() ] diff --git a/geonode/facets/tests.py b/geonode/facets/tests.py index 22a9e18e929..c227b152e35 100644 --- a/geonode/facets/tests.py +++ b/geonode/facets/tests.py @@ -119,6 +119,7 @@ def _create_categories(cls): ("C0", "Cat0"), ("C1", "Cat1"), ("C2", "Cat2"), + ("C3", "Cat3"), ): cls.cats[code] = TopicCategory.objects.create(identifier=code, description=name, gn_description=name) @@ -130,6 +131,7 @@ def _create_keywords(cls): ("K0", "Keyword0"), ("K1", "Keyword1"), ("K2", "Keyword2"), + ("K3", "Keyword3"), ): cls.kw[code] = HierarchicalKeyword.objects.create(slug=code, name=name) @@ -150,26 +152,26 @@ def _create_resources(self): # These are the assigned keywords to the Resources - # RB00 -> T1K0 R0,R1 FEAT K0 C0 - # RB01 -> T0K0 T1K0 R0 FEAT K1 - # RB02 -> T1K0 R1 FEAT K2 C0 - # RB03 -> T0K0 T1K0 K0 - # RB04 -> T1K0 K0,K1 C0 - # RB05 -> T0K0 T1K0 K0,K2 C1 - # RB06 -> T1K0 FEAT - # RB07 -> T0K0 T1K0 FEAT - # RB08 -> T1K0 T1K1 R1 FEAT - # RB09 -> T0K0 T1K0 T1K1 - # RB10 -> T1K1 - # RB11 -> T0K0 T0K1 T1K1 - # RB12 -> T1K1 FEAT - # RB13 -> T0K0 T0K1 R1 FEAT - # RB14 -> FEAT - # RB15 -> T0K0 T0K1 C1 - # RB16 -> C1 - # RB17 -> T0K0 T0K1 - # RB18 -> FEAT C2 - # RB19 -> T0K0 T0K1 FEAT C2 + # RB00 -> T1K0 R0,R1 FEAT K0 C0 + # RB01 -> T0K0 T1K0 R0 FEAT K1 + # RB02 -> T1K0 R1 FEAT K2 C0 + # RB03 -> T0K0 T1K0 K0 + # RB04 -> T1K0 K0K1 C0 + # RB05 -> T0K0 T1K0 K0 K2 C1 + # RB06 -> T1K0 FEAT + # RB07 -> T0K0 T1K0 R2 FEAT K3 C3 + # RB08 -> T1K0 T1K1 R1,R2 FEAT K3 C3 + # RB09 -> T0K0 T1K0 T1K1 R2 K3 C3 + # RB10 -> T1K1 R2 K3 C3 + # RB11 -> T0K0 T0K1 T1K1 + # RB12 -> T1K1 FEAT + # RB13 -> T0K0 T0K1 R1 FEAT + # RB14 -> FEAT + # RB15 -> T0K0 T0K1 C1 + # RB16 -> C1 + # RB17 -> T0K0 T0K1 + # RB18 -> FEAT C2 + # RB19 -> T0K0 T0K1 FEAT C2 if x % 2 == 1: logger.debug(f"ADDING KEYWORDS {self.thesauri_k['0_0']} to RB {d}") @@ -189,6 +191,7 @@ def _create_resources(self): for reg, idx in ( # fmt: skip ("R0", (0, 1)), ("R1", (0, 2, 8, 13)), + ("R2", (7, 8, 9, 10)), ): if x in idx: d.regions.add(self.regions[reg]) @@ -197,6 +200,7 @@ def _create_resources(self): ("K0", (0, 3, 4, 5)), ("K1", [1, 4]), ("K2", [2, 5]), + ("K3", [7, 8, 9, 10]), ): if x in idx: d.keywords.add(self.kw[kw]) @@ -205,6 +209,7 @@ def _create_resources(self): ("C0", [0, 2, 4]), ("C1", [5, 15, 16]), ("C2", [18, 19]), + ("C3", [7, 8, 9, 10]), ): if x in idx: d.category = self.cats[cat] @@ -248,10 +253,11 @@ def test_facets_rich(self): { "name": "category", "topics": { - "total": 3, + "total": 4, "items": [ {"label": "Cat0", "count": 3}, {"label": "Cat1", "count": 3}, + {"label": "Cat3", "count": 4}, {"label": "Cat2", "count": 2}, ], }, @@ -259,11 +265,12 @@ def test_facets_rich(self): { "name": "keyword", "topics": { - "total": 3, + "total": 4, "items": [ {"label": "Keyword0", "count": 4}, {"label": "Keyword1", "count": 2}, {"label": "Keyword2", "count": 2}, + {"label": "Keyword3", "count": 4}, ], }, }, @@ -295,10 +302,11 @@ def test_facets_rich(self): { "name": "region", "topics": { - "total": 2, + "total": 3, "items": [ {"label": "Region0", "key": "R0", "count": 2}, {"label": "Region1", "key": "R1", "count": 4}, + {"label": "Region2", "key": "R2", "count": 4}, ], }, }, @@ -386,15 +394,21 @@ def test_prefiltering(self): ("t_1", {}, 2, 10), ("t_1", {regfilter: "R0"}, 1, 2), ("t_1", {regfilter: "R1"}, 2, 3), - (reginfo["name"], {}, 2, 4), - (reginfo["name"], {t0filter: self.thesauri_k["0_0"].id}, 2, 1), - (reginfo["name"], {t1filter: self.thesauri_k["1_0"].id}, 2, 3), + (reginfo["name"], {}, 3, 4), + (reginfo["name"], {t0filter: self.thesauri_k["0_0"].id}, 3, 2), + (reginfo["name"], {t1filter: self.thesauri_k["1_0"].id}, 3, 3), ): req = self.rf.get(reverse("get_facet", args=[facet]), data=filters) res: JsonResponse = GetFacetView.as_view()(req, facet) obj = json.loads(res.content) - self.assertEqual(totals, obj["topics"]["total"], f"Bad totals for facet '{facet} and filter {filters}") - self.assertEqual(count0, obj["topics"]["items"][0]["count"], f"Bad count0 for facet '{facet}") + self.assertEqual( + totals, + obj["topics"]["total"], + f"Bad totals for facet '{facet} and filter {filters}\nRESPONSE: {obj}", + ) + self.assertEqual( + count0, obj["topics"]["items"][0]["count"], f"Bad count0 for facet '{facet}\nRESPONSE: {obj}" + ) def test_prefiltering_tkeywords(self): regname = RegionFacetProvider().name @@ -402,7 +416,7 @@ def test_prefiltering_tkeywords(self): t1filter = facet_registry.get_provider("t_1").get_info()["filter"] tkey_1_1 = self.thesauri_k["1_1"].id - expected_region = {"R1": 1} + expected_region = {"R1": 1, "R2": 3} expected_feat = {True: 2, False: 3} # Run the single requests @@ -471,49 +485,61 @@ def test_config(self): def test_count0(self): reginfo = RegionFacetProvider().get_info() - regfilter = reginfo["filter"] + regflt = reginfo["filter"] regname = reginfo["name"] catinfo = CategoryFacetProvider().get_info() + catflt = catinfo["filter"] catname = catinfo["name"] kwinfo = KeywordFacetProvider().get_info() - kwfilter = kwinfo["filter"] + kwflt = kwinfo["filter"] kwname = kwinfo["name"] - t0filter = facet_registry.get_provider("t_0").get_info()["filter"] - t1filter = facet_registry.get_provider("t_1").get_info()["filter"] + t0flt = facet_registry.get_provider("t_0").get_info()["filter"] + t1flt = facet_registry.get_provider("t_1").get_info()["filter"] def t(tk): return self.thesauri_k[tk].id - for facet, params, items in ( + for facet, params, items in ( # fmt: skip # thesauri - ("t_1", {regfilter: "R0"}, {t("1_0"): 2}), - ("t_1", {regfilter: "R0", "key": [t("1_0")]}, {t("1_0"): 2}), - ("t_1", {regfilter: "R0", t0filter: t("0_1")}, {}), - ("t_1", {regfilter: "R0", t0filter: t("0_1"), "key": [t("1_0")]}, {t("1_0"): None}), + ("t_1", {regflt: "R0"}, {t("1_0"): 2}), + ("t_1", {regflt: "R0", "key": [t("1_0")]}, {t("1_0"): 2}), + ("t_1", {regflt: "R0", t0flt: t("0_1")}, {}), + ("t_1", {regflt: "R0", t0flt: t("0_1"), "key": [t("1_0")]}, {t("1_0"): None}), ( "t_1", - {regfilter: "R0", t0filter: t("0_1"), "key": [t("1_1"), t("1_0")]}, + {regflt: "R0", t0flt: t("0_1"), "key": [t("1_1"), t("1_0")]}, {t("1_0"): None, t("1_1"): None}, ), ("t_1", {"key": [t("0_1")]}, {}), + ("t_1", {t0flt: t("0_0")}, {t("1_0"): 5, t("1_1"): 2}), + ("t_1", {t0flt: t("0_1")}, {t("1_1"): 1}), + ("t_1", {t0flt: [t("0_1"), t("0_0")]}, {t("1_0"): 5, t("1_1"): 2}), + ("t_1", {catflt: ["C0"]}, {t("1_0"): 3}), + ("t_1", {catflt: ["C0", "C1"]}, {t("1_0"): 4}), # regions - (regname, {t1filter: t("1_1")}, {"R1": 1}), - (regname, {t1filter: t("1_1"), "key": ["R0", "R1"]}, {"R1": 1, "R0": None}), - (regname, {t1filter: t("1_1"), "key": ["R0"]}, {"R0": None}), + (regname, {t1flt: t("1_0")}, {"R0": 2, "R1": 3, "R2": 3}), + (regname, {t1flt: t("1_1")}, {"R1": 1, "R2": 3}), + (regname, {t1flt: [t("1_1"), t("1_0")]}, {"R0": 2, "R1": 3, "R2": 4}), + (regname, {t1flt: t("1_1"), "key": ["R0", "R1"]}, {"R1": 1, "R0": None}), + (regname, {t1flt: t("1_1"), "key": ["R0"]}, {"R0": None}), # category - (catname, {t1filter: t("1_0")}, {"C0": 3, "C1": 1}), - (catname, {t1filter: t("1_0"), "key": ["C0", "C2"]}, {"C0": 3, "C2": None}), - (catname, {kwfilter: "K1"}, {"C0": 1}), - (catname, {kwfilter: "K1", "key": ["C0", "C2"]}, {"C0": 1, "C2": None}), + (catname, {t1flt: t("1_0")}, {"C0": 3, "C1": 1, "C3": 3}), + (catname, {t1flt: t("1_0"), "key": ["C0", "C2"]}, {"C0": 3, "C2": None}), + (catname, {t1flt: [t("1_0"), t("1_1")]}, {"C0": 3, "C1": 1, "C3": 4}), + (catname, {kwflt: "K1"}, {"C0": 1}), + (catname, {kwflt: "K1", "key": ["C0", "C2"]}, {"C0": 1, "C2": None}), # keyword - (kwname, {t0filter: t("0_0")}, {"K0": 2, "K1": 1, "K2": 1}), - (kwname, {t0filter: t("0_0"), regfilter: "R0"}, {"K1": 1}), - (kwname, {t0filter: t("0_0"), regfilter: "R0", "key": ["K0"]}, {"K0": None}), + (kwname, {t0flt: t("0_0")}, {"K0": 2, "K1": 1, "K2": 1, "K3": 2}), + (kwname, {t0flt: t("1_0")}, {"K0": 4, "K1": 2, "K2": 2, "K3": 3}), + (kwname, {t0flt: [t("1_0"), t("1_1")]}, {"K0": 4, "K1": 2, "K2": 2, "K3": 4}), + (kwname, {t0flt: t("0_0"), regflt: "R0"}, {"K1": 1}), + (kwname, {t0flt: t("0_0"), regflt: "R0", "key": ["K0"]}, {"K0": None}), ): req = self.rf.get(reverse("get_facet", args=[facet]), data=params) + req.user = self.admin res: JsonResponse = GetFacetView.as_view()(req, facet) obj = json.loads(res.content) # self.assertEqual(totals, obj["topics"]["total"], f"Bad totals for facet '{facet} and params {params}") From 96d72df6fa3f216e9f40ed33472e82048db8b06a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Nov 2023 08:58:52 +0100 Subject: [PATCH 05/47] Bump black from 23.9.1 to 23.10.1 (#11648) * Bump black from 23.9.1 to 23.10.1 Bumps [black](https://github.com/psf/black) from 23.9.1 to 23.10.1. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.9.1...23.10.1) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 3d5dada6563..483c2f95d0f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -153,7 +153,7 @@ invoke==2.2.0 coverage==7.3.1 requests-toolbelt==1.0.0 flake8==6.1.0 -black==23.9.1 +black==23.10.1 pytest==7.4.2 pytest-bdd==6.1.1 splinter==0.19.0 diff --git a/setup.cfg b/setup.cfg index 42ff67cbaeb..05bcab54342 100644 --- a/setup.cfg +++ b/setup.cfg @@ -178,7 +178,7 @@ install_requires = coverage==7.3.1 requests-toolbelt==1.0.0 flake8==6.1.0 - black==23.9.1 + black==23.10.1 pytest==7.4.2 pytest-bdd==6.1.1 splinter==0.19.0 From cf73b3f8aa1af6505539cc703c4a2033ccd00cc2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Nov 2023 15:21:52 +0100 Subject: [PATCH 06/47] Bump django from 3.2.22 to 3.2.23 (#11654) * Bump django from 3.2.22 to 3.2.23 Bumps [django](https://github.com/django/django) from 3.2.22 to 3.2.23. - [Commits](https://github.com/django/django/compare/3.2.22...3.2.23) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 483c2f95d0f..ba3e83410f2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ Pillow==10.0.1 lxml==4.9.3 psycopg2==2.9.9 -Django==3.2.22 +Django==3.2.23 # Other amqp==5.1.1 diff --git a/setup.cfg b/setup.cfg index 05bcab54342..151e17e7890 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,7 +28,7 @@ install_requires = Pillow==10.0.1 lxml==4.9.3 psycopg2==2.9.9 - Django==3.2.22 + Django==3.2.23 # Other amqp==5.1.1 From a7e3db3b92df28666f4146683e09be03ec48567d Mon Sep 17 00:00:00 2001 From: Alessio Fabiani Date: Thu, 9 Nov 2023 09:35:51 -0500 Subject: [PATCH 07/47] fix: requirements.txt to reduce vulnerabilities (#11656) The following vulnerabilities are fixed by pinning transitive dependencies: - https://snyk.io/vuln/SNYK-PYTHON-DJANGO-6041515 - https://snyk.io/vuln/SNYK-PYTHON-PILLOW-6043904 Co-authored-by: snyk-bot From e7b53a5c8c81a99104dd2aec5f0eab396c760c86 Mon Sep 17 00:00:00 2001 From: Emanuele Tajariol Date: Thu, 9 Nov 2023 18:22:33 +0100 Subject: [PATCH 08/47] [Fixes #11447, #11668] Various fixes in GeoFence permissions (#11669) * [Fixes #11447] Bad role name in creating GeoFence rules * [Fixes #11668] Bad ordering of GeoFence rules --------- Co-authored-by: Giovanni Allegri --- geonode/geoserver/geofence.py | 2 +- geonode/geoserver/manager.py | 14 ++++++++++++-- geonode/geoserver/security.py | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/geonode/geoserver/geofence.py b/geonode/geoserver/geofence.py index c31c6eb8c3c..9e7717569bd 100644 --- a/geonode/geoserver/geofence.py +++ b/geonode/geoserver/geofence.py @@ -83,7 +83,7 @@ def __init__( for field, value in ( ("priority", priority), ("userName", user), - ("roleName", group), + ("roleName", f"ROLE_{group.upper()}" if group is not None and group != "*" else group), ("service", service), ("request", request), ("subfield", subfield), diff --git a/geonode/geoserver/manager.py b/geonode/geoserver/manager.py index 18634e06f58..a88b641b71f 100644 --- a/geonode/geoserver/manager.py +++ b/geonode/geoserver/manager.py @@ -475,6 +475,8 @@ def set_permissions( create_geofence_rules(_resource, perms, _owner, None, batch) exist_geolimits = exist_geolimits or has_geolimits(_resource, _owner, None) + deferred_anon_perms = [] + # All the other users if "users" in permissions and len(permissions["users"]) > 0: for user, user_perms in permissions["users"].items(): @@ -482,7 +484,9 @@ def set_permissions( if _user != _owner: if user == "AnonymousUser": _user = None - create_geofence_rules(_resource, user_perms, _user, None, batch) + deferred_anon_perms.append(user_perms) + else: + create_geofence_rules(_resource, user_perms, _user, None, batch) exist_geolimits = exist_geolimits or has_geolimits(_resource, _user, None) # All the other groups @@ -491,8 +495,14 @@ def set_permissions( _group = Group.objects.get(name=group) if _group and _group.name and _group.name == "anonymous": _group = None - create_geofence_rules(_resource, perms, None, _group, batch) + deferred_anon_perms.append(perms) + else: + create_geofence_rules(_resource, perms, None, _group, batch) exist_geolimits = exist_geolimits or has_geolimits(_resource, None, _group) + + for perm in deferred_anon_perms: + create_geofence_rules(_resource, perm, None, None, batch) + else: # Owner & Managers perms = ( diff --git a/geonode/geoserver/security.py b/geonode/geoserver/security.py index 1d7fd2a8f1f..4cb244e67e3 100644 --- a/geonode/geoserver/security.py +++ b/geonode/geoserver/security.py @@ -284,8 +284,8 @@ def create_geofence_rules(layer, perms, user=None, group=None, batch: Batch = No # Anon limits should go at the end, but it's responsibility of the caller to create first user/group rules for limits, scope, u, g in ( (users_geolimits, "USER", username, None), - (anonymous_geolimits, "ANON", None, None), (groups_geolimits, "GROUP", None, groupname), + (anonymous_geolimits, "ANON", None, None), ): if limits and limits.exists(): logger.debug(f"Adding GeoFence {scope} GeoLimit rule: U:{u} G:{g} L:{layer} ") From e705eaffa1b2a9e85a1d69fb1d76328e6682719e Mon Sep 17 00:00:00 2001 From: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Date: Fri, 10 Nov 2023 18:12:39 +0100 Subject: [PATCH 09/47] Update default avatar image (#11676) * Update default avatar image * Change to default avatar * Reduce avatar dim --- geonode/static/geonode/img/avatar.png | Bin 162510 -> 2195 bytes 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 geonode/static/geonode/img/avatar.png diff --git a/geonode/static/geonode/img/avatar.png b/geonode/static/geonode/img/avatar.png old mode 100644 new mode 100755 index 6882d9784b4ba3979ccfcd9dfcea102375738f83..8a0797b13e31f76c2588feb9b8cab9102cc80d6a GIT binary patch literal 2195 zcmZ{lS5VW57RLY5t0BmxuOJ8*X-SAQ!A1gs08$dfKoCL`l#*-&DHh!Afw!JB0~QT0YU*#SVLCIH-t2Y@}Eb!QO(Za@KG*%JUvvj9LYl-1~H##;yx zF;+<6;8*?8RGiLpL_^V+e+K~ZBft6(ki(ManZgunJCyK(xR|K80HQMN1<&!YMxMvs z9ABGsV?4tBt9fJE)cI;crkaCI{<+E)kyz1wz#!wALlP`dz;w@(P6zXKT$NgqIhJId zoG40^SU<-gGQxxq9qmdvA}Bv85d?&IAET{79*~XMGBoH-_<|LJJn9`=U_n?^G8|+u zHf?&a+Pk;y5w-X(-y$JgufH$h`xfXKO1_tsf@M~!#-IuZZK4!ueoQHq? z5ZvAdwO(gwx-&q9?()PQQo$sc``jmG%OLe)+d6xAyC+j*m0)sC46Mb~eyMWHKpyO@um>2f(myad>ZYu2U`MyPhdWo;`=S2XN$j0&+d zTRNFq@}0UQJm^%Zx|2s2&)r~|OOxpIFUWR(N@3mue!D2_hQ49=2ea%(1A@N0R8Y^U zIDY33o`^n4T;G^PlGy5!3IZdg2i`ClKwq?x=0ayDx?!=-E~Sv43?g4tg@*++XZO$& z``t%D@3eShSo_F@RX5Iq$JR+TSv86QhszmPo!IcH(H)AP-qXJw^wfCA{*klTI;M7J zc>dC=5qMRFD;98DhFL~$j&!I}|4Lk)jzp!4!r!XC?L!xr*H^h#`O-pFS*qO9+OBN( z`%{q2-mFuyPha7KTs=b$?jU=7jSEs}nr%z2PUIxWJAR9T&t1k&hJN?x^C7Zm>R zrIF_N)Dz9zjccc3HJLa$dszm=fT1Lpb-tsY+yR;b3s2w86^ebACt1gY}(ffS&8~t)({J z?_oG6re^^*Dg`u)ZqM9?WE1O&+8)|N9&?;f+RSA!4VO0yS8g_7y#;BZJ+F(M{~Wi3 zIE#kIZ6#eu_l!Yk#*a!Vyse#h6OVmA?E8^^K?tL(rq4~SMQ1Czk*LQDmje|a^J{n^ zc5n4%l@^l3Ft6fH~pA7WNsM! zw6J$NNmSWm$lvF>ZPEmMYJhAVa=zy`wGf%3L6-ZdC{N3zF1h#>r{KVpC+6+WKjhK3 zk+K*I`E?Isoxe0EUa6cR~g02|OpNn!a{KW zCj6c)D84>pCkpp`oF!dXv^p1rKfOpF$kaM2Q!7v`wSUTaRH^IV!ViU3P>33*nt&To zZJd3iylAjB36giBCb2;{%;v0yp7iht;?hw&y=Z0pkX6U%JGS^2TfJtWp~m{&1f7HO z&?I}$>rjJRh7vNdhja)OpeG^Y1i~msi8~U`~M0MfevhU;PP12sQ$IogGlq|M92g`P6 zX_E~d)vf4dA7ul)U)Z}QCs>$W^s90iRnT5PSh{TDN@!30N*rkjTFmU%AfMjAyO@0H zg^kx(Fccc|%`d$)r7W)35-nfH%qA=4Pv)#Qn?T_n$?Dpnezd`(Bdj7=0*U)l>y>P;Fxs+!o9z z7UPpEEnM5NdeGf+12lQ}yhMqdvK?+dLy&pINM&J0ja8V_yKU*w(o|0vGB7fTNKKbD zwx7Js&I=Q?$5oD3y}91WU$5|2E5}xc?8MipD`CC^Kl8-K-~;n|n+oY^V4m_=db_!p z^2mzpZ1PTQHdU!aCKq=ApRpY3X`1-3lgYQT$>-0F)EQdl?5}BUNR>Okxfg6?yzN2M@}7awfjB+pQGeakfM~BwXM_+!1WU+C3C|Kbg-e_C%300fKW&?CUp}JxTa4s;@aX@@=9PmI+wx%v6`TkDv3JU#aCQ6|`k;eemD0^i21<%<30H2obT>t<8 literal 162510 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 H=)0uwsmxf55gWT;sc8G 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 From ee776ca3081fc7f6ec8362e93ccc3ad8e9e5f98b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 10:07:48 +0100 Subject: [PATCH 10/47] Bump vine from 5.0.0 to 5.1.0 (#11662) * Bump vine from 5.0.0 to 5.1.0 Bumps [vine](https://github.com/celery/vine) from 5.0.0 to 5.1.0. - [Release notes](https://github.com/celery/vine/releases) - [Changelog](https://github.com/celery/vine/blob/master/Changelog) - [Commits](https://github.com/celery/vine/compare/v5.0.0...v5.1.0) --- updated-dependencies: - dependency-name: vine dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * - Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index ba3e83410f2..89c2aff6b40 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,7 +16,7 @@ python-slugify==8.0.1 decorator==5.1.1 celery==5.3.4 kombu==5.3.2 -vine==5.0.0 +vine==5.1.0 tqdm==4.66.1 Deprecated==1.2.14 wrapt==1.15.0 diff --git a/setup.cfg b/setup.cfg index 151e17e7890..56a2d540c55 100644 --- a/setup.cfg +++ b/setup.cfg @@ -42,7 +42,7 @@ install_requires = decorator==5.1.1 celery==5.3.4 kombu==5.3.2 - vine==5.0.0 + vine==5.1.0 tqdm==4.66.1 Deprecated==1.2.14 wrapt==1.15.0 From 3439e272d482bc9876be1cb041ab27db6623aadd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 12:17:59 +0100 Subject: [PATCH 11/47] Bump celery from 5.3.4 to 5.3.5 (#11690) * Bump celery from 5.3.4 to 5.3.5 Bumps [celery](https://github.com/celery/celery) from 5.3.4 to 5.3.5. - [Release notes](https://github.com/celery/celery/releases) - [Changelog](https://github.com/celery/celery/blob/main/Changelog.rst) - [Commits](https://github.com/celery/celery/compare/v5.3.4...v5.3.5) --- updated-dependencies: - dependency-name: celery dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * - Align setup.cfg to requirements.txt * - Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani --- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 89c2aff6b40..89e8d16ce97 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,8 +14,8 @@ urllib3==1.26.18 Paver==1.3.4 python-slugify==8.0.1 decorator==5.1.1 -celery==5.3.4 -kombu==5.3.2 +celery==5.3.5 +kombu==5.3.3 vine==5.1.0 tqdm==4.66.1 Deprecated==1.2.14 diff --git a/setup.cfg b/setup.cfg index 56a2d540c55..f0a1e2ae11e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,8 +40,8 @@ install_requires = Paver==1.3.4 python-slugify==8.0.1 decorator==5.1.1 - celery==5.3.4 - kombu==5.3.2 + celery==5.3.5 + kombu==5.3.3 vine==5.1.0 tqdm==4.66.1 Deprecated==1.2.14 From bc45eafb98c629944be3e44fcb73cc71ef06d133 Mon Sep 17 00:00:00 2001 From: Alessio Fabiani Date: Mon, 13 Nov 2023 12:36:44 +0100 Subject: [PATCH 12/47] fix: scripts/docker/nginx/Dockerfile to reduce vulnerabilities (#11637) Co-authored-by: snyk-bot Co-authored-by: Giovanni Allegri --- scripts/docker/nginx/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docker/nginx/Dockerfile b/scripts/docker/nginx/Dockerfile index 5559b30fe74..9b0fe5b4f30 100644 --- a/scripts/docker/nginx/Dockerfile +++ b/scripts/docker/nginx/Dockerfile @@ -1,4 +1,4 @@ -FROM nginx:1.25.2-alpine +FROM nginx:1.25.3-alpine RUN apk add --no-cache openssl inotify-tools vim From 980e4d24ea5d9b2c9ca96413807a5bdf84ba986e Mon Sep 17 00:00:00 2001 From: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Date: Wed, 15 Nov 2023 17:01:45 +0100 Subject: [PATCH 13/47] =?UTF-8?q?[Fixes#11651]=20Implement=20the=20option?= =?UTF-8?q?=20to=20register=20users=20without=20automatic=20assignment=20o?= =?UTF-8?q?=E2=80=A6=20(#11695)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implement the option to register users without automatic assignment of contributor role #11651 * Fixes #11651: configuration rename * Fixes #11651: configuration rename --- .env.sample | 1 + .env_dev | 1 + .env_local | 1 + .env_test | 1 + geonode/people/signals.py | 9 ++++++--- geonode/people/tests.py | 16 ++++++++++++++++ geonode/settings.py | 4 ++++ 7 files changed, 30 insertions(+), 3 deletions(-) diff --git a/.env.sample b/.env.sample index 47ed2e0c24e..f43b64a7823 100644 --- a/.env.sample +++ b/.env.sample @@ -151,6 +151,7 @@ ACCOUNT_EMAIL_CONFIRMATION_EMAIL=False ACCOUNT_EMAIL_CONFIRMATION_REQUIRED=False 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= diff --git a/.env_dev b/.env_dev index 93b0c0e2f5c..029bd5c9de7 100644 --- a/.env_dev +++ b/.env_dev @@ -151,6 +151,7 @@ ACCOUNT_EMAIL_CONFIRMATION_EMAIL=False ACCOUNT_EMAIL_CONFIRMATION_REQUIRED=False 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= diff --git a/.env_local b/.env_local index 5083046741d..7fe89de6cae 100644 --- a/.env_local +++ b/.env_local @@ -151,6 +151,7 @@ ACCOUNT_EMAIL_CONFIRMATION_EMAIL=False ACCOUNT_EMAIL_CONFIRMATION_REQUIRED=False 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= diff --git a/.env_test b/.env_test index a5d6e909abd..b2fd6ebb6a0 100644 --- a/.env_test +++ b/.env_test @@ -157,6 +157,7 @@ ACCOUNT_EMAIL_CONFIRMATION_EMAIL=False ACCOUNT_EMAIL_CONFIRMATION_REQUIRED=False 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= diff --git a/geonode/people/signals.py b/geonode/people/signals.py index 1282a51ceda..9eaeaa47b0f 100644 --- a/geonode/people/signals.py +++ b/geonode/people/signals.py @@ -111,9 +111,12 @@ def profile_post_save(instance, sender, **kwargs): is_anonymous = instance.username == "AnonymousUser" if not is_anonymous: - if Group.objects.filter(name="contributors").count() and not (instance.is_staff or instance.is_superuser): - cont_group = Group.objects.get(name="contributors") - instance.groups.add(cont_group) + if settings.AUTO_ASSIGN_REGISTERED_MEMBERS_TO_CONTRIBUTORS: + if Group.objects.filter(name="contributors").count() and not ( + instance.is_staff or instance.is_superuser + ): + cont_group = Group.objects.get(name="contributors") + instance.groups.add(cont_group) if Group.objects.filter(name=groups_settings.REGISTERED_MEMBERS_GROUP_NAME).count(): registeredmembers_group = Group.objects.get(name=groups_settings.REGISTERED_MEMBERS_GROUP_NAME) instance.groups.add(registeredmembers_group) diff --git a/geonode/people/tests.py b/geonode/people/tests.py index 58cbe579c07..f3636c975c1 100644 --- a/geonode/people/tests.py +++ b/geonode/people/tests.py @@ -455,3 +455,19 @@ def test_password_validators(self): } form = SignupForm(data, email_required=True) self.assertTrue(form.is_valid()) + + def test_new_user_is_assigned_automatically_to_contributors(self): + """ + By default the contributors group is assigned to each new user + """ + new_user = get_user_model().objects.create(username="random_username") + self.assertTrue("contributors" in [x.name for x in new_user.groups.iterator()]) + + @override_settings(AUTO_ASSIGN_REGISTERED_MEMBERS_TO_CONTRIBUTORS=False) + def test_new_user_is_no_assigned_automatically_to_contributors_if_disabled(self): + """ + If AUTO_ASSIGN_REGISTERED_MEMBERS_TO_CONTRIBUTORS is false, each new user is not automatically + assinged to the contributors group + """ + new_user = get_user_model().objects.create(username="random_username") + self.assertFalse("contributors" in [x.name for x in new_user.groups.iterator()]) diff --git a/geonode/settings.py b/geonode/settings.py index db383d7e8b4..2224bce108f 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -2368,3 +2368,7 @@ def get_geonode_catalogue_service(): DEFAULT_DATASET_DOWNLOAD_HANDLER = "geonode.layers.download_handler.DatasetDownloadHandler" DATASET_DOWNLOAD_HANDLERS = ast.literal_eval(os.getenv("DATASET_DOWNLOAD_HANDLERS", "[]")) + +AUTO_ASSIGN_REGISTERED_MEMBERS_TO_CONTRIBUTORS = ast.literal_eval( + os.getenv("AUTO_ASSIGN_REGISTERED_MEMBERS_TO_CONTRIBUTORS", "True") +) From 5eba04acd43c783178c1e4ec4f834b0163b318a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Nov 2023 09:11:06 +0100 Subject: [PATCH 14/47] Bump owslib from 0.29.2 to 0.29.3 (#11686) * Bump owslib from 0.29.2 to 0.29.3 Bumps [owslib](https://github.com/geopython/OWSLib) from 0.29.2 to 0.29.3. - [Release notes](https://github.com/geopython/OWSLib/releases) - [Commits](https://github.com/geopython/OWSLib/compare/0.29.2...0.29.3) --- updated-dependencies: - dependency-name: owslib dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * - Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani Co-authored-by: Giovanni Allegri --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 89e8d16ce97..6d014b23a82 100644 --- a/requirements.txt +++ b/requirements.txt @@ -54,7 +54,7 @@ pyjwt==2.8.0 # geopython dependencies pyproj<3.7.0 -OWSLib==0.29.2 +OWSLib==0.29.3 pycsw==2.6.1 SQLAlchemy==2.0.21 # required by PyCSW Shapely==1.8.5.post1 diff --git a/setup.cfg b/setup.cfg index f0a1e2ae11e..4d9d9f70ba1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -80,7 +80,7 @@ install_requires = # geopython dependencies pyproj<3.7.0 - OWSLib==0.29.2 + OWSLib==0.29.3 pycsw==2.6.1 SQLAlchemy==2.0.21 # required by PyCSW Shapely==1.8.5.post1 From 5abfa5edb38df9b9334219ce0b44d6e50a5fe44e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Nov 2023 10:34:17 +0100 Subject: [PATCH 15/47] Bump black from 23.10.1 to 23.11.0 (#11685) * Bump black from 23.10.1 to 23.11.0 Bumps [black](https://github.com/psf/black) from 23.10.1 to 23.11.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.10.1...23.11.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 6d014b23a82..0be1fad8588 100644 --- a/requirements.txt +++ b/requirements.txt @@ -153,7 +153,7 @@ invoke==2.2.0 coverage==7.3.1 requests-toolbelt==1.0.0 flake8==6.1.0 -black==23.10.1 +black==23.11.0 pytest==7.4.2 pytest-bdd==6.1.1 splinter==0.19.0 diff --git a/setup.cfg b/setup.cfg index 4d9d9f70ba1..615f210196c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -178,7 +178,7 @@ install_requires = coverage==7.3.1 requests-toolbelt==1.0.0 flake8==6.1.0 - black==23.10.1 + black==23.11.0 pytest==7.4.2 pytest-bdd==6.1.1 splinter==0.19.0 From 82eeca1a7181afec27ebafdb6eae57d2f80a9643 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Nov 2023 12:11:14 +0100 Subject: [PATCH 16/47] Bump twisted from 23.8.0 to 23.10.0 (#11664) * Bump twisted from 23.8.0 to 23.10.0 Bumps [twisted](https://github.com/twisted/twisted) from 23.8.0 to 23.10.0. - [Release notes](https://github.com/twisted/twisted/releases) - [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst) - [Commits](https://github.com/twisted/twisted/compare/twisted-23.8.0...twisted-23.10.0) --- updated-dependencies: - dependency-name: twisted dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 0be1fad8588..dafc116d199 100644 --- a/requirements.txt +++ b/requirements.txt @@ -161,7 +161,7 @@ pytest-splinter==3.3.2 pytest-django==4.5.2 setuptools>=59.1.1,<68.3.0 pip==23.2.1 -Twisted==23.8.0 +Twisted==23.10.0 pixelmatch==0.3.0 factory-boy==3.3.0 flaky==3.7.0 diff --git a/setup.cfg b/setup.cfg index 615f210196c..71743233c82 100644 --- a/setup.cfg +++ b/setup.cfg @@ -186,7 +186,7 @@ install_requires = pytest-django==4.5.2 setuptools>=59.1.1,<68.3.0 pip==23.2.1 - Twisted==23.8.0 + Twisted==23.10.0 pixelmatch==0.3.0 factory-boy==3.3.0 flaky==3.7.0 From ae45e105af3df4a0f66d2102d01016b7e6068839 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Nov 2023 14:51:30 +0100 Subject: [PATCH 17/47] Bump amqp from 5.1.1 to 5.2.0 (#11688) * Bump amqp from 5.1.1 to 5.2.0 Bumps [amqp](https://github.com/celery/py-amqp) from 5.1.1 to 5.2.0. - [Release notes](https://github.com/celery/py-amqp/releases) - [Changelog](https://github.com/celery/py-amqp/blob/main/Changelog) - [Commits](https://github.com/celery/py-amqp/compare/v5.1.1...v5.2.0) --- updated-dependencies: - dependency-name: amqp dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index dafc116d199..97cd13a34b6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ psycopg2==2.9.9 Django==3.2.23 # Other -amqp==5.1.1 +amqp==5.2.0 beautifulsoup4==4.12.2 httplib2<0.22.1 hyperlink==21.0.0 diff --git a/setup.cfg b/setup.cfg index 71743233c82..b80f4177d0c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,7 +31,7 @@ install_requires = Django==3.2.23 # Other - amqp==5.1.1 + amqp==5.2.0 beautifulsoup4==4.12.2 httplib2<0.22.1 hyperlink==21.0.0 From a76480fed90746e49e1278fc33fec8f080fb3702 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Nov 2023 14:52:13 +0100 Subject: [PATCH 18/47] Bump jsonschema from 4.19.1 to 4.19.2 (#11661) * Bump jsonschema from 4.19.1 to 4.19.2 Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.19.1 to 4.19.2. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.19.1...v4.19.2) --- updated-dependencies: - dependency-name: jsonschema dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * - Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 97cd13a34b6..81a794a4559 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,7 +20,7 @@ vine==5.1.0 tqdm==4.66.1 Deprecated==1.2.14 wrapt==1.15.0 -jsonschema==4.19.1 +jsonschema==4.19.2 zipstream-new==1.1.8 schema==0.7.5 rdflib==6.3.2 diff --git a/setup.cfg b/setup.cfg index b80f4177d0c..37e8ae01318 100644 --- a/setup.cfg +++ b/setup.cfg @@ -46,7 +46,7 @@ install_requires = tqdm==4.66.1 Deprecated==1.2.14 wrapt==1.15.0 - jsonschema==4.19.1 + jsonschema==4.19.2 zipstream-new==1.1.8 schema==0.7.5 rdflib==6.3.2 From a655d8db27ce631e69fa74c70c08e0fb688caa77 Mon Sep 17 00:00:00 2001 From: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Date: Tue, 21 Nov 2023 12:46:15 +0100 Subject: [PATCH 19/47] Control read only mode with environmental variable #11710 (#11711) * Add env-var to override the readonly mode * Fix flake8 issue * Add test coverage * Add test coverage * Add test coverage * Fix broken test --- .env.sample | 2 ++ geonode/base/tests.py | 11 +++++++++++ geonode/singleton.py | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/.env.sample b/.env.sample index f43b64a7823..962f5a82258 100644 --- a/.env.sample +++ b/.env.sample @@ -253,3 +253,5 @@ RESTART_POLICY_WINDOW=120s DEFAULT_MAX_UPLOAD_SIZE=5368709120 DEFAULT_MAX_PARALLEL_UPLOADS_PER_USER=5 + +# FORCE_READ_ONLY_MODE=False Override the read-only value saved in the configuration \ No newline at end of file diff --git a/geonode/base/tests.py b/geonode/base/tests.py index d61b021ad66..f3741425074 100644 --- a/geonode/base/tests.py +++ b/geonode/base/tests.py @@ -666,6 +666,17 @@ def test_maintenance_true(self): self.assertEqual(response.status_code, 503, "User is allowed to get index page") + @patch.dict(os.environ, {"FORCE_READ_ONLY_MODE": "True"}) + def test_readonly_overwrite_by_env(self): + config = Configuration.load() + self.assertTrue(config.read_only) + + @patch.dict(os.environ, {"FORCE_READ_ONLY_MODE": "False"}) + def test_readonly_is_not_overwrite_by_env(self): + # will take the value from the db + config = Configuration.load() + self.assertFalse(config.read_only) + class TestOwnerRightsRequestUtils(TestCase): def setUp(self): diff --git a/geonode/singleton.py b/geonode/singleton.py index def45c9a430..d6607475716 100644 --- a/geonode/singleton.py +++ b/geonode/singleton.py @@ -20,6 +20,8 @@ # Geonode functionality +import os +import ast from django.db import models @@ -38,6 +40,9 @@ class Meta: @classmethod def load(cls): obj, _ = cls.objects.get_or_create(pk=1) + val = os.getenv("FORCE_READ_ONLY_MODE", None) + if val is not None: + setattr(obj, "read_only", ast.literal_eval(val)) return obj def save(self, *args, **kwargs): From 7cac111e745430fb54ee4142410d7bb756d7d720 Mon Sep 17 00:00:00 2001 From: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Date: Thu, 23 Nov 2023 18:35:53 +0100 Subject: [PATCH 20/47] [Fixes #11716] extension for remote document is not saved (#11717) * [Fixes #11716] extension for remote document is not saved * [Fixes #11716] fix formatting --- geonode/documents/forms.py | 6 +++++- geonode/documents/views.py | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/geonode/documents/forms.py b/geonode/documents/forms.py index 286f98e0a6b..42671e98172 100644 --- a/geonode/documents/forms.py +++ b/geonode/documents/forms.py @@ -130,7 +130,7 @@ class DocumentCreateForm(TranslationModelForm): class Meta: model = Document - fields = ["title", "doc_file", "doc_url"] + fields = ["title", "doc_file", "doc_url", "extension"] widgets = { "name": HiddenInput(attrs={"cols": 80, "rows": 20}), } @@ -159,6 +159,7 @@ def clean(self): cleaned_data = super().clean() doc_file = self.cleaned_data.get("doc_file") doc_url = self.cleaned_data.get("doc_url") + extension = self.cleaned_data.get("extension") if not doc_file and not doc_url and "doc_file" not in self.errors and "doc_url" not in self.errors: logger.error("Document must be a file or url.") @@ -168,6 +169,9 @@ def clean(self): logger.error("A document cannot have both a file and a url.") raise forms.ValidationError(_("A document cannot have both a file and a url.")) + if extension: + cleaned_data["extension"] = extension.replace(".", "") + return cleaned_data def clean_doc_file(self): diff --git a/geonode/documents/views.py b/geonode/documents/views.py index 66b8df09bb7..127b287fd26 100644 --- a/geonode/documents/views.py +++ b/geonode/documents/views.py @@ -173,6 +173,7 @@ def form_valid(self, form): owner=self.request.user, doc_url=doc_form.pop("doc_url", None), title=doc_form.pop("title", file.name), + extension=doc_form.pop("extension", None), files=[storage_path], ), ) @@ -186,6 +187,7 @@ def form_valid(self, form): owner=self.request.user, doc_url=doc_form.pop("doc_url", None), title=doc_form.pop("title", None), + extension=doc_form.pop("extension", None), sourcetype=enumerations.SOURCE_TYPE_REMOTE, ), ) From f7f0cac8a5c2cfff77777fefe279161523aabd42 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Tue, 5 Dec 2023 12:36:56 +0100 Subject: [PATCH 21/47] Increased doc_url (#11748) --- .../migrations/0038_alter_document_doc_url.py | 18 ++++++++++++++++++ geonode/documents/models.py | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 geonode/documents/migrations/0038_alter_document_doc_url.py diff --git a/geonode/documents/migrations/0038_alter_document_doc_url.py b/geonode/documents/migrations/0038_alter_document_doc_url.py new file mode 100644 index 00000000000..8b29c3b31da --- /dev/null +++ b/geonode/documents/migrations/0038_alter_document_doc_url.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.22 on 2023-12-05 10:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('documents', '0037_delete_documentresourcelink'), + ] + + operations = [ + migrations.AlterField( + model_name='document', + name='doc_url', + field=models.URLField(blank=True, help_text='The URL of the document if it is external.', max_length=512, null=True, verbose_name='URL'), + ), + ] diff --git a/geonode/documents/models.py b/geonode/documents/models.py index 78292dfc8c9..d7650f5b0ae 100644 --- a/geonode/documents/models.py +++ b/geonode/documents/models.py @@ -47,7 +47,7 @@ class Document(ResourceBase): doc_url = models.URLField( blank=True, null=True, - max_length=255, + max_length=512, help_text=_("The URL of the document if it is external."), verbose_name=_("URL"), ) From 849265c2af11623410170e1756aa828abf70af31 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 6 Dec 2023 12:05:24 +0100 Subject: [PATCH 22/47] [Fixes #11752] Render remote docs with document embed template (#11753) * render remote docs with document embed template * removed unused import * revert removed unused import * removed unused import --- geonode/documents/views.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/geonode/documents/views.py b/geonode/documents/views.py index 127b287fd26..ca72be2f6a4 100644 --- a/geonode/documents/views.py +++ b/geonode/documents/views.py @@ -85,8 +85,6 @@ def document_link(request, docid): def document_embed(request, docid): - from django.http.response import HttpResponseRedirect - document = get_object_or_404(Document, pk=docid) if not request.user.has_perm("base.download_resourcebase", obj=document.get_self_resource()): @@ -106,8 +104,6 @@ def document_embed(request, docid): "resource": document.get_self_resource(), } return render(request, "documents/document_embed.html", context_dict) - if document.doc_url: - return HttpResponseRedirect(document.doc_url) else: context_dict = { "document_link": reverse("document_link", args=(document.id,)), From a24490800b20ca225632d50a9c9e214ff1623177 Mon Sep 17 00:00:00 2001 From: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Date: Wed, 6 Dec 2023 16:43:26 +0100 Subject: [PATCH 23/47] Harvester error during keyword creation #11755 (#11756) * Add test suite * Fixes #11755: Harvester error during keyword creation * Fixes #11755: remove unwanted commit --- geonode/harvesting/harvesters/base.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/geonode/harvesting/harvesters/base.py b/geonode/harvesting/harvesters/base.py index c10b4c035d5..8c616046eea 100644 --- a/geonode/harvesting/harvesters/base.py +++ b/geonode/harvesting/harvesters/base.py @@ -36,7 +36,6 @@ from .. import ( config, - models, resourcedescriptor, ) @@ -377,16 +376,9 @@ def _get_file_name( return sanitized -def _generate_harvester_keyword(harvester_id): - harvester = models.Harvester.objects.get(pk=harvester_id) - return harvester.name.lower().replace("harvester ", "").replace("harvester_", "").replace("harvester", "").strip() - - def _consolidate_resource_keywords( resource_descriptor: resourcedescriptor.RecordDescription, geonode_resource, harvester_id: int ) -> typing.List[str]: geonode_keywords = geonode_resource.keyword_list() if geonode_resource else [] keywords = list(resource_descriptor.identification.other_keywords) + geonode_keywords - harvester_keyword = _generate_harvester_keyword(harvester_id) - keywords.append(harvester_keyword) return list(set(keywords)) From ea71bcf303c07f918531755a4f5f639df0b23f37 Mon Sep 17 00:00:00 2001 From: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Date: Wed, 6 Dec 2023 16:45:26 +0100 Subject: [PATCH 24/47] [Fixes #11750] Do not send notifications in Celery tasks if notifications are disabled (#11751) * Add test suite * [Fixes #11750] Do not send notifications in Celery tasks if notifications are disabled * [Fixes #11750] Do not send notifications in Celery tasks if notifications are disabled * [Fixes #11750] Do not send notifications in Celery tasks if notifications are disabled * [Fixes #11750] Do not send notifications in Celery tasks if notifications are disabled * [Fixes #11750] Do not send notifications in Celery tasks if notifications are disabled * [Fixes #11750] Do not send notifications in Celery tasks if notifications are disabled * [Fixes #11750] Do not send notifications in Celery tasks if notifications are disabled * [Fixes #11750] Do not send notifications in Celery tasks if notifications are disabled --------- Co-authored-by: Giovanni Allegri --- geonode/notifications_helper.py | 2 +- geonode/tasks/tasks.py | 11 ++++++----- geonode/tasks/tests.py | 16 ++++++---------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/geonode/notifications_helper.py b/geonode/notifications_helper.py index 7f2220f19e9..da265a7f3b3 100644 --- a/geonode/notifications_helper.py +++ b/geonode/notifications_helper.py @@ -69,7 +69,7 @@ def ready(self): def call_celery(func): def wrap(*args, **kwargs): ret = func(*args, **kwargs) - if settings.PINAX_NOTIFICATIONS_QUEUE_ALL: + if has_notifications and settings.PINAX_NOTIFICATIONS_QUEUE_ALL: send_queued_notifications.apply_async(args=(), expiration=30) return ret diff --git a/geonode/tasks/tasks.py b/geonode/tasks/tasks.py index bdd611fea14..1a7763d359d 100644 --- a/geonode/tasks/tasks.py +++ b/geonode/tasks/tasks.py @@ -25,6 +25,7 @@ from django.db import connections, transaction from geonode.celery_app import app +from importlib import import_module try: import pylibmc @@ -168,13 +169,13 @@ def send_queued_notifications(self, *args): advantage of this. """ - from importlib import import_module + from geonode.notifications_helper import has_notifications - notifications = getattr(settings, "NOTIFICATIONS_MODULE", None) + if has_notifications: + from geonode.notifications_helper import notifications - if notifications: - engine = import_module(f"{notifications}.engine") - send_all = getattr(engine, "send_all") + # for some unkown reason, notification.engine is not directly accessible + send_all = getattr(import_module(f"{notifications.__package__}.engine"), "send_all") # Make sure application can write to location where lock files are stored if not args and getattr(settings, "NOTIFICATION_LOCK_LOCATION", None): send_all(settings.NOTIFICATION_LOCK_LOCATION) diff --git a/geonode/tasks/tests.py b/geonode/tasks/tests.py index c3722fca9f8..13ef5151c97 100644 --- a/geonode/tasks/tests.py +++ b/geonode/tasks/tests.py @@ -18,16 +18,12 @@ ######################################################################### from geonode.tests.base import GeoNodeBaseTestSupport +from unittest.mock import patch +from geonode.tasks.tasks import send_queued_notifications class TasksTest(GeoNodeBaseTestSupport): - - """ - Tests geonode.messaging - """ - - def setUp(self): - super().setUp() - - self.adm_un = "admin" - self.adm_pw = "admin" + @patch("geonode.notifications_helper.has_notifications", False) + def test_send_queued_notifications_is_not_called_if_notification_is_off(self): + actual = send_queued_notifications() + self.assertIsNone(actual) From a42f9f2426de444d51ab12046452893679d5803f Mon Sep 17 00:00:00 2001 From: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Date: Wed, 6 Dec 2023 17:59:38 +0100 Subject: [PATCH 25/47] Fix german translation (#11760) * Add test suite * Fix german translation * Fix german translation --- geonode/locale/de/LC_MESSAGES/django.mo | Bin 156832 -> 156837 bytes geonode/locale/de/LC_MESSAGES/django.po | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/locale/de/LC_MESSAGES/django.mo b/geonode/locale/de/LC_MESSAGES/django.mo index 95e04cff54c2ac0d3874ac73c5d7f354f7ee4379..6f83b9fc2f3647e48b3f7da1d9d518596386b16a 100644 GIT binary patch delta 12332 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 L)fMKaCcXdvaA72A delta 12327 zcmXZid7zEe8i4U{Z)B`A7?L>Vu}qO6L{6M2Aw!5lhD1?_Xr~DwnxsgE6p|rsM>i=- zgi@DElm;}Qx(aoZy3cdg`s=sWH>}}Z?^@qJW%2uk=f7Wg)%rS_cT-8Sr*A6ho=%eI zZcZh~k|a6NKb72p-w#M7OS#|UmQ->BrU#{xi?H|LRB}D{#|=p(*|-xQ<$8%*L;Z!J zspJ8!AI1l9_-(1=cKi)TWB*~PWC89SmdYf(D2yMTO4{Qd?2DCePbGEmLEMXL@gAIU zM=EK8MMtEPnwX8#@D7}cr?DSS8JS9Y;!$jPev-7kGnF)^K4DTSDT%LP2mD}CCY4mC zP-b!}DS<7q2zJGD@Fu(nM`AUciB)hN+R%P%fhVvzUOFX}6vC0wd(ieCjLyKq)Sr#@ z7cvws=fX;~furaQYd(@n>f-=>4xh$D*l=oCf(xgmk`JginVw3n!h*!#5MPT0a0AxG zchL!)z;bxrj42Ws*B6II>64HGc)|_{(_xPqf1e9uEV%8e35xh(5O@ zx)~klx99{4JP`(50d2n(+Wt-03}<2)`cHP`707nX;zs((Fycz+Oq!z|^@`q&&iE;G zW~*X-8^?eZTZm;r&KffqEBggrls}f3lo{BmNLC#>03CmYx-Ipe?qhJ`TP9 zCOU(oI0dUeol0KGpCqrM1HEZ(DyfGP&|FxFXX3x`Y(K#kLp%5g-DU^yJp37pWBU0J^7GK=8)7kRhBdI=^O?}$ zNG@b?VKN%(rPvFPVnb{x0k;jg3x6J6I51j&_ub4(Kg3 zxj#T7dJ>CbvV)~Pa z`Lau6d+2V;K_lA_Gc{64avy~nTv)a&e7|?29hZ4IBwa-`IqPFn%tj+{AA00IiCLJ7 zKDP&r;1M(@j-dno6RTj+-LD#^k2SQDSZ&G z=)V6f*1y9usQ-+7_f_!Ts{-bR<;lUP56My&YSFo0%gP z|81Za1^0gotcrutte%0+Y!(`cd1%MW(THtDx6xN<R6@QZsIIv2gA*{0@*c9zJ8y(1v=s-tAr=x4X z6m9>V=R%oCE8p;}IL(O8nJKFJ(SicJm?ZfDR=b{l?gHGrTwBz^D z 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 PIpnUJbNTn155M()?&%;x diff --git a/geonode/locale/de/LC_MESSAGES/django.po b/geonode/locale/de/LC_MESSAGES/django.po index dd8cfaf6914..01910e54f14 100644 --- a/geonode/locale/de/LC_MESSAGES/django.po +++ b/geonode/locale/de/LC_MESSAGES/django.po @@ -342,7 +342,7 @@ msgid "edition" msgstr "Ausgabe" msgid "Attribution" -msgstr "Zitation" +msgstr "Attribution" msgid "DOI" msgstr "DOI" From 2039eb7cd4d62adad954cbe89d237867ecd4e52f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 12:58:53 +0100 Subject: [PATCH 26/47] Don't quote JAVA_OPTS (#11807) (#11810) (cherry picked from commit 8d2dfbf7f71f0a186016b3fd8ef1180a57b45925) Co-authored-by: Giovanni Allegri --- .env.sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.sample b/.env.sample index 962f5a82258..afc97264bc3 100644 --- a/.env.sample +++ b/.env.sample @@ -101,7 +101,7 @@ OGC_REQUEST_POOL_CONNECTIONS=10 # Java Options & Memory ENABLE_JSONP=true outFormat=text/javascript -GEOSERVER_JAVA_OPTS='-Djava.awt.headless=true -Xms4G -Xmx4G -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:PerfDataSamplingInterval=500 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:-UseGCOverheadLimit -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL={geoserver_ui}/geoserver/pdf -DALLOW_ENV_PARAMETRIZATION=true -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3-Unsafe.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine' +GEOSERVER_JAVA_OPTS=-Djava.awt.headless=true -Xms4G -Xmx4G -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:PerfDataSamplingInterval=500 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:-UseGCOverheadLimit -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL={geoserver_ui}/geoserver/pdf -DALLOW_ENV_PARAMETRIZATION=true -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3-Unsafe.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine # ################# # Security From b4e8838ecc75fbb297d9ce175b5c7ffc31ced621 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Tue, 9 Jan 2024 16:19:59 +0100 Subject: [PATCH 27/47] Fix template variable for print base url (#11813) --- .env.sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.sample b/.env.sample index afc97264bc3..6e5dd10da9d 100644 --- a/.env.sample +++ b/.env.sample @@ -101,7 +101,7 @@ OGC_REQUEST_POOL_CONNECTIONS=10 # Java Options & Memory ENABLE_JSONP=true outFormat=text/javascript -GEOSERVER_JAVA_OPTS=-Djava.awt.headless=true -Xms4G -Xmx4G -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:PerfDataSamplingInterval=500 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:-UseGCOverheadLimit -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL={geoserver_ui}/geoserver/pdf -DALLOW_ENV_PARAMETRIZATION=true -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3-Unsafe.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine +GEOSERVER_JAVA_OPTS=-Djava.awt.headless=true -Xms4G -Xmx4G -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:PerfDataSamplingInterval=500 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:-UseGCOverheadLimit -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL={siteurl}/geoserver/pdf -DALLOW_ENV_PARAMETRIZATION=true -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3-Unsafe.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine # ################# # Security From aadf0979cb3f85fd25c315caa74dfef2ced1d67c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 10 Jan 2024 11:34:19 +0100 Subject: [PATCH 28/47] [Fixes #11817] Drop Nginx and Letsencrypt Dockerfiles (#11818) (#11820) * Drop Nginx and Letsencrypt Dockerfiles * align compose files * algin compose filew (2) (cherry picked from commit 535f08cb5d2385b6e6d0aa0e314998a723f896ba) Co-authored-by: Giovanni Allegri --- docker-compose-dev.yml | 9 +- docker-compose-geoserver-server.yml | 4 +- docker-compose-test.yml | 10 +- docker-compose.yml | 10 +- scripts/docker/letsencrypt/Dockerfile | 18 --- scripts/docker/letsencrypt/README.md | 15 -- scripts/docker/letsencrypt/crontab | 8 -- .../docker/letsencrypt/docker-entrypoint.sh | 52 ------- scripts/docker/nginx/Dockerfile | 18 --- scripts/docker/nginx/docker-autoreload.sh | 37 ----- scripts/docker/nginx/docker-entrypoint.sh | 67 --------- scripts/docker/nginx/geonode.conf.envsubst | 134 ------------------ scripts/docker/nginx/nginx.conf.envsubst | 39 ----- .../nginx/nginx.https.available.conf.envsubst | 37 ----- 14 files changed, 14 insertions(+), 444 deletions(-) delete mode 100644 scripts/docker/letsencrypt/Dockerfile delete mode 100644 scripts/docker/letsencrypt/README.md delete mode 100644 scripts/docker/letsencrypt/crontab delete mode 100644 scripts/docker/letsencrypt/docker-entrypoint.sh delete mode 100644 scripts/docker/nginx/Dockerfile delete mode 100644 scripts/docker/nginx/docker-autoreload.sh delete mode 100644 scripts/docker/nginx/docker-entrypoint.sh delete mode 100644 scripts/docker/nginx/geonode.conf.envsubst delete mode 100644 scripts/docker/nginx/nginx.conf.envsubst delete mode 100644 scripts/docker/nginx/nginx.https.available.conf.envsubst diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 0ac801a9621..7c21d3ec374 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -52,7 +52,7 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: - image: geonode/nginx:1.25.1 + image: geonode/nginx:latest build: ./scripts/docker/nginx/ container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: @@ -71,7 +71,6 @@ services: # Gets and installs letsencrypt certificates letsencrypt: image: geonode/letsencrypt:latest - build: ./scripts/docker/letsencrypt/ container_name: letsencrypt4${COMPOSE_PROJECT_NAME} env_file: - .env @@ -81,7 +80,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:latest container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -107,7 +106,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:latest container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: @@ -119,7 +118,7 @@ services: # PostGIS database. db: # use geonode official postgis 15 image - image: geonode/postgis:15 + image: geonode/postgis:latest command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" container_name: db4${COMPOSE_PROJECT_NAME} env_file: diff --git a/docker-compose-geoserver-server.yml b/docker-compose-geoserver-server.yml index 10785a5794a..5a83f79b7c7 100644 --- a/docker-compose-geoserver-server.yml +++ b/docker-compose-geoserver-server.yml @@ -2,7 +2,7 @@ version: '2.2' services: data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:latest restart: on-failure container_name: gsconf4${COMPOSE_PROJECT_NAME} labels: @@ -13,7 +13,7 @@ services: - geoserver-data-dir:/geoserver_data/data geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:latest restart: unless-stopped container_name: geoserver4${COMPOSE_PROJECT_NAME} stdin_open: true diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 9bd764f8da3..22ac6dd0093 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -52,8 +52,7 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: - image: geonode/nginx:1.25.1 - build: ./scripts/docker/nginx/ + image: geonode/nginx:latest container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: - .env_test @@ -84,7 +83,6 @@ services: # Gets and installs letsencrypt certificates letsencrypt: image: geonode/letsencrypt:latest - build: ./scripts/docker/letsencrypt/ container_name: letsencrypt4${COMPOSE_PROJECT_NAME} env_file: - .env_test @@ -94,7 +92,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:latest container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -120,7 +118,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:latest container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: @@ -132,7 +130,7 @@ services: # PostGIS database. db: # use geonode official postgis 15 image - image: geonode/postgis:15 + image: geonode/postgis:latest command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" container_name: db4${COMPOSE_PROJECT_NAME} env_file: diff --git a/docker-compose.yml b/docker-compose.yml index 7cc150f129c..61b85d10503 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -61,8 +61,7 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: - image: geonode/nginx:1.25.1 - build: ./scripts/docker/nginx/ + image: geonode/nginx:latest container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: - .env @@ -80,7 +79,6 @@ services: # Gets and installs letsencrypt certificates letsencrypt: image: geonode/letsencrypt:latest - build: ./scripts/docker/letsencrypt/ container_name: letsencrypt4${COMPOSE_PROJECT_NAME} env_file: - .env @@ -90,7 +88,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.0 + image: geonode/geoserver:latest container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -116,7 +114,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.0 + image: geonode/geoserver_data:latest container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: @@ -128,7 +126,7 @@ services: # PostGIS database. db: # use geonode official postgis 15 image - image: geonode/postgis:15 + image: geonode/postgis:latest command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" container_name: db4${COMPOSE_PROJECT_NAME} env_file: diff --git a/scripts/docker/letsencrypt/Dockerfile b/scripts/docker/letsencrypt/Dockerfile deleted file mode 100644 index 1480342e8f1..00000000000 --- a/scripts/docker/letsencrypt/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM alpine:latest - -RUN apk add --no-cache certbot - -# Installing scripts -ADD docker-entrypoint.sh /docker-entrypoint.sh -RUN chmod +x /docker-entrypoint.sh - -# Installing cronjobs -ADD crontab /crontab -RUN /usr/bin/crontab /crontab && \ - rm /crontab - -# Setup the entrypoint -ENTRYPOINT ["./docker-entrypoint.sh"] - -# We run cron in foreground to update the certificates -CMD /usr/sbin/crond -f diff --git a/scripts/docker/letsencrypt/README.md b/scripts/docker/letsencrypt/README.md deleted file mode 100644 index d6b1ec2247e..00000000000 --- a/scripts/docker/letsencrypt/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Letsencrypt service for Geonode - -This service generates SSL certificates to be used by Nginx. - -## Let's Encrypt - -Upon startup, it generates one SSL certificate from Let's Encrypt using Certbot. It then starts cron (in foreground) to renew the certificates using Certbot renew. - -If for some reason getting the certificate fails, a placeholder certificate is generated. This certificate is invalid, but still allows to encrypt the data and to start the webserver. - -To avoid hitting Let's Encrypt very low rate limits when developping or doing tests, LETSENCRYPT_MODE env var can be set to "disabled" (which will completely bypass Let'sEncrypt, simulating a failure) or to "staging" (using Let'sEncrypt test certificates with higher rates). - -## Autoissued - -An auto-issued certificate is also generate to be used on the LAN if needed. It is also renewed every now and then using the same cron process than above. diff --git a/scripts/docker/letsencrypt/crontab b/scripts/docker/letsencrypt/crontab deleted file mode 100644 index 7ea7203b8f8..00000000000 --- a/scripts/docker/letsencrypt/crontab +++ /dev/null @@ -1,8 +0,0 @@ -# +------------- minute (0 - 59) -# ¦ +------------- hour (0 - 23) -# ¦ ¦ +------------- day of month (1 - 31) -# ¦ ¦ ¦ +------------- month (1 - 12) -# ¦ ¦ ¦ ¦ +------------- day of week (0 - 6) (Sunday to Saturday; 7 is also Sunday on some systems) -# ¦ ¦ ¦ ¦ ¦ - - 0 0,12 * * * date && echo "daily " && /docker-entrypoint.sh diff --git a/scripts/docker/letsencrypt/docker-entrypoint.sh b/scripts/docker/letsencrypt/docker-entrypoint.sh deleted file mode 100644 index d1c4541b075..00000000000 --- a/scripts/docker/letsencrypt/docker-entrypoint.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/sh - -# Exit script in case of error -set -e - -echo $"\n\n\n" -echo "-----------------------------------------------------" -echo "STARTING LETSENCRYPT ENTRYPOINT ---------------------" -date - -# We make the config dir -mkdir -p "/geonode-certificates/$LETSENCRYPT_MODE" - -# Do not exit script in case of error -set +e - -# We run the command -if [ "$LETSENCRYPT_MODE" == "staging" ]; then - printf "\nTrying to get STAGING certificate\n" - certbot --config-dir "/geonode-certificates/$LETSENCRYPT_MODE" certonly --webroot -w "/geonode-certificates" -d "$HTTPS_HOST" -m "$ADMIN_EMAIL" --agree-tos --non-interactive --test-cert -elif [ "$LETSENCRYPT_MODE" == "production" ]; then - printf "\nTrying to get PRODUCTION certificate\n" - certbot --config-dir "/geonode-certificates/$LETSENCRYPT_MODE" certonly --webroot -w "/geonode-certificates" -d "$HTTPS_HOST" -m "$ADMIN_EMAIL" --agree-tos --non-interactive --server https://acme-v02.api.letsencrypt.org/directory -elif [ "$LETSENCRYPT_MODE" == "disabled" ]; then - printf "\nNot trying to get certificate (because LETSENCRYPT_MODE variable is set to disabled) - and stop container\n" - exit 0 -else - printf "\nNot trying to get certificate (simulating failure, because LETSENCRYPT_MODE variable was neither staging nor production\n" - /bin/false -fi - -# If the certbot comand failed, we will create a placeholder certificate -if [ ! $? -eq 0 ]; then - # Exit script in case of error - set -e - - printf "\nFailed to get the certificates !\n" - - printf "\nWaiting 30s to avoid hitting Letsencrypt rate limits before it's even possible to react\n" - sleep 30 - - exit 1 -fi - -printf "\nCertificate have been created/renewed successfully\n" - -echo "-----------------------------------------------------" -echo "FINISHED LETSENCRYPT ENTRYPOINT ---------------------" -echo "-----------------------------------------------------" - -# Run the CMD -exec "$@" diff --git a/scripts/docker/nginx/Dockerfile b/scripts/docker/nginx/Dockerfile deleted file mode 100644 index 9b0fe5b4f30..00000000000 --- a/scripts/docker/nginx/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM nginx:1.25.3-alpine - -RUN apk add --no-cache openssl inotify-tools vim - -WORKDIR /etc/nginx/ - -RUN mkdir -p /etc/nginx/html -RUN touch /etc/nginx/html/index.html - -ADD nginx.conf.envsubst nginx.https.available.conf.envsubst ./ -ADD geonode.conf.envsubst ./sites-enabled/ - -ADD docker-autoreload.sh docker-entrypoint.sh / -ENTRYPOINT ["/docker-entrypoint.sh"] -RUN chmod +x /docker-autoreload.sh -RUN chmod +x /docker-entrypoint.sh - -CMD ["nginx", "-g", "daemon off;"] diff --git a/scripts/docker/nginx/docker-autoreload.sh b/scripts/docker/nginx/docker-autoreload.sh deleted file mode 100644 index 812cc76d723..00000000000 --- a/scripts/docker/nginx/docker-autoreload.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -# This will watch the /geonode-certificates folder and run nginx -s reload whenever there are some changes. -# We use this to reload nginx config when certificates changed. - -# inspired/copied from https://github.com/kubernetes/kubernetes/blob/master/examples/https-nginx/auto-reload-nginx.sh - -while true -do - inotifywait -e create -e modify -e delete -e move -r --exclude "\\.certbot\\.lock|\\.well-known" "/geonode-certificates/$LETSENCRYPT_MODE" - echo "Changes noticed in /geonode-certificates" - - echo "Waiting 5s for additionnal changes" - sleep 5 - - echo "Creating symbolic link for WAN host" - # for some reason, the ln -f flag doesn't work below... - rm -f /certificate_symlink - if [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/fullchain.pem" ] && [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/privkey.pem" ]; then - echo "Certbot certificate exists, we symlink to the live cert" - ln -sf "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST" /certificate_symlink - else - echo "Certbot certificate does not exist, we symlink to autoissued" - ln -sf "/geonode-certificates/autoissued" /certificate_symlink - fi - - # Test nginx configuration - nginx -t - # If it passes, we reload - if [ $? -eq 0 ] - then - echo "Configuration valid, we reload..." - nginx -s reload - else - echo "Configuration not valid, we do not reload." - fi -done diff --git a/scripts/docker/nginx/docker-entrypoint.sh b/scripts/docker/nginx/docker-entrypoint.sh deleted file mode 100644 index e6bec7a1db2..00000000000 --- a/scripts/docker/nginx/docker-entrypoint.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/sh - -# Exit script in case of error -set -e - -echo $"\n\n\n" -echo "-----------------------------------------------------" -echo "STARTING NGINX ENTRYPOINT ---------------------------" -date - -# We make the config dir -mkdir -p "/geonode-certificates/$LETSENCRYPT_MODE" - -echo "Creating autoissued certificates for HTTP host" -if [ ! -f "/geonode-certificates/autoissued/privkey.pem" ] || [[ $(find /geonode-certificates/autoissued/privkey.pem -mtime +365 -print) ]]; then - echo "Autoissued certificate does not exist or is too old, we generate one" - mkdir -p "/geonode-certificates/autoissued/" - openssl req -x509 -nodes -days 1825 -newkey rsa:2048 -keyout "/geonode-certificates/autoissued/privkey.pem" -out "/geonode-certificates/autoissued/fullchain.pem" -subj "/CN=${HTTP_HOST:-HTTPS_HOST}" -else - echo "Autoissued certificate already exists" -fi - -echo "Creating symbolic link for HTTPS certificate" -# for some reason, the ln -f flag doesn't work below... -# TODO : not DRY (reuse same scripts as docker-autoreload.sh) -rm -f /certificate_symlink -if [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/fullchain.pem" ] && [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/privkey.pem" ]; then - echo "Certbot certificate exists, we symlink to the live cert" - ln -sf "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST" /certificate_symlink -else - echo "Certbot certificate does not exist, we symlink to autoissued" - ln -sf "/geonode-certificates/autoissued" /certificate_symlink -fi - -if [ -z "${HTTPS_HOST}" ]; then - HTTP_SCHEME="http" -else - HTTP_SCHEME="https" -fi - -export HTTP_SCHEME=${HTTP_SCHEME:-http} -export GEONODE_LB_HOST_IP=${GEONODE_LB_HOST_IP:-django} -export GEONODE_LB_PORT=${GEONODE_LB_PORT:-8000} -export GEOSERVER_LB_HOST_IP=${GEOSERVER_LB_HOST_IP:-geoserver} -export GEOSERVER_LB_PORT=${GEOSERVER_LB_PORT:-8080} - -echo "Replacing environement variables" -envsubst '\$HTTP_HOST \$HTTPS_HOST \$HTTP_SCHEME \$GEONODE_LB_HOST_IP \$GEONODE_LB_PORT \$GEOSERVER_LB_HOST_IP \$GEOSERVER_LB_PORT \$RESOLVER' < /etc/nginx/nginx.conf.envsubst > /etc/nginx/nginx.conf -envsubst '\$HTTP_HOST \$HTTPS_HOST \$HTTP_SCHEME \$GEONODE_LB_HOST_IP \$GEONODE_LB_PORT \$GEOSERVER_LB_HOST_IP \$GEOSERVER_LB_PORT \$RESOLVER' < /etc/nginx/nginx.https.available.conf.envsubst > /etc/nginx/nginx.https.available.conf -envsubst '\$HTTP_HOST \$HTTPS_HOST \$HTTP_SCHEME \$GEONODE_LB_HOST_IP \$GEONODE_LB_PORT \$GEOSERVER_LB_HOST_IP \$GEOSERVER_LB_PORT' < /etc/nginx/sites-enabled/geonode.conf.envsubst > /etc/nginx/sites-enabled/geonode.conf - -echo "Enabling or not https configuration" -if [ -z "${HTTPS_HOST}" ]; then - echo "" > /etc/nginx/nginx.https.enabled.conf -else - ln -sf /etc/nginx/nginx.https.available.conf /etc/nginx/nginx.https.enabled.conf -fi - -echo "Loading nginx autoreloader" -sh /docker-autoreload.sh & - -echo "-----------------------------------------------------" -echo "FINISHED NGINX ENTRYPOINT ---------------------------" -echo "-----------------------------------------------------" - -# Run the CMD -exec "$@" diff --git a/scripts/docker/nginx/geonode.conf.envsubst b/scripts/docker/nginx/geonode.conf.envsubst deleted file mode 100644 index 1176ce2cc2b..00000000000 --- a/scripts/docker/nginx/geonode.conf.envsubst +++ /dev/null @@ -1,134 +0,0 @@ -include /etc/nginx/mime.types; - -# This is the main geonode conf -charset utf-8; - -# max upload size -client_max_body_size 100G; -client_body_buffer_size 256K; -client_body_timeout 600s; -large_client_header_buffers 4 64k; - -proxy_connect_timeout 600; -proxy_send_timeout 600; -proxy_read_timeout 600; -uwsgi_read_timeout 600; -send_timeout 600; - -fastcgi_hide_header Set-Cookie; - -etag on; - -# compression -gzip on; -gzip_vary on; -gzip_proxied any; -gzip_http_version 1.1; -gzip_disable "MSIE [1-6]\."; -gzip_buffers 16 8k; -gzip_min_length 1100; -gzip_comp_level 6; -gzip_types - text/css - text/javascript - text/xml - text/plain - application/xml - application/xml+rss - application/javascript - application/x-javascript - application/json; - -# GeoServer -location /geoserver { - # Using a variable is a trick to let Nginx start even if upstream host is not up yet - # (see https://sandro-keil.de/blog/2017/07/24/let-nginx-start-if-upstream-host-is-unavailable-or-down/) - set $upstream $GEOSERVER_LB_HOST_IP:$GEOSERVER_LB_PORT; - - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Server $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Proto $HTTP_SCHEME; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_hide_header X-Frame-Options; - proxy_pass http://$upstream; - proxy_http_version 1.1; - proxy_redirect http://$upstream $HTTP_SCHEME://$HTTP_HOST; - proxy_request_buffering off; - client_max_body_size 0; -} - -# GeoNode -location /static/ { - alias /mnt/volumes/statics/static/; - - location ~* \.(?:html|js|jpg|jpeg|gif|png|css|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|ttf|rtf|swf|ico|flv|txt|woff|woff2|svg|xml)$ { - gzip_static always; - expires 30d; - access_log off; - add_header Pragma "public"; - add_header Cache-Control "max-age=31536000, public"; - } -} - -location /uploaded/ { - alias /mnt/volumes/statics/uploaded/; - - location ~* \.(?:html|js|jpg|jpeg|gif|png|css|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|ttf|rtf|swf|ico|flv|txt|woff|woff2|svg|xml)$ { - gzip_static always; - expires 30d; - access_log off; - add_header Pragma "public"; - add_header Cache-Control "max-age=31536000, public"; - } -} - -location / { - # Using a variable is a trick to let Nginx start even if upstream host is not up yet - # (see https://sandro-keil.de/blog/2017/07/24/let-nginx-start-if-upstream-host-is-unavailable-or-down/) - set $upstream $GEONODE_LB_HOST_IP:$GEONODE_LB_PORT; - - if ($request_method = OPTIONS) { - add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, OPTIONS"; - add_header Access-Control-Allow-Headers "Authorization, Content-Type, Accept"; - add_header Access-Control-Allow-Credentials true; - add_header Content-Length 0; - add_header Content-Type text/plain; - add_header Access-Control-Max-Age 1728000; - return 200; - } - - add_header Access-Control-Allow-Credentials false; - add_header Access-Control-Allow-Headers "Content-Type, Accept, Authorization, Origin, User-Agent"; - add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, OPTIONS"; - - proxy_redirect off; - proxy_set_header Host $host; - proxy_set_header Origin $HTTP_SCHEME://$host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Host $server_name; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $HTTP_SCHEME; - proxy_hide_header X-Frame-Options; - proxy_request_buffering off; - - # uwsgi_params - include /etc/nginx/uwsgi_params; - - proxy_pass http://$upstream; - # uwsgi_pass $upstream; - - # when a client closes the connection then keep the channel to uwsgi open. Otherwise uwsgi throws an IOError - uwsgi_ignore_client_abort on; - uwsgi_request_buffering off; - - location ~* \.(?:js|jpg|jpeg|gif|png|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|ttf|rtf|swf|ico|flv|woff|woff2|svg|xml)$ { - gzip_static always; - expires 30d; - access_log off; - add_header Pragma "public"; - add_header Cache-Control "max-age=31536000, public"; - } -} diff --git a/scripts/docker/nginx/nginx.conf.envsubst b/scripts/docker/nginx/nginx.conf.envsubst deleted file mode 100644 index b6065209d51..00000000000 --- a/scripts/docker/nginx/nginx.conf.envsubst +++ /dev/null @@ -1,39 +0,0 @@ -# NOTE : $VARIABLES are env variables replaced by entrypoint.sh using envsubst -# not to be mistaken for nginx variables (also starting with $, but usually lowercase) - -worker_processes auto; - -events { - -} - -http { - server_names_hash_bucket_size 64; - - # Allow Nginx to resolve Docker host names (see https://sandro-keil.de/blog/2017/07/24/let-nginx-start-if-upstream-host-is-unavailable-or-down/) - resolver $RESOLVER; # it seems rancher uses 169.254.169.250 instead of 127.0.0.11 which works well in docker-compose (see /etc/resolv.conf) - - # https - listens on specific name - this uses letsencrypt cert - # this includes a symlink that links either to nginx.https.available.conf if https in enabled - # or to an empty file if https is disabled. - include nginx.https.enabled.conf; - - # http - listens to specific HTTP_HOST only - this is not encrypted (not ideal but admissible on LAN for instance) - # even if not used (HTTP_HOST empty), we must keep it as it's used for internal API calls between django and geoserver - # TODO : do not use unencrypted connection even on LAN, but is it possible to have browser not complaining about unknown authority ? - server { - listen 80; - server_name $HTTP_HOST 127.0.0.1; - - include sites-enabled/*.conf; - } - - # Default server closes the connection (we can connect only using HTTP_HOST and HTTPS_HOST) - server { - listen 80 default_server; - listen 443; - server_name _; - return 444; - } - -} diff --git a/scripts/docker/nginx/nginx.https.available.conf.envsubst b/scripts/docker/nginx/nginx.https.available.conf.envsubst deleted file mode 100644 index fcd1cb34367..00000000000 --- a/scripts/docker/nginx/nginx.https.available.conf.envsubst +++ /dev/null @@ -1,37 +0,0 @@ -# NOTE : $VARIABLES are env variables replaced by entrypoint.sh using envsubst -# not to be mistaken for nginx variables (also starting with $, but usually lowercase) - -# This file is to be included in the main nginx.conf configuration if HTTPS_HOST is set -ssl_session_cache shared:SSL:10m; -ssl_session_timeout 10m; - -# this is the actual HTTPS host -server { - listen 443 ssl; - server_name $HTTPS_HOST; - keepalive_timeout 70; - - ssl_certificate /certificate_symlink/fullchain.pem; - ssl_certificate_key /certificate_symlink/privkey.pem; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers HIGH:!aNULL:!MD5; - - include sites-enabled/*.conf; -} - -# if we try to connect from http, we redirect to https -server { - listen 80; - server_name $HTTPS_HOST $HTTP_HOST; # TODO : once geoserver supports relative urls, we should allow access though both HTTP and HTTPS at the same time and hence remove HTTP_HOST from this line - - # Except for let's encrypt challenge - location /.well-known { - alias /geonode-certificates/.well-known; - include /etc/nginx/mime.types; - } - - # Redirect to https - location / { - return 302 https://$HTTPS_HOST$request_uri; # TODO : we should use 301 (permanent redirect, but not practical for debug) - } -} From 7b99387f0ef3a5528e8e418fedaebe0a56a0ecf4 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 10 Jan 2024 16:10:26 +0100 Subject: [PATCH 29/47] Update Docker tags for 4.2.x (#11824) --- docker-compose.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 61b85d10503..e11bf319688 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -61,7 +61,7 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: - image: geonode/nginx:latest + image: geonode/nginx:1.25.3-v1 container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: - .env @@ -78,7 +78,7 @@ services: # Gets and installs letsencrypt certificates letsencrypt: - image: geonode/letsencrypt:latest + image: geonode/letsencrypt:2.6.0-v1 container_name: letsencrypt4${COMPOSE_PROJECT_NAME} env_file: - .env @@ -88,7 +88,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:latest + image: geonode/geoserver:2.23.3-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -114,7 +114,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:latest + image: geonode/geoserver_data:2.23.3-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: @@ -126,7 +126,7 @@ services: # PostGIS database. db: # use geonode official postgis 15 image - image: geonode/postgis:latest + image: geonode/postgis:15.3-v1 command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" container_name: db4${COMPOSE_PROJECT_NAME} env_file: From 4137c249f1a74aa9dbb36df4f6013537bfe9d42b Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 10 Jan 2024 16:29:09 +0100 Subject: [PATCH 30/47] Use GeoNode 4.2.x Docker image (#11826) --- docker-compose-test.yml | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 22ac6dd0093..8780e0aea7b 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:latest-ubuntu-22.04 + image: geonode/geonode:local restart: unless-stopped env_file: - .env_test diff --git a/docker-compose.yml b/docker-compose.yml index e11bf319688..0f7bfcfd1fc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:latest-ubuntu-22.04 + image: geonode/geonode:4.2.x restart: unless-stopped env_file: - .env From 8e03c53b39197c9ca24015605a66afb85dfd29aa Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 10 Jan 2024 17:17:11 +0100 Subject: [PATCH 31/47] Release 4.2.0 (#11827) * Bump client to 4.2.0 and importer to version 1.0.6 * Bump version to 4.2.0 * fixed docker image tags for test and dev compose files --- docker-compose-dev.yml | 10 +++++----- docker-compose-test.yml | 10 +++++----- geonode/__init__.py | 2 +- requirements.txt | 5 ++--- setup.cfg | 4 ++-- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 7c21d3ec374..7c355038429 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -52,7 +52,7 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: - image: geonode/nginx:latest + image: geonode/nginx:1.25.3-v1 build: ./scripts/docker/nginx/ container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: @@ -70,7 +70,7 @@ services: # Gets and installs letsencrypt certificates letsencrypt: - image: geonode/letsencrypt:latest + image: geonode/letsencrypt:2.6.0-v1 container_name: letsencrypt4${COMPOSE_PROJECT_NAME} env_file: - .env @@ -80,7 +80,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:latest + image: geonode/geoserver:2.23.3-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -106,7 +106,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:latest + image: geonode/geoserver_data:2.23.3-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: @@ -118,7 +118,7 @@ services: # PostGIS database. db: # use geonode official postgis 15 image - image: geonode/postgis:latest + image: geonode/postgis:15.3-v1 command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" container_name: db4${COMPOSE_PROJECT_NAME} env_file: diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 8780e0aea7b..276523a3a4d 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -52,7 +52,7 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: - image: geonode/nginx:latest + image: geonode/nginx:1.25.3-v1 container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: - .env_test @@ -82,7 +82,7 @@ services: # Gets and installs letsencrypt certificates letsencrypt: - image: geonode/letsencrypt:latest + image: geonode/letsencrypt:2.6.0-v1 container_name: letsencrypt4${COMPOSE_PROJECT_NAME} env_file: - .env_test @@ -92,7 +92,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:latest + image: geonode/geoserver:2.23.3-v1 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -118,7 +118,7 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:latest + image: geonode/geoserver_data:2.23.3-v1 container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: @@ -130,7 +130,7 @@ services: # PostGIS database. db: # use geonode official postgis 15 image - image: geonode/postgis:latest + image: geonode/postgis:15.3-v1 command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" container_name: db4${COMPOSE_PROJECT_NAME} env_file: diff --git a/geonode/__init__.py b/geonode/__init__.py index 9b1e32fbb4d..5d15032b0a3 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 0, "dev", 0) +__version__ = (4, 2, 0, "final", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 81a794a4559..124910335d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,9 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -# django-geonode-mapstore-client==4.0.5 --e git+https://github.com/GeoNode/geonode-mapstore-client.git@master#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.2.0 +geonode-importer==1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 37e8ae01318..5e24e8fd6be 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.0.5,<5.0.0 - geonode-importer>=1.0.2 + django-geonode-mapstore-client==4.2.0 + geonode-importer==1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From 73f6ba91da28899a1e0d09d84bcd550e3511688a Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Wed, 10 Jan 2024 17:30:35 +0100 Subject: [PATCH 32/47] Bump to dev dependencies --- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/geonode/__init__.py b/geonode/__init__.py index 5d15032b0a3..9b1e32fbb4d 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 0, "final", 0) +__version__ = (4, 2, 0, "dev", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 124910335d9..4ea6cf81017 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -django-geonode-mapstore-client==4.2.0 -geonode-importer==1.0.6 +-e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client +-e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 5e24e8fd6be..a7e644e412e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client==4.2.0 - geonode-importer==1.0.6 + django-geonode-mapstore-client>=4.2.0,<5.0.0 + geonode-importer>=1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From b1682dbafce403cc91daf965682d654c261a1c85 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 10 Jan 2024 18:55:58 +0100 Subject: [PATCH 33/47] Add long_description_content_type for Markdown (#11831) (#11832) (cherry picked from commit b556709e24fde3122fb480757349afab2df3b1e4) Co-authored-by: Giovanni Allegri --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 498d391199e..2109bd21603 100644 --- a/setup.py +++ b/setup.py @@ -28,6 +28,7 @@ setup( version=__import__("geonode").get_version(), long_description=open("README.md").read(), + long_description_content_type="text/markdown", package_data={ "": ["*.*"], # noqa "": ["static/*.*"], # noqa From 3e1c326ddf0cacc1af71ad6bb652e5f582fbdbca Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 11 Jan 2024 10:35:22 +0100 Subject: [PATCH 34/47] Remove docker-compose-dev reference to nginx script (#11835) --- docker-compose-dev.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 7c355038429..f77b69a506f 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -53,7 +53,6 @@ services: # Nginx is serving django static and media files and proxies to django and geonode geonode: image: geonode/nginx:1.25.3-v1 - build: ./scripts/docker/nginx/ container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: - .env From b8814998155c03b2412e90c7672d897191986885 Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Thu, 11 Jan 2024 10:37:11 +0100 Subject: [PATCH 35/47] Local build for development branch --- docker-compose.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 0f7bfcfd1fc..9c241372858 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,6 +22,9 @@ services: # Our custom django application. It includes Geonode. django: << : *default-common-django + build: + context: ./ + dockerfile: Dockerfile container_name: django4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://django:8000/" From 9f65512c35412767a716b1c04fbac7a16b453d76 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Wed, 17 Jan 2024 18:04:05 +0100 Subject: [PATCH 36/47] Fix minimum version for the client (#11854) Since 4.2.0.dev0 is not considered >= 4.2.0 --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index a7e644e412e..79feeaeb61d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,7 +114,7 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.2.0,<5.0.0 + django-geonode-mapstore-client>=4.1.1,<5.0.0 geonode-importer>=1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 From 3f03d7c8dc080cdc78da2d6925cb969942a21d13 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Mon, 22 Jan 2024 16:46:12 +0100 Subject: [PATCH 37/47] recreated .mo file for italian (#11873) --- geonode/locale/it/LC_MESSAGES/django.mo | Bin 20525 -> 161424 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/geonode/locale/it/LC_MESSAGES/django.mo b/geonode/locale/it/LC_MESSAGES/django.mo index e76a048452590e26ad196fe83e0625f9356e8fdf..cc42b56d611c29c8119d59fe9df28ca870d02a55 100644 GIT binary patch literal 161424 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

Q1;$r@>+O4@-g6eO3I2Lw= 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⪙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 From 445c84c4ababb678b874f1efb21cb61262742d66 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Mon, 22 Jan 2024 16:48:15 +0100 Subject: [PATCH 38/47] [Fixes #11855] Reduce log level in donwload handler (#11856) (#11874) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- geonode/layers/download_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geonode/layers/download_handler.py b/geonode/layers/download_handler.py index d969a0d3703..09eb032a53a 100644 --- a/geonode/layers/download_handler.py +++ b/geonode/layers/download_handler.py @@ -97,7 +97,7 @@ def get_resource(self): _("You do not have download permissions for this dataset."), ) except Exception as e: - logger.exception(e) + logger.debug(e) return self._resource From 47fd6760573645615f2ff4d9dac2dc3129ca06e3 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Mon, 22 Jan 2024 18:00:21 +0100 Subject: [PATCH 39/47] release 4.2.1 (#11875) --- docker-compose.yml | 5 +---- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 9c241372858..37d34a0ad44 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:4.2.x + image: geonode/geonode:4.2.1 restart: unless-stopped env_file: - .env @@ -22,9 +22,6 @@ services: # Our custom django application. It includes Geonode. django: << : *default-common-django - build: - context: ./ - dockerfile: Dockerfile container_name: django4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://django:8000/" diff --git a/geonode/__init__.py b/geonode/__init__.py index 9b1e32fbb4d..db7f3b46ea2 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 0, "dev", 0) +__version__ = (4, 2, 1, "final", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 4ea6cf81017..124910335d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. --e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.2.0 +geonode-importer==1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 79feeaeb61d..5e24e8fd6be 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.1.1,<5.0.0 - geonode-importer>=1.0.6 + django-geonode-mapstore-client==4.2.0 + geonode-importer==1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From cdeb2d95d6224cb364c1dfc52e3a6addf18c0b2c Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Mon, 22 Jan 2024 18:06:08 +0100 Subject: [PATCH 40/47] Bump to 4.2.x --- docker-compose.yml | 5 ++++- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 37d34a0ad44..9c241372858 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: geonode/geonode:4.2.1 + image: geonode/geonode:4.2.x restart: unless-stopped env_file: - .env @@ -22,6 +22,9 @@ services: # Our custom django application. It includes Geonode. django: << : *default-common-django + build: + context: ./ + dockerfile: Dockerfile container_name: django4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://django:8000/" diff --git a/geonode/__init__.py b/geonode/__init__.py index db7f3b46ea2..9b1e32fbb4d 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 1, "final", 0) +__version__ = (4, 2, 0, "dev", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 124910335d9..4ea6cf81017 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. -django-geonode-mapstore-client==4.2.0 -geonode-importer==1.0.6 +-e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client +-e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 5e24e8fd6be..79feeaeb61d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client==4.2.0 - geonode-importer==1.0.6 + django-geonode-mapstore-client>=4.1.1,<5.0.0 + geonode-importer>=1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From bf9b500ccd36c0895eacab0bb2343a0e683cf4bf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:40:57 +0100 Subject: [PATCH 41/47] update version action (#11916) (#11917) (cherry picked from commit 372eb21945172865b2f7cb22718dda352083e573) Co-authored-by: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> --- .github/workflows/flake8.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index a8304f8a1ac..b1b3db4a52e 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -27,7 +27,7 @@ jobs: python-version: ${{matrix.python-version}} - name: Install flake8 & black - run: pip install flake8 black + run: pip install --upgrade $(grep 'flake8\|black' requirements.txt) - name: "Check: flake8" run: | From 5a97c34399c980109145faf0f55253ff5a34fbdc Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 1 Feb 2024 12:49:18 +0100 Subject: [PATCH 42/47] Reformatting for latest Black (#11915) --- create-envfile.py | 6 ++--- geonode/api/resourcebase_api.py | 6 ----- geonode/api/tests.py | 1 - geonode/base/api/permissions.py | 5 ---- geonode/base/api/serializers.py | 2 +- geonode/base/api/tests.py | 6 ++--- geonode/base/forms.py | 1 - geonode/base/tests.py | 1 - geonode/catalogue/metadataxsl/tests.py | 1 - geonode/context_processors.py | 18 +++++++------- geonode/documents/forms.py | 1 - geonode/documents/models.py | 1 - geonode/documents/views.py | 8 ++++--- geonode/geoapps/models.py | 1 - geonode/geoapps/tests.py | 1 - geonode/geoapps/views.py | 8 ++++--- geonode/geoserver/createlayer/tests.py | 1 - geonode/geoserver/tests/integration.py | 2 -- .../harvesting/harvesters/geonodeharvester.py | 24 +++++++++---------- geonode/layers/models.py | 4 ---- geonode/layers/tests.py | 1 - geonode/layers/views.py | 8 ++++--- geonode/maps/models.py | 2 -- geonode/maps/tests.py | 1 - geonode/maps/views.py | 8 ++++--- geonode/monitoring/models.py | 3 --- geonode/security/middleware.py | 1 - geonode/security/models.py | 1 - geonode/security/oauth2_grant_types.py | 1 - geonode/security/oauth2_servers.py | 1 - geonode/security/oauth2_validators.py | 1 - geonode/security/tests.py | 1 - geonode/services/models.py | 1 - geonode/tests/utils.py | 2 -- geonode/upload/upload.py | 1 - geonode/upload/utils.py | 1 - geonode/utils.py | 2 -- 37 files changed, 48 insertions(+), 86 deletions(-) diff --git a/create-envfile.py b/create-envfile.py index c910e912618..88604088ef4 100644 --- a/create-envfile.py +++ b/create-envfile.py @@ -92,9 +92,7 @@ def _get_vals_to_replace(args): _vals_to_replace["letsencrypt_mode"] = ( "disabled" if not _vals_to_replace.get("https_host") - else "staging" - if _jsfile.get("env_type", args.env_type) in ["test"] - else "production" + else "staging" if _jsfile.get("env_type", args.env_type) in ["test"] else "production" ) _vals_to_replace["debug"] = False if _jsfile.get("env_type", args.env_type) in ["prod", "test"] else True _vals_to_replace["email"] = _jsfile.get("email", args.email) @@ -124,7 +122,7 @@ def _get_vals_to_replace(args): prog="ENV file builder", description="Tool for generate environment file automatically. The information can be passed or via CLI or via JSON file ( --file /path/env.json)", usage="python create-envfile.py localhost -f /path/to/json/file.json", - allow_abbrev=False + allow_abbrev=False, ) parser.add_argument( "--noinput", diff --git a/geonode/api/resourcebase_api.py b/geonode/api/resourcebase_api.py index d3a17d08c8a..794a29c884e 100644 --- a/geonode/api/resourcebase_api.py +++ b/geonode/api/resourcebase_api.py @@ -593,7 +593,6 @@ def hydrate_title(self, bundle): class ResourceBaseResource(CommonModelApi): - """ResourceBase api""" class Meta(CommonMetaApi): @@ -607,7 +606,6 @@ class Meta(CommonMetaApi): class FeaturedResourceBaseResource(CommonModelApi): - """Only the featured resourcebases""" class Meta(CommonMetaApi): @@ -620,7 +618,6 @@ class Meta(CommonMetaApi): class LayerResource(CommonModelApi): - """Dataset API""" links = fields.ListField(attribute="links", null=True, use_in="all", default=[]) @@ -756,7 +753,6 @@ class Meta(CommonMetaApi): class MapResource(CommonModelApi): - """Maps API""" def build_filters(self, filters=None, ignore_bad_filters=False, **kwargs): @@ -822,7 +818,6 @@ class Meta(CommonMetaApi): class GeoAppResource(CommonModelApi): - """GeoApps API""" def format_objects(self, objects): @@ -874,7 +869,6 @@ class Meta(CommonMetaApi): class DocumentResource(CommonModelApi): - """Documents API""" def build_filters(self, filters=None, ignore_bad_filters=False, **kwargs): diff --git a/geonode/api/tests.py b/geonode/api/tests.py index 39a428c21fb..61c9214a2c5 100644 --- a/geonode/api/tests.py +++ b/geonode/api/tests.py @@ -386,7 +386,6 @@ def test_tags_lockdown(self): class SearchApiTests(ResourceTestCaseMixin, GeoNodeBaseTestSupport): - """Test the search""" # loading test thesausuri and initial data diff --git a/geonode/base/api/permissions.py b/geonode/base/api/permissions.py index 5dff5b1d33b..75d19ea36d3 100644 --- a/geonode/base/api/permissions.py +++ b/geonode/base/api/permissions.py @@ -41,7 +41,6 @@ class IsSelf(permissions.BasePermission): - """Grant permission only if the current instance is the request user. Used to allow users to edit their own account, nothing to others (even superusers). @@ -62,7 +61,6 @@ def has_object_permission(self, request, view, obj): class IsSelfOrReadOnly(IsSelf): - """Grant permissions if instance *IS* the request user, or read-only. Used to allow users to edit their own account, and others to read. """ @@ -75,7 +73,6 @@ def has_object_permission(self, request, view, obj): class IsSelfOrAdmin(IsSelf): - """Grant R/W to self and superusers/staff members. Deny others.""" def has_permission(self, request, view): @@ -94,7 +91,6 @@ def has_object_permission(self, request, view, obj): class IsSelfOrAdminOrReadOnly(IsSelfOrAdmin): - """Grant R/W to self and superusers/staff members, R/O to others.""" def has_permission(self, request, view): @@ -111,7 +107,6 @@ def has_object_permission(self, request, view, obj): class IsSelfOrAdminOrAuthenticatedReadOnly(IsSelfOrAdmin): - """Grant R/W to self and superusers/staff members, R/O to auth.""" def has_object_permission(self, request, view, obj): diff --git a/geonode/base/api/serializers.py b/geonode/base/api/serializers.py index 01887f4fe4e..eba681a69a1 100644 --- a/geonode/base/api/serializers.py +++ b/geonode/base/api/serializers.py @@ -655,7 +655,7 @@ class Meta: "is_copyable", "blob", "metadata", - "executions" + "executions", # TODO # csw_typename, csw_schema, csw_mdsource, csw_insert_date, csw_type, csw_anytext, csw_wkt_geometry, # metadata_uploaded, metadata_uploaded_preserve, metadata_xml, diff --git a/geonode/base/api/tests.py b/geonode/base/api/tests.py index 4833a955484..fa534cc2bbd 100644 --- a/geonode/base/api/tests.py +++ b/geonode/base/api/tests.py @@ -1951,10 +1951,10 @@ def test_set_resource_thumbnail(self): self.assertEqual(response.json(), "The url must be of an image with format (png, jpeg or jpg)") # using Base64 data as an ASCII byte string - data[ - "file" - ] = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\ + data["file"] = ( + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\ fAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAANSURBVAiZYzAxMfkPAALYAZzx61+bAAAAAElFTkSuQmCC" + ) with patch("geonode.base.models.is_monochromatic_image") as _mck: _mck.return_value = False response = self.client.put(url, data=data, format="json") diff --git a/geonode/base/forms.py b/geonode/base/forms.py index 8c6bd6bd816..8152da290e5 100644 --- a/geonode/base/forms.py +++ b/geonode/base/forms.py @@ -412,7 +412,6 @@ def build_attrs(self, base_attrs=None, extra_attrs=None, **kwargs): class ResourceBaseForm(TranslationModelForm, LinkedResourceForm): - """Base form for metadata, should be inherited by childres classes of ResourceBase""" abstract = forms.CharField(label=_("Abstract"), required=False, widget=TinyMCE()) diff --git a/geonode/base/tests.py b/geonode/base/tests.py index f3741425074..bcadaa07931 100644 --- a/geonode/base/tests.py +++ b/geonode/base/tests.py @@ -166,7 +166,6 @@ def test_add_missing_metadata_author_or_poc(self): class TestCreationOfContactRolesByDifferentInputTypes(ThumbnailTests): - """ Test that contact roles can be set as people profile """ diff --git a/geonode/catalogue/metadataxsl/tests.py b/geonode/catalogue/metadataxsl/tests.py index e09c1291a5f..bce9b262c6e 100644 --- a/geonode/catalogue/metadataxsl/tests.py +++ b/geonode/catalogue/metadataxsl/tests.py @@ -25,7 +25,6 @@ class MetadataXSLTest(GeoNodeBaseTestSupport): - """ Tests geonode.catalogue.metadataxsl app/module """ diff --git a/geonode/context_processors.py b/geonode/context_processors.py index e4ce5757521..1230a20cbf8 100644 --- a/geonode/context_processors.py +++ b/geonode/context_processors.py @@ -86,15 +86,17 @@ def resource_urls(request): EXIF_ENABLED=getattr(settings, "EXIF_ENABLED", False), FAVORITE_ENABLED=getattr(settings, "FAVORITE_ENABLED", False), SEARCH_FILTERS=getattr(settings, "SEARCH_FILTERS", False), - THESAURI_FILTERS=[ - t["name"] - for t in [ - settings.THESAURUS, + THESAURI_FILTERS=( + [ + t["name"] + for t in [ + settings.THESAURUS, + ] + if t.get("filter") ] - if t.get("filter") - ] - if hasattr(settings, "THESAURUS") - else [t.identifier for t in thesaurus], + if hasattr(settings, "THESAURUS") + else [t.identifier for t in thesaurus] + ), MAP_CLIENT_USE_CROSS_ORIGIN_CREDENTIALS=getattr(settings, "MAP_CLIENT_USE_CROSS_ORIGIN_CREDENTIALS", False), SHOW_PROFILE_EMAIL=getattr(settings, "SHOW_PROFILE_EMAIL", False), OGC_SERVER=getattr(settings, "OGC_SERVER", None), diff --git a/geonode/documents/forms.py b/geonode/documents/forms.py index 42671e98172..7568dc6863b 100644 --- a/geonode/documents/forms.py +++ b/geonode/documents/forms.py @@ -117,7 +117,6 @@ class DocumentDescriptionForm(forms.Form): class DocumentCreateForm(TranslationModelForm): - """ The document upload form. """ diff --git a/geonode/documents/models.py b/geonode/documents/models.py index d7650f5b0ae..e4815dc8da9 100644 --- a/geonode/documents/models.py +++ b/geonode/documents/models.py @@ -37,7 +37,6 @@ class Document(ResourceBase): - """ A document is any kind of information that can be attached to a map such as pdf, images, videos, xls... """ diff --git a/geonode/documents/views.py b/geonode/documents/views.py index ca72be2f6a4..49a4c605b1b 100644 --- a/geonode/documents/views.py +++ b/geonode/documents/views.py @@ -322,9 +322,11 @@ def document_metadata( category_form = CategoryForm( request.POST, prefix="category_choice_field", - initial=int(request.POST["category_choice_field"]) - if "category_choice_field" in request.POST and request.POST["category_choice_field"] - else None, + initial=( + int(request.POST["category_choice_field"]) + if "category_choice_field" in request.POST and request.POST["category_choice_field"] + else None + ), ) if hasattr(settings, "THESAURUS"): diff --git a/geonode/geoapps/models.py b/geonode/geoapps/models.py index db57d96f3e3..a3edfff60e1 100644 --- a/geonode/geoapps/models.py +++ b/geonode/geoapps/models.py @@ -31,7 +31,6 @@ class GeoApp(ResourceBase): - """ A GeoApp it is a generic container for every client applications the user might want to create or define. diff --git a/geonode/geoapps/tests.py b/geonode/geoapps/tests.py index c42c1733af6..c4566d604e2 100644 --- a/geonode/geoapps/tests.py +++ b/geonode/geoapps/tests.py @@ -31,7 +31,6 @@ class GeoAppTests(GeoNodeBaseTestSupport): - """Tests geonode.geoapps module""" fixtures = ["initial_data.json", "group_test_data.json", "default_oauth_apps.json"] diff --git a/geonode/geoapps/views.py b/geonode/geoapps/views.py index f83457ae67e..6cb6814bb25 100644 --- a/geonode/geoapps/views.py +++ b/geonode/geoapps/views.py @@ -216,9 +216,11 @@ def geoapp_metadata( category_form = CategoryForm( request.POST, prefix="category_choice_field", - initial=int(request.POST["category_choice_field"]) - if "category_choice_field" in request.POST and request.POST["category_choice_field"] - else None, + initial=( + int(request.POST["category_choice_field"]) + if "category_choice_field" in request.POST and request.POST["category_choice_field"] + else None + ), ) if hasattr(settings, "THESAURUS"): diff --git a/geonode/geoserver/createlayer/tests.py b/geonode/geoserver/createlayer/tests.py index 87d40a4d56d..eb18bc45b34 100644 --- a/geonode/geoserver/createlayer/tests.py +++ b/geonode/geoserver/createlayer/tests.py @@ -33,7 +33,6 @@ class CreateLayerCoreTest(GeoNodeBaseTestSupport): - """ Test createlayer application. """ diff --git a/geonode/geoserver/tests/integration.py b/geonode/geoserver/tests/integration.py index 7fd155210ca..39d8040e80f 100644 --- a/geonode/geoserver/tests/integration.py +++ b/geonode/geoserver/tests/integration.py @@ -56,7 +56,6 @@ def _log(msg, *args): @override_settings(SITEURL="http://localhost:8001/") class GeoNodeGeoServerSync(GeoNodeLiveTestSupport): - """ Tests GeoNode/GeoServer syncronization """ @@ -104,7 +103,6 @@ def test_set_attributes_from_geoserver(self): @override_settings(SITEURL="http://localhost:8002/") class GeoNodeGeoServerCapabilities(GeoNodeLiveTestSupport): - """ Tests GeoNode/GeoServer GetCapabilities per layer, user, category and map """ diff --git a/geonode/harvesting/harvesters/geonodeharvester.py b/geonode/harvesting/harvesters/geonodeharvester.py index 0f9de873476..dad1571b920 100644 --- a/geonode/harvesting/harvesters/geonodeharvester.py +++ b/geonode/harvesting/harvesters/geonodeharvester.py @@ -433,14 +433,14 @@ def _get_resource_list_params(self, offset: typing.Optional[int] = 0) -> typing. result["filter{title.icontains}"] = self.resource_title_filter if self.start_date_filter is not None: start_date = dateutil.parser.parse(self.start_date_filter) - result[ - "filter{date.gte}" - ] = f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + result["filter{date.gte}"] = ( + f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + ) if self.end_date_filter is not None: end_date = dateutil.parser.parse(self.end_date_filter) - result[ - "filter{date.lte}" - ] = f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + result["filter{date.lte}"] = ( + f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + ) if self.keywords_filter is not None: result["filter{keywords.slug.in}"] = self.keywords_filter if self.categories_filter is not None: @@ -738,14 +738,14 @@ def _get_resource_list_params(self, offset: typing.Optional[int] = 0) -> typing. result["title__icontains"] = self.resource_title_filter if self.start_date_filter is not None: start_date = dateutil.parser.parse(self.start_date_filter) - result[ - "date__gte" - ] = f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + result["date__gte"] = ( + f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + ) if self.end_date_filter is not None: end_date = dateutil.parser.parse(self.end_date_filter) - result[ - "date__lte" - ] = f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + result["date__lte"] = ( + f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" + ) if self.keywords_filter is not None: result["keywords__slug__in"] = ",".join(self.keywords_filter) if self.categories_filter is not None: diff --git a/geonode/layers/models.py b/geonode/layers/models.py index 22eb2eff0cd..bed803f7220 100644 --- a/geonode/layers/models.py +++ b/geonode/layers/models.py @@ -61,7 +61,6 @@ class Style(models.Model, PermissionLevelMixin): - """Model for storing styles.""" name = models.CharField(_("style name"), max_length=255, unique=True) @@ -103,7 +102,6 @@ def __init__(self): class Dataset(ResourceBase): - """ Dataset (inherits ResourceBase fields) """ @@ -376,7 +374,6 @@ def view_count_up(self, user, do_local=False): class AttributeManager(models.Manager): - """Helper class to access filtered attributes""" def visible(self): @@ -384,7 +381,6 @@ def visible(self): class Attribute(models.Model): - """ Auxiliary model for storing layer attributes. diff --git a/geonode/layers/tests.py b/geonode/layers/tests.py index c4d0bf88f0b..bc7d6ff27b6 100644 --- a/geonode/layers/tests.py +++ b/geonode/layers/tests.py @@ -90,7 +90,6 @@ class DatasetsTest(GeoNodeBaseTestSupport): - """Tests geonode.layers app/module""" type = "dataset" diff --git a/geonode/layers/views.py b/geonode/layers/views.py index f7729d2ce09..8b0c585af9c 100644 --- a/geonode/layers/views.py +++ b/geonode/layers/views.py @@ -414,9 +414,11 @@ def dataset_metadata( category_form = CategoryForm( request.POST, prefix="category_choice_field", - initial=int(request.POST["category_choice_field"]) - if "category_choice_field" in request.POST and request.POST["category_choice_field"] - else None, + initial=( + int(request.POST["category_choice_field"]) + if "category_choice_field" in request.POST and request.POST["category_choice_field"] + else None + ), ) if not category_form.is_valid(): logger.error(f"Dataset Category form is not valid: {category_form.errors}") diff --git a/geonode/maps/models.py b/geonode/maps/models.py index 546b71fb8ce..ad7630abc99 100644 --- a/geonode/maps/models.py +++ b/geonode/maps/models.py @@ -37,7 +37,6 @@ class Map(ResourceBase): - """ A Map aggregates several layers together and annotates them with a viewport configuration. @@ -231,7 +230,6 @@ class Meta(ResourceBase.Meta): class MapLayer(models.Model): - """ The MapLayer model represents a layer included in a map. This doesn't just identify the dataset, but also extra options such as which style to load diff --git a/geonode/maps/tests.py b/geonode/maps/tests.py index fdb5d74bb42..9d0748a8db2 100644 --- a/geonode/maps/tests.py +++ b/geonode/maps/tests.py @@ -79,7 +79,6 @@ class MapsTest(NotificationsTestsHelper): - """Tests geonode.maps app/module""" fixtures = ["initial_data.json", "group_test_data.json", "default_oauth_apps.json"] diff --git a/geonode/maps/views.py b/geonode/maps/views.py index bc4271b8799..a82c1741e74 100644 --- a/geonode/maps/views.py +++ b/geonode/maps/views.py @@ -107,9 +107,11 @@ def map_metadata( category_form = CategoryForm( request.POST, prefix="category_choice_field", - initial=int(request.POST["category_choice_field"]) - if "category_choice_field" in request.POST and request.POST["category_choice_field"] - else None, + initial=( + int(request.POST["category_choice_field"]) + if "category_choice_field" in request.POST and request.POST["category_choice_field"] + else None + ), ) if hasattr(settings, "THESAURUS"): diff --git a/geonode/monitoring/models.py b/geonode/monitoring/models.py index 18f302c73dc..dd28350f81a 100644 --- a/geonode/monitoring/models.py +++ b/geonode/monitoring/models.py @@ -69,7 +69,6 @@ def get_geoip(): class Host(models.Model): - """ Describes one physical instance """ @@ -83,7 +82,6 @@ def __str__(self): class ServiceType(models.Model): - """ Service Type list """ @@ -129,7 +127,6 @@ def is_system_monitor(self): class Service(models.Model): - """ Service is a entity describing deployed processes. """ diff --git a/geonode/security/middleware.py b/geonode/security/middleware.py index 07fa80ed745..82bdc6ea9b3 100644 --- a/geonode/security/middleware.py +++ b/geonode/security/middleware.py @@ -70,7 +70,6 @@ class LoginRequiredMiddleware(MiddlewareMixin): - """ Requires a user to be logged in to access any page that is not white-listed. diff --git a/geonode/security/models.py b/geonode/security/models.py index b89a00c2782..2a878368827 100644 --- a/geonode/security/models.py +++ b/geonode/security/models.py @@ -57,7 +57,6 @@ class PermissionLevelError(Exception): class PermissionLevelMixin: - """ Mixin for adding "Permission Level" methods to a model class -- eg role systems where a diff --git a/geonode/security/oauth2_grant_types.py b/geonode/security/oauth2_grant_types.py index 63b865269a6..7ab3575fca1 100644 --- a/geonode/security/oauth2_grant_types.py +++ b/geonode/security/oauth2_grant_types.py @@ -76,7 +76,6 @@ def code_challenge_method_plain(verifier, challenge): class OAuth2AuthorizationCodeGrant(GrantTypeBase): - """`Authorization Code Grant`_ The authorization code grant type is used to obtain both access diff --git a/geonode/security/oauth2_servers.py b/geonode/security/oauth2_servers.py index ead8a714e5b..5a1890aefd6 100644 --- a/geonode/security/oauth2_servers.py +++ b/geonode/security/oauth2_servers.py @@ -46,7 +46,6 @@ class OIDCServer( AuthorizationEndpoint, IntrospectEndpoint, TokenEndpoint, ResourceEndpoint, RevocationEndpoint, UserInfoEndpoint ): - """An all-in-one endpoint featuring all four major grant types.""" def __init__( diff --git a/geonode/security/oauth2_validators.py b/geonode/security/oauth2_validators.py index 0b93b6ed0c6..c5b0bfea230 100644 --- a/geonode/security/oauth2_validators.py +++ b/geonode/security/oauth2_validators.py @@ -34,7 +34,6 @@ class OIDCValidator(OAuth2Validator): - """e.g. Check username and password correspond to a valid and active User, if fails try Facebook token authentication diff --git a/geonode/security/tests.py b/geonode/security/tests.py index f80a0ef8a52..433f4aa6de7 100644 --- a/geonode/security/tests.py +++ b/geonode/security/tests.py @@ -104,7 +104,6 @@ def write(self, buf): class SecurityTests(ResourceTestCaseMixin, GeoNodeBaseTestSupport): - """ Tests for the Geonode security app. """ diff --git a/geonode/services/models.py b/geonode/services/models.py index db56adba495..c6ccf3874b4 100644 --- a/geonode/services/models.py +++ b/geonode/services/models.py @@ -118,7 +118,6 @@ class Meta: class ServiceProfileRole(models.Model): - """ ServiceProfileRole is an intermediate model to bind Profiles and Services and apply roles. """ diff --git a/geonode/tests/utils.py b/geonode/tests/utils.py index 4466f76a6e2..b861f2a0e8a 100644 --- a/geonode/tests/utils.py +++ b/geonode/tests/utils.py @@ -62,7 +62,6 @@ def upload_step(step=None): class Client(DjangoTestClient): - """client for making http requests""" def __init__(self, url, user, passwd, *args, **kwargs): @@ -310,7 +309,6 @@ def check_dataset(uploaded): from pinax.notifications.models import NoticeQueueBatch class NotificationsTestsHelper(GeoNodeBaseTestSupport): - """ Helper class for notification tests This provides: diff --git a/geonode/upload/upload.py b/geonode/upload/upload.py index 0777cb83d3a..4a3feb25d7b 100644 --- a/geonode/upload/upload.py +++ b/geonode/upload/upload.py @@ -39,7 +39,6 @@ class UploaderSession: - """All objects held must be able to survive a good pickling""" # the gsimporter session object diff --git a/geonode/upload/utils.py b/geonode/upload/utils.py index d81f63e9ba5..ea8189e47b9 100644 --- a/geonode/upload/utils.py +++ b/geonode/upload/utils.py @@ -111,7 +111,6 @@ def _log(msg, *args, level="error"): class JSONResponse(HttpResponse): - """JSON response class.""" def __init__(self, obj="", json_opts=None, content_type="application/json", *args, **kwargs): diff --git a/geonode/utils.py b/geonode/utils.py index d15dafe3162..ffa931c3cf4 100755 --- a/geonode/utils.py +++ b/geonode/utils.py @@ -137,7 +137,6 @@ class ServerDoesNotExist(Exception): class OGC_Server(object): # LGTM: @property will not work in old-style classes - """ OGC Server object. """ @@ -211,7 +210,6 @@ def __str__(self): class OGC_Servers_Handler: - """ OGC Server Settings Convenience dict. """ From c4c52c18405885a1f2699e3b8723b8760026605b Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Thu, 1 Feb 2024 13:29:25 +0100 Subject: [PATCH 43/47] =?UTF-8?q?[Backport=204.2.x=20]=20[Fixes=20#11912]?= =?UTF-8?q?=20GWC=20layers=20only=20cache=20default=20style=20after=20B/R?= =?UTF-8?q?=20restore=20=E2=80=A6=20(#11914)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Fixes #11912] GWC layers only cache default style after B/R restore (#11913) Co-authored-by: G. Allegri * Reformatting for latest Black --------- Co-authored-by: Emanuele Tajariol --- .../management/commands/create_tile_layers.py | 73 +++++++++++++++---- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/geonode/br/management/commands/create_tile_layers.py b/geonode/br/management/commands/create_tile_layers.py index eb5d2cfc12b..57b81d805aa 100644 --- a/geonode/br/management/commands/create_tile_layers.py +++ b/geonode/br/management/commands/create_tile_layers.py @@ -42,12 +42,12 @@ application/json;type=utfgrid + image/gif + image/jpeg image/png + image/png8 image/vnd.jpeg-png - image/jpeg image/vnd.jpeg-png8 - image/gif - image/png8 @@ -66,6 +66,11 @@ EPSG:900913 + 0 + 0 + true + 0 + """ @@ -73,9 +78,36 @@ class Command(BaseCommand): help = "Create missing TileLayers in GWC" def add_arguments(self, parser): - pass + parser.add_argument( + '-f', + '--force', + dest="force", + action='store_true', + help="Force tile layer re-creation also if it already exists in GWC") + + parser.add_argument( + '-l', + '--layer', + dest="layers", + action='append', + help="Only process specified layers ") + + parser.add_argument( + '-d', + '--dry-run', + dest="dry-run", + action='store_true', + help="Do not actually perform any change on GWC") def handle(self, **options): + force = options.get('force') + requested_layers = options.get('layers') + dry_run = options.get('dry-run') + + logger.debug(f"FORCE is {force}") + logger.debug(f"DRY-RUN is {dry_run}") + logger.debug(f"LAYERS is {requested_layers}") + try: baseurl = settings.OGC_SERVER["default"]["LOCATION"] user = settings.OGC_SERVER["default"]["USER"] @@ -91,24 +123,38 @@ def handle(self, **options): cnt_old = 0 cnt_new = 0 cnt_bad = 0 + cnt_skip = 0 + cnt_force = 0 for layer in layers: i += 1 logger.info(f"- {i}/{tot} Processing layer: {layer.typename}") + + if requested_layers and layer.typename not in requested_layers: + logger.info(" - Layer filtered out by args") + cnt_skip += 1 + continue + r = requests.get(f"{baseurl}gwc/rest/layers/{layer.typename}.xml", auth=HTTPBasicAuth(user, passwd)) if r.status_code == 200: - logger.info(" - Layer already configured") - cnt_old += 1 - continue + if force: + logger.info(" - Forcing layer configuration in GWC") + cnt_force += 1 + else: + logger.info(" - Layer already configured in GWC") + cnt_old += 1 + continue try: data = REQ_TEMPLATE.format(layer.name) url = f"{baseurl}gwc/rest/layers/{layer.typename}.xml" logger.info(" - Configuring...") - response = requests.put( - url, data=data, headers={"Content-Type": "text/xml"}, auth=HTTPBasicAuth(user, passwd) - ) - if response.status_code == 200: + if not dry_run: + response = requests.put( + url, data=data, headers={"Content-Type": "text/xml"}, auth=HTTPBasicAuth(user, passwd) + ) + + if dry_run or response.status_code == 200: logger.info(f" - Done {layer.name}") cnt_new += 1 else: @@ -121,6 +167,7 @@ def handle(self, **options): raise e logger.info("Work completed") - logger.info(f"- TileLayers configured: {cnt_new}") + logger.info(f"- TileLayers configured: {cnt_new}" + (f" (forced {cnt_force})" if cnt_force else "")) logger.info(f"- TileLayers in error : {cnt_bad}") - logger.info(f"- TileLayers found : {cnt_old}") + logger.info(f"- TileLayers untouched : {cnt_old}") + logger.info(f"- TileLayers skipped : {cnt_skip}") From 3f382b28053c4d2e8d97fe803efc83a1f67ae0a9 Mon Sep 17 00:00:00 2001 From: Giovanni Allegri Date: Fri, 2 Feb 2024 16:17:14 +0100 Subject: [PATCH 44/47] Upgrade Geoserver with fix for oauth2 (#11929) * Upgrade Geoserver with fix for oauth2 * fixes to black formaating --- docker-compose-dev.yml | 2 +- docker-compose-test.yml | 2 +- docker-compose.yml | 2 +- geonode/base/api/tests.py | 6 ++--- .../harvesting/harvesters/geonodeharvester.py | 24 +++++++++---------- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index f77b69a506f..19b81b0985a 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -79,7 +79,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.3-v1 + image: geonode/geoserver:2.23.3-v2 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 276523a3a4d..a0da45aafa0 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -92,7 +92,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.3-v1 + image: geonode/geoserver:2.23.3-v2 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" diff --git a/docker-compose.yml b/docker-compose.yml index 9c241372858..d073b1cbbcf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -91,7 +91,7 @@ services: # Geoserver backend geoserver: - image: geonode/geoserver:2.23.3-v1 + image: geonode/geoserver:2.23.3-v2 container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" diff --git a/geonode/base/api/tests.py b/geonode/base/api/tests.py index fa534cc2bbd..4833a955484 100644 --- a/geonode/base/api/tests.py +++ b/geonode/base/api/tests.py @@ -1951,10 +1951,10 @@ def test_set_resource_thumbnail(self): self.assertEqual(response.json(), "The url must be of an image with format (png, jpeg or jpg)") # using Base64 data as an ASCII byte string - data["file"] = ( - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\ + data[ + "file" + ] = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\ fAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAANSURBVAiZYzAxMfkPAALYAZzx61+bAAAAAElFTkSuQmCC" - ) with patch("geonode.base.models.is_monochromatic_image") as _mck: _mck.return_value = False response = self.client.put(url, data=data, format="json") diff --git a/geonode/harvesting/harvesters/geonodeharvester.py b/geonode/harvesting/harvesters/geonodeharvester.py index dad1571b920..0f9de873476 100644 --- a/geonode/harvesting/harvesters/geonodeharvester.py +++ b/geonode/harvesting/harvesters/geonodeharvester.py @@ -433,14 +433,14 @@ def _get_resource_list_params(self, offset: typing.Optional[int] = 0) -> typing. result["filter{title.icontains}"] = self.resource_title_filter if self.start_date_filter is not None: start_date = dateutil.parser.parse(self.start_date_filter) - result["filter{date.gte}"] = ( - f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" - ) + result[ + "filter{date.gte}" + ] = f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" if self.end_date_filter is not None: end_date = dateutil.parser.parse(self.end_date_filter) - result["filter{date.lte}"] = ( - f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" - ) + result[ + "filter{date.lte}" + ] = f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" if self.keywords_filter is not None: result["filter{keywords.slug.in}"] = self.keywords_filter if self.categories_filter is not None: @@ -738,14 +738,14 @@ def _get_resource_list_params(self, offset: typing.Optional[int] = 0) -> typing. result["title__icontains"] = self.resource_title_filter if self.start_date_filter is not None: start_date = dateutil.parser.parse(self.start_date_filter) - result["date__gte"] = ( - f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" - ) + result[ + "date__gte" + ] = f"{start_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" if self.end_date_filter is not None: end_date = dateutil.parser.parse(self.end_date_filter) - result["date__lte"] = ( - f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" - ) + result[ + "date__lte" + ] = f"{end_date.astimezone(dt.timezone.utc).replace(microsecond=0).isoformat().split('+')[0]}Z" if self.keywords_filter is not None: result["keywords__slug__in"] = ",".join(self.keywords_filter) if self.categories_filter is not None: From 6128b84993e6f58cf2b9ce031a7cb337e363fe0a Mon Sep 17 00:00:00 2001 From: "G. Allegri" Date: Mon, 5 Feb 2024 10:41:06 +0100 Subject: [PATCH 45/47] Prepare release 4.2.2 --- geonode/__init__.py | 2 +- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/geonode/__init__.py b/geonode/__init__.py index 9b1e32fbb4d..95d5717c446 100644 --- a/geonode/__init__.py +++ b/geonode/__init__.py @@ -19,7 +19,7 @@ import os -__version__ = (4, 2, 0, "dev", 0) +__version__ = (4, 2, 2, "final", 0) default_app_config = "geonode.apps.AppConfig" diff --git a/requirements.txt b/requirements.txt index 4ea6cf81017..124910335d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -88,8 +88,8 @@ pinax-notifications==6.0.0 pinax-ratings==4.0.0 # GeoNode org maintained apps. --e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer +django-geonode-mapstore-client==4.2.0 +geonode-importer==1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 diff --git a/setup.cfg b/setup.cfg index 79feeaeb61d..5e24e8fd6be 100644 --- a/setup.cfg +++ b/setup.cfg @@ -114,8 +114,8 @@ install_requires = pinax-ratings==4.0.0 # GeoNode org maintained apps. - django-geonode-mapstore-client>=4.1.1,<5.0.0 - geonode-importer>=1.0.6 + django-geonode-mapstore-client==4.2.0 + geonode-importer==1.0.6 django-avatar==7.1.1 geonode-oauth-toolkit==2.2.2 geonode-user-messages==2.0.2 From cdea68131de06d1a9d54659fb338eaacfc5012b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:28:33 +0100 Subject: [PATCH 46/47] build(deps): bump django-allauth from 0.54.0 to 0.60.1 (#11908) * build(deps): bump django-allauth from 0.54.0 to 0.60.1 Bumps [django-allauth](https://github.com/pennersr/django-allauth) from 0.54.0 to 0.60.1. - [Changelog](https://github.com/pennersr/django-allauth/blob/main/ChangeLog.rst) - [Commits](https://github.com/pennersr/django-allauth/compare/0.54.0...0.60.1) --- updated-dependencies: - dependency-name: django-allauth dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * - Align setup.cfg to requirements.txt * - allauth.account.middleware.AccountMiddleware must be added to settings.MIDDLEWARE * - fix def get_provider(self, request, provider) override issue * - fix def get_provider(self, request, provider) override issue * - fix socialaccount testcases * - fix build --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani --- geonode/people/adapters.py | 26 +++++- .../providers/geonode_openid_connect/tests.py | 80 ++++++++++++++++++- geonode/settings.py | 1 + requirements.txt | 5 ++ setup.cfg | 4 +- 5 files changed, 112 insertions(+), 4 deletions(-) diff --git a/geonode/people/adapters.py b/geonode/people/adapters.py index 2a24f6f0bc1..7d0ef8dacb2 100644 --- a/geonode/people/adapters.py +++ b/geonode/people/adapters.py @@ -43,7 +43,7 @@ from django.http import HttpResponseRedirect from django.core.exceptions import ValidationError from django.utils.module_loading import import_string - +from django.core.exceptions import ImproperlyConfigured from geonode.groups.models import GroupProfile logger = logging.getLogger(__name__) @@ -257,6 +257,30 @@ class GenericOpenIDConnectAdapter(OAuth2Adapter, SocialAccountAdapter): profile_url = PROFILE_URL id_token_issuer = ID_TOKEN_ISSUER + def get_provider(self, request=None, provider=None): + """Looks up a `provider`, supporting subproviders by looking up by + `provider_id`. + """ + from allauth.socialaccount.providers import registry + + request = request or self.request + provider = provider or self.provider_id + provider_class = registry.get_class(provider) + if provider_class is None or provider_class.uses_apps: + app = self.get_app(request, provider=provider) + if not provider_class: + # In this case, the `provider` argument passed was a + # `provider_id`. + provider_class = registry.get_class(app.provider) + if not provider_class: + raise ImproperlyConfigured(f"unknown provider: {app.provider}") + return provider_class(request, app=app) + elif provider_class: + assert not provider_class.uses_apps + return provider_class(request, app=None) + else: + raise ImproperlyConfigured(f"unknown provider: {app.provider}") + def complete_login(self, request, app, token, response, **kwargs): extra_data = {} if self.profile_url: diff --git a/geonode/people/socialaccount/providers/geonode_openid_connect/tests.py b/geonode/people/socialaccount/providers/geonode_openid_connect/tests.py index 04be234c6c3..3baa76fb317 100644 --- a/geonode/people/socialaccount/providers/geonode_openid_connect/tests.py +++ b/geonode/people/socialaccount/providers/geonode_openid_connect/tests.py @@ -19,8 +19,10 @@ from __future__ import absolute_import, unicode_literals import json +import pytest from datetime import datetime, timedelta from importlib import import_module +from unittest.mock import Mock, patch from django.conf import settings from django.core import mail @@ -31,13 +33,28 @@ from allauth.account import app_settings as account_settings from allauth.account.adapter import get_adapter +from allauth.socialaccount.models import SocialAccount from allauth.account.models import EmailAddress, EmailConfirmation from allauth.account.signals import user_signed_up # from allauth.socialaccount.models import SocialAccount from allauth.socialaccount.providers.apple.client import jwt_encode from allauth.socialaccount.tests import OAuth2TestsMixin -from allauth.tests import TestCase +from allauth.tests import TestCase, mocked_response + + +@pytest.fixture +def settings_with_google_provider(settings): + settings.SOCIALACCOUNT_PROVIDERS = { + "geonode_openid_connect": { + "APP": { + "client_id": "app123id", + "key": "google", + "secret": "dummy", + } + } + } + return settings @override_settings( @@ -45,6 +62,25 @@ SOCIALACCOUNT_AUTO_SIGNUP=True, ACCOUNT_SIGNUP_FORM_CLASS=None, ACCOUNT_EMAIL_VERIFICATION=account_settings.EmailVerificationMethod.MANDATORY, + SOCIALACCOUNT_PROVIDERS={ + "geonode_openid_connect": { + "NAME": "Google", + "SCOPE": [ + "profile", + "email", + ], + "AUTH_PARAMS": { + "access_type": "online", + "prompt": "select_account consent", + }, + "COMMON_FIELDS": {"email": "email", "last_name": "family_name", "first_name": "given_name"}, + "ACCOUNT_CLASS": "allauth.socialaccount.providers.google.provider.GoogleAccount", + "ACCESS_TOKEN_URL": "https://oauth2.googleapis.com/token", + "AUTHORIZE_URL": "https://accounts.google.com/o/oauth2/v2/auth", + "ID_TOKEN_ISSUER": "https://accounts.google.com", + "OAUTH_PKCE_ENABLED": True, + } + }, ) class GoogleTests(OAuth2TestsMixin, TestCase): provider_id = "geonode_openid_connect" @@ -54,6 +90,9 @@ def setUp(self): self.email = "raymond.penners@example.com" self.identity_overwrites = {} + def test_account_tokens(self, multiple_login=False): + pass + def get_google_id_token_payload(self): now = datetime.utcnow() client_id = "app123id" # Matches `setup_app` @@ -227,3 +266,42 @@ class AppInSettingsTests(GoogleTests): """ pass + + +def test_login_by_token(db, client, settings_with_google_provider): + client.cookies.load({"g_csrf_token": "csrf"}) + with patch("allauth.socialaccount.providers.google.views.jwt.get_unverified_header") as g_u_h: + with mocked_response({"dummykid": "-----BEGIN CERTIFICATE-----"}): + with patch("allauth.socialaccount.providers.google.views.load_pem_x509_certificate") as load_pem: + with patch("allauth.socialaccount.providers.google.views.jwt.decode") as decode: + decode.return_value = { + "iss": "https://accounts.google.com", + "aud": "client_id", + "sub": "123sub", + "hd": "example.com", + "email": "raymond@example.com", + "email_verified": True, + "at_hash": "HK6E_P6Dh8Y93mRNtsDB1Q", + "name": "Raymond Penners", + "picture": "https://lh5.googleusercontent.com/photo.jpg", + "given_name": "Raymond", + "family_name": "Penners", + "locale": "en", + "iat": 123, + "exp": 456, + } + g_u_h.return_value = { + "alg": "RS256", + "kid": "dummykid", + "typ": "JWT", + } + pem = Mock() + load_pem.return_value = pem + pem.public_key.return_value = "key" + resp = client.post( + reverse("google_login_by_token"), + {"credential": "dummy", "g_csrf_token": "csrf"}, + ) + assert resp.status_code == 302 + socialaccount = SocialAccount.objects.get(uid="123sub") + assert socialaccount.user.email == "raymond@example.com" diff --git a/geonode/settings.py b/geonode/settings.py index 2224bce108f..d902044e378 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -805,6 +805,7 @@ MIDDLEWARE = ( "corsheaders.middleware.CorsMiddleware", "django.middleware.common.CommonMiddleware", + "allauth.account.middleware.AccountMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.contrib.sites.middleware.CurrentSiteMiddleware", diff --git a/requirements.txt b/requirements.txt index 67f7a84d1b8..114ff67117e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -32,8 +32,13 @@ pathvalidate==3.2.0 sentry-sdk # Django Apps +<<<<<<< HEAD django-allauth==0.54.0 django-appconf==1.0.5 +======= +django-allauth==0.60.1 +django-appconf==1.0.6 +>>>>>>> c7c4dfb46 (build(deps): bump django-allauth from 0.54.0 to 0.60.1 (#11908)) django-celery-results==2.5.1 django-filter==23.3 django-imagekit==4.1.0 diff --git a/setup.cfg b/setup.cfg index 5e24e8fd6be..371b86adf2e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -55,8 +55,8 @@ install_requires = pathvalidate==3.2.0 # Django Apps - django-allauth==0.54.0 - django-appconf==1.0.5 + django-allauth==0.60.1 + django-appconf==1.0.6 django-celery-results==2.5.1 django-filter==23.3 django-imagekit==4.1.0 From 6f7108b7ce78e3d31a770e2cb37890f3e0bc50f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 10:47:19 +0100 Subject: [PATCH 47/47] build(deps): bump django-allauth from 0.60.1 to 0.61.1 (#11950) * build(deps): bump django-allauth from 0.60.1 to 0.61.1 Bumps [django-allauth](https://github.com/pennersr/django-allauth) from 0.60.1 to 0.61.1. - [Changelog](https://github.com/pennersr/django-allauth/blob/main/ChangeLog.rst) - [Commits](https://github.com/pennersr/django-allauth/compare/0.60.1...0.61.1) --- updated-dependencies: - dependency-name: django-allauth dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * - Align setup.cfg to requirements.txt --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afabiani --- requirements.txt | 7 +------ setup.cfg | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/requirements.txt b/requirements.txt index 114ff67117e..c523787d4bc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -32,13 +32,8 @@ pathvalidate==3.2.0 sentry-sdk # Django Apps -<<<<<<< HEAD -django-allauth==0.54.0 -django-appconf==1.0.5 -======= -django-allauth==0.60.1 +django-allauth==0.61.1 django-appconf==1.0.6 ->>>>>>> c7c4dfb46 (build(deps): bump django-allauth from 0.54.0 to 0.60.1 (#11908)) django-celery-results==2.5.1 django-filter==23.3 django-imagekit==4.1.0 diff --git a/setup.cfg b/setup.cfg index 371b86adf2e..b7989c59867 100644 --- a/setup.cfg +++ b/setup.cfg @@ -55,7 +55,7 @@ install_requires = pathvalidate==3.2.0 # Django Apps - django-allauth==0.60.1 + django-allauth==0.61.1 django-appconf==1.0.6 django-celery-results==2.5.1 django-filter==23.3