限制數據訪問?

重要

本教程是 開始 教程的擴展。請確保您已經完成了該教程,并使用您構建的 estate 模塊作為本教程中練習的基礎。如果您想從一個干凈的基礎開始,請從 technical-training-solutions 存儲庫中獲取 16.0-core 分支。

到目前為止,我們主要關注實現有用的功能。然而,在大多數業務場景中, 安全性 很快成為一個問題:目前,

  • 任何員工(即 group_user )都可以創建、讀取、更新或刪除屬性、屬性類型或屬性標簽。

  • 如果安裝了 estate_account 模塊,則只有被允許與發票交互的代理商才能確認銷售,因為這對于 創建發票 是必要的。

然而:

  • 我們不希望第三方能夠直接訪問屬性。

  • 并非我們所有的員工都是房地產經紀人(例如行政人員、物業經理等),我們不希望非經紀人看到可用的房產。

  • 房地產經紀人不需要或不能決定哪些物業類型或標簽是 可用的 。

  • 房地產經紀人可以擁有 獨家 房產,我們不希望一個經紀人能夠管理另一個經紀人的獨家房產。

  • 所有房地產經紀人都應該能夠確認他們可以管理的房產的銷售情況,但我們不希望他們能夠驗證或標記系統中的任何發票為已付款。

注解

對于小型企業,這些限制可能是可以接受的。

因為用戶可以更容易地禁用不必要的安全規則,而不是從頭開始創建它們,所以最好保守一些并限制訪問:如果必要或方便,用戶可以放寬訪問權限。

用戶組?

另請參閱

有關此主題的文檔可以在 安全參考 中找到。

編碼規范 記錄了主數據項的格式和位置。

目標

在本節的結尾處,

  • 我們可以將員工設為 房地產經紀人房地產經理 。

  • admin 用戶是房地產經理。

  • 我們有一位新的 房地產經紀人 員工,沒有訪問發票或管理的權限。

如果每次需要更改就將安全規則附加到員工上,那么將不切實際,因此 將安全規則和用戶鏈接起來。它們對應于可以分配給員工的角色。

對于大多數Odoo應用程序 1,一個很好的基線是擁有 用戶管理員 (或管理者)角色:管理員可以更改應用程序的配置并監督其全部使用,而用戶可以使用應用程序 2。

這個基準線對我們來說似乎足夠了:

  • 房地產經理可以配置系統(管理可用類型和標簽),并監督管道中的每個屬性。

  • 房地產經紀人可以管理他們負責的房產,或者是沒有被任何經紀人特別管理的房產。

根據Odoo的數據驅動特性,一個組不過是 res.groups 模型的一條記錄。它們通常是模塊的 主數據 的一部分,定義在模塊的數據文件中。

一個簡單的例子 可以在這里找到.

Exercise

  1. 在適當的文件夾中創建 security.xml 文件,并將其添加到 __manifest__.py 文件中。

  2. 如果還沒有,請在您的 __manifest__.py 中添加一個名為 'category' 的字段,其值為 Real Estate/Brokerage 。

  3. 添加一個記錄,創建一個ID為“estate_group_user”,名稱為“代理商”,類別為“base.module_category_real_estate_brokerage”的組。

  4. 在下面,添加一個記錄,創建一個ID為“estate_group_manager”的組,名稱為“Manager”,類別為“base.module_category_real_estate_brokerage”?!癳state_group_manager”組需要暗示“estate_group_user”。

注解

這個 category 是從哪里來的?它是一個 模塊類別 。在這里,我們使用了類別ID base.module_category_real_estate_brokerage ,它是根據模塊的 __manifest__.py 中設置的 category 自動由Odoo生成的。您還可以在這里找到Odoo提供的 默認模塊類別列表。

小技巧

由于我們修改了數據文件,請記得重新啟動Odoo并使用“-u estate”更新模塊。

如果你進入 設置 ? 用戶管理 并打開 admin 用戶 (”Mitchell Admin”),你應該會看到一個新的部分:

../../_images/groups.png

將管理員用戶設置為“房地產經理”。

Exercise

通過Web界面,創建一個只有“房地產經紀人”訪問權限的新用戶。該用戶不應具有任何發票或管理訪問權限。

使用一個私密的標簽頁或窗口以新用戶身份登錄(記得設置密碼),作為房地產經紀人,您應該只能看到房地產應用程序,可能還有討論(聊天)應用程序:

../../_images/agent.png

訪問權限?

另請參閱

有關此主題的文檔可以在 訪問權限 中找到。

目標

在本節的結尾處,

  • 不是房地產經紀人的員工將看不到房地產應用程序。

  • 房地產經紀人將無法更新物業類型或標簽。

訪問權限最初在 第五章:安全性 - 簡介 中引入。

訪問權限是通過組為用戶提供訪問模型的一種方式:將訪問權限與組關聯,然后所有具有該組的用戶都將具有訪問權限。

例如,我們不希望房地產經紀人能夠修改可用的房產類型,因此我們不會將該訪問權限鏈接到“用戶”組。

訪問權限只能授予訪問權限,不能刪除它:當檢查訪問權限時,系統會查看與用戶(通過任何組)關聯的任何訪問權限是否授予該訪問權限。

創建

讀取

更新

刪除

A

X

X

B

X

C

X

擁有 A 和 C 組的用戶可以做任何事情,但不能刪除對象,而擁有 B 和 C 組的用戶可以讀取和更新它,但不能創建或刪除它。

注解

  • 訪問權限的組可以省略,這意味著ACL適用于 每個用戶 ,這是一個有用但風險很高的后備方案,因為根據安裝的應用程序,它甚至可以授予非用戶訪問模型的權限。

  • 如果用戶沒有任何訪問權限,則不會被授予訪問權限(默認拒絕)。

  • 如果菜單項指向一個用戶無法訪問且沒有子菜單可見的模型,則該菜單將不會顯示。

Exercise

更新訪問權限文件為:

  • 將所有對象的完全訪問權限授予您的房地產經理組。

  • 給予經紀人(房地產用戶)只讀取類型和標簽的訪問權限。

  • 不要給任何人刪除屬性的權限。

  • 檢查您的代理用戶是否無法更改類型或標簽,或刪除屬性,但是他們可以創建或更新屬性。

警告

記得給你的 ir.model.access 記錄分配不同的 xids,否則它們會互相覆蓋。

由于“演示”用戶沒有成為房地產經紀人或經理,因此他們甚至不應該能夠看到房地產應用程序。請使用私人選項卡或窗口進行檢查(“演示”用戶的密碼為“demo”)。

記錄規則?

另請參閱

有關此主題的文檔可以在 記錄規則 中找到。

目標

在本節結束時,代理商將無法看到專屬于同事的屬性;但經理仍然可以看到所有內容。

訪問權限可以授予對整個模型的訪問權限,但通常我們需要更具體的控制:雖然代理可以總體上與屬性進行交互,但我們可能不希望他們更新或甚至查看由他們的同事管理的屬性。

記錄 規則 提供了這種精度:它們可以授予或拒絕對單個記錄的訪問權限:

<record id="rule_id" model="ir.rule">
    <field name="name">A description of the rule's role</field>
    <field name="model_id" ref="model_to_manage"/>
    <field name="perm_read" eval="False"/>
    <field name="groups" eval="[Command.link(ref('base.group_user'))]"/>
    <field name="domain_force">[
        '|', ('user_id', '=', user.id),
             ('user_id', '=', False)
    ]</field>
</record>

搜索域 是管理訪問權限的方式:如果記錄通過,則授予訪問權限,否則拒絕訪問。

小技巧

因為規則往往相當復雜且不是批量創建的,所以它們通常是使用 XML 而不是用于訪問權限的 CSV 創建的。

上述規則:

  • 僅適用于“創建”、“更新”(寫入)和“刪除”(取消鏈接)操作:我們希望每個員工都能夠查看其他用戶的記錄,但只有作者/受托人才能更新記錄。

  • 是否為 非全局 ,這樣我們就可以為例如經理提供額外的規則。

  • 如果當前用戶( user.id )已設置(例如已創建或已分配)記錄,則允許操作,或者如果記錄根本沒有關聯用戶,則允許操作。

注解

如果沒有為模型和操作定義或應用規則,則允許操作( 默認允許 ),如果訪問權限設置不正確(太寬松),則可能會產生奇怪的影響。

Exercise

定義一個規則,限制代理商只能查看或修改沒有銷售員或者他們是銷售員的屬性。

您可能想創建第二個房地產經紀人用戶,或者為一些物業指定銷售經理或其他用戶。

確認您的房地產經理仍然可以看到所有的房產。如果不能,為什么?請記?。?/p>

estate_group_manager 組需要暗示 estate_group_user 。

安全性覆蓋?

繞過安全措施?

目標

在本節結束時,代理人應該能夠確認物業銷售,而無需訪問發票。

如果您作為房地產經紀人嘗試將某個屬性標記為“已售出”,則應該會收到訪問錯誤的提示:

../../_images/error.png

這是因為在過程中, estate_account 嘗試創建發票,但創建發票需要擁有所有發票管理的權限。

我們希望代理商能夠確認銷售,而不需要他們擁有完全的發票訪問權限,這意味著我們需要 繞過 Odoo的正常安全檢查,以便 創建 發票,盡管當前用戶沒有權利這樣做。

在Odoo中,有兩種主要的繞過現有安全檢查的方式,要么是故意的,要么是作為副作用:

  • sudo() 方法將在”sudo模式”下創建一個新的記錄集,這將忽略所有訪問權限和記錄規則(盡管硬編碼的組和用戶檢查仍然適用)。

  • 執行原始的 SQL 查詢將繞過訪問權限和記錄規則,因為繞過 ORM 本身會產生副作用。

Exercise

更新 estate_account 在創建發票時繞過訪問權限和規則。

危險

通常應避免使用這些功能,并在檢查當前用戶和操作是否能夠繞過正常訪問權限驗證后,小心使用。

在這種模式下執行的操作應該盡可能少地依賴用戶輸入,并且應該盡可能地驗證它們。

以編程方式檢查安全性?

目標

在本節結束時,發票的創建應該對 estate 的更改具有安全性彈性。

在Odoo中,只有通過ORM執行數據訪問時才會檢查訪問權限和記錄規則,例如通過ORM方法創建、讀取、搜索、寫入或取消鏈接記錄。其他方法不一定會檢查任何類型的訪問權限。

在上一節中,我們在 action_sold 中創建發票時繞過了記錄規則。任何用戶都可以到達此繞過點,而不需要檢查任何訪問權限:

  • 在創建發票之前,在“estate_account”中的“action_sold”中添加打印語句(因為創建發票會訪問屬性,因此會觸發ACL檢查),例如:

    print(" reached ".center(100, '='))
    

您應該在Odoo日志中看到 reached ,然后是一個訪問錯誤。

危險

僅僅因為你已經在 Python 代碼中,并不意味著任何訪問權限或規則已經或將被檢查。

目前 ,訪問是通過訪問 self 上的數據以及調用 super() (它執行相同的操作并 更新 self )來隱式檢查的,從而觸發訪問錯誤并取消事務,”取消創建”我們的發票。

然而 ,如果將來發生變化,或者我們在方法中添加副作用(例如向政府機構報告銷售情況),或者在“estate”中引入錯誤,非代理人就有可能觸發他們無權訪問的操作。

因此,在執行非 CRUD 操作、合法地繞過 ORM 或安全性,或觸發其他副作用時,執行 顯式安全檢查 非常重要。

可以通過以下方式執行顯式安全檢查:

  • 檢查當前用戶是誰( self.env.user ),并將其與特定模型或記錄進行匹配。

  • 檢查當前用戶是否具有特定的硬編碼組,以允許或拒絕操作( self.env.user.has_group )。

  • 在記錄集上調用 check_access_rights(operation) 方法,可以驗證當前用戶是否有訪問模型本身的權限。

  • 在非空記錄集上調用 check_access_rule(operations) ,這將驗證當前用戶是否被允許對集合中的 每個 記錄執行操作。

警告

檢查訪問權限和檢查記錄規則是兩個不同的操作,如果您正在檢查記錄規則,則通常需要事先檢查訪問權限。

Exercise

在創建發票之前,請使用 check_access_rightscheck_access_rule 確保當前用戶可以更新屬性,包括發票所屬的特定屬性。

重新運行繞過腳本,檢查錯誤是否在打印之前發生。

多公司安全性?

另請參閱

多公司指南 介紹了多公司設施的概述,特別是 多公司安全規則 。

關于規則的文檔可以在 記錄規則 中找到。

目標

在本節結束時,代理商只能訪問其所屬機構(或機構)的屬性。

由于某種原因,我們可能需要將我們的房地產業務管理為多個公司,例如我們可能擁有大部分自主機構、特許經營設置或多個品牌(可能是從收購其他房地產企業而來),這些公司在法律或財務上保持分離。

Odoo可以在同一系統內管理多個公司,但實際處理取決于各個模塊:Odoo本身提供了管理公司相關字段和 多公司規則 的工具,這是我們要關注的內容。

我們希望不同的機構之間相互“隔離”,每個機構擁有自己的屬性和用戶(無論是代理商還是經理),只能看到與其機構相關聯的屬性。

與以前一樣,由于這是基于非平凡記錄的,用戶放寬規則比收緊規則更容易,因此默認采用相對較強的安全模型是有意義的。

多公司規則只是基于 company_idscompany_id 字段的記錄規則:

  • company_ids 是當前用戶可以訪問的所有公司

  • company_id 是當前活動公司(用戶當前所在/工作的公司)。

多公司規則通常使用前者,即檢查記錄是否與用戶可以訪問的 一個 公司相關聯:

<record model="ir.rule" id="hr_appraisal_plan_comp_rule">
    <field name="name">Appraisal Plan multi-company</field>
    <field name="model_id" ref="model_hr_appraisal_plan"/>
    <field name="domain_force">[
        '|', ('company_id', '=', False),
             ('company_id', 'in', company_ids)
    ]</field>
</record>

危險

多公司規則通常是 全局的 ,否則會有很高的風險,額外的規則會繞過多公司規則。

Exercise

  • estate.property 中添加一個 company_id 字段,它應該是必需的(我們不希望沒有代理的屬性),并且應該默認為當前用戶的當前公司。

  • 創建一個新公司,并在該公司中添加一個新的房地產經紀人。

  • 經理應該是兩家公司的成員。

  • 舊代理商只應是舊公司的成員。

  • 在每個公司中創建一些屬性(可以使用公司選擇器作為經理或使用代理人)。取消默認銷售員以避免觸發 規則。

  • 所有代理商都可以看到所有公司,這是不可取的,需要添加記錄規則來限制此行為。

警告

當您更改模型或數據時,請記得在模塊上運行 --update 命令

可見性 != 安全性?

目標

在本節結束時,房地產經紀人不應該看到房地產應用程序的“設置”菜單,但仍應能夠設置屬性類型或標簽。

特定的Odoo模型可以直接與組(或公司、用戶)關聯。在使用之前,有必要弄清楚這種關聯是 安全 還是 可見性 功能:

  • “可見性”功能意味著用戶仍然可以訪問模型或記錄,否則,通過界面的另一部分或者通過 使用RPC遠程執行操作 ,在某些情況下,在Web界面中可能不可見。

  • 安全性 功能意味著用戶無法訪問記錄、字段或操作。

以下是一些例子:

Exercise

房地產經紀人無法添加物業類型或標簽,但可以在創建物業時從物業表單視圖中查看它們的選項。

設置菜單只會給他們的界面增加噪音,將其僅對經理可見。

盡管不再有訪問“屬性類型”和“屬性標簽”菜單的權限,但代理商仍然可以訪問底層對象,因為他們仍然可以選擇標簽或類型來設置其屬性。

1

Odoo應用程序是一組相關的模塊,涵蓋一個業務領域或領域,通常由基礎模塊和一些擴展組成,以添加可選或特定功能,或鏈接到其他業務領域。

2

對于大多數或所有員工都會使用的應用程序,可以取消”應用程序用戶”角色,并直接授予所有員工其權限,例如通常所有員工都可以提交費用或請假。