details: https://code.tryton.org/tryton/commit/ed31faeb2a98
branch: 8.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 7fc4b3654d95 -r ed31faeb2a98 trytond/CHANGELOG
--- a/trytond/CHANGELOG Thu Nov 05 18:52:34 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 8.0.12 - 2026-10-15
diff -r 7fc4b3654d95 -r ed31faeb2a98 trytond/trytond/tests/test_wizard.py
--- a/trytond/trytond/tests/test_wizard.py Thu Nov 05 18:52:34 2026 +0100
+++ b/trytond/trytond/tests/test_wizard.py Fri Oct 30 16:25:08 2026 +0100
@@ -36,6 +36,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()
@@ -91,6 +107,22 @@
session_id, start_state, end_state = Wizard.create()
@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 7fc4b3654d95 -r ed31faeb2a98 trytond/trytond/wizard/wizard.py
--- a/trytond/trytond/wizard/wizard.py Thu Nov 05 18:52:34 2026 +0100
+++ b/trytond/trytond/wizard/wizard.py Fri Oct 30 16:25:08 2026 +0100
@@ -319,14 +319,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
@@ -408,8 +414,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 = defaultdict(dict)
data.update(json.loads(session.data, object_hook=JSONDecoder()))
for state_name, state in self.states.items():