-
Notifications
You must be signed in to change notification settings - Fork 17
Open
Description
Ldap: remove_user_memberships() deletes Group objects instead of removing user membership
Description
The remove_user_memberships() function in backend.py deletes Django Group objects instead of removing the user from those groups. This causes associated GroupProfiles to be cascade-deleted, resulting in data loss.
Affected Code
geonode_ldap/backend.py, line 278:
def remove_user_memberships(user):
existing_group_profile_memberships = GroupMember.objects.filter(
user=user).values_list("group__slug", flat=True)
user.groups.filter(name__in=existing_group_profile_memberships).delete() # BUG: deletes Group objects!
GroupMember.objects.filter(user=user).delete()Problem
user.groups.filter(...).delete() deletes the Group objects themselves, not the user's membership in those groups.
Since GroupProfile.group has on_delete=CASCADE, this causes the associated GroupProfiles to be deleted at the database level.
Impact
- When
AUTH_LDAP_MIRROR_GROUPS=True, every LDAP user login can delete groups - Groups that other users belong to are destroyed
- No Django admin log is created (cascade delete bypasses ORM logging)
- Difficult to diagnose - groups silently disappear
Steps to Reproduce
- Enable
AUTH_LDAP_MIRROR_GROUPS = True - Create a GroupProfile with members
- Have an LDAP user who is a member of that group log in
- The Django Group and GroupProfile are deleted
Suggested Fix
def remove_user_memberships(user):
"""Remove user from all GroupMember instances and Django groups.
This function cleans up a user's group memberships before reassigning
new ones based on LDAP. It operates on both:
- Django's auth.Group (used for permissions)
- GeoNode's GroupMember (used for UI and group management)
"""
# Get list of GroupProfile slugs where this user is currently a member
# GroupMember links users to GroupProfiles, and we need the slug
# because Django Group.name matches GroupProfile.slug
existing_group_profile_memberships = GroupMember.objects.filter(
user=user).values_list("group__slug", flat=True)
# Find the Django Group objects that match these slugs
# user.groups is the ManyToMany relation to auth.Group
groups_to_remove = user.groups.filter(name__in=existing_group_profile_memberships)
# CORRECT: Use .remove() to remove the user from these groups
# This only removes the relationship (user <-> group), NOT the Group objects
# The * unpacks the queryset into individual arguments
user.groups.remove(*groups_to_remove)
# Delete the GeoNode GroupMember entries for this user
# This removes the user's membership records from GeoNode's group system
GroupMember.objects.filter(user=user).delete()Environment
- GeoNode 4.x
- geonode_ldap from geonode-contribs
Metadata
Metadata
Assignees
Labels
No labels