[FIX] portal: use correct author for comments on shared records

Steps to reproduce
------------------

1. Create two partners A and B.
2. Create a shareable record, e.g. a sales order, and set A as the customer.
3. Share the record with B.
4. Use the share link sent to B and comment on the record.
5. Your comments will be sent with A as the author.

Expected behavior
-----------------

Share links sent to a customer should make you comment as that customer.

Task-2883044

X-original-commit: df162acc589b74b0e3c1e9687ce6a1980233f5f1
Part-of: odoo/odoo#94695
This commit is contained in:
Vincent Larcin
2022-06-28 10:23:43 +02:00
committed by Thibault Delavallée
parent b2c8932db1
commit 7a2650760d
6 changed files with 95 additions and 9 deletions
+9 -8
View File
@@ -15,11 +15,11 @@ from odoo.exceptions import AccessError, MissingError, UserError
def _check_special_access(res_model, res_id, token='', _hash='', pid=False):
record = request.env[res_model].browse(res_id).sudo()
if token: # Token Case: token is the global one of the document
if _hash and pid: # Signed Token Case: hash implies token is signed by partner pid
return consteq(_hash, record._sign_token(pid))
elif token: # Token Case: token is the global one of the document
token_field = request.env[res_model]._mail_post_token_field
return (token and record and consteq(record[token_field], token))
elif _hash and pid: # Signed Token Case: hash implies token is signed by partner pid
return consteq(_hash, record._sign_token(pid))
else:
raise Forbidden()
@@ -64,8 +64,11 @@ def _message_post_helper(res_model, res_id, message, token='', _hash=False, pid=
# deduce author of message
author_id = request.env.user.partner_id.id if request.env.user.partner_id else False
# Signed Token Case: author_id is forced
if _hash and pid:
author_id = pid
# Token Case: author is document customer (if not logged) or itself even if user has not the access
if token:
elif token:
if request.env.user._is_public():
# TODO : After adding the pid and sign_token in access_url when send invoice by email, remove this line
# TODO : Author must be Public User (to rename to 'Anonymous')
@@ -73,9 +76,6 @@ def _message_post_helper(res_model, res_id, message, token='', _hash=False, pid=
else:
if not author_id:
raise NotFound()
# Signed Token Case: author_id is forced
elif _hash and pid:
author_id = pid
email_from = None
if author_id and 'email_from' not in kw:
@@ -101,7 +101,7 @@ def _message_post_helper(res_model, res_id, message, token='', _hash=False, pid=
class PortalChatter(http.Controller):
def _portal_post_filter_params(self):
return ['token', 'hash', 'pid']
return ['token', 'pid']
def _portal_post_check_attachments(self, attachment_ids, attachment_tokens):
if len(attachment_tokens) != len(attachment_ids):
@@ -145,6 +145,7 @@ class PortalChatter(http.Controller):
'attachment_ids': False, # will be added afterward
}
post_values.update((fname, kw.get(fname)) for fname in self._portal_post_filter_params())
post_values['_hash'] = kw.get('hash')
message = _message_post_helper(**post_values)
result.update({'default_message_id': message.id})
+1 -1
View File
@@ -19,7 +19,7 @@ real applications. """,
'rating',
# 'snailmail',
'mass_mailing',
'mass_mailing_sms',
'mass_mailing_sms', # adds portal
'phone_validation',
'sms',
],
@@ -4,6 +4,25 @@
from odoo import api, fields, models
class MailTestPortal(models.Model):
""" A model intheriting from mail.thread with some fields used for portal
sharing, like a partner, ..."""
_description = 'Chatter Model for Portal'
_name = 'mail.test.portal'
_inherit = [
'mail.thread',
'portal.mixin',
]
name = fields.Char()
partner_id = fields.Many2one('res.partner', 'Customer')
def _compute_access_url(self):
self.access_url = False
for record in self.filtered('id'):
record.access_url = '/my/test_portal/%s' % self.id
class MailTestRating(models.Model):
""" A model inheriting from mail.thread with some fields used for SMS
gateway, like a partner, a specific mobile phone, ... """
@@ -1,4 +1,6 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_mail_test_portal_all,mail.test.portal.all,model_mail_test_portal,,1,0,0,0
access_mail_test_portal_user,mail.test.portal.user,model_mail_test_portal,base.group_user,1,1,1,1
access_mail_test_rating_all,mail.test.rating.all,model_mail_test_rating,,0,0,0,0
access_mail_test_rating_portal,mail.test.rating.portal,model_mail_test_rating,base.group_portal,1,0,0,0
access_mail_test_rating_user,mail.test.rating.user,model_mail_test_rating,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_mail_test_portal_all mail.test.portal.all model_mail_test_portal 1 0 0 0
3 access_mail_test_portal_user mail.test.portal.user model_mail_test_portal base.group_user 1 1 1 1
4 access_mail_test_rating_all mail.test.rating.all model_mail_test_rating 0 0 0 0
5 access_mail_test_rating_portal mail.test.rating.portal model_mail_test_rating base.group_portal 1 0 0 0
6 access_mail_test_rating_user mail.test.rating.user model_mail_test_rating base.group_user 1 1 1 1
+1
View File
@@ -7,6 +7,7 @@ from . import test_phone_blacklist
from . import test_mass_mailing
from . import test_mass_mailing_statistics
from . import test_mass_sms
from . import test_portal
from . import test_rating
from . import test_sms_composer
from . import test_sms_management
@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import http
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon, TestMailFullRecipients
from odoo.tests import tagged, users
from odoo.tests.common import HttpCase
@tagged('portal')
class TestPortal(HttpCase, TestMailFullCommon, TestMailFullRecipients):
def setUp(self):
super(TestPortal, self).setUp()
self.record_portal = self.env['mail.test.portal'].create({
'partner_id': self.partner_1.id,
'name': 'Test Portal Record',
})
self.record_portal._portal_ensure_token()
@users('employee')
def test_portal_mixin(self):
""" Test internals of portal mixin """
customer = self.partner_1.with_env(self.env)
record_portal = self.env['mail.test.portal'].create({
'partner_id': customer.id,
'name': 'Test Portal Record',
})
self.assertFalse(record_portal.access_token)
self.assertEqual(record_portal.access_url, '/my/test_portal/%s' % record_portal.id)
record_portal._portal_ensure_token()
self.assertTrue(record_portal.access_token)
def test_portal_share_comment(self):
""" Test posting through portal controller allowing to use a hash to
post wihtout access rights. """
self.authenticate(None, None)
post_url = f"{self.record_portal.get_base_url()}/mail/chatter_post"
# test as not logged
self.opener.post(
url=post_url,
json={
'params': {
'csrf_token': http.Request.csrf_token(self),
'hash': self.record_portal._sign_token(self.partner_2.id),
'message': 'Test',
'pid': self.partner_2.id,
'redirect': '/',
'res_model': self.record_portal._name,
'res_id': self.record_portal.id,
'token': self.record_portal.access_token,
},
},
)
message = self.record_portal.message_ids[0]
self.assertIn('Test', message.body)
self.assertEqual(message.author_id, self.partner_2)