OCA / server-ux

GNU Affero General Public License v3.0
158 stars 515 forks source link

base_tier_validation: blocking notifications cron, a.k.a. should it block sudo writes? #875

Closed yajo closed 3 months ago

yajo commented 4 months ago

Module

base_tier_validation

Describe the bug

We have a database where base_tier_validation is installed along with other addons from its family.

The cron mail.ir_cron_send_scheduled_message is blocked in loop because of that addon.

To Reproduce

Affected versions: 16.0 and probably others.

Steps to reproduce the behavior:

  1. Have some record that:
    • Needs to notify a customer.
    • Has no portal token.
    • Is pending tier validation.
  2. Run the cron (you can do it manually)

Actual behavior

Cron enters fail loop. Traceback:

2024-05-06 12:30:04,883 42 INFO odoo odoo.addons.base.models.ir_cron: Starting job `Notification: Send scheduled message notifications`.
2024-05-06 12:30:04,889 42 INFO odoo odoo.addons.mail.models.mail_message_schedule: Send 1 scheduled messages
2024-05-06 12:30:04,921 42 ERROR odoo odoo.addons.base.models.ir_cron: Call from cron Notification: Send scheduled message notifications for server action #115 failed in Job #6
Traceback (most recent call last):
  File "/opt/odoo/custom/src/odoo/odoo/addons/base/models/ir_cron.py", line 391, in _callback
    self.env['ir.actions.server'].browse(server_action_id).run()
  File "/opt/odoo/custom/src/odoo/odoo/addons/base/models/ir_actions.py", line 674, in run
    res = runner(run_self, eval_context=eval_context)
  File "/opt/odoo/auto/addons/website/models/ir_actions_server.py", line 61, in _run_action_code_multi
    res = super(ServerAction, self)._run_action_code_multi(eval_context)
  File "/opt/odoo/custom/src/odoo/odoo/addons/base/models/ir_actions.py", line 544, in _run_action_code_multi
    safe_eval(self.code.strip(), eval_context, mode="exec", nocopy=True, filename=str(self))  # nocopy allows to return 'action'
  File "/opt/odoo/custom/src/odoo/odoo/tools/safe_eval.py", line 383, in safe_eval
    return unsafe_eval(c, globals_dict, locals_dict)
  File "ir.actions.server(115,)", line 1, in <module>
  File "/opt/odoo/auto/addons/mail/models/mail_message_schedule.py", line 51, in _send_notifications_cron
    messages_scheduled._send_notifications()
  File "/opt/odoo/auto/addons/mail/models/mail_message_schedule.py", line 80, in _send_notifications
    record._notify_thread(schedule.mail_message_id, msg_vals=False, **notify_kwargs)
  File "/opt/odoo/auto/addons/sms/models/mail_thread.py", line 240, in _notify_thread
    recipients_data = super(MailThread, self)._notify_thread(message, msg_vals=msg_vals, **kwargs)
  File "/opt/odoo/auto/addons/mail_mobile/models/mail_thread.py", line 25, in _notify_thread
    recipients_data = super(MailThread, self)._notify_thread(message, msg_vals=msg_vals, **kwargs)
  File "/opt/odoo/auto/addons/mail_post_defer/models/mail_thread.py", line 33, in _notify_thread
    return super()._notify_thread(message, msg_vals=msg_vals, **kwargs)
  File "/opt/odoo/auto/addons/mail/models/mail_thread.py", line 2471, in _notify_thread
    self._notify_thread_by_email(message, recipients_data, msg_vals=msg_vals, **kwargs)
  File "/opt/odoo/auto/addons/mail/models/mail_thread.py", line 2557, in _notify_thread_by_email
    recipients_groups_data = self._notify_get_recipients_classify(partners_data, model_name, msg_vals=msg_vals)
  File "/opt/odoo/auto/addons/mail/models/mail_thread.py", line 2957, in _notify_get_recipients_classify
    groups = self._notify_get_recipients_groups(msg_vals=local_msg_vals)
  File "/opt/odoo/auto/addons/sale/models/sale_order.py", line 1236, in _notify_get_recipients_groups
    groups = super()._notify_get_recipients_groups(msg_vals=msg_vals)
  File "/opt/odoo/auto/addons/portal/models/mail_thread.py", line 30, in _notify_get_recipients_groups
    access_token = self._portal_ensure_token()
  File "/opt/odoo/auto/addons/portal/models/portal_mixin.py", line 32, in _portal_ensure_token
    self.sudo().write({'access_token': str(uuid.uuid4())})
  File "/opt/odoo/auto/addons/delivery_auto_refresh/models/sale_order.py", line 92, in write
    )._auto_refresh_delivery()
  File "/opt/odoo/auto/addons/delivery_auto_refresh/models/sale_order.py", line 65, in _auto_refresh_delivery
    self.with_context(auto_refresh_delivery=True)._remove_delivery_line()
  File "/opt/odoo/auto/addons/delivery_auto_refresh/models/sale_order.py", line 112, in _remove_delivery_line
    res = super()._remove_delivery_line()
  File "/opt/odoo/auto/addons/delivery/models/sale_order.py", line 56, in _remove_delivery_line
    to_delete.unlink()
  File "/opt/odoo/auto/addons/delivery/models/sale_order.py", line 193, in unlink
    self.filtered('is_delivery').order_id.filtered('carrier_id').carrier_id = False
  File "/opt/odoo/custom/src/odoo/odoo/fields.py", line 1325, in __set__
    records.write({self.name: write_value})
  File "/opt/odoo/auto/addons/delivery_auto_refresh/models/sale_order.py", line 84, in write
    res = super().write(vals)
  File "/opt/odoo/auto/addons/sale_stock/models/sale_order.py", line 121, in write
    res = super(SaleOrder, self).write(values)
  File "/opt/odoo/auto/addons/mail/models/mail_thread.py", line 315, in write
    result = super(MailThread, self).write(values)
  File "/opt/odoo/auto/addons/mail/models/mail_activity_mixin.py", line 241, in write
    return super(MailActivityMixin, self).write(vals)
  File "/opt/odoo/auto/addons/base_tier_validation/models/tier_validation.py", line 282, in write
    raise ValidationError(_("The operation is under validation."))
odoo.exceptions.ValidationError: Esta operación está en proceso de validación.

Expected behavior Cron should work. Notifications should be sent, no matter the validation status.

Additional context

A possibility to fix the problem would be:

  1. Add portal to the dependencies of base_tier_validation
  2. Override _portal_ensure_token().
  3. Call super with_context(skip_validation_check=True)

However, pay attention to this part of the traceback:

  File "/opt/odoo/auto/addons/portal/models/portal_mixin.py", line 32, in _portal_ensure_token
    self.sudo().write({'access_token': str(uuid.uuid4())})

As you can see, the token is being written with sudo. I think it's a bug to block writes in sudo.

@moduon MT-5997

Shide commented 4 months ago

I think the block is not happening when writting access_token because when performing a validation, this functions must be called and access_token is allowed to be written

yajo commented 4 months ago

Ah good catch! Then the problem must be around these lines:

File "/opt/odoo/auto/addons/delivery_auto_refresh/models/sale_order.py", line 92, in write
  )._auto_refresh_delivery()
File "/opt/odoo/auto/addons/delivery_auto_refresh/models/sale_order.py", line 65, in _auto_refresh_delivery
  self.with_context(auto_refresh_delivery=True)._remove_delivery_line()
File "/opt/odoo/auto/addons/delivery_auto_refresh/models/sale_order.py", line 112, in _remove_delivery_line
  res = super()._remove_delivery_line()
File "/opt/odoo/auto/addons/delivery/models/sale_order.py", line 56, in _remove_delivery_line
  to_delete.unlink()
File "/opt/odoo/auto/addons/delivery/models/sale_order.py", line 193, in unlink
  self.filtered('is_delivery').order_id.filtered('carrier_id').carrier_id = False
yajo commented 4 months ago

Then this should be the real fix: https://github.com/OCA/delivery-carrier/pull/815

yajo commented 3 months ago

Fixed by https://github.com/OCA/delivery-carrier/pull/799.