安全
odoo提供了兩種方式來(lái)管理數(shù)據(jù)權(quán)限而不需要通過(guò)手寫(xiě)權(quán)限管理相關(guān)代碼,每種方式都通過(guò)用戶組來(lái)指定用戶:一個(gè)用戶屬于多個(gè)用戶組渣窜,安全機(jī)制通過(guò)用戶組關(guān)聯(lián)作用到用戶
訪問(wèn)控制
1.通過(guò)ir.model.access記錄來(lái)管理铺根,定義對(duì)整個(gè)模型的訪問(wèn)權(quán)限
2.每一條記錄包含有 (1)對(duì)應(yīng)的授權(quán)模型 (2)授予的權(quán)限 (3) 可選的用戶組
3.訪問(wèn)權(quán)限控制是附加的,對(duì)于一個(gè)模型用戶擁有賦予它所在組的權(quán)限:如果用戶所在用戶組1擁有寫(xiě)權(quán)限乔宿,用戶組2有刪除權(quán)限位迂,那么該用戶擁有寫(xiě)和刪除權(quán)限)
4.如果沒(méi)有指定用戶組,這條權(quán)限控制就會(huì)作用在所有用戶上详瑞,否則只會(huì)作用在指定組的用戶上
5.可用的權(quán)限是:寫(xiě)(perm_create),搜索和讀取(perm_read),更新現(xiàn)有記錄(perm_write),刪除記錄(perm_unlink)
記錄行規(guī)則
記錄行規(guī)則規(guī)定進(jìn)行(create, read, update or delete)操作時(shí)數(shù)據(jù)需要滿足的條件掂林,它會(huì)在應(yīng)用了訪問(wèn)控制權(quán)限之后逐條記錄進(jìn)行應(yīng)用
記錄行規(guī)則的要素:
1.需要被應(yīng)用規(guī)則的model
2.需要應(yīng)用的規(guī)則(如果設(shè)置了perm_read ,那么只在讀取記錄時(shí)檢查)
3.需要應(yīng)用規(guī)則的用戶組坝橡,如果沒(méi)指定用戶組泻帮,那么該規(guī)則就是全局的
4.用來(lái)檢查記錄是否滿足條件的domain表達(dá)式,如果true表示可訪問(wèn)驳庭,false表示不可訪問(wèn)刑顺,domain表達(dá)式使用兩個(gè)上下文變量:user - 當(dāng)前用戶記錄氯窍,time - python time
全局規(guī)則和基于用戶組的規(guī)則使用方式不同:
- 全局規(guī)則必須全部滿足才能賦予權(quán)限
- 用戶組規(guī)則是附加的饲常,只要滿足其中一個(gè)就可以有權(quán)限(需要滿足全局權(quán)限)
記錄行規(guī)則對(duì)于管理員用戶是沒(méi)有作用的
字段權(quán)限
一個(gè)ORM字段可以通過(guò)groups屬性來(lái)指定一個(gè)可訪問(wèn)的組列表(以逗號(hào)分隔)
如果當(dāng)前用戶不在指定的任何一個(gè)用戶組中蹲堂,那么不能訪問(wèn)該字段
- 沒(méi)訪問(wèn)權(quán)限的字段會(huì)自動(dòng)從視圖中移除
- 沒(méi)權(quán)限的字段也會(huì)從fields_get() 函數(shù)的返回中移除
- 嘗試去讀或?qū)懳词跈?quán)字段會(huì)報(bào)出一個(gè)權(quán)限錯(cuò)誤
工作流轉(zhuǎn)換規(guī)則
工作流也可以通過(guò)指定用戶組來(lái)控制權(quán)限,用戶不在指定組內(nèi)的將不會(huì)觸發(fā)相應(yīng)動(dòng)作
模塊測(cè)試
odoo支持通過(guò)單元測(cè)試來(lái)測(cè)試模塊贝淤,寫(xiě)測(cè)試用例只需要在模塊文件夾建立一個(gè)test文件夾柒竞,測(cè)試模塊文件名須以test_開(kāi)頭,并且在__ init __.py里導(dǎo)入
your_module
|-- ...
`-- tests
|-- __init__.py
|-- test_bar.py
`-- test_foo.py
#__init__.py
from . import test_foo, test_bar
默認(rèn)只能運(yùn)行python官方提供的部分測(cè)試播聪,odoo提供了一些用來(lái)測(cè)試odoo內(nèi)容的工具
class odoo.tests.common.TransactionCase(methodName='runTest')
每個(gè)測(cè)試方法運(yùn)行在自己的事務(wù)中的測(cè)試用例朽基,使用自己的數(shù)據(jù)庫(kù)游標(biāo),當(dāng)用例執(zhí)行完自動(dòng)回滾browse_ref(xid) 返回指定id的記錄對(duì)象
ref(xid) 返回提供的external identifier對(duì)應(yīng)的數(shù)據(jù)庫(kù)id离陶,與get_object_reference一致
class odoo.tests.common.SingleTransactionCase(methodName='runTest')
所有測(cè)試方法都在同一個(gè)事務(wù)中執(zhí)行的測(cè)試用例稼虎,事務(wù)從第一個(gè)測(cè)試方法開(kāi)始,直到最后一個(gè)完成才回滾browse_ref(xid) 返回指定id的記錄對(duì)象
ref(xid) 返回提供的external identifier對(duì)應(yīng)的數(shù)據(jù)庫(kù)id招刨,與get_object_reference一致
默認(rèn)情況下霎俩,在安裝好對(duì)應(yīng)模塊后會(huì)自動(dòng)執(zhí)行對(duì)應(yīng)的測(cè)試用例,也可配置為在所有模塊安裝完成后再運(yùn)行
odoo.tests.common.at_install(flag)
設(shè)置安裝測(cè)試用例沉眶,flag參數(shù)(boolean)設(shè)置該測(cè)試用例是否在安裝時(shí)執(zhí)行打却,默認(rèn)情況下會(huì)在安裝完該模塊后,安裝下一個(gè)模塊前自動(dòng)運(yùn)行用例odoo.tests.common.post_install(flag)
設(shè)置安裝后測(cè)試用例谎倔,flag參數(shù)(boolean)表示是否在安裝后自動(dòng)運(yùn)行用例柳击,默認(rèn)情況下測(cè)試用例只會(huì)在所有模塊安裝完成后才運(yùn)行
class TestModelA(common.TransactionCase):
def test_some_action(self):
record = self.env['model.a'].create({'field': 'value'})
record.some_action()
self.assertEqual(
record.field,
expected_field_value)
# other tests...
當(dāng)啟動(dòng)odoo時(shí)如果指定--test-enable ,測(cè)試用例會(huì)在安裝或更新模塊時(shí)運(yùn)行
web控制器
路由
odoo.http.route(route=None, **kw) 裝飾器可以裝對(duì)應(yīng)方法裝飾為處理對(duì)應(yīng)的http請(qǐng)求片习,該方法須是Controller的子類
參數(shù)列表:
- route -- 字符串或數(shù)組捌肴,決定哪個(gè)http請(qǐng)求匹配所裝飾的方法,可以是當(dāng)個(gè)字符串藕咏、或多個(gè)字符串的數(shù)組状知,用的是werkzeug的路由http://werkzeug.pocoo.org/docs/routing/
- type -- 請(qǐng)求的類型,可以是http或json
- auth -- 認(rèn)證方法的類型侈离,可以是以下幾種:
- user - 必須是認(rèn)證的用戶试幽,該請(qǐng)求基于已認(rèn)證的用戶
- public - 當(dāng)不通過(guò)認(rèn)證訪問(wèn)時(shí)使用公用的認(rèn)證
- none - 相應(yīng)的方法總是可用,一般用于框架和認(rèn)證模塊卦碾,對(duì)應(yīng)請(qǐng)求沒(méi)有辦法訪問(wèn)數(shù)據(jù)庫(kù)或指向數(shù)據(jù)庫(kù)的設(shè)置
- methods 這個(gè)請(qǐng)求所應(yīng)用的一系列http方法铺坞,如果沒(méi)指定則是所有方法
- cors 跨域資源cors參數(shù)
- csrf(boolean) 是否開(kāi)啟CSRF保護(hù),默認(rèn)True
1.如果表單是用python代碼生成的洲胖,可通過(guò)request.csrf_token() 獲取csrf
2.如果表單是用javascript生成的济榨,CSRF token會(huì)自動(dòng)被添加到QWEB環(huán)境變量中,通過(guò)require('web.core').csrf_token
使用
3.如果終端可從其他地方以api或webhook形式調(diào)用绿映,需要將對(duì)應(yīng)的csrf禁用擒滑,此時(shí)最好用其他方式進(jìn)行驗(yàn)證
請(qǐng)求
請(qǐng)求對(duì)象在收到請(qǐng)求時(shí)自動(dòng)設(shè)置到odoo.http.request
class odoo.http.WebRequest(httprequest)
所有odoo WEB請(qǐng)求的父類腐晾,一般用于進(jìn)行請(qǐng)求對(duì)象的初始化
- httprequest 原始的werkzeug.wrappers.Request對(duì)象
- params 請(qǐng)求參數(shù)的映射
- cr 當(dāng)前方法調(diào)用的初始游標(biāo),當(dāng)使用none的認(rèn)證方式時(shí)讀取游標(biāo)會(huì)報(bào)錯(cuò)
- context 當(dāng)前請(qǐng)求的上下文鍵值映射
- env 綁定到當(dāng)前請(qǐng)求的環(huán)境
- session 儲(chǔ)存當(dāng)前請(qǐng)求session數(shù)據(jù)的OpenERPSession
- debug 指定當(dāng)前請(qǐng)求是否是debug模式
- db 當(dāng)前請(qǐng)求所關(guān)聯(lián)的數(shù)據(jù)庫(kù)丐一,當(dāng)使用none認(rèn)證時(shí)為None
- csrf_token(time_limit=3600) 為該請(qǐng)求生成并返回一個(gè)token(參數(shù)以秒計(jì)算藻糖,默認(rèn)1小時(shí),如果傳None表示與當(dāng)前用戶session時(shí)間相同)
class odoo.http.HttpRequest(*args)
用于處理http類型請(qǐng)求的函數(shù)库车,匹配路由參數(shù)巨柒、查詢參數(shù)、表格參數(shù)柠衍,如果有指定文件也會(huì)傳給該方法洋满。為防止重名,路由參數(shù)優(yōu)先級(jí)最高珍坊。
該函數(shù)的返回有三種:
- 無(wú)效值牺勾,HTTP響應(yīng)會(huì)返回一個(gè)204(沒(méi)有內(nèi)容)
- 一個(gè)werkzeug 響應(yīng)對(duì)象
- 一個(gè)字符串或unicode,會(huì)被響應(yīng)對(duì)象包裝并使用HTML解析
make_response(data, headers=None, cookies=None)
用于生成沒(méi)有HTML的響應(yīng) 或 自定義響應(yīng)頭阵漏、cookie的html響應(yīng)
由于處理函數(shù)只以字符串形式返回html標(biāo)記內(nèi)容驻民,需要組成一個(gè)完整的響應(yīng)對(duì)象,這樣客戶端才能解析
參數(shù):
- data (basestring) -- 響應(yīng)主體
- headers ([(name, value)]) -- http響應(yīng)頭
- cookies (collections.Mapping) -- 發(fā)送給客戶端的cookie
not_found(description=None)
給出404 NOT FOUND響應(yīng)
render(template, qcontext=None, lazy=True, **kw)
渲染qweb模板袱饭,在調(diào)度完成后會(huì)對(duì)給定的模板進(jìn)行渲染川无,同時(shí)模板和qcontext可以被靜態(tài)響應(yīng)修改或替換
參數(shù):
- template (basestring) -- 用于渲染的模板
- qcontext (dict) -- 用于渲染的上下文環(huán)境
- lazy (bool) -- 渲染動(dòng)作是否應(yīng)該拖延到最后執(zhí)行
- kw -- 轉(zhuǎn)發(fā)到werkzeug響應(yīng)對(duì)象
class odoo.http.JsonRequest(*args)
處理通過(guò)http發(fā)來(lái)的json rpc格式請(qǐng)求
說(shuō)明:
1.method -- 忽略
2.params -- 須是一個(gè)json格式對(duì)象
3.處理方法返回的結(jié)果是一個(gè)json-rpc格式的,以JSON-RPC Response對(duì)象的形式組裝
正確的請(qǐng)求:
--> {"jsonrpc": "2.0",
"method": "call",
"params": {"context": {},
"arg1": "val1" },
"id": null}
<-- {"jsonrpc": "2.0",
"result": { "res1": "val1" },
"id": null}
出錯(cuò)的請(qǐng)求:
--> {"jsonrpc": "2.0",
"method": "call",
"params": {"context": {},
"arg1": "val1" },
"id": null}
<-- {"jsonrpc": "2.0",
"error": {"code": 1,
"message": "End user error message.",
"data": {"code": "codestring",
"debug": "traceback" } },
"id": null}
響應(yīng)
class odoo.http.Response(*args, **kw)
響應(yīng)對(duì)象通過(guò)控制器的路由傳遞虑乖,在werkzeug.wrappers.Response之外懦趋,該類的構(gòu)造方法會(huì)添加以下參數(shù)到qweb的渲染中
- template (basestring) -- 用于渲染的模板
- qcontext (dict) -- 用在渲染中的上下文環(huán)境
- uid (int) -- 用于調(diào)用ir.ui.view渲染的用戶id,None時(shí)使用當(dāng)前請(qǐng)求的id
上面的參數(shù)在實(shí)際渲染之前可以隨時(shí)作為Response對(duì)象的屬性修改
- render() - 渲染響應(yīng)對(duì)象的模板疹味,并返回內(nèi)容
- flatten() - 強(qiáng)制渲染響應(yīng)對(duì)象的模板仅叫,將結(jié)果設(shè)置為響應(yīng)主體,并將模板復(fù)原
控制器
控制器像Model一樣需要定義成可擴(kuò)展的糙捺,但不能用同樣的機(jī)制诫咱,所以采用了另外一套機(jī)制
一般通過(guò)繼承的形式創(chuàng)建:class odoo.http.Controller
以route裝飾器來(lái)裝飾定義的方法:
class MyController(odoo.http.Controller):
@route('/some_url', auth='public')
def handler(self):
return stuff()
為了覆蓋一個(gè)controller,可以繼承它并將相關(guān)方法都覆蓋:
class Extension(MyController):
@route()
def handler(self):
do_before()
return super(Extension, self).handler()
- 需要通過(guò)route裝飾器來(lái)讓controller方法對(duì)外部可訪問(wèn)洪灯,如果函數(shù)被重定義時(shí)沒(méi)有route裝飾坎缭,它就會(huì)對(duì)外面不可見(jiàn)。
- 裝飾器方法是相關(guān)聯(lián)的签钩,如果覆蓋的方法沒(méi)有參數(shù)那么原方法參數(shù)會(huì)自動(dòng)保留掏呼;如果覆蓋方法有提供參數(shù)就會(huì)將原參數(shù)覆蓋,如:
#下例會(huì)將handler方法由public變?yōu)閡ser認(rèn)證模式铅檩,需要登錄
class Restrict(MyController):
@route(auth='user')
def handler(self):
return super(Restrict, self).handler()
譯自odoo官方文檔:http://www.odoo.com/documentation/10.0/reference/security.html憎夷,http://www.odoo.com/documentation/10.0/reference/testing.html ,http://www.odoo.com/documentation/10.0/reference/http.html,不當(dāng)之處歡迎批評(píng)指正。
內(nèi)容發(fā)布自http://www.reibang.com/u/6fdae8ec06bc昧旨,轉(zhuǎn)載請(qǐng)注明出處