[FIX] mail: visibility rules for channel notifications
Avoid raising an access denied error for messages that
the user has indeed be notified about.
The issue arose when a message posted on a document inaccessible
to the user was notified to one of the channels the user
is subscribed to.
The access control logic on messages relies on 2 heuristics
to grant read access to a message:
a. either the user was notified about the messages, by being
a follower of the document, or a subscriber of a channel
following the document (in that case the user can see the
message but not the document)
b. or the user has read access to the document on which the
message is posted (in that case the user can see both
the message and the document)
Case `a.` sometimes fail to match when a message got notified
to several channels including one the user was not subscribed
to. Depending on the order of the returned rows in the SQL
query, the "foreign" channels could shadow the channels of
the user, making `a.` a non-match.
If case `b.` did not match either, the user would have the
`read` access denied, even though the message was visible by
the `search()` method.
The fix explicitly makes case `a.` match if the user was
notified in *at least* one channel.
This was not done through a change of the SQL query ORDER,
for readability reasons.
This commit is contained in:
@@ -741,7 +741,13 @@ class Message(models.Model):
|
||||
ON channel_partner.channel_id = channel.id AND channel_partner.partner_id = (%%s)
|
||||
WHERE m.id = ANY (%%s)""" % self._table, (self.env.user.partner_id.id, self.env.user.partner_id.id, self.ids,))
|
||||
for mid, rmod, rid, author_id, parent_id, partner_id, channel_id in self._cr.fetchall():
|
||||
message_values[mid] = {'model': rmod, 'res_id': rid, 'author_id': author_id, 'parent_id': parent_id, 'partner_id': partner_id, 'channel_id': channel_id}
|
||||
message_values[mid] = {
|
||||
'model': rmod,
|
||||
'res_id': rid,
|
||||
'author_id': author_id,
|
||||
'parent_id': parent_id,
|
||||
'notified': any((message_values[mid].get('notified'), partner_id, channel_id))
|
||||
}
|
||||
else:
|
||||
self._cr.execute("""SELECT DISTINCT id, model, res_id, author_id, parent_id FROM "%s" WHERE id = ANY (%%s)""" % self._table, (self.ids,))
|
||||
for mid, rmod, rid, author_id, parent_id in self._cr.fetchall():
|
||||
@@ -780,7 +786,7 @@ class Message(models.Model):
|
||||
other_ids = set(self.ids).difference(set(author_ids), set(notified_ids))
|
||||
model_record_ids = _generate_model_record_ids(message_values, other_ids)
|
||||
if operation in ['read', 'write']:
|
||||
notified_ids = [mid for mid, message in message_values.iteritems() if message.get('partner_id') or message.get('channel_id')]
|
||||
notified_ids = [mid for mid, message in message_values.iteritems() if message.get('notified')]
|
||||
elif operation == 'create':
|
||||
for doc_model, doc_ids in model_record_ids.items():
|
||||
followers = self.env['mail.followers'].sudo().search([
|
||||
|
||||
Reference in New Issue
Block a user