details: https://code.tryton.org/tryton/commit/46d9f7f4254e
branch: 7.4
user: Nicolas Évrard <[email protected]>
date: Wed Dec 03 08:47:20 2025 +0100
description:
Filter Many2Many group fields on active = True
When the field is used in a domain adding this filter ensure that
comparison
with None will succeed when there are only inactive groups in the field.
Closes #14369
(grafted from 6ec84dbcdde99641b803ebcdfee5aaa0edf9f548)
diffstat:
trytond/trytond/res/user.py | 10 ++-
trytond/trytond/tests/test_access.py | 106 +++++++++++++++++++++++++++++++++++
2 files changed, 114 insertions(+), 2 deletions(-)
diffs (151 lines):
diff -r 6060670997cb -r 46d9f7f4254e trytond/trytond/res/user.py
--- a/trytond/trytond/res/user.py Tue Dec 02 13:39:07 2025 +0100
+++ b/trytond/trytond/res/user.py Wed Dec 03 08:47:20 2025 +0100
@@ -633,16 +633,22 @@
'''
pool = Pool()
UserGroup = pool.get('res.user-res.group')
+ Group = pool.get('res.group')
+
transaction = Transaction()
user = transaction.user
groups = cls._get_groups_cache.get(user)
if groups is not None:
return groups
cursor = transaction.connection.cursor()
+ group = Group.__table__()
user_group = UserGroup.user_group_all_table()
- cursor.execute(*user_group.select(
+ cursor.execute(*user_group
+ .join(group, 'LEFT', user_group.group == group.id)
+ .select(
user_group.group,
- where=user_group.user == user,
+ where=((user_group.user == user)
+ & (group.active == Literal(True))),
order_by=[user_group.group.asc]))
groups = tuple(g for g, in cursor)
cls._get_groups_cache.set(user, groups)
diff -r 6060670997cb -r 46d9f7f4254e trytond/trytond/tests/test_access.py
--- a/trytond/trytond/tests/test_access.py Tue Dec 02 13:39:07 2025 +0100
+++ b/trytond/trytond/tests/test_access.py Wed Dec 03 08:47:20 2025 +0100
@@ -227,6 +227,56 @@
self._assert_raises(record)
@with_transaction(context=_context)
+ def test_no_access_with_inactive_group(self):
+ "Test no access with inactive group"
+ pool = Pool()
+ Group = pool.get('res.group')
+ ModelAccess = pool.get('ir.model.access')
+ TestAccess = pool.get(self.model_name)
+
+ inactive_group, = Group.create([{'name': 'Test', 'active': False}])
+ record, = TestAccess.create([{}])
+ ModelAccess.create([{
+ 'model': self.model_name,
+ 'group': None,
+ self._perm: False,
+ }])
+ ModelAccess.create([{
+ 'model': self.model_name,
+ 'group': inactive_group.id,
+ self._perm: True,
+ }])
+
+ self._assert_raises(record)
+
+ @with_transaction(context=_context)
+ def test_no_access_with_member_inactive_group(self):
+ "Test no access when member of an inactive group"
+ pool = Pool()
+ Group = pool.get('res.group')
+ ModelAccess = pool.get('ir.model.access')
+ TestAccess = pool.get(self.model_name)
+
+ inactive_group, = Group.create([{
+ 'name': 'Test',
+ 'active': False,
+ 'users': [('add', [Transaction().user])],
+ }])
+ record, = TestAccess.create([{}])
+ ModelAccess.create([{
+ 'model': self.model_name,
+ 'group': None,
+ self._perm: False,
+ }])
+ ModelAccess.create([{
+ 'model': self.model_name,
+ 'group': inactive_group.id,
+ self._perm: True,
+ }])
+
+ self._assert_raises(record)
+
+ @with_transaction(context=_context)
def test_one_access_with_other_group_no_perm(self):
"Test one access with other group no perm"
pool = Pool()
@@ -655,6 +705,62 @@
self._assert2(record)
@with_transaction(context=_context)
+ def test_no_access_with_inactive_group(self):
+ "Test no access with inactive group"
+ pool = Pool()
+ Group = pool.get('res.group')
+ FieldAccess = pool.get('ir.model.field.access')
+ TestAccess = pool.get('test.access')
+
+ inactive_group, = Group.create([{'name': 'Test', 'active': False}])
+ record, = TestAccess.create([{}])
+ FieldAccess.create([{
+ 'model': 'test.access',
+ 'field': 'field1',
+ 'group': None,
+ self._perm: False,
+ }])
+ FieldAccess.create([{
+ 'model': 'test.access',
+ 'field': 'field1',
+ 'group': inactive_group.id,
+ self._perm: True,
+ }])
+
+ self._assert_raises1(record)
+ self._assert2(record)
+
+ @with_transaction(context=_context)
+ def test_no_access_with_member_inactive_group(self):
+ "Test no access when member of an inactive group"
+ pool = Pool()
+ Group = pool.get('res.group')
+ FieldAccess = pool.get('ir.model.field.access')
+ TestAccess = pool.get('test.access')
+
+ inactive_group, = Group.create([{
+ 'name': 'Test',
+ 'active': False,
+ 'users': [('add', [Transaction().user])],
+ }])
+ record, = TestAccess.create([{}])
+ FieldAccess.create([{
+ 'model': 'test.access',
+ 'field': 'field1',
+ 'group': None,
+ self._perm: False,
+ }])
+ FieldAccess.create([{
+ 'model': 'test.access',
+ 'field': 'field1',
+ 'group': inactive_group.id,
+ self._perm: True,
+ }])
+
+ self._assert_raises1(record)
+ self._assert2(record)
+
+ @with_transaction(context=_context)
def test_one_access_with_other_group_no_perm(self):
"Test one access with other group no perm"
pool = Pool()