diff options
| author | Thibault Delavallée <tde@openerp.com> | 2012-12-12 17:06:34 +0100 |
|---|---|---|
| committer | Thibault Delavallée <tde@openerp.com> | 2012-12-12 17:06:34 +0100 |
| commit | f1ee7f1ad9fe4a9a92e2058862f2c149347df3cd (patch) | |
| tree | d4a8b19865a6e3017d28266b01ae4297584c1d95 /addons | |
| parent | 179f525dc7be6199da6f089da519faa3683a5ea5 (diff) | |
[IMP] mail_message: added the right to reply to a message wes received even if we cannot see the related document.
bzr revid: tde@openerp.com-20121212160634-umbiq2erwijm2d20
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/mail/mail_message.py | 71 | ||||
| -rw-r--r-- | addons/mail/tests/test_mail_message.py | 25 |
2 files changed, 65 insertions, 31 deletions
diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 6bed14fc5fa..2751e332f30 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -608,55 +608,73 @@ class mail_message(osv.Model): - uid have read access to the related document if model, res_id - otherwise: raise - create: if - - no model, no res_id, I create a private message + - no model, no res_id, I create a private message OR - pid in message_follower_ids if model, res_id OR + - mail_notification (parent_id.id, pid) exists, uid has been notified of the parent, OR - uid have write access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - uid has write access on the related document if model, res_id - - Otherwise: raise + - otherwise: raise - unlink: if - uid has write access on the related document if model, res_id - - Otherwise: raise + - otherwise: raise """ + def _generate_model_record_ids(msg_val, msg_ids=[]): + """ :param model_record_ids: {'model': {'res_id': (msg_id, msg_id)}, ... } + :param message_values: {'msg_id': {'model': .., 'res_id': .., 'author_id': ..}} + """ + model_record_ids = {} + for id in msg_ids: + if msg_val[id]['model'] and msg_val[id]['res_id']: + model_record_ids.setdefault(msg_val[id]['model'], dict()).setdefault(msg_val[id]['res_id'], set()).add(msg_val[id]['res_id']) + return model_record_ids + if uid == SUPERUSER_ID: return if isinstance(ids, (int, long)): ids = [ids] + not_obj = self.pool.get('mail.notification') + fol_obj = self.pool.get('mail.followers') partner_id = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=None)['partner_id'][0] # Read mail_message.ids to have their values message_values = dict.fromkeys(ids) - model_record_ids = {} - cr.execute('SELECT DISTINCT id, model, res_id, author_id FROM "%s" WHERE id = ANY (%%s)' % self._table, (ids,)) - for id, rmod, rid, author_id in cr.fetchall(): - message_values[id] = {'res_model': rmod, 'res_id': rid, 'author_id': author_id} - if rmod: - model_record_ids.setdefault(rmod, dict()).setdefault(rid, set()).add(id) - - # Author condition, for read and create (private message) -> could become an ir.rule, but not till we do not have a many2one variable field + cr.execute('SELECT DISTINCT id, model, res_id, author_id, parent_id FROM "%s" WHERE id = ANY (%%s)' % self._table, (ids,)) + for id, rmod, rid, author_id, parent_id in cr.fetchall(): + message_values[id] = {'model': rmod, 'res_id': rid, 'author_id': author_id, 'parent_id': parent_id} + + # Author condition (READ, WRITE, CREATE (private)) -> could become an ir.rule ? + author_ids = [] if operation == 'read' or operation == 'write': author_ids = [mid for mid, message in message_values.iteritems() if message.get('author_id') and message.get('author_id') == partner_id] 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 = [] + + # Parent condition, for create (check for received notifications for the created message parent) + notified_ids = [] + if operation == 'create': + parent_ids = [message.get('parent_id') for mid, message in message_values.iteritems() + if message.get('parent_id')] + not_ids = not_obj.search(cr, SUPERUSER_ID, [('message_id.id', 'in', parent_ids), ('partner_id', '=', partner_id)], context=context) + not_parent_ids = [notif.message_id.id for notif in not_obj.browse(cr, SUPERUSER_ID, not_ids, context=context)] + notified_ids += [mid for mid, message in message_values.iteritems() + if message.get('parent_id') in not_parent_ids] # Notification condition, for read (check for received notifications and create (in message_follower_ids)) -> could become an ir.rule, but not till we do not have a many2one variable field + other_ids = set(ids).difference(set(author_ids), set(notified_ids)) + model_record_ids = _generate_model_record_ids(message_values, other_ids) if operation == 'read': - not_obj = self.pool.get('mail.notification') not_ids = not_obj.search(cr, SUPERUSER_ID, [ ('partner_id', '=', partner_id), ('message_id', 'in', ids), ], context=context) notified_ids = [notification.message_id.id for notification in not_obj.browse(cr, SUPERUSER_ID, not_ids, context=context)] elif operation == 'create': - notified_ids = [] for doc_model, doc_dict in model_record_ids.items(): - fol_obj = self.pool.get('mail.followers') fol_ids = fol_obj.search(cr, SUPERUSER_ID, [ ('res_model', '=', doc_model), ('res_id', 'in', list(doc_dict.keys())), @@ -664,22 +682,15 @@ class mail_message(osv.Model): ], context=context) fol_mids = [follower.res_id for follower in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context)] notified_ids += [mid for mid, message in message_values.iteritems() - if message.get('res_model') == doc_model and message.get('res_id') in fol_mids] - else: - notified_ids = [] - - # Calculate remaining ids, and related model/res_ids - model_record_ids = {} - other_ids = set(ids).difference(set(author_ids), set(notified_ids)) - for id in other_ids: - if message_values[id]['res_model']: - model_record_ids.setdefault(message_values[id]['res_model'], set()).add(message_values[id]['res_id']) + if message.get('model') == doc_model and message.get('res_id') in fol_mids] # CRUD: Access rights related to the document + other_ids = other_ids.difference(set(notified_ids)) + model_record_ids = _generate_model_record_ids(message_values, other_ids) document_related_ids = [] - for model, mids in model_record_ids.items(): + for model, doc_dict in model_record_ids.items(): model_obj = self.pool.get(model) - mids = model_obj.exists(cr, uid, mids) + mids = model_obj.exists(cr, uid, doc_dict.keys()) if operation in ['create', 'write', 'unlink']: model_obj.check_access_rights(cr, uid, 'write') model_obj.check_access_rule(cr, uid, mids, 'write', context=context) @@ -687,10 +698,10 @@ class mail_message(osv.Model): model_obj.check_access_rights(cr, uid, operation) model_obj.check_access_rule(cr, uid, mids, operation, context=context) document_related_ids += [mid for mid, message in message_values.iteritems() - if message.get('res_model') == model and message.get('res_id') in mids] + if message.get('model') == model and message.get('res_id') in mids] # Calculate remaining ids: if not void, raise an error - other_ids = other_ids - set(document_related_ids) + other_ids = other_ids.difference(set(document_related_ids)) if not other_ids: return raise orm.except_orm(_('Access Denied'), diff --git a/addons/mail/tests/test_mail_message.py b/addons/mail/tests/test_mail_message.py index 3030d6d0d3e..39bb99007ee 100644 --- a/addons/mail/tests/test_mail_message.py +++ b/addons/mail/tests/test_mail_message.py @@ -123,7 +123,8 @@ class test_mail_access_rights(TestMailBase): user_bert_id, user_raoul_id = self.user_bert_id, self.user_raoul_id # Prepare groups: Pigs (employee), Jobs (public) - self.mail_group.message_post(cr, uid, self.group_pigs_id, body='Message') + pigs_msg_id = self.mail_group.message_post(cr, uid, self.group_pigs_id, body='Message') + priv_msg_id = self.mail_group.message_post(cr, uid, self.group_priv_id, body='Message') # prepare an attachment attachment_id = self.ir_attachment.create(cr, uid, {'datas': 'My attachment'.encode('base64'), 'name': 'doc.txt', 'datas_fname': 'doc.txt'}) @@ -184,11 +185,20 @@ class test_mail_access_rights(TestMailBase): # Do: Bert create a private message -> ko, no creation rights self.assertRaises(except_orm, self.mail_message.create, cr, user_bert_id, {'body': 'Test'}) + # Do: Raoul creates a message on Jobs -> ok, write access to the related document self.mail_message.create(cr, user_raoul_id, {'model': 'mail.group', 'res_id': self.group_jobs_id, 'body': 'Test'}) # Do: Raoul creates a message on Priv -> ko, no write access to the related document self.assertRaises(except_orm, self.mail_message.create, cr, user_raoul_id, {'model': 'mail.group', 'res_id': self.group_priv_id, 'body': 'Test'}) + # Do: Raoul creates a private message -> ok + self.mail_message.create(cr, user_raoul_id, {'body': 'Test'}) + # Do: Raoul creates a reply to a message on Priv -> ko + self.assertRaises(except_orm, self.mail_message.create, + cr, user_raoul_id, {'model': 'mail.group', 'res_id': self.group_priv_id, 'body': 'Test', 'parent_id': priv_msg_id}) + # Do: Raoul creates a reply to a message on Priv-> ok if has received parent + self.mail_notification.create(cr, uid, {'message_id': priv_msg_id, 'partner_id': self.partner_raoul_id}) + self.mail_message.create(cr, user_raoul_id, {'model': 'mail.group', 'res_id': self.group_priv_id, 'body': 'Test', 'parent_id': priv_msg_id}) def test_20_message_set_star(self): """ Tests for starring messages and its related access rights """ @@ -326,6 +336,11 @@ class test_mail_access_rights(TestMailBase): self.mail_group.message_post, cr, user_bert_id, self.group_jobs_id, body='I love Pigs') + # Do: Bert writes on its own profile, ko because no message create access + with self.assertRaises(except_orm): + self.res_users.message_post(cr, user_bert_id, user_bert_id, body='I love Bert') + self.res_partner.message_post(cr, user_bert_id, partner_bert_id, body='I love Bert') + # ---------------------------------------- # CASE2: Raoul, employee # ---------------------------------------- @@ -350,3 +365,11 @@ class test_mail_access_rights(TestMailBase): {'subject': 'Subject', 'body': 'Body text'}, {'default_composition_mode': 'reply', 'default_parent_id': pigs_msg_id}) mail_compose.send_mail(cr, user_raoul_id, [compose_id]) + + # Do: Raoul writes on its own profile, ok because follower of its partner + self.res_users.message_post(cr, user_raoul_id, user_raoul_id, body='I love Raoul') + self.res_partner.message_post(cr, user_raoul_id, partner_raoul_id, body='I love Raoul') + compose_id = mail_compose.create(cr, user_raoul_id, + {'subject': 'Subject', 'body': 'Body text', 'partner_ids': []}, + {'default_composition_mode': 'comment', 'default_model': 'res.users', 'default_res_id': self.user_raoul_id}) + mail_compose.send_mail(cr, user_raoul_id, [compose_id]) |
