mail_thread.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. import hashlib
  4. import hmac
  5. from odoo import api, fields, models, _
  6. class MailThread(models.AbstractModel):
  7. _inherit = 'mail.thread'
  8. _mail_post_token_field = 'access_token' # token field for external posts, to be overridden
  9. website_message_ids = fields.One2many('mail.message', 'res_id', string='Website Messages',
  10. domain=lambda self: [('model', '=', self._name), '|', ('message_type', '=', 'comment'), ('message_type', '=', 'email')], auto_join=True,
  11. help="Website communication history")
  12. def _notify_get_recipients_groups(self, msg_vals=None):
  13. groups = super()._notify_get_recipients_groups(msg_vals=msg_vals)
  14. if not self:
  15. return groups
  16. portal_enabled = isinstance(self, type(self.env['portal.mixin']))
  17. if not portal_enabled:
  18. return groups
  19. customer = self._mail_get_partners()[self.id]
  20. if customer:
  21. access_token = self._portal_ensure_token()
  22. local_msg_vals = dict(msg_vals or {})
  23. local_msg_vals['access_token'] = access_token
  24. local_msg_vals['pid'] = customer.id
  25. local_msg_vals['hash'] = self._sign_token(customer.id)
  26. local_msg_vals.update(customer.signup_get_auth_param()[customer.id])
  27. access_link = self._notify_get_action_link('view', **local_msg_vals)
  28. new_group = [
  29. ('portal_customer', lambda pdata: pdata['id'] == customer.id, {
  30. 'has_button_access': True,
  31. 'button_access': {
  32. 'url': access_link,
  33. },
  34. 'notification_is_customer': True,
  35. })
  36. ]
  37. else:
  38. new_group = []
  39. # enable portal users that should have access through portal (if not access rights
  40. # will do their duty)
  41. portal_group = next(group for group in groups if group[0] == 'portal')
  42. portal_group[2]['active'] = True
  43. portal_group[2]['has_button_access'] = True
  44. return new_group + groups
  45. def _sign_token(self, pid):
  46. """Generate a secure hash for this record with the email of the recipient with whom the record have been shared.
  47. This is used to determine who is opening the link
  48. to be able for the recipient to post messages on the document's portal view.
  49. :param str email:
  50. Email of the recipient that opened the link.
  51. """
  52. self.ensure_one()
  53. # check token field exists
  54. if self._mail_post_token_field not in self._fields:
  55. raise NotImplementedError(_(
  56. "Model %(model_name)s does not support token signature, as it does not have %(field_name)s field.",
  57. model_name=self._name,
  58. field_name=self._mail_post_token_field
  59. ))
  60. # sign token
  61. secret = self.env["ir.config_parameter"].sudo().get_param("database.secret")
  62. token = (self.env.cr.dbname, self[self._mail_post_token_field], pid)
  63. return hmac.new(secret.encode('utf-8'), repr(token).encode('utf-8'), hashlib.sha256).hexdigest()