From 91cd7f620a37c2fb26a56d90a20afcbb0dc6c1a5 Mon Sep 17 00:00:00 2001 From: wesleybl Date: Thu, 21 Sep 2023 15:49:37 -0300 Subject: [PATCH] Does not allow a Site Administrator delete Manager --- src/plone/restapi/services/users/delete.py | 20 +++++++++++++++---- .../restapi/tests/test_services_users.py | 9 +++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/plone/restapi/services/users/delete.py b/src/plone/restapi/services/users/delete.py index e7517f6655..91158b8c83 100644 --- a/src/plone/restapi/services/users/delete.py +++ b/src/plone/restapi/services/users/delete.py @@ -1,6 +1,7 @@ +from AccessControl import getSecurityManager from plone.restapi.services import Service +from Products.CMFCore.permissions import ManagePortal from Products.CMFCore.utils import getToolByName -from zope.component.hooks import getSite from zope.interface import implementer from zope.publisher.interfaces import IPublishTraverse @@ -15,6 +16,11 @@ class UsersDelete(Service): def __init__(self, context, request): super().__init__(context, request) self.params = [] + self.portal_membership = getToolByName(context, "portal_membership") + + @property + def is_zope_manager(self): + return getSecurityManager().checkPermission(ManagePortal, self.context) def publishTraverse(self, request, name): # Consume any path segments after /@users as parameters @@ -27,9 +33,15 @@ def _get_user_id(self): raise Exception("Must supply exactly one parameter (user id)") return self.params[0] + def _get_user(self, user_id): + return self.portal_membership.getMemberById(user_id) + def reply(self): - portal = getSite() - portal_membership = getToolByName(portal, "portal_membership") + if not self.is_zope_manager: + user = self._get_user(self._get_user_id) + current_roles = user.getRoles() + if "Manager" in current_roles: + return self.reply_no_content(status=403) delete_memberareas = ( self.request.get("delete_memberareas", True) not in FALSE_VALUES @@ -39,7 +51,7 @@ def reply(self): self.request.get("delete_localroles", True) not in FALSE_VALUES ) - delete_successful = portal_membership.deleteMembers( + delete_successful = self.portal_membership.deleteMembers( (self._get_user_id,), delete_memberareas=delete_memberareas, delete_localroles=delete_localroles, diff --git a/src/plone/restapi/tests/test_services_users.py b/src/plone/restapi/tests/test_services_users.py index 4f1c5b86cb..fce04b276c 100644 --- a/src/plone/restapi/tests/test_services_users.py +++ b/src/plone/restapi/tests/test_services_users.py @@ -1354,3 +1354,12 @@ def test_manager_update_manager(self): noam = api.user.get(userid="noam") self.assertIn("Manager", noam.getRoles()) + + def test_siteadm_not_delete_manager(self): + self.set_siteadm() + api.user.grant_roles(username="noam", roles=["Manager"]) + transaction.commit() + self.api_session.delete("/@users/noam") + transaction.commit() + + self.assertIsNotNone(api.user.get(userid="noam"))