Check rule only if _check_access is set and enforce companies rule

issue4080
review343891009
This commit is contained in:
Cédric Krier committed 2021-04-10 23:46:23 +02:00
1 parent 1abbfa5eb7
commit 34fabe65fe
8 files changed
+98 -23

No files matched your search

+2
View File
@@ -1,3 +1,5 @@
* Enforce companies rule
* Add company filter
* Remove tree structure from company
* Add test on context of company multivalue target fields
* Use report header for CompanyReport
+16 -2
View File
@@ -56,14 +56,19 @@ class Rule(metaclass=PoolMeta):
def __setup__(cls):
super().__setup__()
cls.domain.help += '\n- "employee" from the current user'
cls.domain.help += '\n- "companies" from the current user'
@classmethod
def _get_cache_key(cls):
key = super(Rule, cls)._get_cache_key()
# XXX Use company from context instead of browse to prevent infinite
# loop, but the cache is cleared when User is written.
return key + (Transaction().context.get('company'),
Transaction().context.get('employee'))
context = Transaction().context
return key + (
context.get('company'),
context.get('employee'),
context.get('company_filter'),
)
@classmethod
def _get_context(cls):
@@ -79,6 +84,15 @@ class Rule(metaclass=PoolMeta):
_check_access=False, _datetime=None):
context['employee'] = EvalEnvironment(
Employee(user.employee.id), Employee)
if user.company_filter == 'one':
context['companies'] = [user.company.id] if user.company else []
context['employees'] = [user.employee.id] if user.employee else []
elif user.company_filter == 'all':
context['companies'] = [c.id for c in user.companies]
context['employees'] = [e.id for e in user.employees]
else:
context['companies'] = []
context['employees'] = []
return context
+14 -14
View File
@@ -15,36 +15,36 @@ this repository contains the full copyright notices and license terms. -->
<field name="name">sequence_tree</field>
</record>
<record model="ir.rule.group" id="rule_group_sequence">
<field name="name">User in company</field>
<record model="ir.rule.group" id="rule_group_sequence_companies">
<field name="name">User in companies</field>
<field name="model" search="[('model', '=', 'ir.sequence')]"/>
<field name="global_p" eval="True"/>
</record>
<record model="ir.rule" id="rule_sequence1">
<record model="ir.rule" id="rule_sequence_companies1">
<field name="domain"
eval="[('company', '=', Eval('user', {}).get('company', None))]"
eval="[('company', 'in', Eval('companies', []))]"
pyson="1"/>
<field name="rule_group" ref="rule_group_sequence"/>
<field name="rule_group" ref="rule_group_sequence_companies"/>
</record>
<record model="ir.rule" id="rule_sequence2">
<record model="ir.rule" id="rule_sequence_comapnies2">
<field name="domain" eval="[('company', '=', None)]" pyson="1"/>
<field name="rule_group" ref="rule_group_sequence"/>
<field name="rule_group" ref="rule_group_sequence_companies"/>
</record>
<record model="ir.rule.group" id="rule_group_sequence_strict">
<field name="name">User in company</field>
<record model="ir.rule.group" id="rule_group_sequence_strict_companies">
<field name="name">User in companies</field>
<field name="model" search="[('model', '=', 'ir.sequence.strict')]"/>
<field name="global_p" eval="True"/>
</record>
<record model="ir.rule" id="rule_sequence_strict1">
<record model="ir.rule" id="rule_sequence_strict_companies1">
<field name="domain"
eval="[('company', '=', Eval('user', {}).get('company', None))]"
eval="[('company', 'in', Eval('companies', []))]"
pyson="1"/>
<field name="rule_group" ref="rule_group_sequence_strict"/>
<field name="rule_group" ref="rule_group_sequence_strict_companies"/>
</record>
<record model="ir.rule" id="rule_sequence_strict2">
<record model="ir.rule" id="rule_sequence_strict_companies2">
<field name="domain" eval="[('company', '=', None)]" pyson="1"/>
<field name="rule_group" ref="rule_group_sequence_strict"/>
<field name="rule_group" ref="rule_group_sequence_strict_companies"/>
</record>
<record model="ir.ui.view" id="cron_view_form">
+10
View File
@@ -55,12 +55,18 @@ class User(metaclass=PoolMeta):
],
depends=['company', 'employees'],
help="Select the employee to make the user behave as such.")
company_filter = fields.Selection([
('one', "Current"),
('all', "All"),
], "Company Filter",
help="Define records of which companies are shown.")
@classmethod
def __setup__(cls):
super(User, cls).__setup__()
cls._context_fields.insert(0, 'company')
cls._context_fields.insert(0, 'employee')
cls._context_fields.insert(0, 'company_filter')
@classmethod
def __register__(cls, module):
@@ -99,6 +105,10 @@ class User(metaclass=PoolMeta):
def default_company(cls):
return Transaction().context.get('company')
@classmethod
def default_company_filter(cls):
return 'one'
def get_status_bar(self, name):
def same_company(record):
return record.company == self.company
+3 -3
View File
@@ -4,12 +4,12 @@
try:
from trytond.modules.company.tests.test_company import (
suite, create_company, set_company, create_employee,
PartyCompanyCheckEraseMixin, CompanyMultiValueTestMixin)
PartyCompanyCheckEraseMixin, CompanyTestMixin)
except ImportError:
from .test_company import (
suite, create_company, set_company, create_employee,
PartyCompanyCheckEraseMixin, CompanyMultiValueTestMixin)
PartyCompanyCheckEraseMixin, CompanyTestMixin)
__all__ = [
'suite', 'create_company', 'set_company', 'create_employee',
'PartyCompanyCheckEraseMixin', 'CompanyMultiValueTestMixin']
'PartyCompanyCheckEraseMixin', 'CompanyTestMixin']
+45 -3
View File
@@ -1,12 +1,15 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import unittest
from collections import defaultdict
from contextlib import contextmanager
import trytond.tests.test_tryton
from trytond.model import ModelView, ModelStorage
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
from trytond.transaction import Transaction
from trytond.pool import Pool, isregisteredby
from trytond.pyson import Eval, PYSONEncoder
from trytond.modules.currency.tests import create_currency, add_currency_rate
from trytond.modules.party.tests import PartyCheckEraseMixin
@@ -65,7 +68,7 @@ class PartyCompanyCheckEraseMixin(PartyCheckEraseMixin):
return super().setup_check_erase_party()
class CompanyMultiValueTestMixin:
class CompanyTestMixin:
@with_transaction()
def test_company_multivalue_context(self):
@@ -97,10 +100,49 @@ class CompanyMultiValueTestMixin:
'in "%s"."%s" context' % (
company, mname, fname))
@with_transaction()
def test_company_rule(self):
"Test missing company rule"
pool = Pool()
Rule = pool.get('ir.rule')
Company = pool.get('company.company')
Employee = pool.get('company.employee')
User = pool.get('res.user')
to_check = defaultdict(set)
for mname, model in pool.iterobject():
if (not isregisteredby(model, self.module)
or model.__access__
or not (issubclass(model, ModelView)
and issubclass(model, ModelStorage))
or issubclass(model, (Company, Employee, User))):
continue
for fname, field in model._fields.items():
if (field._type == 'many2one'
and issubclass(field.get_target(), Company)):
to_check[fname].add(mname)
for fname, models in to_check.items():
rules = Rule.search([
('rule_group', 'where', [
('model.model', 'in', list(models)),
('global_p', '=', True),
('perm_read', '=', True),
]),
('domain', '=', PYSONEncoder(sort_keys=True).encode(
[(fname, 'in', Eval('companies', []))])),
])
with_rules = {r.rule_group.model.model for r in rules}
self.assertGreaterEqual(with_rules, models,
msg='Models "%(models)s" are missing a global rule '
'for field "%(field)s"' % {
'models': ', '.join(models - with_rules),
'field': fname,
})
class CompanyTestCase(
PartyCompanyCheckEraseMixin, CompanyMultiValueTestMixin,
ModuleTestCase):
PartyCompanyCheckEraseMixin, CompanyTestMixin, ModuleTestCase):
'Test Company module'
module = 'company'
+3
View File
@@ -6,6 +6,9 @@ this repository contains the full copyright notices and license terms. -->
position="before">
<label name="company"/>
<field name="company" widget="selection"/>
<label name="company_filter"/>
<field name="company_filter"/>
<label name="employee"/>
<field name="employee" widget="selection"/>
<field name="companies" colspan="2"/>
+5 -1
View File
@@ -5,7 +5,11 @@ this repository contains the full copyright notices and license terms. -->
<xpath expr="/form/notebook/page/separator[@name='signature']"
position="before">
<label name="company"/>
<field name="company" widget="selection"/>
<group id="company" col="-1">
<field name="company" widget="selection"/>
<label name="company_filter"/>
<field name="company_filter"/>
</group>
<label name="employee"/>
<field name="employee" widget="selection"/>
</xpath>