From 855db26df1b5b44c122b9e30bf06afc0fc6fdaae Mon Sep 17 00:00:00 2001 From: Manuel Reinhardt Date: Mon, 16 Sep 2024 15:03:56 +0200 Subject: [PATCH] Index managerRolesAndUsers on the object itself without switching from client to admin. Refs syslabcom/scrum#2640 --- src/osha/oira/client/browser/client.py | 21 ++++++++++++++-- src/osha/oira/client/indexers.py | 25 +++---------------- .../__init__.py | 0 .../upgrade.py | 25 +++++++++++++++++++ 4 files changed, 47 insertions(+), 24 deletions(-) create mode 100644 src/osha/oira/upgrade/v1/20240916134747_reindex_manager_roles/__init__.py create mode 100644 src/osha/oira/upgrade/v1/20240916134747_reindex_manager_roles/upgrade.py diff --git a/src/osha/oira/client/browser/client.py b/src/osha/oira/client/browser/client.py index a1413a7d0..5d5116c40 100644 --- a/src/osha/oira/client/browser/client.py +++ b/src/osha/oira/client/browser/client.py @@ -134,6 +134,24 @@ def _get_mailing_lists_for(self, brain): for language in languages ] + def filter_permission(self, brains, query, user): + """Pick those elements from `brains` where the `user` has manager permissions + on the element's counterpart in the CMS (`sectors` folder). + The `query` must be the one that was used to retrieve the `brains` from the + catalog and is modified to yield the corresponding items in the CMS. + """ + catalog = api.portal.get_tool(name="portal_catalog") + query["portal_type"] = ["euphorie.country", "euphorie.surveygroup"] + query["path"] = ("/".join(api.portal.get().sectors.getPhysicalPath()),) + query["managerRolesAndUsers"] = catalog._listAllowedRolesAndUsers(user) + admin_brains = catalog(**query) + admin_paths = [result.getPath() for result in admin_brains] + return [ + brain + for brain in brains + if brain.getPath().replace("client", "sectors") in admin_paths + ] + @property def results(self): """List of "mailing list" path/names. @@ -170,7 +188,6 @@ def results(self): query = { "portal_type": ["euphorie.clientcountry", "euphorie.survey"], "path": "/".join(self.context.getPhysicalPath()), - "managerRolesAndUsers": catalog._listAllowedRolesAndUsers(user), "sort_on": "sortable_title", } @@ -181,7 +198,7 @@ def results(self): else: query["path"] = "/".join((query["path"], q)) - brains = catalog(**query) + brains = self.filter_permission(catalog(**query), query, user) for brain in brains: results.extend(self._get_mailing_lists_for(brain)) diff --git a/src/osha/oira/client/indexers.py b/src/osha/oira/client/indexers.py index ef1dda87f..4b0b44688 100644 --- a/src/osha/oira/client/indexers.py +++ b/src/osha/oira/client/indexers.py @@ -1,36 +1,17 @@ from AccessControl.PermissionRole import rolesForPermissionOn -from euphorie.client.client import IClient -from plone import api from plone.indexer import indexer from Products.CMFCore.CatalogTool import _mergedLocalRoles from Products.CMFCore.utils import getToolByName from zope.interface import Interface -def is_in_client(obj): - for parent in obj.aq_chain: - if IClient.providedBy(parent): - return True - return False - - @indexer(Interface) -def managerRolesAndUsers(client_obj): - """For client objects, index the roles and users that have the - `Euphorie: Manage country` permission on the object's counterpart in the admin - section, i.e. not the permissions on the object itself are relevant, but its base - that was copied via the "publish to client" feature. +def managerRolesAndUsers(obj): + """Index the roles and users that have the `Euphorie: Manage country` + permission on the object. Used in regulating access to mailing lists. Modeled after `allowedRolesAndUsers` from standard Plone.""" - if not is_in_client(client_obj): - return None - - sectors = api.portal.get().sectors - obj = sectors.restrictedTraverse(client_obj.getPhysicalPath()[3:], None) - if not obj: - return None - allowed = set(rolesForPermissionOn("Euphorie: Manage country", obj)) allowed = allowed | {"Manager", "Sector", "CountryManager"} localroles = {} diff --git a/src/osha/oira/upgrade/v1/20240916134747_reindex_manager_roles/__init__.py b/src/osha/oira/upgrade/v1/20240916134747_reindex_manager_roles/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/osha/oira/upgrade/v1/20240916134747_reindex_manager_roles/upgrade.py b/src/osha/oira/upgrade/v1/20240916134747_reindex_manager_roles/upgrade.py new file mode 100644 index 000000000..28b12c1c3 --- /dev/null +++ b/src/osha/oira/upgrade/v1/20240916134747_reindex_manager_roles/upgrade.py @@ -0,0 +1,25 @@ +from ftw.upgrade import UpgradeStep +from plone import api + +import logging + + +logger = logging.getLogger(__name__) + + +class ReindexManagerRoles(UpgradeStep): + """Reindex manager roles.""" + + def __call__(self): + self.install_upgrade_profile() + sectors = api.portal.get().sectors + client = api.portal.get().client + for context in [sectors, client]: + for brain in api.content.find(context=context, depth=3): + try: + obj = brain.getObject() + except KeyError: + logger.info("Could not get object %s", brain.getPath()) + continue + if hasattr(obj, "reindexObject"): + obj.reindexObject(idxs=["managerRolesAndUsers"])