details:   https://code.tryton.org/tryton/commit/eda14099dc6d
branch:    7.0
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 |  102 +++++++++++++++++++++++++++++++++++
 2 files changed, 110 insertions(+), 2 deletions(-)

diffs (147 lines):

diff -r 2d6556560df5 -r eda14099dc6d 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 2d6556560df5 -r eda14099dc6d 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
@@ -234,6 +234,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.id,
+                    'group': None,
+                    self._perm: False,
+                    }])
+        ModelAccess.create([{
+                    'model': self.model.id,
+                    '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.id,
+                    'group': None,
+                    self._perm: False,
+                    }])
+        ModelAccess.create([{
+                    'model': self.model.id,
+                    '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()
@@ -667,6 +717,58 @@
         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([{
+                    'field': self.field1.id,
+                    'group': None,
+                    self._perm: False,
+                    }])
+        FieldAccess.create([{
+                    'field': self.field1.id,
+                    '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([{
+                    'field': self.field1.id,
+                    'group': None,
+                    self._perm: False,
+                    }])
+        FieldAccess.create([{
+                    'field': self.field1.id,
+                    '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()

Reply via email to