2015-12-02 36 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