Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions subscription_oca/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"data/ir_cron.xml",
"data/sale_subscription_data.xml",
"wizard/close_subscription_wizard.xml",
"security/subscription_security.xml",
"security/ir.model.access.csv",
],
"installable": True,
Expand Down
22 changes: 22 additions & 0 deletions subscription_oca/security/subscription_security.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2026 Domatix - Alvaro Domatix
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="sale_subscription_company_rule" model="ir.rule">
<field name="name">Subscription: multi-company rule</field>
<field name="model_id" ref="model_sale_subscription" />
<field name="global" eval="False" />
<field name="groups" eval="[(4, ref('sales_team.group_sale_salesman'))]" />
<field name="domain_force">[('company_id', 'in', company_ids)]</field>
</record>

<record id="sale_subscription_line_company_rule" model="ir.rule">
<field name="name">Subscription Line: multi-company rule</field>
<field name="model_id" ref="model_sale_subscription_line" />
<field name="global" eval="False" />
<field name="groups" eval="[(4, ref('sales_team.group_sale_salesman'))]" />
<field
name="domain_force"
>[('sale_subscription_id.company_id', 'in', company_ids)]</field>
</record>
</odoo>
1 change: 1 addition & 0 deletions subscription_oca/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from . import test_subscription_oca
from . import test_subscription_security
97 changes: 97 additions & 0 deletions subscription_oca/tests/test_subscription_security.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Copyright 2026 Domatix - Alvaro Domatix
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo.exceptions import AccessError
from odoo.tests.common import new_test_user

from odoo.addons.base.tests.common import BaseCommon


class TestSubscriptionSecurity(BaseCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))

cls.company_a = cls.env["res.company"].create({"name": "Company A"})
cls.company_b = cls.env["res.company"].create({"name": "Company B"})

cls.user_company_a = new_test_user(
cls.env,
login="subscription_oca_user_company_a",
groups="sales_team.group_sale_salesman",
company_id=cls.company_a.id,
company_ids=[(6, 0, [cls.company_a.id])],
)

cls.pricelist_a = cls.env["product.pricelist"].create(
{"name": "Pricelist A", "company_id": cls.company_a.id}
)
cls.pricelist_b = cls.env["product.pricelist"].create(
{"name": "Pricelist B", "company_id": cls.company_b.id}
)
cls.partner = cls.env["res.partner"].create({"name": "Multi-company partner"})
cls.template = cls.env["sale.subscription.template"].create(
{
"name": "Multi-company template",
"code": "MC-TMPL",
}
)
cls.product = cls.env["product.product"].create(
{"name": "Multi-company product", "subscribable": True}
)

cls.subscription_a = cls.env["sale.subscription"].create(
{
"company_id": cls.company_a.id,
"partner_id": cls.partner.id,
"template_id": cls.template.id,
"pricelist_id": cls.pricelist_a.id,
}
)
cls.subscription_b = cls.env["sale.subscription"].create(
{
"company_id": cls.company_b.id,
"partner_id": cls.partner.id,
"template_id": cls.template.id,
"pricelist_id": cls.pricelist_b.id,
}
)
cls.line_a = cls.env["sale.subscription.line"].create(
{
"sale_subscription_id": cls.subscription_a.id,
"product_id": cls.product.id,
}
)
cls.line_b = cls.env["sale.subscription.line"].create(
{
"sale_subscription_id": cls.subscription_b.id,
"product_id": cls.product.id,
}
)

def test_user_can_read_own_company_subscription(self):
subscription = self.subscription_a.with_user(self.user_company_a)
subscription.read(["name"])

def test_user_cannot_read_other_company_subscription(self):
subscription = self.subscription_b.with_user(self.user_company_a)
with self.assertRaises(AccessError):
subscription.read(["name"])

def test_user_cannot_search_other_company_subscription(self):
found = (
self.env["sale.subscription"]
.with_user(self.user_company_a)
.search([("id", "=", self.subscription_b.id)])
)
self.assertFalse(found)

def test_user_cannot_read_other_company_subscription_line(self):
line = self.line_b.with_user(self.user_company_a)
with self.assertRaises(AccessError):
line.read(["name"])

def test_user_can_read_own_company_subscription_line(self):
line = self.line_a.with_user(self.user_company_a)
line.read(["name"])
Loading