[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-4385ebe3-6188-4cb8-9d56-6a70efe86cff":3,"$feCuh9OrKdAtruzAUdPnOZTh9yjzerGSonV35amo2IBg":43},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":34},"4385ebe3-6188-4cb8-9d56-6a70efe86cff","odoo-security-rules","Odoo访问控制专家：ir.model.access.csv、记录规则（ir.rule）、组和多公司安全模式。","cat_prod_data","mod_productivity","sickn33,productivity","---\nname: odoo-security-rules\ndescription: \"Expert in Odoo access control: ir.model.access.csv, record rules (ir.rule), groups, and multi-company security patterns.\"\nrisk: safe\nsource: \"self\"\n---\n\n# Odoo Security Rules\n\n## Overview\n\nSecurity in Odoo is managed at two levels: **model-level access** (who can read\u002Fwrite which models) and **record-level rules** (which records a user can see). This skill helps you write correct `ir.model.access.csv` entries and `ir.rule` domain-based record rules.\n\n## When to Use This Skill\n\n- Setting up access rights for a new custom module.\n- Restricting records so users only see their own data or their company's data.\n- Debugging \"Access Denied\" or \"You are not allowed to access\" errors.\n- Implementing multi-company record visibility rules.\n\n## How It Works\n\n1. **Activate**: Mention `@odoo-security-rules` and describe the access scenario.\n2. **Generate**: Get correct CSV access lines and XML record rules.\n3. **Debug**: Paste an access error and get a diagnosis with the fix.\n\n## Examples\n\n### Example 1: ir.model.access.csv\n\n```csv\nid,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink\naccess_hospital_patient_user,hospital.patient.user,model_hospital_patient,base.group_user,1,0,0,0\naccess_hospital_patient_manager,hospital.patient.manager,model_hospital_patient,base.group_erp_manager,1,1,1,1\n```\n\n> **Note:** Use `base.group_erp_manager` for ERP managers, not `base.group_system` — that group is reserved for Odoo's technical superusers. Always create a custom group for module-specific manager roles:\n>\n> ```xml\n> \u003Crecord id=\"group_hospital_manager\" model=\"res.groups\">\n>     \u003Cfield name=\"name\">Hospital Manager\u003C\u002Ffield>\n>     \u003Cfield name=\"category_id\" ref=\"base.module_category_hidden\"\u002F>\n> \u003C\u002Frecord>\n> ```\n\n### Example 2: Record Rule — Users See Only Their Own Records\n\n```xml\n\u003Crecord id=\"rule_hospital_patient_own\" model=\"ir.rule\">\n    \u003Cfield name=\"name\">Hospital Patient: Own Records Only\u003C\u002Ffield>\n    \u003Cfield name=\"model_id\" ref=\"model_hospital_patient\"\u002F>\n    \u003Cfield name=\"domain_force\">[('create_uid', '=', user.id)]\u003C\u002Ffield>\n    \u003Cfield name=\"groups\" eval=\"[(4, ref('base.group_user'))]\"\u002F>\n    \u003Cfield name=\"perm_read\" eval=\"True\"\u002F>\n    \u003Cfield name=\"perm_write\" eval=\"True\"\u002F>\n    \u003Cfield name=\"perm_create\" eval=\"True\"\u002F>\n    \u003Cfield name=\"perm_unlink\" eval=\"False\"\u002F>\n\u003C\u002Frecord>\n```\n\n> **Important:** If you omit `\u003Cfield name=\"groups\">`, the rule becomes **global** and applies to ALL users, including admins. Always assign a group unless you explicitly intend a global restriction.\n\n### Example 3: Multi-Company Record Rule\n\n```xml\n\u003Crecord id=\"rule_hospital_patient_company\" model=\"ir.rule\">\n    \u003Cfield name=\"name\">Hospital Patient: Multi-Company\u003C\u002Ffield>\n    \u003Cfield name=\"model_id\" ref=\"model_hospital_patient\"\u002F>\n    \u003Cfield name=\"domain_force\">\n        ['|', ('company_id', '=', False),\n               ('company_id', 'in', company_ids)]\n    \u003C\u002Ffield>\n    \u003Cfield name=\"groups\" eval=\"[(4, ref('base.group_user'))]\"\u002F>\n\u003C\u002Frecord>\n```\n\n## Best Practices\n\n- ✅ **Do:** Start with the most restrictive access and open up as needed.\n- ✅ **Do:** Use `company_ids` (plural) in multi-company rules — it includes all companies the user belongs to.\n- ✅ **Do:** Test rules using a non-admin user in debug mode — `sudo()` bypasses all record rules entirely.\n- ✅ **Do:** Create dedicated security groups per module rather than reusing core Odoo groups.\n- ❌ **Don't:** Give `perm_unlink = 1` to regular users unless deletion is explicitly required by the business process.\n- ❌ **Don't:** Leave `group_id` blank in `ir.model.access.csv` unless you intend to grant public (unauthenticated) access.\n- ❌ **Don't:** Use `base.group_system` for module managers — that grants full technical access including server configurations.\n\n## Limitations\n\n- Does not cover **field-level access control** (`ir.model.fields` read\u002Fwrite restrictions) — those require custom OWL or Python overrides.\n- **Portal and public user** access rules have additional nuances not fully covered here; test carefully with `base.group_portal`.\n- Record rules are **bypassed by `sudo()`** — any code running in superuser context ignores all `ir.rule` entries.\n- Does not cover **row-level security via PostgreSQL** (RLS) — Odoo manages all security at the ORM layer.\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,229,615,"2026-05-16 13:32:29",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"效率工具","productivity","mdi-lightning-bolt-outline","文档处理、数据分析、自动化工作流",4,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"数据分析","data-analysis","mdi-chart-bar","数据可视化、统计分析",2,30,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"41259aeb-1056-46f2-ba1a-50a57618c182","1.0.0","odoo-security-rules.zip",1873,"uploads\u002Fskills\u002F4385ebe3-6188-4cb8-9d56-6a70efe86cff\u002Fodoo-security-rules.zip","8ee5cb5e54f6c183bbe4cab6704a091e5b4a8488d2e85fb84ba9f329686bfaf8","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":4314}]",{"code":44,"message":45,"data":46},200,"success",{"items":47,"stats":48,"page":51},[],{"averageRating":49,"totalRatings":49,"ratingCounts":50},0,[49,49,49,49,49],{"limit":52,"offset":49,"hasMore":53,"nextOffset":52,"ratedOnly":16},15,false]