我尝试更改内容类型的所有者在事件订阅者(IObjectAddedEvent)中移动后更改。
对于我的示例,我将内容类型称为合同。 创建合同时,将其移入容器
我有两种类型的用户角色:Contractor和ContractManager
合同中有一个名为“承包商”的字段,这是具有承包商角色的所有用户的选择。 ContractManager也是承包商。 只有ContractManager可以更改承包商字段,否则当承包商尝试创建合同时,只会显示其名称。 此外,除非ContractManager恰好是该合同的承包商/所有者,否则ContractManager无法对其进行编辑,只需编辑一次。
我为合同创建了一个工作流程,在工作流程中,我这样做是为了只有拥有所有者角色的用户才具有查看权限。
在我用于事件订阅者的events.py文件中,我有:
@grok.subscriber(Contract, IObjectAddedEvent)
def contractAdded(obj, event):
#generate id of container contract will be moved into when its created
#create a container (representing a week, i.e. contracts_12_5_2015)
#if it doesn't already exist
#copy and paste contract into container
moved_contract = contracts[contract_container_id][obj.id]
changeOwnership(moved_contract, obj.contractor)
def changeOwnership(user_id, obj):
aq_base(obj).__ac_local_roles_block__ = True
userid = u"%s" % userid
membership = getToolByName(obj, 'portal_membership')
user = membership.getMemberById(userid)
obj.changeOwnership(user)
obj.setCreators(userid,)
owners = [o for o in obj.users_with_local_role('Owner')]
for owner in owners:
roles = list(obj.get_local_roles_for_userid(owner))
roles.remove('Owner')
if roles:
obj.manage_setLocalRoles(owner, roles)
else:
obj.manage_delLocalRoles([owner])
roles = list(obj.get_local_roles_for_userid(userid))
if 'Owner' not in roles:
roles.append('Owner')
obj.manage_setLocalRoles(userid, roles)
obj.reindexObjectSecurity()
不幸的是,当我以ContractManager身份登录并更改承包商的身份时,我收到此错误:
Traceback (innermost last):
Module ZPublisher.Publish, line 138, in publish
Module ZPublisher.mapply, line 77, in mapply
Module ZPublisher.Publish, line 48, in call_object
Module Solgema.fullcalendar.browser.dx, line 68, in __call__
Module plone.z3cform.layout, line 50, in update
Module plone.dexterity.browser.add, line 117, in update
Module plone.z3cform.fieldsets.extensible, line 59, in update
Module plone.z3cform.patch, line 30, in GroupForm_update
Module z3c.form.group, line 145, in update
Module plone.app.z3cform.csrf, line 21, in execute
Module z3c.form.action, line 98, in execute
Module z3c.form.button, line 315, in __call__
Module z3c.form.button, line 170, in __call__
Module plone.dexterity.browser.add, line 100, in handleAdd
Module z3c.form.form, line 250, in createAndAdd
Module plone.dexterity.browser.add, line 79, in add
AttributeError: 'NoneType' object has no attribute 'id'
我假设登录用户需要reindexObjectSecurity的查看权限才能工作。当我进入工作流管理器(通过ZMI)并添加了ContractManager的查看权限时,所有者已成功更改,但在我的情况下,我尝试将其设置为只有所有者才能在导航中看到。如果是这样的话有办法解决这个问题吗?
答案 0 :(得分:3)
您可以使用context manager
在此操作期间更改SecurityManager。
这样,您可以将一些特定的代码行作为具有必要权限的其他用户运行。
此示例上下文管理器以系统用户身份运行代码:
import AccessControl
class SwitchedToSystemUser(object):
"""Switch temp. to System user
"""
def __init__(self):
self._original_security = None
def __enter__(self):
assert self._original_security is None
self._original_security = AccessControl.getSecurityManager()
_system_user = AccessControl.SecurityManagement.SpecialUsers.system
AccessControl.SecurityManagement.newSecurityManager(None, _system_user)
def __exit__(self, _exc_type, _exc_value, _traceback):
AccessControl.SecurityManagement.setSecurityManager(
self._original_security)
self._original_security = None
使用示例:
// CODE FOR LOGGED-IN USER
...
with SwitchedToSystemUser():
// DO STUFF AS SYSTEM USER
// MORE CODE FOR LOGGED-IN USER
您还可以查看plone.api.env
,它为上下文管理员提供了一个或多个用户角色。