diff --git a/.clabot b/.clabot
index d5ef84bf2a5..fd19f7e3b3b 100644
--- a/.clabot
+++ b/.clabot
@@ -89,6 +89,7 @@
"jwkaltz",
"dsuren1",
"Valyrian-Code",
- "brynsofz"
+ "brynsofz",
+ "christianbraun"
]
}
diff --git a/geonode/groups/migrations/0036_fix_groupprofile_access_default.py b/geonode/groups/migrations/0036_fix_groupprofile_access_default.py
new file mode 100644
index 00000000000..bb922454f11
--- /dev/null
+++ b/geonode/groups/migrations/0036_fix_groupprofile_access_default.py
@@ -0,0 +1,38 @@
+from django.db import migrations, models
+
+# The old default, with a stray apostrophe that matches none of the field's own
+# GROUP_CHOICES. Every GroupProfile created without an explicit access — which is
+# what geonode_ldap's group mirroring does — was stored with this value.
+BAD_DEFAULT = "public'"
+
+
+def repair_access(apps, schema_editor):
+ GroupProfile = apps.get_model("groups", "GroupProfile")
+ GroupProfile.objects.filter(access=BAD_DEFAULT).update(access="public")
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("groups", "0035_remove_modeltranslation"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="groupprofile",
+ name="access",
+ field=models.CharField(
+ choices=[
+ ("public", "Public"),
+ ("public-invite", "Public (invite-only)"),
+ ("private", "Private"),
+ ],
+ default="public",
+ help_text="Public: Any registered user can view and join a public group.
Public (invite-only):Any registered user can view the group. Only invited users can join.
Private: Registered users cannot see any details about the group, including membership. Only invited users can join.",
+ max_length=15,
+ verbose_name="Access",
+ ),
+ ),
+ # Reversing would mean writing the invalid value back, so this only goes
+ # forward; the AlterField above is reversible on its own.
+ migrations.RunPython(repair_access, migrations.RunPython.noop),
+ ]
diff --git a/geonode/groups/models.py b/geonode/groups/models.py
index a4cddca47db..ad904698e8b 100644
--- a/geonode/groups/models.py
+++ b/geonode/groups/models.py
@@ -91,7 +91,7 @@ class GroupProfile(models.Model):
email = models.EmailField(_("Email"), null=True, blank=True, help_text=email_help_text)
keywords = TaggableManager(_("Keywords"), help_text=_("A space or comma-separated list of keywords"), blank=True)
access = models.CharField(
- _("Access"), max_length=15, default="public'", choices=GROUP_CHOICES, help_text=access_help_text
+ _("Access"), max_length=15, default="public", choices=GROUP_CHOICES, help_text=access_help_text
)
categories = models.ManyToManyField(GroupCategory, verbose_name=_("Categories"), blank=True, related_name="groups")
created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
diff --git a/geonode/groups/tests.py b/geonode/groups/tests.py
index 9e58f6bf3ab..f29f6e65810 100644
--- a/geonode/groups/tests.py
+++ b/geonode/groups/tests.py
@@ -93,6 +93,17 @@ def test_registered_group_exists(self):
group = Group.objects.filter(name=groups_settings.REGISTERED_MEMBERS_GROUP_NAME).first()
self.assertTrue(group)
+ def test_default_access_is_a_valid_choice(self):
+ """
+ Ensures a GroupProfile created without an explicit access gets one of the
+ field's own GROUP_CHOICES, so that code filtering on access="public"
+ (e.g. geonode.people.utils.get_available_users) can see it.
+ """
+ group = GroupProfile.objects.create(slug="default_access_group", title="default_access_group")
+ self.assertEqual(group.access, "public")
+ self.assertIn(group.access, dict(GroupProfile.GROUP_CHOICES))
+ self.assertIn(group, GroupProfile.objects.filter(access="public"))
+
def test_users_group_list_view(self):
"""
1. Ensures that a superuser can see the whole group list.