details: https://code.tryton.org/tryton/commit/927c959404b9
branch: 7.0
user: Cédric Krier <[email protected]>
date: Fri Oct 30 16:25:08 2026 +0100
description:
Restrict the wizard session to the user who created it
Closes #15206
(grafted from 2bad239629b382318b219dc99887df4f06b6dd86)
diffstat:
trytond/CHANGELOG | 2 ++
trytond/trytond/tests/test_wizard.py | 32 ++++++++++++++++++++++++++++++++
trytond/trytond/wizard/wizard.py | 16 +++++++++++++---
3 files changed, 47 insertions(+), 3 deletions(-)
diffs (98 lines):
diff -r 8d3ea53120f2 -r 927c959404b9 trytond/CHANGELOG
--- a/trytond/CHANGELOG Thu Nov 05 18:53:44 2026 +0100
+++ b/trytond/CHANGELOG Fri Oct 30 16:25:08 2026 +0100
@@ -1,3 +1,5 @@
+* Restrict the wizard session to the user who created it (issue15206)
+* Do not permit to execute wizards without models or groups (issue15205)
* Only permit administrators to execute wizards without models or groups
(issue15205)
Version 7.0.59 - 2026-10-15
diff -r 8d3ea53120f2 -r 927c959404b9 trytond/trytond/tests/test_wizard.py
--- a/trytond/trytond/tests/test_wizard.py Thu Nov 05 18:53:44 2026 +0100
+++ b/trytond/trytond/tests/test_wizard.py Fri Oct 30 16:25:08 2026 +0100
@@ -35,6 +35,22 @@
Wizard.delete(session_id)
@with_transaction()
+ def test_delete_different_user(self):
+ "Delete session from a different user"
+ pool = Pool()
+ Wizard = pool.get('test.test_wizard', type='wizard')
+ User = pool.get('res.user')
+
+ user = User(login='foo')
+ user.save()
+
+ session_id, _, _ = Wizard.create()
+
+ with Transaction().set_user(user.id):
+ with self.assertRaises(AccessError):
+ Wizard.delete(session_id)
+
+ @with_transaction()
def test_session(self):
'Session Wizard'
pool = Pool()
@@ -73,6 +89,22 @@
self.assertEqual(group_b.name, 'Group B')
@with_transaction()
+ def test_session_different_user(self):
+ "Use session from a different user"
+ pool = Pool()
+ Wizard = pool.get('test.test_wizard', type='wizard')
+ User = pool.get('res.user')
+
+ user = User(login='foo')
+ user.save()
+
+ session_id, _, _ = Wizard.create()
+
+ with Transaction().set_user(user.id):
+ with self.assertRaises(AccessError):
+ Wizard(session_id)
+
+ @with_transaction()
def test_execute(self):
'Execute Wizard'
pool = Pool()
diff -r 8d3ea53120f2 -r 927c959404b9 trytond/trytond/wizard/wizard.py
--- a/trytond/trytond/wizard/wizard.py Thu Nov 05 18:53:44 2026 +0100
+++ b/trytond/trytond/wizard/wizard.py Fri Oct 30 16:25:08 2026 +0100
@@ -310,14 +310,20 @@
@classmethod
def delete(cls, session_id):
"Delete the session"
- Session = Pool().get('ir.session.wizard')
+ pool = Pool()
+ Session = pool.get('ir.session.wizard')
+ transaction = Transaction()
+ session = Session(session_id)
+ if session.create_uid.id != transaction.user:
+ raise AccessError(
+ gettext('ir.msg_access_wizard_error', wizard=cls.__name__))
end = getattr(cls, cls.end_state, None)
if end:
wizard = cls(session_id)
action = end(wizard)
else:
action = None
- Session.delete([Session(session_id)])
+ Session.delete([session])
return action
@classmethod
@@ -395,8 +401,12 @@
def __init__(self, session_id):
pool = Pool()
Session = pool.get('ir.session.wizard')
- self._session_id = session_id
+ transaction = Transaction()
session = Session(session_id)
+ if session.create_uid.id != transaction.user:
+ raise AccessError(
+ gettext('ir.msg_access_wizard_error', wizard=self.__name__))
+ self._session_id = session.id
data = json.loads(session.data, object_hook=JSONDecoder())
for state_name, state in self.states.items():
if isinstance(state, StateView):