From cd4b50de6f5a6bfa063b2d8268cb8bc58c6a74f6 Mon Sep 17 00:00:00 2001 From: Adrian Torres Date: Wed, 11 Mar 2020 14:13:17 +0000 Subject: [PATCH] [FIX] base: don't uninstall already uninstalled modules Before this commit: - Install some random module that can be uninstalled (so not base) - Open the uninstall wizard for said module in two different tabs / windows / whatever - In one tab, confirm the module uninstall and wait for it to be done - As soon as the other tab is done with the uninstall, go to the second one with the uninstall wizard still open, and proceed with the second uninstall - Boom, the registry crashes and completely fucks up the DB because there's no check at all that prevents the uninstall of already uninstalled modules. After this commit: - `ir.module.module.button_uninstall` will check if all the modules being uninstalled are in the installed state and if not a UserError will be raised, preventing a second uninstall of the module which could potentially break the DB Do note that this fix is LOCAL, the problem is however more or less global, wherever there's user-actionable buttons that should only be pressed once there's a potential for bugs / breakage if a similar fix is not implemented locally. Perhaps a more global fix should be implemented eventually, but it's generally less annoying for business cases since those probably won't break the registry, see task 1859014. opw-2213679 opw-2212594 opw-2206446 closes odoo/odoo#47450 X-original-commit: 8c1bb22ec0222dca652e0649454b986c06cb1368 Signed-off-by: Adrian Torres (adt) --- odoo/addons/base/models/ir_module.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/odoo/addons/base/models/ir_module.py b/odoo/addons/base/models/ir_module.py index f042dd5aa7b..70f0b1d08ec 100644 --- a/odoo/addons/base/models/ir_module.py +++ b/odoo/addons/base/models/ir_module.py @@ -605,6 +605,11 @@ class Module(models.Model): def button_uninstall(self): if 'base' in self.mapped('name'): raise UserError(_("The `base` module cannot be uninstalled")) + if not all(state == 'installed' for state in self.mapped('state')): + raise UserError(_( + "One or more of the selected modules have already been uninstalled, if you " + "believe this to be an error, you may try again later or contact support." + )) deps = self.downstream_dependencies() (self + deps).write({'state': 'to remove'}) return dict(ACTION_DICT, name=_('Uninstall'))