限制數據訪問?
重要
本教程是 開始 教程的擴展。請確保您已經完成了該教程,并使用您構建的 estate
模塊作為本教程中練習的基礎。如果您想從一個干凈的基礎開始,請從 technical-training-solutions 存儲庫中獲取 16.0-core
分支。
到目前為止,我們主要關注實現有用的功能。然而,在大多數業務場景中, 安全性 很快成為一個問題:目前,
任何員工(即
group_user
)都可以創建、讀取、更新或刪除屬性、屬性類型或屬性標簽。如果安裝了
estate_account
模塊,則只有被允許與發票交互的代理商才能確認銷售,因為這對于 創建發票 是必要的。
然而:
我們不希望第三方能夠直接訪問屬性。
并非我們所有的員工都是房地產經紀人(例如行政人員、物業經理等),我們不希望非經紀人看到可用的房產。
房地產經紀人不需要或不能決定哪些物業類型或標簽是 可用的 。
房地產經紀人可以擁有 獨家 房產,我們不希望一個經紀人能夠管理另一個經紀人的獨家房產。
所有房地產經紀人都應該能夠確認他們可以管理的房產的銷售情況,但我們不希望他們能夠驗證或標記系統中的任何發票為已付款。
注解
對于小型企業,這些限制可能是可以接受的。
因為用戶可以更容易地禁用不必要的安全規則,而不是從頭開始創建它們,所以最好保守一些并限制訪問:如果必要或方便,用戶可以放寬訪問權限。
用戶組?
目標
在本節的結尾處,
我們可以將員工設為 房地產經紀人 或 房地產經理 。
admin
用戶是房地產經理。我們有一位新的 房地產經紀人 員工,沒有訪問發票或管理的權限。
如果每次需要更改就將安全規則附加到員工上,那么將不切實際,因此 組 將安全規則和用戶鏈接起來。它們對應于可以分配給員工的角色。
對于大多數Odoo應用程序 1,一個很好的基線是擁有 用戶 和 管理員 (或管理者)角色:管理員可以更改應用程序的配置并監督其全部使用,而用戶可以使用應用程序 2。
這個基準線對我們來說似乎足夠了:
房地產經理可以配置系統(管理可用類型和標簽),并監督管道中的每個屬性。
房地產經紀人可以管理他們負責的房產,或者是沒有被任何經紀人特別管理的房產。
根據Odoo的數據驅動特性,一個組不過是 res.groups
模型的一條記錄。它們通常是模塊的 主數據 的一部分,定義在模塊的數據文件中。
一個簡單的例子 可以在這里找到.
Exercise
在適當的文件夾中創建
security.xml
文件,并將其添加到__manifest__.py
文件中。如果還沒有,請在您的
__manifest__.py
中添加一個名為'category'
的字段,其值為Real Estate/Brokerage
。添加一個記錄,創建一個ID為“estate_group_user”,名稱為“代理商”,類別為“base.module_category_real_estate_brokerage”的組。
在下面,添加一個記錄,創建一個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”),你應該會看到一個新的部分:

將管理員用戶設置為“房地產經理”。
Exercise
通過Web界面,創建一個只有“房地產經紀人”訪問權限的新用戶。該用戶不應具有任何發票或管理訪問權限。
使用一個私密的標簽頁或窗口以新用戶身份登錄(記得設置密碼),作為房地產經紀人,您應該只能看到房地產應用程序,可能還有討論(聊天)應用程序:

訪問權限?
另請參閱
有關此主題的文檔可以在 訪問權限 中找到。
目標
在本節的結尾處,
不是房地產經紀人的員工將看不到房地產應用程序。
房地產經紀人將無法更新物業類型或標簽。
訪問權限最初在 第五章:安全性 - 簡介 中引入。
訪問權限是通過組為用戶提供訪問模型的一種方式:將訪問權限與組關聯,然后所有具有該組的用戶都將具有訪問權限。
例如,我們不希望房地產經紀人能夠修改可用的房產類型,因此我們不會將該訪問權限鏈接到“用戶”組。
訪問權限只能授予訪問權限,不能刪除它:當檢查訪問權限時,系統會查看與用戶(通過任何組)關聯的任何訪問權限是否授予該訪問權限。
組 |
創建 |
讀取 |
更新 |
刪除 |
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
。
安全性覆蓋?
繞過安全措施?
目標
在本節結束時,代理人應該能夠確認物業銷售,而無需訪問發票。
如果您作為房地產經紀人嘗試將某個屬性標記為“已售出”,則應該會收到訪問錯誤的提示:

這是因為在過程中, 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_rights
和 check_access_rule
確保當前用戶可以更新屬性,包括發票所屬的特定屬性。
重新運行繞過腳本,檢查錯誤是否在打印之前發生。
多公司安全性?
目標
在本節結束時,代理商只能訪問其所屬機構(或機構)的屬性。
由于某種原因,我們可能需要將我們的房地產業務管理為多個公司,例如我們可能擁有大部分自主機構、特許經營設置或多個品牌(可能是從收購其他房地產企業而來),這些公司在法律或財務上保持分離。
Odoo可以在同一系統內管理多個公司,但實際處理取決于各個模塊:Odoo本身提供了管理公司相關字段和 多公司規則 的工具,這是我們要關注的內容。
我們希望不同的機構之間相互“隔離”,每個機構擁有自己的屬性和用戶(無論是代理商還是經理),只能看到與其機構相關聯的屬性。
與以前一樣,由于這是基于非平凡記錄的,用戶放寬規則比收緊規則更容易,因此默認采用相對較強的安全模型是有意義的。
多公司規則只是基于 company_ids
或 company_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界面中可能不可見。
安全性 功能意味著用戶無法訪問記錄、字段或操作。
以下是一些例子:
在Python中, 模型字段 上的組是一種安全功能,組外的用戶將無法檢索該字段,甚至不知道它的存在。
例如:在服務器操作中, 只有系統用戶才能查看或更新Python代碼.
在 XML 中, 視圖元素 上的組是一個可見性特性,組外的用戶將無法看到表單中的元素或其內容,但他們仍然可以與對象(包括該字段)進行交互。
菜單和操作上的分組是可見性功能,菜單或操作不會顯示在界面上,但這并不妨礙直接與底層對象進行交互。
示例: 只有系統管理員可以看到電子學習設置菜單。
Exercise
房地產經紀人無法添加物業類型或標簽,但可以在創建物業時從物業表單視圖中查看它們的選項。
設置菜單只會給他們的界面增加噪音,將其僅對經理可見。
盡管不再有訪問“屬性類型”和“屬性標簽”菜單的權限,但代理商仍然可以訪問底層對象,因為他們仍然可以選擇標簽或類型來設置其屬性。