[REVIEW] mail: some code cleanup before merging.

mail.message: fixed to_read condition
mail.message: cleaned message_read code
mail.thread: fixed mega security hole, giving superuser rights when creating objects in mail.thread

bzr revid: tde@openerp.com-20121019095919-xa95j10f22va6djm
This commit is contained in:
Thibault Delavallée
2012-10-19 11:59:19 +02:00
parent 4ab127557d
commit fbb80f4ba6
3 changed files with 42 additions and 48 deletions
+33 -39
View File
@@ -78,7 +78,7 @@ class mail_message(osv.Model):
notif_ids = notif_obj.search(cr, uid, [
('partner_id', 'in', [partner_id]),
('message_id', 'in', ids),
('read', '=', True)
('read', '=', False)
], context=context)
for notif in notif_obj.browse(cr, uid, notif_ids, context=context):
res[notif.message_id.id] = not notif.read
@@ -256,8 +256,7 @@ class mail_message(osv.Model):
for message_id in id_list:
message = read_messages[message_id]
# get all childs
# SHOULD NOT BE SUPERUSED_ID -> check search is correctly implemented in mail.message
# TDE note: check search is correctly implemented in mail.message
not_loaded_ids = self.search(cr, uid, [
('parent_id', '=', message['id']),
('id', 'not in', message_loaded_ids),
@@ -310,7 +309,7 @@ class mail_message(osv.Model):
'type': 'expandable',
'parent_id': parent_id,
'id': -1,
'max_limit': True
'max_limit': True,
})
return message_list
@@ -345,11 +344,9 @@ class mail_message(osv.Model):
further parents
:return list: list of trees of messages
"""
# print '>>> executing message_read', message_loaded_ids
if message_loaded_ids:
domain += [('id', 'not in', message_loaded_ids)]
limit = limit or self._message_read_limit
limit = 200
read_messages = {}
message_list = []
@@ -362,38 +359,37 @@ class mail_message(osv.Model):
# TDE FIXME: check access rights on search are implemented for mail.message
# fetch messages according to the domain, add their parents if uid has access to
if not ids:
ids = self.search(cr, uid, domain, context=context, limit=limit)
for message in self.read(cr, uid, ids, self._message_read_fields, context=context):
# if not in tree and not in message_loded list
if not read_messages.get(message.get('id')) and message.get('id') not in message_loaded_ids:
read_messages[message.get('id')] = message
message_list.append(self._message_get_dict(cr, uid, message, context=context))
ids = self.search(cr, uid, domain, context=context, limit=limit)
for message in self.read(cr, uid, ids, self._message_read_fields, context=context):
# if not in tree and not in message_loded list
if not read_messages.get(message.get('id')) and message.get('id') not in message_loaded_ids:
read_messages[message.get('id')] = message
message_list.append(self._message_get_dict(cr, uid, message, context=context))
# get all parented message if the user have the access
parent = self._get_parent(cr, uid, message, context=context)
while parent and parent.get('id') != parent_id:
if not read_messages.get(parent.get('id')) and parent.get('id') not in message_loaded_ids:
read_messages[parent.get('id')] = parent
message_list.append(self._message_get_dict(cr, uid, parent, context=context))
parent = self._get_parent(cr, uid, parent, context=context)
# get all parented message if the user have the access
parent = self._get_parent(cr, uid, message, context=context)
while parent and parent.get('id') != parent_id:
if not read_messages.get(parent.get('id')) and parent.get('id') not in message_loaded_ids:
read_messages[parent.get('id')] = parent
message_list.append(self._message_get_dict(cr, uid, parent, context=context))
parent = self._get_parent(cr, uid, parent, context=context)
# get the child expandable messages for the tree
message_list = sorted(message_list, key=lambda k: k['id'])
message_list = self._message_read_expandable(cr, uid, message_list, read_messages,
message_loaded_ids=message_loaded_ids, domain=domain, context=context, parent_id=parent_id, limit=limit)
# get the child expandable messages for the tree
message_list = sorted(message_list, key=lambda k: k['id'])
message_list = self._message_read_expandable(cr, uid, message_list, read_messages,
message_loaded_ids=message_loaded_ids, domain=domain, context=context, parent_id=parent_id, limit=limit)
# message_list = sorted(message_list, key=lambda k: k['id'])
return message_list
# TDE Note: do we need this ?
def user_free_attachment(self, cr, uid, context=None):
attachment = self.pool.get('ir.attachment')
attachment_list = []
attachment_ids = attachment.search(cr, uid, [('res_model', '=', 'mail.message'), ('create_uid', '=', uid)])
if len(attachment_ids):
attachment_list = [{'id': attach.id, 'name': attach.name, 'date': attach.create_date} for attach in attachment.browse(cr, uid, attachment_ids, context=context)]
return attachment_list
# def user_free_attachment(self, cr, uid, context=None):
# attachment = self.pool.get('ir.attachment')
# attachment_list = []
# attachment_ids = attachment.search(cr, uid, [('res_model', '=', 'mail.message'), ('create_uid', '=', uid)])
# if len(attachment_ids):
# attachment_list = [{'id': attach.id, 'name': attach.name, 'date': attach.create_date} for attach in attachment.browse(cr, uid, attachment_ids, context=context)]
# return attachment_list
#------------------------------------------------------
# Email api
@@ -414,7 +410,7 @@ class mail_message(osv.Model):
- create: if
- I am in the document message_follower_ids OR
- I can write on the related document if res_model, res_id OR
- I write a mail to another user (no res_model)
- I create a private message (no model, no res_id)
- Otherwise: raise
- write: if
- I can write on the related document if res_model, res_id
@@ -452,10 +448,14 @@ class mail_message(osv.Model):
if operation == 'read':
author_ids = [mid for mid, message in message_values.iteritems()
if message.get('author_id') and message.get('author_id') == partner_id]
# Create: Check messages you create that are private messages -> ir.rule ?
elif operation == 'create':
author_ids = [mid for mid, message in message_values.iteritems()
if not message.get('model') and not message.get('res_id')]
else:
author_ids = []
# Create: Check message_follower_ids and author_ids
# Create: Check message_follower_ids
if operation == 'create':
doc_follower_ids = []
for model, mids in model_record_ids.items():
@@ -471,12 +471,6 @@ class mail_message(osv.Model):
else:
doc_follower_ids = []
# Create/write: Check author_ids
if operation == 'create' or operation == 'write':
author_ids = author_ids+[mid for mid, message in message_values.iteritems()
if message.get('author_id') and message.get('author_id') == partner_id and not message.get('res_model')]
# Calculate remaining ids, and related model/res_ids
model_record_ids = {}
other_ids = set(ids).difference(set(notified_ids), set(author_ids), set(doc_follower_ids))
+8 -8
View File
@@ -108,12 +108,12 @@ class mail_thread(osv.AbstractModel):
# find the document followers, update the data
fol_obj = self.pool.get('mail.followers')
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
fol_ids = fol_obj.search(cr, uid, [
('partner_id', '=', user_pid),
('res_id', 'in', ids),
('res_model', '=', self._name),
], context=context)
for fol in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context):
for fol in fol_obj.browse(cr, uid, fol_ids, context=context):
thread_subtype_dict = res[fol.res_id]['message_subtype_data']
for subtype in fol.subtype_ids:
thread_subtype_dict[subtype.name]['followed'] = True
@@ -225,8 +225,8 @@ class mail_thread(osv.AbstractModel):
def create(self, cr, uid, vals, context=None):
""" Override to subscribe the current user. """
thread_id = super(mail_thread, self).create(cr, SUPERUSER_ID, vals, context=context)
self.message_subscribe_users(cr, SUPERUSER_ID, [thread_id], [uid], context=context)
thread_id = super(mail_thread, self).create(cr, uid, vals, context=context)
self.message_subscribe_users(cr, uid, [thread_id], [uid], context=context)
return thread_id
def unlink(self, cr, uid, ids, context=None):
@@ -705,10 +705,10 @@ class mail_thread(osv.AbstractModel):
mail_message = self.pool.get('mail.message')
attachment_ids = ir_attachment.search(cr, SUPERUSER_ID, [('res_model', '=', 'mail.message'), ('res_id', '=', 0), ('create_uid', '=', uid), ('id', 'in', attachments)], context=context)
if attachment_ids:
ir_attachment.write(cr, SUPERUSER_ID, attachment_ids, { 'res_model': self._name, 'res_id': thread_id }, context=context)
mail_message.write(cr, SUPERUSER_ID, [new_message_id], {'attachment_ids': [(6, 0, [pid for pid in attachment_ids])]} )
new_message = self.pool.get('mail.message').message_read(cr, uid, [new_message_id])
ir_attachment.write(cr, SUPERUSER_ID, attachment_ids, {'res_model': self._name, 'res_id': thread_id}, context=context)
mail_message.write(cr, SUPERUSER_ID, [new_message_id], {'attachment_ids': [(6, 0, [pid for pid in attachment_ids])]}, context=context)
new_message = self.pool.get('mail.message').message_read(cr, uid, [new_message_id], context=context)
return new_message
#------------------------------------------------------
+1 -1
View File
@@ -11,7 +11,7 @@
</record>
<record id="mail_followers_read_own" model="ir.rule">
<field name="name">mail.followers: read its own entries</field>
<field name="name">mail.followers: read and write its own entries</field>
<field name="model_id" ref="model_mail_followers"/>
<field name="domain_force">[('partner_id', '=', user.partner_id.id)]</field>
<field name="perm_create" eval="False"/>