اگر با اُدو کار کرده باشی، احتمالاً میدونی که یکی از پرچالش ترین بخشها در هر پروژه، مدیریت دسترسیهاست. بارها پیش اومده که کاربری بیش از حد دسترسی داشته و دادهها رو به هم ریخته، یا برعکس آنقدر محدود شده که حتی کار خودش رو هم نمیتونسته انجام بده.
این مقاله حاصل تجربهی واقعی در پروژههای مختلفه؛ جایی که مجبور شدیم ACL ،Record Rule و منوها رو طوری طراحی کنیم که هم امنیت دادهها حفظ بشه و هم کاربرها راحت بتونن کارشون رو انجام بدن.
مستند سازی دسترسی ها: نقطهی شروع
قبل از اینکه حتی یک خط کد بنویسی، باید بدونی هر گروه کاربری دقیقاً چه کاری باید بتونه انجام بده. برای این کار، یه جدول ساده ولی قدرتمند میسازیم:
این جدول هم برای تیم فنی واضحه، هم برای مشتری قابل فهمه. بعداً همین جدول تبدیل میشه به ACL و Record Rule.
تعریف دستهبندی ها (ir.module.category): مرتب سازی فرم کاربر
اگه همهی گروهها رو توی یک دسته بذاری، فرم کاربر پر از چک باکس میشه.
ولی اگه برای هر بخش مثل Office و Finance و Commerce یک دسته بندی جدا بسازی، Odoo اونها رو به شکل SelectBox نشون میده.
<record model="ir.module.category" id="module_category_odooist"><field name="name">Odooist</field>
<field name="sequence">1</field>
</record>
<record id="module_category_office" model="ir.module.category">
<field name="name">Office</field>
<field name="parent_id" ref="module_category_odooist"/>
<field name="sequence">1</field>
</record>
<record id="module_category_finance" model="ir.module.category">
<field name="name">Finance</field>
<field name="parent_id" ref="module_category_odooist"/>
<field name="sequence">2</field>
</record>
<record id="module_category_commerce" model="ir.module.category">
<field name="name">Commerce</field>
<field name="parent_id" ref="module_category_odooist"/>
<field name="sequence">3</field>
</record>
اینطوری فرم کاربر مرتبتره و انتخاب نقشها هم منطقیتر میشه.
تعریف گروه ها (res.groups): نقش ها و ارث بری منطقی
با توجه به نیاز ما توی این پروژه برای هر دسته، دو گروه تعریف میکنیم: User و Manager.
مدیر باید همهی دسترسی های کارمند رو داشته باشه، پس از implied_ids استفاده میکنیم:
<record id="group_office_user" model="res.groups">
<field name="name">Office / User</field>
<field name="category_id" ref="module_category_office"/>
</record>
<record id="group_office_manager" model="res.groups">
<field name="name">Office / Manager</field>
<field name="category_id" ref="module_category_office"/>
<field name="implied_ids" eval="[(4, ref('group_office_user'))]"/>
</record>
تعریف سطح دسترسی (ir.model.access.csv): دسترسی کلی
ACL مشخص میکنه که هر گروه روی هر مدل چه کاری میتونه بکنه:
- خواندن (
perm_read) - نوشتن (
perm_write) - ایجاد (
perm_create) - حذف (
perm_unlink)
مثال از ACL برای مدل sale.order:
"id","name","model_id","group_id","perm_read","perm_write","perm_create","perm_unlink" "access_sale_order_office_user","Sale Order Office User","model_sale_order","group_office_user",1,1,0,0 "access_sale_order_office_manager","Sale Order Office Manager","model_sale_order","group_office_manager",1,1,1,1
اینجا کارمند اداری میتونه سفارش فروش رو بخونه و ویرایش کنه، ولی اجازهی ایجاد و حذف نداره و همچنین مدیر اداری اجازه همه دسترسی ها رو داره.
نوشتن قواعد رکوردها (ir.rule): محدود کردن رکوردها
ACL فقط میگه «چه کاری»، ولی نمیگه «روی کدوم رکورد».
برای این کار از Record Rule استفاده میکنیم.
مثال: فقط رکوردهای خودش
<record id="rule_sale_order_own" model="ir.rule">
<field name="name">Sale Orders - Own Only</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="domain_force">[('user_id','=',user.id)]</field>
<field name="groups" eval="[(4, ref('group_commerce_user'))]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="False"/>
</record>
مثال: فقط اشخاص حقوقی
<record id="rule_partner_companies" model="ir.rule">
<field name="name">Partners - Companies Only</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="domain_force">[('is_company','=',True)]</field>
<field name="groups" eval="[(4, ref('group_finance_user'))]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_unlink" eval="False"/>
</record>
حواست باشه اگه در Record Rule پرمیشن ها (perm_read, perm_write, perm_create, perm_unlink) رو ننویسی، Odoo پیشفرض همه رو True میگیره. همین باعث میشه کاربری که نباید حذف کنه، بتونه رکورد حذف کنه.
مدیریت منوها (ir.ui.menu): نمایش منو بر اساس گروه
گاهی ACL و Rule درستن، ولی کاربر هنوز منویی رو می بینه که نباید ببینه. اینجا باید روی ir.ui.menu گروه بذاری:
<menuitem id="menu_finance_root" name="Finance" groups="group_finance_user,group_finance_manager"/> <menuitem id="menu_finance_reports" name="Reports" parent="menu_finance_root" groups="group_finance_manager"/>
- کاربر
Finance / Userفقط منوی اصلی رو میبینه. - کاربر
Finance / Managerعلاوه بر اون، منوی گزارشها رو هم میبینه.
تست دسترسی های اعمال شده
بعد از اینکه ACL و Rule رو نوشتی، حتماً با یه کاربر تستی وارد شو و رفتار سیستم رو بررسی کن.
- آیا منوها درست مخفی شدن؟
- آیا فقط رکوردهای مجاز دیده میشن؟
- آیا عملیات حذف یا ایجاد محدود شده؟
هیچ چیز جای تست واقعی رو نمیگیره.