Check rule only if _check_access is set and enforce companies rule
issue4080 review343891009
This commit is contained in:
1 parent
1abbfa5eb7
commit
34fabe65fe
8 files changed
+98
-23
No files matched your search
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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
@@ -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
@@ -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'
|
||||
|
||||
|
||||
@@ -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,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>
|
||||
|
||||
Reference in new issue
Block a user