「Odoo 基础教程系列」第七篇——从 Todo 应用开始(6)
在今年的情人節(jié)(2018.02.14)那天,我寫了一篇博客說(shuō)即將要開一個(gè)坑,也就是大家在看的這個(gè)系列的教程。今天這個(gè)系列教程即將迎來(lái)它的最后一篇內(nèi)容了,我們將要來(lái)學(xué)習(xí) Odoo 中權(quán)限相關(guān)的內(nèi)容。
用戶組
在多用戶系統(tǒng)中,并不是所有數(shù)據(jù)都是可以開放給全部用戶的,所以在多用戶系統(tǒng)中,權(quán)限管理是非常重要的一環(huán)。通常我們會(huì)根據(jù)業(yè)務(wù)和組織架構(gòu)對(duì)用戶進(jìn)行分組管理,也就是我們常說(shuō)的用戶組或角色組,然后再根據(jù)用戶組對(duì)用戶所能接觸到的數(shù)據(jù)內(nèi)容進(jìn)行控制。
在 Odoo 的權(quán)限管理體系中,同樣也有用戶組這一概念的存在,和其他框架(如 Django)可以說(shuō)大同小異?;氐轿覀兊?Todo 應(yīng)用里來(lái),從一開始我們就是用的超級(jí)管理員賬戶 admin 登錄和操作的,這在任何生產(chǎn)環(huán)境和測(cè)試環(huán)境里都是不允許出現(xiàn)的,但是在前面的教程里,我們都沒有提到過(guò)賬戶和權(quán)限相關(guān)的內(nèi)容,是為了讓教程能一路走下來(lái),所以我們今天就來(lái)糾正這個(gè)錯(cuò)誤。
在我們的 Todo 應(yīng)用中,假設(shè)有「用戶」和「管理員」兩個(gè)用戶組,普通用戶可以創(chuàng)建、修改和刪除自己創(chuàng)建的待辦事項(xiàng),而管理員除了擁有普通用戶的操作權(quán)限外,還可以創(chuàng)建、修改和刪除分類數(shù)據(jù)。
現(xiàn)在我們就來(lái)看看應(yīng)該如何定義這兩個(gè)用戶組,和定義其他數(shù)據(jù)一樣,我們同樣需要在 xml 文件中定義用戶組數(shù)據(jù),找到模塊下的 security 目錄,然后創(chuàng)建一個(gè) todo_security.xml 文件,用于定義我們的用戶組數(shù)據(jù):
<?xml version="1.0" encoding="utf-8"?> <odoo><data noupdate="0"><record id="module_category_todo" model="ir.module.category"><field name="name">待辦事項(xiàng)</field></record><record id="group_todo_user" model="res.groups"><field name="name">用戶</field><field name="implied_ids" eval="[(4, ref('base.group_user'))]"/><field name="category_id" ref="todo.module_category_todo"/><field name="users" eval="[(4, ref('base.user_root'))]"/></record><record id="group_todo_manager" model="res.groups"><field name="name">管理員</field><field name="implied_ids"eval="[(4, ref('base.group_user')), (4, ref('todo.group_todo_user'))]"/><field name="category_id" ref="todo.module_category_todo"/><field name="users" eval="[(4, ref('base.user_root'))]"/></record></data> </odoo>這里總共有 3 條記錄,分別是 Todo 模塊分類(ir.module.category)和「用戶」及「管理員」兩個(gè)用戶組(res.groups),重點(diǎn)來(lái)看看用戶組里各個(gè)字段所代表的含義:
- category_id:該用戶組所屬的模塊分類
- implied_ids:在當(dāng)前用戶組下的用戶,同時(shí)加入該字段所指定的用戶組中
- users:該字段所指定的用戶默認(rèn)被加入到當(dāng)前用戶組中
在上面的記錄中,還有兩個(gè)引用(ref),分別是 base.group_user 基礎(chǔ)用戶組和 base.user_root 管理員賬戶。
別忘了把 'security/todo_security.xml' 加入到 __manifest__.py 的 data 列表中,將它放在 # 'security/ir.model.access.csv' 這一行的上面,然后升級(jí)更新模塊之后打開設(shè)置菜單下的「用戶」菜單,打開管理員賬戶 Administrator 的表單視圖。
這時(shí)我們可以看到在「Application Accesses」下出現(xiàn)了我們剛剛創(chuàng)建的「待辦事項(xiàng)」模塊分類,進(jìn)入編輯模式后,可以看到有「用戶」和「管理員」兩個(gè)選項(xiàng)
可以發(fā)現(xiàn)超級(jí)管理員賬戶已經(jīng)默認(rèn)被分配到了待辦事項(xiàng)分類下的「管理員」組中了,這也和我們前面說(shuō)的 users 字段所表現(xiàn)的行為是一致的,再返回列表,打開 Demo User 這個(gè)賬戶看看,是不是并沒有加入我們創(chuàng)建的用戶組中的任何一個(gè)呢 :)
用戶組權(quán)限
用戶組創(chuàng)建好了之后,事情遠(yuǎn)遠(yuǎn)還沒有結(jié)束,因?yàn)槲覜]并沒有為這兩個(gè)用戶組分配相關(guān)數(shù)據(jù)的操作權(quán)限。那如果我們現(xiàn)在創(chuàng)建一個(gè)新的用戶,并且加入到任意的用戶組中,然后登錄訪問(wèn)系統(tǒng),會(huì)發(fā)生什么呢?實(shí)踐出真知,我們來(lái)創(chuàng)建一個(gè) test 用戶并且分配到「用戶」組中,然后登錄看看會(huì)發(fā)生什么
注:修改新創(chuàng)建的賬戶密碼,打開 Action 下拉菜單,點(diǎn)擊 Change Password 即可修改
打開隱身窗口或者在另一個(gè)瀏覽器上登錄,你會(huì)看到頁(yè)面上什么都沒有,為什么會(huì)這樣?
不要感到迷惑,這確實(shí)是因?yàn)槲覀儧]有給用戶組分配任何數(shù)據(jù)的操作權(quán)限導(dǎo)致的,用戶沒有對(duì)數(shù)據(jù)的讀寫權(quán)限,自然就無(wú)法查看到相關(guān)的內(nèi)容了。在 Odoo 中給用戶組分配權(quán)限,是以模型為單位的,也就是說(shuō)只有某個(gè)用戶組被分配了對(duì)應(yīng)模型的權(quán)限之后,該用戶組內(nèi)的用戶才能操作對(duì)應(yīng)模型下的數(shù)據(jù)。用戶組權(quán)限的定義是以 .csv 格式文件存儲(chǔ)的,在創(chuàng)建模塊時(shí)默認(rèn)已經(jīng)生成了一個(gè)權(quán)限記錄文件 security/ir.model.access.csv,打開它我們可以看到里面有一條記錄,這是在創(chuàng)建模塊時(shí)自動(dòng)生成的,可以看到里面有 8 個(gè)字段,分別代表的含義如下
- id:這條權(quán)限記錄的 id,可以類比為 xml_id
- name:權(quán)限記錄的名稱
- model_id:id:要配置權(quán)限的模型的外部 ID (以 model_ 開頭)
- group_id:id:應(yīng)用此條權(quán)限配置的用戶組的 id,若為空則默認(rèn)對(duì)所有用戶組生效
- perm_read:讀取記錄的權(quán)限,1 為擁有該權(quán)限,0 為不分配該權(quán)限
- perm_write:編輯更新記錄的權(quán)限,取值同上
- perm_create:創(chuàng)建新記錄的權(quán)限,取值同上
- perm_unlink:刪除記錄的權(quán)限,取值同上
如果不理解也沒關(guān)系,我們先來(lái)給「用戶」組添加對(duì)模型 todo.task 的操作權(quán)限,通過(guò)實(shí)例會(huì)更容易理解:
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_todo_task_user,todo.task.user,model_todo_task,group_todo_user,1,1,1,1我們?cè)谶@里為「用戶」組(group_todo_user)添加了對(duì) todo.task 待辦事項(xiàng)模型的讀寫創(chuàng)建和刪除四個(gè)操作的權(quán)限,然后打開 __manifest__.py 并將 # 'security/ir.model.access.csv' 這行的注釋取消掉,然后升級(jí)更新模塊,然后刷新剛剛登錄的 test 賬戶的界面,是不是可以看到有數(shù)據(jù)了呢
終于不是空空如也的頁(yè)面了,可是有沒有覺得哪里不對(duì)呢?是的,這個(gè)賬戶是新的賬戶,但是卻看到了超級(jí)管理員創(chuàng)建的數(shù)據(jù),拋開這個(gè)問(wèn)題不管先,這個(gè)我們后面會(huì)再來(lái)解決。現(xiàn)在我們要做的是創(chuàng)建一條新的記錄,看看能不能成功創(chuàng)建一條新的記錄
Oops! 在選擇分類的時(shí)候突然彈出了個(gè)錯(cuò)誤,這是怎么回事呢,來(lái)仔細(xì)看看錯(cuò)誤提示的內(nèi)容
對(duì)不起,你沒有權(quán)限訪問(wèn)該文檔。如果你認(rèn)為這是一個(gè)錯(cuò)誤,請(qǐng)聯(lián)系系統(tǒng)管理員。(文檔模型:todo.category)
看起來(lái)問(wèn)題并不在我們的待辦事項(xiàng)(todo.task)模型上,而是在分類模型上,我們剛剛分配用戶組權(quán)限時(shí)只分配了待辦事項(xiàng)模型的權(quán)限,所以當(dāng)用戶視圖讀取分類模型的數(shù)據(jù)時(shí),就會(huì)提示沒有權(quán)限訪問(wèn)。解決這個(gè)問(wèn)題同樣很簡(jiǎn)單,只需要加上分類模型的權(quán)限即可
access_todo_category_user,todo.category.user,model_todo_category,group_todo_user,1,0,0,0將上面的權(quán)限定義加到 ir.model.access.csv 文件的行末,然后升級(jí)更新模塊后再次創(chuàng)建,這次終于成功創(chuàng)建起來(lái)了。
對(duì)權(quán)限分配這部分內(nèi)容的認(rèn)識(shí)有沒有比剛開始更開始要清晰一些了呢?那我們這里就留一個(gè)小作業(yè)吧:
為用戶組「管理員」添加權(quán)限,允許該用戶組下的用戶對(duì)分類模型進(jìn)行管理,包括創(chuàng)建、刪除、更新和讀取如果不知道寫得是否正確,可以參考源碼中的我的寫法。
記錄集權(quán)限
用戶組權(quán)限是粒度較粗的權(quán)限控制方式,它只能針對(duì)于某一個(gè)模型的全部記錄應(yīng)用相關(guān)權(quán)限配置,但是某些時(shí)候,我們會(huì)需要粒度更細(xì)的權(quán)限控制方式。一個(gè)現(xiàn)成的例子就是上一節(jié)中,我們用新建的測(cè)試賬戶登錄后,可以看到超級(jí)管理員所創(chuàng)建的待辦事項(xiàng)的記錄,這是不合理的,一個(gè)普通的用戶,應(yīng)該只能看到和操作他所創(chuàng)建的記錄。
值得慶幸的是,Odoo 為我們提供了基于記錄集的權(quán)限控制方式,我們可以很輕松地根據(jù)業(yè)務(wù)需求編寫相應(yīng)的規(guī)則,將權(quán)限控制的粒度精細(xì)到具體的記錄上。為了體現(xiàn)記錄集權(quán)限的用法,我們將假設(shè)在我們的 Todo 應(yīng)用中,普通用戶只能讀取和操作由自己創(chuàng)建的待辦事項(xiàng),而管理員則可以查看和刪除(但不能修改)所有用戶創(chuàng)建的待辦事項(xiàng)。
通常和權(quán)限相關(guān)的內(nèi)容,我們都會(huì)在模塊的 security 目錄下進(jìn)行定義,記錄集規(guī)則的定義自然也不例外。我們創(chuàng)建一個(gè) ir_rule.xml 的文件,然后添加記錄集規(guī)則的定義
<?xml version="1.0" encoding="utf-8"?> <odoo><data noupdate="1"><record id="rule_todo_task_user" model="ir.rule"><field name="name">待辦事項(xiàng)規(guī)則 - 用戶</field><field name="model_id" ref="model_todo_task"/><field name="domain_force">[('create_uid', '=', user.id)]</field><field name="groups" eval="[(4, ref('todo.group_todo_user'))]"/><field name="perm_read" eval="True"/><field name="perm_write" eval="True"/><field name="perm_create" eval="True"/><field name="perm_unlink" eval="True"/></record><record id="rule_todo_task_manager" model="ir.rule"><field name="name">待辦事項(xiàng)規(guī)則 - 管理員</field><field name="model_id" ref="model_todo_task"/><field name="domain_force">[('create_uid', '!=', user.id)]</field><field name="groups" eval="[(4, ref('todo.group_todo_manager'))]"/><field name="perm_read" eval="True"/><field name="perm_write" eval="False"/><field name="perm_create" eval="True"/><field name="perm_unlink" eval="True"/></record></data> </odoo>之后要做的事當(dāng)然就是把 'security/ir_rule.xml' 添加到 __manifest__.py 的 data 中啦,再來(lái)就是升級(jí)更新模塊,現(xiàn)在刷新瀏覽器,應(yīng)該看不到其他用戶創(chuàng)建的待辦事項(xiàng)記錄了,完美達(dá)成目的~現(xiàn)在讓我們回到管理員賬戶所在的瀏覽器,然后創(chuàng)建一個(gè)新的賬戶,并添加到「管理員」組內(nèi),接著再新開一個(gè)隱身窗口登錄這個(gè)新創(chuàng)建的管理員賬戶,我們可以看到和預(yù)期的結(jié)果一樣,管理員可以看到全部用戶創(chuàng)建的待辦事項(xiàng)記錄,隨便點(diǎn)擊一條記錄并編輯,修改任意內(nèi)容后保存,這時(shí)候你會(huì)發(fā)現(xiàn)彈出了一個(gè)錯(cuò)誤警告
這個(gè)錯(cuò)誤提示我們當(dāng)前用戶沒有權(quán)限修改這一條記錄,就如我們前面的假設(shè)一樣,管理員不能修改其他用戶創(chuàng)建的記錄,剩下的創(chuàng)建和刪除,大家可以隨意測(cè)試。
看完了效果之后,又到了解釋說(shuō)明的時(shí)間了,我們先來(lái)看到定義的規(guī)則里最后四個(gè)屬性字段,是不是很熟悉呢?沒錯(cuò),這就是我們?cè)诙x用戶組權(quán)限時(shí)所看到的表示讀寫創(chuàng)建和刪除這四個(gè)操作的屬性,在記錄集權(quán)限的定義里,他們的含義是一樣的,只不過(guò)屬性值從 0 和 1 變成了 True 和 False,然后我們?cè)賮?lái)看看另外幾個(gè)字段:
- model_id:要應(yīng)用該規(guī)則的模型的外部 ID
- domain_force:過(guò)濾條件,符合該條件的記錄都將按照所定義權(quán)限進(jìn)行檢查,其中變量 user 表示當(dāng)前用戶的實(shí)例對(duì)象,可以直接使用
- groups:應(yīng)用該規(guī)則的用戶組,如果不指定則默認(rèn)對(duì)全部用戶應(yīng)用該規(guī)則
菜單隱藏
目前為止,一切看起來(lái)都很不錯(cuò),不過(guò)還有點(diǎn)美中不足。我們?cè)俅未蜷_測(cè)試賬戶所在的瀏覽器窗口,我們前面留了一個(gè)小作業(yè),分類只允許管理員進(jìn)行管理,那么我們自然不希望普通用戶看到多余的菜單內(nèi)容了,所以某些時(shí)候用戶雖然對(duì)某些數(shù)據(jù)具有可讀的權(quán)限,但是未必會(huì)想要開放對(duì)應(yīng)的菜單入口給這些用戶。而我們要根據(jù)用戶組來(lái)對(duì)菜單的可見性進(jìn)行處理,其實(shí)也很簡(jiǎn)單,只需要在對(duì)應(yīng)的菜單項(xiàng)上添加一個(gè) groups 屬性即可,里面的值可以是逗號(hào)分隔的多個(gè)用戶組的外部 ID,以「分類」菜單為例
<!-- views/menus.xml --> <menuitem action="action_todo_category" id="submenu_todo_category" name="分類"parent="menu_todo_submenu" sequence="8" groups="todo.group_todo_manager"/>就這么簡(jiǎn)單,更新模塊之后刷新瀏覽器看看,「分類」菜單是不是已經(jīng)被隱藏起來(lái)了呢,而管理員賬戶依然可以看到該菜單。除了菜單外,在視圖的字段上也可以通過(guò)添加屬性 groups 達(dá)到針對(duì)不同的用戶組隱藏相關(guān)字段的目的。
以上就是這篇教程的全部?jī)?nèi)容了,老規(guī)矩,代碼都在 GitHub 倉(cāng)庫(kù)「Odoo-Tutorial-Demo」中。
寫在最后
雖說(shuō)這是「Odoo 基礎(chǔ)教程系列」的最后一篇內(nèi)容了,但是這不意味著之后不會(huì)再寫 Odoo 相關(guān)的內(nèi)容了,感謝大家一直以來(lái)的支持,雖然很小眾,但是也有不少小伙伴給予了一些正面的鼓勵(lì),雖然更新速度很慢很慢,但是這個(gè)系列終于還是完成啦!自我感覺還是有很多寫得不好的地方,希望以后可以寫得更好~
如果大家有什么問(wèn)題想要得到解答,可以加入群里,和其他小伙伴一起交流或者提問(wèn),添加下面這個(gè)微信,備注 Odoo 加群,通過(guò)后將會(huì)拉入群里的 :)
總結(jié)
以上是生活随笔為你收集整理的「Odoo 基础教程系列」第七篇——从 Todo 应用开始(6)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: STP生成树协议基础
- 下一篇: Apollo_Lattice palnn