Skip to content

Commit 923e9ea

Browse files
committed
[IMP] estate: add security, groups, and access restrictions
Introduce proper security model for estate management: - Add two groups: * Estate Agent: can access and manage their own properties. * Estate Manager: inherits Agent, can configure property types/tags. - Define access rights (ACLs): * Agents: can read, create, write their own estate properties. * Managers: can read all, and write their own records. - Add record rules: * Agents: only see their own properties or unassigned ones. * Managers: read all properties, but only update their own. - Secure configuration menus: * Property types and tags only visible to Managers. * Properties menu accessible to Agents and Managers. - Enforce programmatic security: * Use `self.check_access('write')` before creating invoices to prevent bypassing ORM rules from Python code. This ensures: - Non-agents cannot access estate records. - Agents cannot interfere with each other’s properties. - Managers retain global visibility. - Invoices and other side-effects are resilient to security bypass.
1 parent 5c55b4f commit 923e9ea

File tree

6 files changed

+66
-7
lines changed

6 files changed

+66
-7
lines changed

estate/__manifest__.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
{
22
"name": "Real Estate",
33
"description": "",
4+
"category": "Real Estate/Brokerage",
45
"depends": ["base"],
56
"sequence": 1,
67
"data": [
8+
"security/security.xml",
79
"security/ir.model.access.csv",
810
"data/ir_cron_data.xml",
911
"views/estate_property_views.xml",
@@ -13,9 +15,9 @@
1315
"views/estate_menus.xml",
1416
"views/res_users_views.xml",
1517
],
16-
'assets': {
17-
'web.assets_backend': [
18-
'estate/static/src/css/custom.css',
18+
"assets": {
19+
"web.assets_backend": [
20+
"estate/static/src/css/custom.css",
1921
],
2022
},
2123
"license": "LGPL-3",

estate/models/estate_property.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ class EstateProperty(models.Model):
8484
string="Best Offer",
8585
compute="_compute_best_price",
8686
)
87+
company_id = fields.Many2one(
88+
"res.company",
89+
required=True,
90+
default=lambda self: self.env.company,
91+
string="Agency",
92+
)
8793

8894
@api.depends("living_area", "garden_area", "garden")
8995
def _compute_total_area(self):

estate/security/ir.model.access.csv

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
22
access_estate_property,estate.property,model_estate_property,base.group_user,1,1,1,1
3-
access_estate_property_type,estate.property.type,model_estate_property_type,base.group_user,1,1,1,1
4-
access_estate_property_tag,estate.property.tag,model_estate_property_tag,base.group_user,1,1,1,1
5-
access_estate_property_offer,estate.property.offer,model_estate_property_offer,base.group_user,1,1,1,1
3+
access_estate_property_manager,estate.property.manager,model_estate_property,estate_group_manager,1,1,1,1
4+
access_estate_property_type_manager,estate.property.type.manager,model_estate_property_type,estate_group_manager,1,1,1,1
5+
access_estate_property_tag_manager,estate.property.tag.manager,model_estate_property_tag,estate_group_manager,1,1,1,1
6+
access_estate_property_offer_manager,estate.property.offer.manager,model_estate_property_offer,estate_group_manager,1,1,1,1
7+
8+
access_estate_property_user,estate.property.user,model_estate_property,estate_group_user,1,1,1,0
9+
access_estate_property_offer_user,estate.property.offer.user,model_estate_property_offer,estate_group_user,1,1,1,0
10+
access_estate_property_type_user,estate.property.type.user,model_estate_property_type,estate_group_user,1,0,0,0
11+
access_estate_property_tag_user,estate.property.tag.user,model_estate_property_tag,estate_group_user,1,0,0,0

estate/security/security.xml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<odoo>
3+
<record id="estate_group_user" model="res.groups">
4+
<field name="name">Agent</field>
5+
<field name="category_id" ref="base.module_category_real_estate_brokerage"/>
6+
</record>
7+
8+
<record id="estate_group_manager" model="res.groups">
9+
<field name="name">Manager</field>
10+
<field name="category_id" ref="base.module_category_real_estate_brokerage"/>
11+
<field name="implied_ids" eval="[(4, ref('estate_group_user'))]"/>
12+
</record>
13+
14+
<data noupdate="1">
15+
<record id="estate_property_speicific_user" model="ir.rule">
16+
<field name="name">Estate property view to specific user</field>
17+
<field name="model_id" ref="model_estate_property"/>
18+
<field name="perm_read" eval="True"/>
19+
<field name="perm_write" eval="True"/>
20+
<field name="groups" eval="[Command.link(ref('estate.estate_group_user'))]"/>
21+
<field name="domain_force">['|', ('salesman_id', '=', user.id),('salesman_id', '=', False)]</field>
22+
</record>
23+
24+
<record id="estate_property_specific_manager" model="ir.rule">
25+
<field name="name">Estate property view to specific manager</field>
26+
<field name="model_id" ref="model_estate_property"/>
27+
<field name="groups" eval="[Command.link(ref('estate.estate_group_manager'))]"/>
28+
<field name="perm_read" eval="True"/>
29+
</record>
30+
31+
<record id="estate_property_company_rule" model="ir.rule">
32+
<field name="name">Estate Property Multi-Company Rule</field>
33+
<field name="model_id" ref="model_estate_property"/>
34+
<field name="global" eval="True"/>
35+
<field name="domain_force">['|', ('company_id', '=', False),('company_id', 'in', company_ids)]</field>
36+
</record>
37+
</data>
38+
</odoo>

estate/views/estate_menus.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<menuitem id="estate_menu_properties" name="Advertisements">
66
<menuitem id="estate_property_menu_action" action="estate_property_action"/>
77
</menuitem>
8-
<menuitem id="estate_menu_property_types" name="Settings">
8+
<menuitem id="estate_menu_property_types" name="Settings" groups="estate_group_manager">
99
<menuitem id="estate_property_type_menu_action" action="estate_property_type_action"/>
1010
<menuitem id="estate_property_tag_menu_action" action="estate_property_tag_action"/>
1111
</menuitem>

estate_account/models/estate_property.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
from odoo import models, fields, Command
2+
from odoo.exceptions import AccessError
23

34

45
class EstateProperty(models.Model):
56
_inherit = "estate.property"
67

78
def action_set_sold(self):
9+
10+
try:
11+
self.check_access("write")
12+
except AccessError:
13+
raise AccessError("You are not allowed to sell this property. Contact your manager.")
14+
815
self.env["account.move"].sudo().create(
916
{
1017
"partner_id": self.buyer_id.id,

0 commit comments

Comments
 (0)