details: https://code.tryton.org/tryton/commit/22897711abb0
branch: default
user: Cédric Krier <[email protected]>
date: Thu Nov 05 16:02:45 2026 +0100
description:
Only permit administrators to execute wizards without models or groups
Closes #15205
diffstat:
trytond/CHANGELOG | 1 +
trytond/trytond/tests/test_wizard.py | 41 ++++++++++++++++++++++++++++++++++++
trytond/trytond/tests/wizard.py | 5 ++++
trytond/trytond/tests/wizard.xml | 6 +++++
trytond/trytond/wizard/wizard.py | 8 ++++++-
5 files changed, 60 insertions(+), 1 deletions(-)
diffs (115 lines):
diff -r 6c39c9437f47 -r 22897711abb0 trytond/CHANGELOG
--- a/trytond/CHANGELOG Wed Oct 21 12:36:12 2026 +0200
+++ b/trytond/CHANGELOG Thu Nov 05 16:02:45 2026 +0100
@@ -1,3 +1,4 @@
+* Only permit administrators to execute wizards without models or groups
(issue15205)
Version 8.2.0 - 2026-10-05
--------------------------
diff -r 6c39c9437f47 -r 22897711abb0 trytond/trytond/tests/test_wizard.py
--- a/trytond/trytond/tests/test_wizard.py Wed Oct 21 12:36:12 2026 +0200
+++ b/trytond/trytond/tests/test_wizard.py Thu Nov 05 16:02:45 2026 +0100
@@ -204,3 +204,44 @@
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()
+
+ Wizard.execute(session_id, {}, start_state)
diff -r 6c39c9437f47 -r 22897711abb0 trytond/trytond/tests/wizard.py
--- a/trytond/trytond/tests/wizard.py Wed Oct 21 12:36:12 2026 +0200
+++ b/trytond/trytond/tests/wizard.py Thu Nov 05 16:02:45 2026 +0100
@@ -47,10 +47,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 6c39c9437f47 -r 22897711abb0 trytond/trytond/tests/wizard.xml
--- a/trytond/trytond/tests/wizard.xml Wed Oct 21 12:36:12 2026 +0200
+++ b/trytond/trytond/tests/wizard.xml Thu Nov 05 16:02:45 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 6c39c9437f47 -r 22897711abb0 trytond/trytond/wizard/wizard.py
--- a/trytond/trytond/wizard/wizard.py Wed Oct 21 12:36:12 2026 +0200
+++ b/trytond/trytond/wizard/wizard.py Thu Nov 05 16:02:45 2026 +0100
@@ -264,7 +264,7 @@
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 models and (not model or model not in models):
groups = Group.browse(User.get_groups())
raise AccessError(
gettext(
@@ -294,6 +294,12 @@
):
ModelAccess.check(model, 'write')
+ if 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')