From 603e13fa00a393bcf6156aab4994e4268395c5a2 Mon Sep 17 00:00:00 2001 From: alt-odoo Date: Thu, 24 Jun 2021 09:14:29 +0000 Subject: [PATCH] [FIX] lunch: access rights error on ir.cron for lunch manager When a lunch manager tries to archive a vendor, we automatically update its related cron. This is triggering an access rights error if the user does not have access to ir.cron model. We should allow him to archive the vendor without error. closes odoo/odoo#72750 X-original-commit: 5b8eff9d771a9071327473d2185624f69e1057c1 Signed-off-by: Julien Castiaux Signed-off-by: Alex Tuyls Co-authored-by: Julien Castiaux --- addons/lunch/models/lunch_alert.py | 11 +- addons/lunch/models/lunch_supplier.py | 11 +- addons/lunch/tests/common.py | 185 +++++++++++++------------- addons/lunch/tests/test_alert.py | 8 +- addons/lunch/tests/test_supplier.py | 14 +- 5 files changed, 125 insertions(+), 104 deletions(-) diff --git a/addons/lunch/models/lunch_alert.py b/addons/lunch/models/lunch_alert.py index 91c77e55116..1bb21f95b56 100644 --- a/addons/lunch/models/lunch_alert.py +++ b/addons/lunch/models/lunch_alert.py @@ -110,10 +110,11 @@ class LunchAlert(models.Model): sendat_tz += timedelta(days=1) sendat_utc = sendat_tz.astimezone(pytz.UTC).replace(tzinfo=None) - alert.cron_id.name = f"Lunch: alert chat notification ({alert.name})" - alert.cron_id.active = cron_required - alert.cron_id.nextcall = sendat_utc - alert.cron_id.code = dedent(f"""\ + cron = alert.cron_id.sudo() + cron.name = f"Lunch: alert chat notification ({alert.name})" + cron.active = cron_required + cron.nextcall = sendat_utc + cron.code = dedent(f"""\ # This cron is dynamically controlled by {self._description}. # Do NOT modify this cron, modify the related record instead. env['{self._name}'].browse([{alert.id}])._notify_chat()""") @@ -148,7 +149,7 @@ class LunchAlert(models.Model): self._sync_cron() def unlink(self): - crons = self.cron_id + crons = self.cron_id.sudo() super().unlink() crons.unlink() diff --git a/addons/lunch/models/lunch_supplier.py b/addons/lunch/models/lunch_supplier.py index bb9ace17fa8..77c0da0dbff 100644 --- a/addons/lunch/models/lunch_supplier.py +++ b/addons/lunch/models/lunch_supplier.py @@ -121,10 +121,11 @@ class LunchSupplier(models.Model): sendat_tz += timedelta(days=1) sendat_utc = sendat_tz.astimezone(pytz.UTC).replace(tzinfo=None) - supplier.cron_id.active = supplier.active and supplier.send_by == 'mail' - supplier.cron_id.name = f"Lunch: send automatic email to {supplier.name}" - supplier.cron_id.nextcall = sendat_utc - supplier.cron_id.code = dedent(f"""\ + cron = supplier.cron_id.sudo() + cron.active = supplier.active and supplier.send_by == 'mail' + cron.name = f"Lunch: send automatic email to {supplier.name}" + cron.nextcall = sendat_utc + cron.code = dedent(f"""\ # This cron is dynamically controlled by {self._description}. # Do NOT modify this cron, modify the related record instead. env['{self._name}'].browse([{supplier.id}])._send_auto_email()""") @@ -159,7 +160,7 @@ class LunchSupplier(models.Model): self._sync_cron() def unlink(self): - crons = self.cron_id + crons = self.cron_id.sudo() super().unlink() crons.unlink() diff --git a/addons/lunch/tests/common.py b/addons/lunch/tests/common.py index 1b3732a22a2..2739d71d943 100644 --- a/addons/lunch/tests/common.py +++ b/addons/lunch/tests/common.py @@ -2,7 +2,7 @@ from datetime import datetime from freezegun import freeze_time -from odoo.tests import common +from odoo.tests import common, new_test_user fakenow = datetime(2021, 1, 29, 12, 20, 0) @@ -17,96 +17,103 @@ class TestsCommon(common.TransactionCase): def setUp(self): super(TestsCommon, self).setUp() - self.location_office_1 = self.env['lunch.location'].create({ - 'name' : 'Farm 1', - }) - - self.location_office_2 = self.env['lunch.location'].create({ - 'name': 'Farm 2', - }) - - self.partner_pizza_inn = self.env['res.partner'].create({ - 'name': 'Pizza Inn', - }) - - self.supplier_pizza_inn = self.env['lunch.supplier'].create({ - 'partner_id': self.partner_pizza_inn.id, - 'send_by': 'mail', - 'automatic_email_time': 11, - 'available_location_ids': [ - (6, 0, [self.location_office_1.id, self.location_office_2.id]) - ], - }) - - self.partner_kothai = self.env['res.partner'].create({ - 'name': 'Kothai', - }) - - self.supplier_kothai = self.env['lunch.supplier'].create({ - 'partner_id': self.partner_kothai.id, - 'send_by': 'mail', - 'automatic_email_time': 10, - 'tz': 'America/New_York', - }) - - self.partner_coin_gourmand = self.env['res.partner'].create({ - 'name': 'Coin Gourmand', - }) - - self.supplier_coin_gourmand = self.env['lunch.supplier'].create({ - 'partner_id': self.partner_coin_gourmand.id, - 'send_by': 'phone', - 'available_location_ids': [ - (6, 0, [self.location_office_1.id, self.location_office_2.id]) - ], - }) - - self.category_pizza = self.env['lunch.product.category'].create({ - 'name': 'Pizza', - }) - - self.category_sandwich = self.env['lunch.product.category'].create({ - 'name': 'Sandwich', - }) - - self.product_pizza = self.env['lunch.product'].create({ - 'name': 'Pizza', - 'category_id': self.category_pizza.id, - 'price': 9, - 'supplier_id': self.supplier_pizza_inn.id, - }) - - self.product_sandwich_tuna = self.env['lunch.product'].create({ - 'name': 'Tuna Sandwich', - 'category_id': self.category_sandwich.id, - 'price': 3, - 'supplier_id': self.supplier_coin_gourmand.id, - }) - - self.topping_olives = self.env['lunch.topping'].create({ - 'name': 'Olives', - 'price': 0.3, - 'category_id': self.category_pizza.id, - }) - self.env['lunch.cashmove'].create({ 'amount': 100, }) - self.alert_ny = self.env['lunch.alert'].create({ - 'name': 'New York UTC-5', - 'mode': 'chat', - 'notification_time': 10, - 'notification_moment': 'am', - 'tz': 'America/New_York', - 'message': "", - }).with_context(tz='America/New_York') + self.manager = new_test_user(self.env, 'cle-lunch-manager', 'base.group_user,base.group_partner_manager,lunch.group_lunch_manager') + with self.with_user('cle-lunch-manager'): - self.alert_tokyo = self.env['lunch.alert'].create({ - 'name': 'Tokyo UTC+9', - 'mode': 'chat', - 'notification_time': 8, - 'notification_moment': 'am', - 'tz': 'Asia/Tokyo', - 'message': "", - }).with_context(tz='Asia/Tokyo') + self.location_office_1 = self.env['lunch.location'].create({ + 'name' : 'Farm 1', + }) + + self.location_office_2 = self.env['lunch.location'].create({ + 'name': 'Farm 2', + }) + + self.partner_pizza_inn = self.env['res.partner'].create({ + 'name': 'Pizza Inn', + }) + + self.supplier_pizza_inn = self.env['lunch.supplier'].create({ + 'partner_id': self.partner_pizza_inn.id, + 'send_by': 'mail', + 'automatic_email_time': 11, + 'available_location_ids': [ + (6, 0, [self.location_office_1.id, self.location_office_2.id]) + ], + }) + + self.partner_kothai = self.env['res.partner'].create({ + 'name': 'Kothai', + }) + + self.supplier_kothai = self.env['lunch.supplier'].create({ + 'partner_id': self.partner_kothai.id, + 'send_by': 'mail', + 'automatic_email_time': 10, + 'tz': 'America/New_York', + }) + + self.partner_coin_gourmand = self.env['res.partner'].create({ + 'name': 'Coin Gourmand', + }) + + self.supplier_coin_gourmand = self.env['lunch.supplier'].create({ + 'partner_id': self.partner_coin_gourmand.id, + 'send_by': 'phone', + 'available_location_ids': [ + (6, 0, [self.location_office_1.id, self.location_office_2.id]) + ], + }) + + self.category_pizza = self.env['lunch.product.category'].create({ + 'name': 'Pizza', + }) + + self.category_sandwich = self.env['lunch.product.category'].create({ + 'name': 'Sandwich', + }) + + self.product_pizza = self.env['lunch.product'].create({ + 'name': 'Pizza', + 'category_id': self.category_pizza.id, + 'price': 9, + 'supplier_id': self.supplier_pizza_inn.id, + }) + + self.product_sandwich_tuna = self.env['lunch.product'].create({ + 'name': 'Tuna Sandwich', + 'category_id': self.category_sandwich.id, + 'price': 3, + 'supplier_id': self.supplier_coin_gourmand.id, + }) + + self.topping_olives = self.env['lunch.topping'].create({ + 'name': 'Olives', + 'price': 0.3, + 'category_id': self.category_pizza.id, + }) + + self.env['lunch.cashmove'].create({ + 'amount': 100, + }) + + self.alert_ny = self.env['lunch.alert'].create({ + 'name': 'New York UTC-5', + 'mode': 'chat', + 'notification_time': 10, + 'notification_moment': 'am', + 'tz': 'America/New_York', + 'message': "", + }).with_context(tz='America/New_York') + + self.alert_tokyo = self.env['lunch.alert'].create({ + 'name': 'Tokyo UTC+9', + 'mode': 'chat', + 'notification_time': 8, + 'notification_moment': 'am', + 'tz': 'Asia/Tokyo', + 'message': "", + }).with_context(tz='Asia/Tokyo') diff --git a/addons/lunch/tests/test_alert.py b/addons/lunch/tests/test_alert.py index 148a1757c27..1b411689c8d 100644 --- a/addons/lunch/tests/test_alert.py +++ b/addons/lunch/tests/test_alert.py @@ -1,10 +1,12 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from datetime import datetime, timedelta from odoo import fields +from odoo.tests import common from odoo.addons.lunch.tests.common import TestsCommon class TestAlarm(TestsCommon): + @common.users('cle-lunch-manager') def test_cron_sync_create(self): cron_ny = self.alert_ny.cron_id self.assertTrue(cron_ny.active) @@ -17,6 +19,7 @@ class TestAlarm(TestsCommon): tokyo_cron = self.alert_tokyo.cron_id self.assertEqual(tokyo_cron.nextcall, datetime(2021, 1, 29, 23, 0)) # Tokyo is UTC+9 but the cron is posponed + @common.users('cle-lunch-manager') def test_cron_sync_active(self): cron_ny = self.alert_ny.cron_id @@ -38,6 +41,7 @@ class TestAlarm(TestsCommon): self.alert_ny.until = False self.assertTrue(cron_ny.active) + @common.users('cle-lunch-manager') def test_cron_sync_nextcall(self): cron_ny = self.alert_ny.cron_id old_nextcall = cron_ny.nextcall @@ -46,8 +50,8 @@ class TestAlarm(TestsCommon): self.assertEqual(cron_ny.nextcall, old_nextcall - timedelta(hours=5) + timedelta(days=1)) # Simulate cron execution - cron_ny.lastcall = old_nextcall - timedelta(hours=5) - cron_ny.nextcall += timedelta(days=1) + cron_ny.sudo().lastcall = old_nextcall - timedelta(hours=5) + cron_ny.sudo().nextcall += timedelta(days=1) self.alert_ny.notification_time += 7 self.assertEqual(cron_ny.nextcall, old_nextcall + timedelta(days=1, hours=2)) diff --git a/addons/lunch/tests/test_supplier.py b/addons/lunch/tests/test_supplier.py index 49be5e1b960..9040db7befd 100644 --- a/addons/lunch/tests/test_supplier.py +++ b/addons/lunch/tests/test_supplier.py @@ -6,6 +6,7 @@ from datetime import datetime, time, timedelta from unittest.mock import patch from odoo import fields +from odoo.tests import common from odoo.addons.lunch.tests.common import TestsCommon @@ -24,6 +25,7 @@ class TestSupplier(TestsCommon): self.saturday_1pm = datetime(2018, 11, 3, 13, 0, 0) self.saturday_8pm = datetime(2018, 11, 3, 20, 0, 0) + @common.users('cle-lunch-manager') def test_send_email_cron(self): self.supplier_kothai.cron_id.ensure_one() self.assertEqual(self.supplier_kothai.cron_id.nextcall.time(), time(15, 0)) @@ -34,8 +36,9 @@ env['lunch.supplier'].browse([{self.supplier_kothai.id}])._send_auto_email()""") cron_id = self.supplier_kothai.cron_id.id self.supplier_kothai.unlink() - self.assertFalse(self.env['ir.cron'].search([('id', '=', cron_id)])) + self.assertFalse(self.env['ir.cron'].sudo().search([('id', '=', cron_id)])) + @common.users('cle-lunch-manager') def test_compute_available_today(self): tests = [(self.monday_1am, True), (self.monday_10am, True), (self.monday_1pm, True), (self.monday_8pm, True), @@ -49,6 +52,7 @@ env['lunch.supplier'].browse([{self.supplier_kothai.id}])._send_auto_email()""") self.env['lunch.supplier'].invalidate_cache(['available_today'], [self.supplier_pizza_inn.id]) + @common.users('cle-lunch-manager') def test_search_available_today(self): ''' This test checks that _search_available_today returns a valid domain @@ -75,6 +79,7 @@ env['lunch.supplier'].browse([{self.supplier_kothai.id}])._send_auto_email()""") with patch.object(fields.Datetime, 'now', return_value=self.monday_10am) as _: assert self.supplier_pizza_inn in Supplier.search([('available_today', '=', True)]) + @common.users('cle-lunch-manager') def test_auto_email_send(self): with patch.object(fields.Datetime, 'now', return_value=self.monday_1pm) as _: with patch.object(fields.Date, 'today', return_value=self.monday_1pm.date()) as _: @@ -134,6 +139,7 @@ env['lunch.supplier'].browse([{self.supplier_kothai.id}])._send_auto_email()""") self.supplier_pizza_inn._send_auto_email() + @common.users('cle-lunch-manager') def test_cron_sync_create(self): cron_ny = self.supplier_kothai.cron_id # I am at New-York self.assertTrue(cron_ny.active) @@ -143,6 +149,7 @@ env['lunch.supplier'].browse([{self.supplier_kothai.id}])._send_auto_email()""") ["env['lunch.supplier'].browse([%i])._send_auto_email()" % self.supplier_kothai.id]) self.assertEqual(cron_ny.nextcall, datetime(2021, 1, 29, 15, 0)) # New-york is UTC-5 + @common.users('cle-lunch-manager') def test_cron_sync_active(self): cron_ny = self.supplier_kothai.cron_id @@ -156,6 +163,7 @@ env['lunch.supplier'].browse([{self.supplier_kothai.id}])._send_auto_email()""") self.supplier_kothai.send_by = 'mail' self.assertTrue(cron_ny.active) + @common.users('cle-lunch-manager') def test_cron_sync_nextcall(self): cron_ny = self.supplier_kothai.cron_id old_nextcall = cron_ny.nextcall @@ -164,8 +172,8 @@ env['lunch.supplier'].browse([{self.supplier_kothai.id}])._send_auto_email()""") self.assertEqual(cron_ny.nextcall, old_nextcall - timedelta(hours=5) + timedelta(days=1)) # Simulate cron execution - cron_ny.lastcall = old_nextcall - timedelta(hours=5) - cron_ny.nextcall += timedelta(days=1) + cron_ny.sudo().lastcall = old_nextcall - timedelta(hours=5) + cron_ny.sudo().nextcall += timedelta(days=1) self.supplier_kothai.automatic_email_time += 7 self.assertEqual(cron_ny.nextcall, old_nextcall + timedelta(days=1, hours=2))