2015-12-02 45 views
2

我试图在事件订阅者(IObjectAddedEvent)中移动内容类型后更改内容类型的所有者。Plone/dexterity-在某个事件中,如何更改只有所有者具有查看权限的内容类型对象的所有权角色?

对于我的示例,我将该内容类型称为合同。 当创建一个合同,其移动到一个容器

有两种类型的用户角色,我有:承包商和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的View Permission时,所有者成功更改了,但在我的情况下,我试图使其只有Owner才能在导航中看到。如果是这种情况,是否有办法解决这个问题?

回答

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,它提供上下文管理器通过用户或角色。

+0

谢谢你的回答。 我尝试使用changeOwnserhip函数中的api.env,但它似乎仍然卡住。 与api.env.adopt_user(用户名= USER_ID): #Change所有权,改变本地角色 obj.reindexObjectSecurity() 我加了一个打印语句后,我重新索引安全性,看它是否被通过了与它,但我仍然得到相同的错误,就好像AddEvent不会自己完成,除非登录用户是所有者,就像在事件完成之前实际上并没有添加对象一样。它几乎就像我需要在AddEvent完成后发生的事件一样? –

+1

你可以把你试过的代码放在什么地方(包括使用adopt_role/adopt_user? – Mathias

+0

任何进度?如果这是一个安全问题,它可以在正确的地方使用正确的安全管理器解决,否则我们需要调查更多。 ..我们需要更多的代码 – Mathias