diff --git a/message_security_author/README.rst b/message_security_author/README.rst new file mode 100644 index 00000000..1c94c108 --- /dev/null +++ b/message_security_author/README.rst @@ -0,0 +1,69 @@ +.. image:: https://img.shields.io/badge/license-LGPL--3-blue.png + :target: https://www.gnu.org/licenses/lgpl + :alt: License: LGPL-3 + +======================= +Message Security Author +======================= + +Some modules like `mail_tracking` give the users the possibility to access to +the messages by indirect ways. Odoo have not yet regulated what the users can +do to messages because by default in Odoo no users can access to them. + +Thus, this `message_security_author` module enters in scene. + +This module restricts who can edit/delete messages. Specifically, a message +may be edited or deleted if and only if: + +- The user is who created the message previously. +- The user have special permission (is in the group `Mail Message Manager`) + +Installation +============ + +To install this module, simply follow the standard install process. + +Usage +===== + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/205/11.0 + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smash it by providing detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Miquel Raïch + +Do not contact contributors directly about support or help with technical issues. + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/message_security_author/__init__.py b/message_security_author/__init__.py new file mode 100644 index 00000000..7d768b54 --- /dev/null +++ b/message_security_author/__init__.py @@ -0,0 +1,3 @@ +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from . import models diff --git a/message_security_author/__manifest__.py b/message_security_author/__manifest__.py new file mode 100644 index 00000000..49a79f83 --- /dev/null +++ b/message_security_author/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2019 Eficent Business and IT Consulting Services, S.L. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +{ + "name": "Message Security Author", + "summary": "The edition/deletion of messages is restricted", + "version": "11.0.1.0.0", + "category": "Social Network", + "website": "http://github.com/OCA/social", + "author": "Eficent, " + "Odoo Community Association (OCA)", + "license": "LGPL-3", + "application": False, + 'installable': True, + "depends": [ + "mail", + ], + "data": [ + "security/security.xml", + ], + 'maintainers': ['mreficent'], +} diff --git a/message_security_author/models/__init__.py b/message_security_author/models/__init__.py new file mode 100644 index 00000000..4ae6f401 --- /dev/null +++ b/message_security_author/models/__init__.py @@ -0,0 +1,4 @@ +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from . import mail_message +from . import mail_thread diff --git a/message_security_author/models/mail_message.py b/message_security_author/models/mail_message.py new file mode 100644 index 00000000..1877cb86 --- /dev/null +++ b/message_security_author/models/mail_message.py @@ -0,0 +1,45 @@ +# Copyright 2019 Eficent Business and IT Consulting Services, S.L. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo import api, models, _ +from odoo.exceptions import AccessError + + +class Message(models.Model): + _inherit = 'mail.message' + + @api.multi + def write(self, vals): + user = self.env.user + if self._uid == 1: + rec = super(Message, self).write(vals=vals) + elif self._name != 'mail.message': + rec = super(Message, self).write(vals=vals) + elif user.has_group( + 'message_security_author.group_mail_message_manager'): + rec = super(Message, self).write(vals=vals) + elif not self.filtered(lambda m: user not in m.author_id.user_ids): + rec = super(Message, self).write(vals=vals) + else: + raise AccessError( + _("Sorry, you are not allowed to modify this document.")) + return rec + + @api.multi + def unlink(self): + user = self.env.user + if self._uid == 1: + rec = super(Message, self).unlink() + elif self._name != 'mail.message': + rec = super(Message, self).unlink() + elif self._context.get('deleting_mail_thread'): + rec = super(Message, self).unlink() + elif user.has_group( + 'message_security_author.group_mail_message_manager'): + rec = super(Message, self).unlink() + elif not self.filtered(lambda m: user not in m.author_id.user_ids): + rec = super(Message, self).unlink() + else: + raise AccessError( + _("Sorry, you are not allowed to delete this document.")) + return rec diff --git a/message_security_author/models/mail_thread.py b/message_security_author/models/mail_thread.py new file mode 100644 index 00000000..7905eeab --- /dev/null +++ b/message_security_author/models/mail_thread.py @@ -0,0 +1,13 @@ +# Copyright 2019 Eficent Business and IT Consulting Services, S.L. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo import api, models + + +class MailThread(models.AbstractModel): + _inherit = 'mail.thread' + + @api.multi + def unlink(self): + return super(MailThread, self.with_context( + deleting_mail_thread=True)).unlink() diff --git a/message_security_author/readme/CONTRIBUTORS.rst b/message_security_author/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..2e34e218 --- /dev/null +++ b/message_security_author/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Miquel Raïch diff --git a/message_security_author/readme/DESCRIPTION.rst b/message_security_author/readme/DESCRIPTION.rst new file mode 100644 index 00000000..be9d9f03 --- /dev/null +++ b/message_security_author/readme/DESCRIPTION.rst @@ -0,0 +1,11 @@ +Some modules like `mail_tracking` give the users the possibility to access to +the messages by indirect ways. Odoo have not yet regulated what the users can +do to messages because by default in Odoo no users can access to them. + +Thus, this `message_security_author` module enters in scene. + +This module restricts who can edit/delete messages. Specifically, a message +may be edited or deleted if and only if: + +- The user is who created the message previously. +- The user have special permission (is in the group `Mail Message Manager`) diff --git a/message_security_author/readme/INSTALL.rst b/message_security_author/readme/INSTALL.rst new file mode 100644 index 00000000..af1f3229 --- /dev/null +++ b/message_security_author/readme/INSTALL.rst @@ -0,0 +1 @@ +To install this module, simply follow the standard install process. diff --git a/message_security_author/security/security.xml b/message_security_author/security/security.xml new file mode 100644 index 00000000..ff0cdcb8 --- /dev/null +++ b/message_security_author/security/security.xml @@ -0,0 +1,11 @@ + + + + + + Mail Message Manager + + + + diff --git a/message_security_author/static/description/icon.png b/message_security_author/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/message_security_author/static/description/icon.png differ diff --git a/message_security_author/tests/__init__.py b/message_security_author/tests/__init__.py new file mode 100644 index 00000000..390eaff4 --- /dev/null +++ b/message_security_author/tests/__init__.py @@ -0,0 +1,3 @@ +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from . import test_message_security_author diff --git a/message_security_author/tests/test_message_security_author.py b/message_security_author/tests/test_message_security_author.py new file mode 100644 index 00000000..f09bd005 --- /dev/null +++ b/message_security_author/tests/test_message_security_author.py @@ -0,0 +1,97 @@ +# Copyright 2019 Eficent Business and IT Consulting Services, S.L. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo.tests.common import TransactionCase +from odoo.exceptions import AccessError + + +class TestMessageSecurityAuthor(TransactionCase): + + def setUp(self): + super(TestMessageSecurityAuthor, self).setUp() + self.partner_obj = self.env['res.partner'] + self.user_obj = self.env['res.users'] + self.message_obj = self.env['mail.message'] + employee_group = self.env.ref('base.group_user') + partner_manager_group = self.env.ref('base.group_partner_manager') + message_manager_group = self.env.ref( + 'message_security_author.group_mail_message_manager') + + self.user1 = self.user_obj.with_context( + no_reset_password=True).create({ + 'name': 'user 1', + 'login': 'test_user_1', + 'email': 'user1@example.com', + 'groups_id': [(6, 0, [ + employee_group.id, partner_manager_group.id, + message_manager_group.id, + ])], + }) + self.user2 = self.user_obj.with_context( + no_reset_password=True).create({ + 'name': 'user2', + 'login': 'test_user_2', + 'email': 'user2@example.com', + 'groups_id': [(6, 0, [ + employee_group.id, partner_manager_group.id, + ])], + }) + + self.partner = self.partner_obj.create({ + 'name': 'Ugly contact', + }) + + self.partner.sudo(self.user1).with_context( + mail_notrack=True).message_post( + body='I think you are ugly', + subtype='mail.mt_comment', + message_type='comment', + ) + + self.message_user_1 = self.message_obj.search( + [('body', '=', 'I think you are ugly'), + ('model', '=', 'res.partner'), + ('res_id', '=', self.partner.id)], limit=1) + + self.partner.sudo(self.user2).with_context( + mail_notrack=True).message_post( + body='Me too haha', + subtype='mail.mt_comment', + message_type='comment', + ) + + self.message_user_2 = self.message_obj.search( + [('body', '=', 'Me too haha'), ('model', '=', 'res.partner'), + ('res_id', '=', self.partner.id)], limit=1) + + def test_user1_manipulate_message(self): + self.message_user_1.sudo(self.user1).write({'body': 'sorry'}) + self.assertIn('sorry', self.message_user_1.body) + self.message_user_2.sudo(self.user1).write({'body': 'wtf'}) + self.assertIn('wtf', self.message_user_2.body) + self.message_user_1.sudo(self.user1).unlink() + self.assertFalse(self.message_user_1.exists().id) + self.message_user_2.sudo(self.user1).unlink() + self.assertFalse(self.message_user_2.exists().id) + self.assertTrue(self.partner.exists().id) + + def test_user1_delete_partner(self): + self.partner.sudo(self.user1).unlink() + self.assertFalse(self.message_user_1.exists().id) + self.assertFalse(self.message_user_2.exists().id) + + def test_user2_manipulate_message(self): + with self.assertRaises(AccessError): + self.message_user_1.sudo(self.user2).write({'body': 'sorry'}) + self.message_user_2.sudo(self.user2).write({'body': 'wtf'}) + self.assertIn('wtf', self.message_user_2.body) + with self.assertRaises(AccessError): + self.message_user_1.sudo(self.user2).unlink() + self.message_user_2.sudo(self.user2).unlink() + self.assertFalse(self.message_user_2.exists().id) + self.assertTrue(self.partner.exists().id) + + def test_user2_delete_partner(self): + self.partner.sudo(self.user2).unlink() + self.assertFalse(self.message_user_1.exists().id) + self.assertFalse(self.message_user_2.exists().id)