1. 程式人生 > 實用技巧 >odoo13學習---11 訪問安全

odoo13學習---11 訪問安全

訪問安全

在這一章中,我們將看到如何執行以下內容:

為了簡明扼要地說明這一點,本章中的內容對現有模組做了一些小小的補充。

技術要求

本章的技術要求包括使用我們在第四章中建立的模組,建立Odoo附加模組。為了遵循這裡的示例,您應該建立並準備使用該模組。

本章中使用的所有程式碼都可以從以下的GitHub儲存庫下載:https:// github.com/packtpublishing/odoo-12-develop-cookbookthird - edition/tree/master/chapter11。

檢視下面的視訊,檢視執行中的程式碼:http://bit.ly/2UCfwlX


建立安全組並將其分配給使用者

  安全訪問在Odoo是通過安全組配置:許可權被給予組,然後組被分配給使用者每個功能區域都有由中心應用程式提供的基本安全組。

  當附加元件模組擴充套件現有應用程式時,它們應該向相應的組新增許可權,如後面的“新增對模型的安全訪問”所示。當附加模組新增現有中央應用程式尚未覆蓋的新功能區域時,它們應該新增相應的安全組。通常,我們至少應該具有使用者和管理人員角色。

  以我們在第4章中介紹的庫為例,建立Odoo附加模組,它不適合任何一個Odoo核心應用程式,所以我們將為它新增安全組。

準備

  這個配製假設您已經準備好了一個Odoo例項,my_module可用,如第4章“建立Odoo附加模組”所述。

怎麼做呢?

  要向模組中新增新的訪問安全組,請執行以下步驟:

  1.確保__manifest__.py附加元件模組清單定義了類別鍵:  

'category': 'Library',

  2.將新的security/groups.xml檔案新增到manifest資料鍵:

'data': [
  'security/groups.xml',
  'views/library_book.xml',
],

  3.為security/library_security_xml的資料記錄新增新的XML檔案,以空結構開始:

<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Data records go here -->
</odoo>

  4.在data XML元素中為兩個新組新增記錄標記

<record id="group_library_user" model="res.groups">
  <field name="name">User</field>
  <field name="category_id" ref="base.module_category_library"/>
  <field name="implied_ids" eval="[(4,ref('base.group_user'))]"/>
</record>

<record id="group_library_librarian" model="res.groups">   <field name="name">Librarians</field>   <field name="category_id" ref="base.module_category_library"/>   <field name="implied_ids" eval="[(4,ref('group_library_user'))]"/>   <field name="users" eval="[(4, ref('base.user_admin'))]"/> </record>

  如果我們升級add-on模組,這兩條記錄將被載入。為了在UI中檢視這些組,您需要啟用開發人員模式。然後可以通過設定|Users|Groups選單選項檢視它們。

  在Odoo v12中,新新增的模型的預設安全工作方式與以前的模型不同。在v12中,如果您正在新增一個新模型,管理使用者不會獲得該模型的訪問許可權。這意味著為該模型新增的選單和檢視對管理使用者不可見。為了顯示它,您需要為該模型新增訪問規則,這在“新增對模型的安全訪問”內容中出現。順便說一下,您可以通過超級使用者訪問新新增的模型;要了解更多關於它,請參考訪問Odoo作為一個超級使用者配方從第4章,建立Odoo附加模組。

它是如何工作的…

  附加模組按功能領域或主要應用程式組織,如會計和金融、銷售或人力資源。它們是由manifest檔案中的類別鍵定義的。

  如果一個類別名稱還不存在,它將自動建立為了方便起見,還將為新類別名生成一個小寫字母的base.module_category_<category_name_in_manifest> XML ID,用下劃線替換空格。這對於將安全組與應用程式類別關聯起來非常有用

  在我們的示例中,我們使用了庫類別名,它生成了base.module_category_library XML識別符號。

  按照約定,包含安全相關元素的資料檔案應該放在安全子目錄中。

  您還需要在manifest檔案中註冊安全檔案。檔案在模組maniest的資料鍵中宣告的順序很重要,因為在定義安全組之前,您不能在其他檢視或ACL檔案中使用安全組的引用。最好將安全資料檔案放在列表的頂部,在ACL檔案和其他使用者介面資料檔案之前。

  在我們的示例中,我們用<record>建立了組。標記,它將建立res.groups模型的一條記錄。res.group模型中最重要的列如下:

  name:這是組的顯示名稱。

  category_id:這是對應用程式類別的引用,用於在使用者表單中組織組。

  implied_ids:這是要從其中繼承許可權的其他組

  users:這是屬於這個組的使用者列表在新的附加元件模組中,我們通常希望admin使用者屬於應用程式的manager組。

  第一個安全組使用implied_ids作為base.group_user組。這是僱員使用者組,也是所有後端使用者期望共享的基本安全組。

  第二個安全組在users欄位上設定一個值,將其分配給管理員使用者,該使用者具有基數。user_admin XML ID。

  屬於某個安全組的使用者將自動屬於它的隱含組如果將Librarians組分配給任何使用者,則該使用者也將包括在使用者組中,因為Librarians組將使用者組包含在其implied_ids列中。

  另外,安全組授予的訪問許可權是累積的。如果使用者所屬的任何組(直接或暗示)授予該許可權,則使用者具有該許可權。

  一些安全組在使用者表單中顯示為選擇框,而不是單個複選框當涉及的組位於相同的應用程式類別中,並且通過implied_ids進行線性關聯時,就會發生這種情況例如,組A有隱含組B,組B有隱含組c。如果一個組通過implied_ids與任何其他組無關,您將看到一個複選框,而不是選擇框。

  請注意,在前面欄位中定義的關係還具有可以在相關模型(如安全組和使用者)中編輯的反向關係。

  在引用欄位(如category_idimplied_ids)上設定值是使用相關記錄的XML id和一些特殊語法完成的。該語法將在第7章模組資料中詳細解釋。

有更多的…

  特別的base.group_no_one安全組稱為Extra Rights也值得注意。在以前的Odoo版本中,它預設用於隱藏高階功能,只有當技術功能標誌被啟用時才可見。從版本9.0開始,這一點已經改變了,只要啟用Developer模式,這些特性都是可見的。

  安全組授予的訪問許可權只能是累積的。無法拒絕組提供的訪問。這意味著用於定製許可權的手動建立的組應該從許可權少於預期許可權(如果有的話)的最近組繼承,然後新增所需的所有剩餘許可權。

組也有這些額外的欄位可用:

  •   Menus (menu_access欄位):這些是組可以訪問的選單項
  •   Views (view_access欄位):這些是組可以訪問的UI檢視
  •   訪問許可權(model_access欄位):這是它對模型的訪問許可權,詳細內容在“向模型新增安全訪問”內容中
  •   規則(rule_groups欄位):這些是應用於組的記錄級訪問規則,詳見使用記錄規則內容限制記錄訪問
  •   註釋(註釋欄位):這是組的描述或評論文字

新增對模型的安全訪問

  附加模組新增新模型是很常見的。例如,在第4章“建立Odoo附加模組”中,我們添加了一個新的Library Books模型。在開發過程中很容易錯過為新模型建立安全訪問許可權的過程,並且您可能會發現很難看到已經建立的選單和檢視,因為從Odoo version 12開始,admin使用者沒有獲得對新模型的預設訪問許可權。為了檢視新模型的檢視和選單,您必須新增安全訪問控制列表(acl)。

  但是,沒有ACL的模型將在載入時觸發警告日誌訊息,通知使用者缺少ACL定義:

WARNING The model library.book has no access rules, consider adding one example, access_library_book, access_library_book, model_library_book, base.group_user,1,0,0,0

  您還可以通過超級使用者訪問新新增的模型,因為這繞過了所有的安全規則。要了解更多關於這一點,請參考訪問Odoo作為一個超級使用者配方從第4章,建立Odoo Add-On模組。超級使用者特性只對管理員使用者可用。因此,為了讓非admin使用者可以使用新模型,我們需要定義它們的訪問控制列表,以便Odoo知道它應該如何訪問它們,以及每個使用者組應該允許執行哪些操作。

準備

  我們將採取我們在第4章建立的模組,建立Odoo附加模組,並新增缺少的acl到它。

怎麼做呢?

  my_library應該已經包含了models/library_book.py Python檔案,該檔案建立了library.book模型。現在我們將新增一個數據檔案,通過執行以下步驟來描述這個模型的安全訪問控制:

  1.編輯__manifest__.py檔案以宣告一個新的資料檔案:

data: [
  # ...Security Groups
  'security/ir.model.access.csv',
  # ...Other data files
]

  2.使用以下程式碼向模組中新增一個新的security/ir.model.access.csv檔案:

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
acl_book,library.book_default,model_library_book,base_group_user,1,0,0,0
acl_book_librarian,library.book_librarian,model_library_book,group_library_librarian,1,1,1,1

  然後,我們應該升級模組,將這些ACL記錄新增到我們的Odoo資料庫中。更重要的是,如果我們使用演示使用者登入到一個演示資料庫,我們應該能夠訪問Library選單選項而不會出現任何安全錯誤。

它是如何工作的…

  安全訪問控制列表儲存在核心ir.model.access模型中。我們只需要新增描述每個使用者組預期訪問許可權的記錄。

  任何型別的資料檔案都可以,但通常的做法是使用CSV檔案。該檔案可以放在add-on模組目錄中的任何位置,但約定是將所有與安全相關的檔案放在一個安全子目錄中。

  我們的內容中的第一步將這個新資料檔案新增到manifest中。第二步新增描述安全訪問控制規則的檔案。CSV檔案必須以載入記錄的模型命名,因此使用的名稱不僅是約定,而且是強制的;詳見第7章模組資料。

  如果模組還建立了新的安全組,那麼它的資料檔案應該在acl資料檔案之前的清單中宣告,因為您可能希望將它們用於acl。它們必須在處理ACL檔案時已經建立。

  CSV檔案中的列如下:

  id:這是該規則的XML id內部識別符號。模組內的任何唯一名稱都可以,但約定是使用access_<model>_<group>

  name:這是訪問規則的標題。通常使用access.<model>_<group>名。

  model_id:這是模型的XML id。Odoo自動將這種ID分配給model_<name>格式的模型,使用模型的_name下劃線代替點。如果模型是在不同的外接程式模組中建立的,則需要包含模組名稱的完全限定XML ID。

  group_id:id:這是使用者組的XML id。如果為空,則適用於所有使用者基本模組提供了一些基本組,比如針對所有員工的base.group_user和針對管理使用者的base.group_system其他應用程式可以新增自己的使用者組。

  perm_read:前一組的成員可以讀取模型記錄。它接受兩個值:0或1。使用0限制對模型的讀訪問,使用1提供讀訪問。

  perm_write:前一組的成員可以更新模型記錄。它接受兩個值:0或1。使用0限制對模型的寫訪問,使用1提供寫訪問。

  perm_create:前一個組的成員可以新增這個模型的新記錄。它接受兩個值:0或1。使用0限制對模型的建立訪問,使用1提供建立訪問。

  perm_unlink:前一組的成員可以刪除此模型的記錄。它接受兩個值:0或1。使用0限制對模型的斷開連結訪問,使用1提供斷開連結訪問。

  我們使用的CSV檔案添加了對僱員|僱員標準安全組的只讀訪問權和對管理|設定組的完全寫訪問權。

  員工使用者組base.group_user特別重要,因為Odoo標準應用程式新增的使用者組是從它繼承的這意味著,如果我們需要一個能被所有後端使用者訪問的新模型,而不管他們使用的是什麼特定的應用程式,我們應該將該許可權新增到員工組中。

  生成的acl可以在除錯模式下從GUI中檢視,導航到Settings|Technical|Security|Access Controls列表,如下圖所示:

  有些人發現使用這個使用者介面來定義acl,然後使用export特性來生成CSV檔案更容易。

有更多的…

  將此許可權授予在建立安全組中定義的Library使用者和Library組,並將它們分配給使用者內容,這對我們來說是有意義的。如果您遵循了這個方法,那麼遵循這個方法是一個很好的練習,使組識別符號適應庫識別符號。

  需要注意的是,add-on模組提供的訪問列表不應該直接定製,因為它們將在下一次模組升級時重新載入,從而破壞任何可能從GUI完成的定製。

  要定製acl,可以使用兩種方法。一種是建立新的安全組,從模組提供的安全組繼承,並在其上新增額外的許可權,但這隻允許我們新增許可權,而不是刪除許可權。更靈活的方法是在特定ACL線路上取消選中活動標誌以禁用它們。active欄位在預設情況下是不可見的,因此我們需要編輯樹檢視來新增<fieldname="active" />列。我們還可以為附加或替換許可權新增新的ACL行。在模組升級時,停用的ACL不會被重新啟用,新增的ACL行不會受到影響。

  還有一點值得注意,acl只應用於常規模型,不需要為抽象或瞬態模型定義。如果定義了,這些將被忽略,並在伺服器日誌中觸發一條警告訊息。


限制對模型中的欄位的訪問

  在某些情況下,我們可能需要更細粒度的訪問控制,還可能需要限制對模型中特定欄位的訪問。

  只有特定的安全組可以使用groups屬性訪問欄位。我們將向您展示如何新增對Library Books模型具有有限訪問權的欄位。

怎麼做呢?

  要新增訪問許可權僅限於特定安全組的欄位,請執行以下步驟:

  1.編輯模型檔案,新增欄位:

is_public =fields.Boolean(groups='my_library.group_library_librarian')
private_notes =fields.Text(groups='my_library.group_library_librarian')

  2.在XML檔案中編輯檢視,新增欄位:

<field name="is_public" />
<field name="private_notes" />

  就是這樣。現在,升級add-on模組以使模型中的更改發生。如果您與一個沒有系統配置訪問許可權的使用者登入,比如在一個有演示資料的資料庫中進行演示,那麼Library Books表單將不會顯示該欄位。

它是如何工作的…

  具有groups屬性的欄位將被特別處理,以檢查使用者是否屬於該屬性中指示的任何安全組。如果一個使用者不屬於一個特定的組,Odoo將從UI和限制ORM操作該欄位刪除該欄位。

  注意,這種安全性不是表面的。該欄位不僅隱藏在使用者介面中,而且在其他ORM操作(如讀和寫)中對使用者不可用。對於XML-RPC或JSON-RPC呼叫也是如此。

  在業務邏輯或on-change UI事件中使用這些欄位時要小心(@api onchange methods);對於無法訪問欄位的使用者,它們可能會引發錯誤。

  一種解決方法是使用特權提升,例如sudo()模型方法或計算欄位的compute_sudo欄位屬性。

  groups值是一個字串,其中包含一個逗號分隔的安全組有效XML id列表找到特定組的XML ID的最簡單方法是啟用developer模式並導航到組的表單,在Settings|Users|Groups處,然後從debug選單中訪問View Metadata選項,如下面的螢幕截圖所示:

有更多的…

  在某些情況下,我們需要一個欄位可用或不可用,這取決於特定的條件,比如欄位中的值,例如stage_idstate這通常是在檢視級別處理的,使用屬性如狀態或attrs來根據特定條件動態顯示或隱藏欄位。有關詳細描述,請參閱第10章後端檢視。

  注意,這些技術僅在使用者介面級別工作,並不提供實際的訪問安全性。為此,您應該在業務邏輯層中添加簽入。新增裝飾有@constraints的模型方法,實現預期的特定驗證,或者擴充套件createwriteunlink方法來新增驗證邏輯。在第6章基本伺服器端業務邏輯中,您可以進一步瞭解如何做到這一點。


使用記錄規則限制記錄訪問

  應用程式的一個常見需求是能夠限制哪些記錄對特定模型上的每個使用者可用。

  這是通過使用記錄規則實現的。記錄規則是在模型上定義的域篩選器表示式,它將被新增到受影響使用者所做的每個資料查詢中

  作為示例,我們將在Library Books模型中新增一個記錄規則,以便員工組中的使用者將只能訪問公共圖書。

  這個配製假設您已經準備好了一個例項,my_library可用,如第4章建立Odoo Add-On模組所述。

怎麼做呢?

  記錄規則是使用資料XML檔案新增的。為此,請執行以下步驟:

  1.確保manifest data key引用了security/library_security.xml檔案:

'data': [
  'security/library_security.xml',
  # ...
],

  2.我們應該有一個security/library_security.xml資料檔案,帶有建立安全組的<odoo>部分:

<odoo noupdate="1">
  <record model="ir.rule" id="library_book_user_rule">
    <field name="name">Library: see only own books</field>
    <field name="model_id" ref="model_library_book"/>
    <field name="groups" eval="[(4,ref('my_library.group_library_user'))]"/>
    <field name="domain_force">
      [('is_public', '=', True)]
    </field>
</record>
<record model="ir.rule" id="library_book_all_rule">   <field name="name">Library: see all books</field>   <field name="model_id" ref="model_library_book"/>   <field name="groups" eval="[(4,ref('my_library.group_library_librarian'))]"/>     <field name="domain_force">[(1, '=', 1)]</field>   </record> </odoo>

  升級add-on模組將在Odoo例項中載入記錄規則。如果您正在使用演示資料,則可以通過預設的演示使用者對其進行測試,從而將庫使用者許可權授予演示使用者。如果不使用演示資料,可以建立具有庫使用者許可權的新使用者。

它是如何工作的…

  記錄規則只是載入在ir.rule核心模型中的資料記錄。雖然新增它們的檔案可以位於模組中的任何位置,但約定是在security子目錄中。通常有一個同時具有安全組和記錄規則的XML檔案。

與組不同的是,在標準模組中,記錄規則被裝載在帶有noupdate="1"屬性的odoo部分中這樣,那些記錄將不會在模組升級時被重新載入,這意味著對它們的手動定製是安全的,並且在以後的升級中仍然有效。

  為了與官方模組保持一致,我們還應該將記錄規則放在<odoo noupdate="1">節中。

  在設定|Technical|Security|Record rules選單選項中可以看到記錄規則,如下截圖所示:

  下面是本例中使用的最重要的記錄規則欄位:

  Name (Name):規則的描述性標題。

  Object(model_id):對應用規則的模型的引用。

  Groups(groups):規則應用於的安全組。如果沒有指定任何安全組,則認為該規則是全域性的,並以不同的方式應用(繼續使用此內容以瞭解有關組的更多資訊)。

  Domain(domain):用於過濾記錄的域表示式。該規則只會應用於這些經過篩選的記錄。我們為庫使用者安全組建立的第一個記錄規則。它使用[('is_public','=',True)]域表示式,只選擇公開的圖書。因此,圖書館使用者安全組的使用者將只能看到公共圖書。記錄規則中使用的域表示式使用ORM物件在伺服器端執行。因此,點符號可以用於左邊的欄位(第一個元組元素)。例如,[('country_id.code','=','IN')]域表示式將只顯示擁有印度國家的記錄。

  由於記錄規則主要基於當前使用者,所以您可以在域的右側(第三個元組元素)使用使用者記錄集。因此,如果您想要顯示當前使用者的公司記錄,您可以使用[('conpany_id','=',user.company_id.id)]域。另外,如果您想要顯示當前使用者建立的記錄,您可以使用[('user_id', '=',user.id)]域。

  我們希望圖書管理員安全小組能夠看到所有的圖書,不管它們是公共的還是私人的。因為它繼承了圖書館使用者組,除非我們對它做了一些處理,否則它也將只能看到公共圖書。

  非全域性記錄規則使用OR邏輯操作符連線在一起;每個規則都新增訪問許可權,並且從不刪除訪問許可權。為了讓圖書管理員能夠訪問所有圖書,我們可以向其新增一個記錄規則來新增對所有圖書的訪問,如下所示:[('is_public','in',[True, False])]。

  這裡我們選擇了不同的方式,使用[(1,'=',1)]特殊規則無條件地提供對所有圖書記錄的訪問。雖然這看起來是多餘的,但請記住,否則,可以自定義Library user規則,使一些書籍遠離設定使用者。域是特殊的,因為域元組的第一個元素必須是欄位名;這種情況是不正確的兩種情況之一。特殊域[(1,'=',0)]從來都不是真的,但是對於記錄規則也不是很有用,因為這種型別的規則用於限制對所有記錄的訪問。訪問列表也可以這樣做。

  如果您激活了超級使用者,記錄規則將被忽略。當測試您的記錄規則時,確保您使用了另一個使用者

有更多的…

  當一個記錄規則沒有分配給任何安全組時,它被標記為全域性的,並且處理方式與其他規則不同。

  全域性記錄規則比組級記錄規則的作用更大,可以設定無法覆蓋的訪問限制。從技術上講,它們是由AND操作符連線的。在標準模組中,它們用於實現多公司安全訪問,以便每個使用者只能看到他們公司的資料。

  總之,規則的非全域性記錄規則用OR操作符連線在一起;它們被加在一起,如果任何規則授予了一條記錄的訪問權,那麼它就是可訪問的。然後,全域性記錄規則使用AND操作符向常規記錄規則提供的訪問許可權新增限制。由全域性記錄規則新增的限制不能被常規記錄規則覆蓋


使用安全組啟用特性

  安全組可以限制某些特性,以便只有屬於這些組的使用者才能訪問它們。安全組還可以繼承其他組,因此它們也可以授予它們的許可權。

  這兩個特性結合在一起用來實現Odoo的可用性特性:特性切換安全組還可以用來為一個Odoo例項中的部分或所有使用者啟用或禁用特性。

  此內容展示瞭如何向配置設定新增選項,並展示了啟用其他特性的兩種方法,使用安全組使它們可見,或者通過安裝額外的模組來新增它們。

  對於第一種情況,我們將使圖書發行日期成為一個可選的附加特性,對於第二種情況,作為示例,我們將提供一個選項來安裝Notes模組。

準備

  這個配製使用my_library,在第4章建立Odoo附加模組中有描述。我們將需要使用安全組,因此您還需要遵循本章中的“新增對模型的安全訪問”內容。

  在此內容中,一些識別符號需要引用附加元件模組的技術名稱。我們假設這是my_library。如果您使用不同的名稱,請將my_library替換為您的附加元件模組的實際技術名稱。

怎麼做呢?

  要新增配置選項,請遵循以下步驟:

  1.要新增所需的依賴項和新的XML資料檔案,像下面這樣編輯__manifest__.py檔案並檢查它是否依賴於base_setup:

{ 
  'name': 'Cookbook code',   'category': 'Library',   'depends': ['base_setup'],   'data': [     'security/ir.model.access.csv',     'security/groups.xml',     'views/library_book.xml',     'views/res_config_settings.xml',   ], }

2.要新增用於啟用特性的新安全組,編輯security/library_book.xml檔案,並新增以下記錄:

<record id="group_release_dates" model="res.groups">
  <field name="name">Library: release date feature</field>
  <field name="category_id"  ref="base.module_category_hidden" />
</record>

3.要使圖書發行日期只在啟用這個選項時可見,請在models/library_book.py檔案中編輯欄位定義:

class LibraryBook(models.Model):
  # ...
  date_release = fields.Date('Release Date',groups='my_library.group_release_dates')

4.編輯model /__init__.py檔案,為配置設定模型新增一個新的Python檔案:

from . import library_book
from . import res_config_settings

5.要通過新增新選項來擴充套件核心配置嚮導,請使用以下程式碼新增models/res_config_settings.py檔案:

# -*- coding: utf-8 -*-
from odoo import models, fields

class ConfigSettings(models.TransientModel):
    _inherit = 'res.config.settings'
    group_release_dates = fields.Boolean("Manage book release dates",group='base.group_user',implied_group='my_library.group_release_dates',    )
    module_note = fields.Boolean("Install Notes app")

6.為了讓選項在UI中可用,新增views/res_config_settings.xml,它擴充套件了表單檢視:

<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <record id="view_general_config_library" model="ir.ui.view">
        <field name="name">Configuration: add Library options</field>
        <field name="model">res.config.settings</field>
        <field name="inherit_id" ref="base_setup.res_config_settings_view_form" />
        <field name="arch" type="xml">
            <div id="business_documents" position="before">
                <h2>Library</h2>
                <div class="row mt16 o_settings_container">
                    <!-- Release Dates option -->
                    <div class="col-12 col-lg-6 o_setting_box">
                        <div class="o_setting_left_pane">
                            <field name="group_release_dates" class="oe_inline"/>
                        </div>
                        <div class="o_setting_right_pane">
                            <label for="group_release_dates"/>
                            <div class="text-muted">
                                Enable relase date feature on books
                            </div>
                        </div>
                    </div>
                    <!-- Release Dates option -->
                    <div class="col-12 col-lg-6 o_setting_box">
                        <div class="o_setting_left_pane">
                            <field name="module_note" class="oe_inline"/>
                        </div>
                        <div class="o_setting_right_pane">
                            <label for="module_note"/>
                            <div class="text-muted">
                                Install note module
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </field>
    </record>
</odoo>

升級add-on模組之後,兩個新的配置選項應該可以在設定|常規設定中使用。螢幕應該是這樣的:

它是如何工作的…

  核心基礎模組提供res.config.settings模型,提供選項啟用選項背後的業務邏輯。base_setup附加模組使用res.config.settings模型提供幾個基本配置選項,以便在新資料庫中可用。它還使設定|通用設定選單可用。

  base_setup模組將res.config.settings調整到中央管理儀表板,因此我們需要擴充套件它以新增我們自己的配置設定。如果我們決定為庫應用程式建立一個特定的設定表單,我們仍然可以用不同的_name繼承res.config.settings模型,然後為新模型提供這些設定的選單選項和表單檢視。我們在第9章“高階伺服器端開發技術”的“新增自己的設定選項內容”中已經看到了這種方法。

  我們使用了兩種不同的方法來啟用這些特性:一種方法是啟用安全組並使該特性對使用者可見,另一種方法是安裝提供該特性的附加模組。處理這兩種情況的邏輯由基本的res.config.settings模型提供。

  內容的第一步將base_setup附加元件模組新增到依賴項中,因為它提供了對我們想要使用的res.config.settings模型的擴充套件。它還添加了一個額外的XML資料檔案,我們將需要該檔案向General Settings表單新增新選項。

  在第二步中,我們建立一個新的安全組,Library: release date特性。要啟用的特性應該僅對該組可見,因此在啟用該組之前它將被隱藏。

  在我們的示例中,我們希望只有在啟用了相應的配置選項時,圖書的釋出日期才可用。為了實現這一點,我們在欄位上使用groups屬性,以便它僅對這個安全組可用。我們在模型級別上這樣做,以便它自動應用到使用該欄位的所有UI檢視。

  最後,我們擴充套件了res.config.settings模型以新增新的選項。每個選項都是一個布林欄位,其名稱必須以group_module_開頭,這取決於我們希望它做什麼。

  group_ option欄位應該具有implied_group屬性,並且應該是一個字串,其中包含一個以逗號分隔的XML id列表,用於在啟用時啟用安全組。XML id必須採用完整的形式,包括模組名稱、點和識別符號名稱,如module_name.identifier

  我們還可以提供一個group屬性來指定將為哪些安全組啟用該特性。如果沒有定義組,那麼它將對所有基於員工的組啟用。因此,相關組將不適用於門戶安全組,因為它們不像其他常規安全組那樣繼承員工基礎安全組。

  啟用背後的機制非常簡單:它將group屬性中的安全組新增到implied_group中,從而使相關特性對相應的使用者可見。

  module_ option欄位不需要任何附加屬性。欄位名的其餘部分標識啟用該選項時要安裝的模組。在我們的示例中,module_note將安裝note模組。

  取消複選框將在沒有警告的情況下解除安裝模組,這可能會導致資料丟失(結果是模型或欄位和模組資料將被刪除)。為了避免不小心取消複選框,secure_uninstall社群模組(來自https://github.com/oca/server-tools)在解除安裝附加元件模組之前提示使用者輸入密碼。

  此內容的最後一步將其新增到General Settings表單檢視中,它位於id="business_documents"的業務文件組之前。我們使用這個id進行檢視繼承。它用模組名作為ID建立自己的div,這是一種很好的做法,因為擴充套件my_library的其他模組可以輕鬆地將它們自己的配置項新增到這個div中。

有更多的…

  配置設定也可以使用default_字首命名欄位。當其中一個具有值時,ORM將其設定為全域性預設值。設定欄位應該有一個default_model屬性來標識受影響的模型,而default_字首後面的欄位名稱標識將設定預設值的模型欄位。

  另外,沒有上述三個字首的欄位也可以用於其他設定,但是您需要實現邏輯來填充它們的值,使用get_default_ name作為字首的方法,並在它們的值被編輯時使用set_ name作為字首的方法。

  對於那些想深入瞭解配置設定細節的人來說,最好的文件是在Odoo的原始碼./ Odoo /addons/base/models/res_config.py中,其中有大量的註釋和所有細節的解釋。


作為超級使用者訪問記錄集

  在前面的菜內容中,我們看到了安全技術,例如訪問規則、安全組和記錄規則。使用這些技術,您可以避免未經授權的訪問。然而,有時您會遇到複雜的業務案例,在這些案例中您希望訪問或修改記錄,即使使用者沒有訪問權。例如,假設公共使用者不能訪問潛在客戶記錄,但是通過提交網站表單,使用者可以在後端生成潛在客戶記錄。

  使用sudo(),您可以作為超級使用者訪問記錄集。我們已經在第9章高階伺服器端開發技術中改變執行操作配方的使用者中看到了sudo()。在這裡,我們將看到,即使在欄位上提供了ACL規則或添加了安全組,仍然可以通過sudo()進行訪問。

怎麼做呢?

  我們將使用與上一個內容相同的my_library模組。我們已經有了一個ALC規則,它為普通使用者提供只讀讀取。我們將新增一個帶有安全組的新欄位,以便只有圖書管理員可以訪問它。在此之後,我們將由普通使用者修改欄位值。遵循以下步驟來實現這一點:

1.在library.book模型中新增新欄位:

report_missing = fields.Text(string="Book is missing",groups='my_library.group_library_librarian')

2.在表單檢視中新增欄位:

<field name="report_missing"/>

3.在library.book模型中新增report_missing_book()方法:

def report_missing_book(self):
  self.ensure_one()
  message = "Book is missing (Reported by: %s)" % self.env.user.name
  self.sudo().write({
    'report_missing': message
  })

4.在表單檢視中新增按鈕,從使用者介面觸發此方法:

<button name="report_missing_book" string="Report Missing Book" type="object"/>

  重新啟動伺服器並更新模組以應用這些更改。

它是如何工作的…

  在步驟1和步驟2中,我們在模型和表單檢視中添加了一個名為report_missing的新欄位。注意,我們將my_library.group_library_librarian組放在Python中的欄位上,因此該欄位只能由Librarian使用者訪問。

  在下一步中,我們添加了report_missing_book()方法,在該方法的主體中更新了report_missing欄位的值。注意,我們在呼叫write方法之前使用了sudo()。

  最後,我們在表單檢視中添加了一個按鈕,以從使用者介面觸發該方法。

  要測試此實現,需要使用非library使用者登入。如果您已經載入了帶有演示資料的資料庫,那麼您可以與演示使用者一起登入,然後在圖書的表單檢視中單擊Missing book report按鈕。單擊該按鈕時,將呼叫report_missing_book()方法,這將在report_missing欄位中寫入訊息,即使使用者沒有正確的許可權。您可以通過管理使用者檢查欄位的值,因為該欄位將隱藏在演示使用者中。

  在單擊Report Missing Book按鈕時,我們將在report_missing_book()方法中獲得當前圖書的記錄集作為引數self.。在向圖書記錄集寫入值之前,我們使用self.sudo()這將返回相同的記錄集,但使用不同的環境。這個記錄集將擁有來自超級使用者的環境,並且它將繞過所有訪問規則和記錄規則。正因為如此,非圖書管理員的使用者將能夠在圖書記錄中進行書寫。甚至模型的日誌欄位write_uid也將具有超級使用者的值。

有更多的…

  在使用sudo()時需要格外小心,因為它繞過了所有的訪問許可權。在多公司環境中,如果您沒有正確使用它,它可能會產生問題。如果希望作為另一個使用者訪問記錄集,可以在sudo中傳遞該使用者的ID,比如self_sudo(uid)這將返回該使用者環境的記錄集。這樣,它就不會繞過所有的訪問規則和記錄規則,但是您可以執行該使用者所允許的所有操作。


基於組隱藏檢視元素和選單

  在前面的內容中,我們看到了如何在Python欄位定義中使用組引數對某些使用者隱藏欄位。在使用者介面中隱藏欄位還有另一種方法:在檢視定義中的XML標記上新增安全組。

還可以在選單上使用安全組對特定使用者隱藏它們。

準備

  對於此內容,我們將重用上一個菜譜中的my_library附加元件模組。在上一個內容中,我們在<header>標籤中添加了一個按鈕。我們將通過新增一個groups屬性來對一些使用者隱藏整個標題。

  為book.category模型新增模型、檢視和選單。我們將對使用者隱藏類別選單。參考第5章,應用模型,瞭解如何新增模型檢視和選單。

怎麼做呢?

  按照給定的步驟隱藏基於安全組的元素:

1.在<header>上新增一個groups屬性,可以對其他使用者隱藏它:

...
<header groups="my_library.group_library_user">
...

2.在<menuitem>圖書類別中新增groups屬性,只對圖書管理員使用者顯示:

<menuitem name="Book Categories"
  id="library_book_category_menu"
  parent="library_base_menu"
  action="library_book_category_action"
  groups="my_library.group_library_librarian"/>

重新啟動伺服器並更新模組以應用更改。

它是如何工作的…

  在第一步中,我們添加了groups="my_library.group_library_user"。這意味著整個標題部分只對圖書館使用者和圖書管理員可見。沒有group_library_user的普通後端使用者將看不到標題部分。

  在步驟2中,我們在menuitem上添加了groups="my_library.group_library_librarian"屬性。這意味著該選單僅對圖書管理員使用者可見。您幾乎可以在任何地方使用groups屬性,包括<field>、<notebook>、<group>、<menuitems>或檢視架構中的任何標籤。Odoo將隱藏那些元素,如果使用者沒有該組。您可以在web頁面和QWeb報告中使用相同的組屬性,這將在第13章自動化、工作流和列印輸出和第15章CMS網站開發中介紹。

  正如我們在本章超級使用者的訪問記錄集中看到的,我們可以使用Python欄位定義中的groups引數對一些使用者隱藏欄位。請注意,欄位上的安全組和檢視上的Python安全組之間有很大的區別。Python中的安全組提供了真正的安全性;未經授權的使用者甚至不能通過ORM或RPC呼叫訪問欄位。然而,檢視中的組只是為了提高可用性。在XML檔案中通過組隱藏的欄位仍然可以通過RPC或ORM訪問。