Browse Source

Prevent to send web notifications to other users

Only the admin user (sudo) is allowed to send notifications to other
users. The normal users can only send notifications to themselves.

This is to prevent attackers to craft malicious notifications and send
them to other users using RPC.

Correction based on the idea of @hbrunn
pull/1073/head
Guewen Baconnier 6 years ago
parent
commit
7924072514
  1. 7
      web_notify/models/res_users.py
  2. 11
      web_notify/tests/test_res_users.py

7
web_notify/models/res_users.py

@ -3,7 +3,7 @@
# Copyright 2018 Camptocamp # Copyright 2018 Camptocamp
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models, _
from odoo import api, exceptions, fields, models, _, SUPERUSER_ID
from odoo.addons.web.controllers.main import clean_action from odoo.addons.web.controllers.main import clean_action
@ -48,6 +48,11 @@ class ResUsers(models.Model):
@api.multi @api.multi
def _notify_channel(self, channel_name_field, message, title, **options): def _notify_channel(self, channel_name_field, message, title, **options):
if (self.env.uid != SUPERUSER_ID
and any(user.id != self.env.uid for user in self)):
raise exceptions.UserError(
_('Sending a notification to another user is forbidden.')
)
if options.get('action'): if options.get('action'):
options['action'] = clean_action(options['action']) options['action'] = clean_action(options['action'])
bus_message = { bus_message = {

11
web_notify/tests/test_res_users.py

@ -3,6 +3,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import json import json
from odoo import exceptions
from odoo.tests import common from odoo.tests import common
from odoo.addons.bus.models.bus import json_dump from odoo.addons.bus.models.bus import json_dump
import mock import mock
@ -100,3 +101,13 @@ class TestResUsers(common.TransactionCase):
first_pos_call_args = pos_call_args[0] first_pos_call_args = pos_call_args[0]
self.assertIsInstance(first_pos_call_args, list) self.assertIsInstance(first_pos_call_args, list)
self.assertEqual(len(users), len(first_pos_call_args)) self.assertEqual(len(users), len(first_pos_call_args))
def test_notify_other_user(self):
other_user = self.env.ref('base.user_demo')
other_user_model = self.env['res.users'].sudo(other_user)
with self.assertRaises(exceptions.UserError):
other_user_model.browse(self.env.uid).notify_info('hello')
def test_notify_admin_allowed_other_user(self):
other_user = self.env.ref('base.user_demo')
other_user.notify_info('hello')
Loading…
Cancel
Save