diff --git a/CHANGES.rst b/CHANGES.rst index 515fc44b..257872a0 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -32,6 +32,10 @@ Changelog - Add principals to groups that already exist during import (#228) [pbauer] +- In export_members ignore transitive membership of groups (#240) + [pbauer] + + 1.10 (2023-10-11) ----------------- diff --git a/src/collective/exportimport/export_other.py b/src/collective/exportimport/export_other.py index ded77b94..1db617de 100644 --- a/src/collective/exportimport/export_other.py +++ b/src/collective/exportimport/export_other.py @@ -300,8 +300,14 @@ def _getUserPassword(self, userId): def _getUserData(self, userId): member = self.pms.getMemberById(userId) - groups = member.getGroups() - groups = [i for i in groups if i not in self.AUTO_GROUPS] + groups = [] + group_ids = [i for i in member.getGroups() if i not in self.AUTO_GROUPS] + # Drop groups in which the user is a transitive member + for group_id in group_ids: + group = api.group.get(group_id) + plone_group = group.getGroup() + if userId in plone_group.getMemberIds(): + groups.append(group_id) group_roles = [] for gid in groups: group_roles.extend(self.group_roles.get(gid, [])) diff --git a/src/collective/exportimport/tests/test_export.py b/src/collective/exportimport/tests/test_export.py index 3b9fd5e6..831f3e7d 100644 --- a/src/collective/exportimport/tests/test_export.py +++ b/src/collective/exportimport/tests/test_export.py @@ -305,6 +305,31 @@ def test_export_members(self): if member["username"] == TEST_USER_ID: self.assertTrue(member["roles"], ["Member"]) + def test_export_indirect_members(self): + direct = api.group.create("Direct") + indirect = api.group.create("Indirect") + api.group.add_user(group=direct, username=TEST_USER_ID) + # Make user a indirect member of the group indirect + api.group.add_user(group=direct, user=indirect) + + transaction.commit() + browser = self.open_page("@@export_members") + browser.getForm(action="@@export_members").submit(name="form.submitted") + contents = browser.contents + if not browser.contents: + contents = DATA[-1] + data = json.loads(contents) + self.assertIn("groups", data.keys()) + self.assertIn("members", data.keys()) + members = data["members"] + membernames = [member["username"] for member in members] + self.assertIn(TEST_USER_ID, membernames) + for member in members: + if member["username"] == TEST_USER_ID: + self.assertEqual(member["username"], TEST_USER_ID) + # Only direct membership is exported + self.assertEqual(member["groups"], ["Direct"]) + def test_export_defaultpages_empty(self): browser = self.open_page("@@export_defaultpages") browser.getForm(action="@@export_defaultpages").submit(name="form.submitted")