details:   https://code.tryton.org/tryton/commit/8d3ea53120f2
branch:    7.0
user:      Cédric Krier <[email protected]>
date:      Thu Nov 05 18:53:44 2026 +0100
description:
        Only permit administrators to execute wizards without models or groups

        Closes #15205
        (grafted from 22897711abb09d83f972c6a2b850cccbfa877021)
diffstat:

 trytond/CHANGELOG                    |   1 +
 trytond/trytond/tests/test_wizard.py |  53 +++++++++++++++++++++++++++++++++--
 trytond/trytond/tests/wizard.py      |   5 +++
 trytond/trytond/tests/wizard.xml     |   6 ++++
 trytond/trytond/wizard/wizard.py     |  14 ++++++++-
 5 files changed, 73 insertions(+), 6 deletions(-)

diffs (152 lines):

diff -r 91493426a8dd -r 8d3ea53120f2 trytond/CHANGELOG
--- a/trytond/CHANGELOG Fri Oct 30 09:31:43 2026 +0100
+++ b/trytond/CHANGELOG Thu Nov 05 18:53:44 2026 +0100
@@ -1,3 +1,4 @@
+* Only permit administrators to execute wizards without models or groups 
(issue15205)
 
 Version 7.0.59 - 2026-10-15
 ---------------------------
diff -r 91493426a8dd -r 8d3ea53120f2 trytond/trytond/tests/test_wizard.py
--- a/trytond/trytond/tests/test_wizard.py      Fri Oct 30 09:31:43 2026 +0100
+++ b/trytond/trytond/tests/test_wizard.py      Thu Nov 05 18:53:44 2026 +0100
@@ -145,10 +145,55 @@
         "Execute wizard on wrong model"
         pool = Pool()
         Wizard = pool.get('test.test_wizard', type='wizard')
+        User = pool.get('res.user')
+
+        user = User(login='foo')
+        user.save()
+        session_id, start_state, end_state = Wizard.create()
+
+        with Transaction().set_user(user.id):
+            with self.assertRaises(AccessError):
+                with Transaction().set_context(
+                        active_model='test.test_wizard.start'):
+                    Wizard.execute(session_id, {}, start_state)
+
+    @with_transaction(context={'_check_access': True})
+    def test_execute_without_model(self):
+        "Execute wizard without model"
+        pool = Pool()
+        Wizard = pool.get('test.test_wizard_no_model', type='wizard')
+        User = pool.get('res.user')
+
+        user = User(login='foo')
+        user.save()
+        session_id, start_state, end_state = Wizard.create()
+
+        with Transaction().set_user(user.id):
+            with self.assertRaises(AccessError):
+                Wizard.execute(session_id, {}, start_state)
+
+    @with_transaction(context={'_check_access': True})
+    def test_execute_without_model_with_group(self):
+        "Execute wizard without model and groups"
+        pool = Pool()
+        Wizard = pool.get('test.test_wizard_no_model', type='wizard')
+        User = pool.get('res.user')
+        Group = pool.get('res.group')
+
+        user = User(login='foo', groups=[Group(name="Group")])
+        user.save()
+        session_id, start_state, end_state = Wizard.create()
+
+        with Transaction().set_user(user.id):
+            with self.assertRaises(AccessError):
+                Wizard.execute(session_id, {}, start_state)
+
+    @with_transaction(context={'_check_access': True})
+    def test_execute_without_model_with_admin(self):
+        "Execute wizard without model"
+        pool = Pool()
+        Wizard = pool.get('test.test_wizard_no_model', type='wizard')
 
         session_id, start_state, end_state = Wizard.create()
 
-        with self.assertRaises(AccessError):
-            with Transaction().set_context(
-                    active_model='test.test_wizard.start'):
-                Wizard.execute(session_id, {}, start_state)
+        Wizard.execute(session_id, {}, start_state)
diff -r 91493426a8dd -r 8d3ea53120f2 trytond/trytond/tests/wizard.py
--- a/trytond/trytond/tests/wizard.py   Fri Oct 30 09:31:43 2026 +0100
+++ b/trytond/trytond/tests/wizard.py   Thu Nov 05 18:53:44 2026 +0100
@@ -49,10 +49,15 @@
         return 'end'
 
 
+class TestWizardNoModel(TestWizard):
+    __name__ = 'test.test_wizard_no_model'
+
+
 def register(module):
     Pool.register(
         TestWizardStart,
         module=module, type_='model')
     Pool.register(
         TestWizard,
+        TestWizardNoModel,
         module=module, type_='wizard')
diff -r 91493426a8dd -r 8d3ea53120f2 trytond/trytond/tests/wizard.xml
--- a/trytond/trytond/tests/wizard.xml  Fri Oct 30 09:31:43 2026 +0100
+++ b/trytond/trytond/tests/wizard.xml  Thu Nov 05 18:53:44 2026 +0100
@@ -21,5 +21,11 @@
             <field name="wiz_name">test.test_wizard</field>
             <field name="model">test.access</field>
         </record>
+
+        <record model="ir.action.wizard" id="test_wizard_no_model">
+            <field name="name">Test Wizard</field>
+            <field name="wiz_name">test.test_wizard_no_model</field>
+            <field name="model" eval="None"/>
+        </record>
     </data>
 </tryton>
diff -r 91493426a8dd -r 8d3ea53120f2 trytond/trytond/wizard/wizard.py
--- a/trytond/trytond/wizard/wizard.py  Fri Oct 30 09:31:43 2026 +0100
+++ b/trytond/trytond/wizard/wizard.py  Thu Nov 05 18:53:44 2026 +0100
@@ -251,11 +251,16 @@
         ModelAccess = pool.get('ir.model.access')
         ActionWizard = pool.get('ir.action.wizard')
         User = pool.get('res.user')
+        ModelData = pool.get('ir.model.data')
         context = Transaction().context
 
         if Transaction().user == 0:
             return
 
+        admin_group = ModelData.get_id('res.group_admin')
+        groups = set(User.get_groups())
+        is_admin = admin_group in groups
+
         with check_access():
             model = context.get('active_model')
             if model:
@@ -264,12 +269,11 @@
                 ModelAccess.check(model, 'read')
             models = ActionWizard.get_models(
                 cls.__name__, action_id=context.get('action_id'))
-            if model and models and model not in models:
+            if not is_admin and models and (not model or model not in models):
                 raise AccessError(gettext(
                         'ir.msg_access_wizard_model_error',
                         wizard=cls.__name__,
                         model=model))
-            groups = set(User.get_groups())
             wizard_groups = ActionWizard.get_groups(cls.__name__,
                 action_id=context.get('action_id'))
             if wizard_groups:
@@ -282,6 +286,12 @@
                         or Model.write.__func__ != ModelSQL.write.__func__):
                     ModelAccess.check(model, 'write')
 
+            if not is_admin and not models and not wizard_groups:
+                raise AccessError(
+                    gettext(
+                        'ir.msg_access_wizard_error',
+                        wizard=cls.__name__))
+
             if model:
                 ids = context.get('active_ids') or []
                 id_ = context.get('active_id')

Reply via email to