From 17d3df41953667494a624e5fb74695e165efd78a Mon Sep 17 00:00:00 2001
From: Vincent Pelletier <vincent@nexedi.com>
Date: Mon, 24 Apr 2017 15:57:40 +0900
Subject: [PATCH] ERP5Security.ERP5UserLoginManager: Special-case
 user_id='System Processes'

Because of ERP5Type.UnrestrictedMethod, 'System Processes' can own objects.
Such objects can be proxy-role'd scripts, and proxy-role mechanism
triggers many users look-ups (each time security is evaluated, which is
virtually every getattr). Each such lookup will do a query for 'System
Processes' user, which will (hopefully) find nothing anyway.
So special-case 'System Processes' when looking by user_id by skipping
the search altogether (enforcing the inability to locate this user,
consistently with Zope assumptions, and consistently with previous
behaviour).
---
 product/ERP5Security/ERP5LoginUserManager.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/product/ERP5Security/ERP5LoginUserManager.py b/product/ERP5Security/ERP5LoginUserManager.py
index 10b9a3e95b..3820117b77 100644
--- a/product/ERP5Security/ERP5LoginUserManager.py
+++ b/product/ERP5Security/ERP5LoginUserManager.py
@@ -40,11 +40,12 @@ from AccessControl import SpecialUsers
 from Shared.DC.ZRDB.DA import DatabaseError
 from zLOG import LOG, ERROR
 
+SYSTEM_USER_USER_NAME = SpecialUsers.system.getUserName()
 # To prevent login thieves
 SPECIAL_USER_NAME_SET = (
   ERP5Security.SUPER_USER,
   SpecialUsers.nobody.getUserName(),
-  SpecialUsers.system.getUserName(),
+  SYSTEM_USER_USER_NAME,
   # Note: adding emergency_user is pointless as its login is variable, so no
   # way to prevent another user from stealing its login.
 )
@@ -196,6 +197,10 @@ class ERP5LoginUserManager(BasePlugin):
       # PluggableAuthService.searchUsers.
       if isinstance(id, str):
         id = (id, )
+      # Short-cut "System Processes" as not being searchable by user_id.
+      # This improves performance in proxy-role'd execution by avoiding an
+      # sql query expected to find no user.
+      id = [x for x in id if x != SYSTEM_USER_USER_NAME]
       if id:
         if exact_match:
           requested = set(id).__contains__
-- 
2.30.9