From 15c934a1abfc72c965a6b46618b7b2ae6fad49cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Voet=20=28ryv=29?= <ryv@odoo.com> Date: Wed, 8 Jan 2020 10:09:20 +0000 Subject: [PATCH] [IMP] (website_)mail: improve routes and management of mail followers Purpose of this commit is to improve model of followers, notably management code and its use in routes. Indeed it is quite an old model and code had to be cleaned a bit to improve code readability and maintenance. In this commit we * remove unnecessary code examples in gamification about followers: using that model as example of code for goals is probably not a good idea as it is technical; * rewrite routes called by JS are simplified to better match JS implementation; * introduce computed fields to fetch related partner or channel name, email (partner only) and active status; LINKS Task 1933771 Task 2078313 closes odoo/odoo#39808 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com> Co-authored-by: Remy Voet <ryv@odoo.com> Co-authored-by: jgi-odoo <jgi@odoo.com> Co-authored-by: Xavier-Do <xdo@odoo.com> --- addons/gamification/data/goal_base.xml | 9 --- addons/gamification/views/goal.xml | 2 +- addons/mail/controllers/main.py | 57 ++++++++++------- addons/mail/models/mail_followers.py | 18 ++++++ addons/mail/models/mail_thread.py | 25 ++++---- addons/mail/security/ir.model.access.csv | 5 +- addons/mail/security/mail_security.xml | 10 --- addons/mail/static/src/js/followers.js | 35 +++++++---- addons/mail/static/src/xml/followers.xml | 10 +-- addons/mail/static/tests/chatter_tests.js | 69 +++++++++++---------- addons/test_mail/tests/test_mail_channel.py | 11 ++-- addons/website_mail/controllers/main.py | 18 +++--- 12 files changed, 148 insertions(+), 121 deletions(-) diff --git a/addons/gamification/data/goal_base.xml b/addons/gamification/data/goal_base.xml index af96a4806cf7..3289073cb132 100644 --- a/addons/gamification/data/goal_base.xml +++ b/addons/gamification/data/goal_base.xml @@ -280,15 +280,6 @@ Thank you, <field name="action_id" eval="ref('action_new_simplified_res_users')" /> </record> - <record model="gamification.goal.definition" id="definition_nbr_following"> - <field name="name">Mail Group Following</field> - <field name="description">Follow mail.channels to receive news</field> - <field name="computation_mode">python</field> - <field name="compute_code">result = env['mail.followers'].search_count([('res_model', '=', 'mail.channel'), ('partner_id', '=', object.user_id.partner_id.id)])</field> - <field name="action_id" eval="ref('mail.mail_channel_action_view')" /> - </record> - - <!-- challenges --> <record model="gamification.challenge" id="challenge_base_discover"> <field name="name">Complete your Profile</field> diff --git a/addons/gamification/views/goal.xml b/addons/gamification/views/goal.xml index 7301891f7052..1f43e81fc6ec 100644 --- a/addons/gamification/views/goal.xml +++ b/addons/gamification/views/goal.xml @@ -249,7 +249,7 @@ attrs="{'invisible':[('computation_mode','!=','sum')], 'required':[('computation_mode','=','sum')]}"/> <field name="field_date_id" class="oe_inline" attrs="{'invisible':[('computation_mode','not in',('sum', 'count'))]}"/> <field name="domain" attrs="{'invisible':[('computation_mode','not in',('sum', 'count'))], 'required':[('computation_mode','in',('sum', 'count'))]}" class="oe_inline"/> - <field name="compute_code" attrs="{'invisible':[('computation_mode','!=','python')], 'required':[('computation_mode','=','python')]}" placeholder="e.g. result = env['mail.followers'].search_count([('res_model', '=', 'mail.channel'), ('partner_id', '=', object.user_id.partner_id.id)])"/> + <field name="compute_code" attrs="{'invisible':[('computation_mode','!=','python')], 'required':[('computation_mode','=','python')]}"/> <field name="condition" widget="radio"/> </group> <group string="Optimisation" name="optimisation" attrs="{'invisible': [('computation_mode', '!=', 'count')]}"> diff --git a/addons/mail/controllers/main.py b/addons/mail/controllers/main.py index 2dbc9c09288f..b8a2387dbed0 100644 --- a/addons/mail/controllers/main.py +++ b/addons/mail/controllers/main.py @@ -141,55 +141,66 @@ class MailController(http.Controller): return True @http.route('/mail/read_followers', type='json', auth='user') - def read_followers(self, follower_ids, res_model): - followers = [] - # When editing the followers, the "pencil" icon that leads to the edition of subtypes - # should be always be displayed and not only when "debug" mode is activated. - is_editable = True - partner_id = request.env.user.partner_id - follower_id = None + def read_followers(self, follower_ids): + request.env['mail.followers'].check_access_rights("read") follower_recs = request.env['mail.followers'].sudo().browse(follower_ids) res_ids = follower_recs.mapped('res_id') + res_models = set(follower_recs.mapped('res_model')) + if len(res_models) > 1: + raise AccessError(_("Can't read followers with different targeted model")) + res_model = res_models.pop() + request.env[res_model].check_access_rights("read") request.env[res_model].browse(res_ids).check_access_rule("read") + + followers = [] + follower_id = None for follower in follower_recs: - is_uid = partner_id == follower.partner_id - follower_id = follower.id if is_uid else follower_id + if follower.partner_id == request.env.user.partner_id: + follower_id = follower.id followers.append({ 'id': follower.id, - 'name': follower.partner_id.name or follower.channel_id.name, - 'email': follower.partner_id.email if follower.partner_id else None, - 'res_model': 'res.partner' if follower.partner_id else 'mail.channel', - 'res_id': follower.partner_id.id or follower.channel_id.id, - 'is_editable': is_editable, - 'is_uid': is_uid, - 'active': follower.partner_id.active or bool(follower.channel_id), + 'partner_id': follower.partner_id.id, + 'channel_id': follower.channel_id.id, + 'name': follower.name, + 'email': follower.email, + 'is_active': follower.is_active, + # When editing the followers, the "pencil" icon that leads to the edition of subtypes + # should be always be displayed and not only when "debug" mode is activated. + 'is_editable': True }) return { 'followers': followers, - 'subtypes': self.read_subscription_data(res_model, follower_id) if follower_id else None + 'subtypes': self.read_subscription_data(follower_id) if follower_id else None } @http.route('/mail/read_subscription_data', type='json', auth='user') - def read_subscription_data(self, res_model, follower_id): + def read_subscription_data(self, follower_id): """ Computes: - message_subtype_data: data about document subtypes: which are available, which are followed if any """ - followers = request.env['mail.followers'].browse(follower_id) + request.env['mail.followers'].check_access_rights("read") + follower = request.env['mail.followers'].sudo().browse(follower_id) + follower.ensure_one() + request.env[follower.res_model].check_access_rights("read") + request.env[follower.res_model].browse(follower.res_id).check_access_rule("read") # find current model subtypes, add them to a dictionary - subtypes = request.env['mail.message.subtype'].search(['&', ('hidden', '=', False), '|', ('res_model', '=', res_model), ('res_model', '=', False)]) + subtypes = request.env['mail.message.subtype'].search([ + '&', ('hidden', '=', False), + '|', ('res_model', '=', follower.res_model), ('res_model', '=', False)]) + followed_subtypes_ids = set(follower.subtype_ids.ids) subtypes_list = [{ 'name': subtype.name, 'res_model': subtype.res_model, 'sequence': subtype.sequence, 'default': subtype.default, 'internal': subtype.internal, - 'followed': subtype.id in followers.mapped('subtype_ids').ids, + 'followed': subtype.id in followed_subtypes_ids, 'parent_model': subtype.parent_id.res_model, 'id': subtype.id } for subtype in subtypes] - subtypes_list = sorted(subtypes_list, key=lambda it: (it['parent_model'] or '', it['res_model'] or '', it['internal'], it['sequence'])) - return subtypes_list + return sorted(subtypes_list, + key=lambda it: (it['parent_model'] or '', it['res_model'] or '', it['internal'], it['sequence'])) @http.route('/mail/view', type='http', auth='public') def mail_action_view(self, model=None, res_id=None, access_token=None, **kwargs): diff --git a/addons/mail/models/mail_followers.py b/addons/mail/models/mail_followers.py index b9b3f53e8b94..2cd2d48b38d1 100644 --- a/addons/mail/models/mail_followers.py +++ b/addons/mail/models/mail_followers.py @@ -35,6 +35,12 @@ class Followers(models.Model): subtype_ids = fields.Many2many( 'mail.message.subtype', string='Subtype', help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall.") + name = fields.Char('Name', compute='_compute_related_fields', + help="Name of the related partner (if exist) or the related channel") + email = fields.Char('Email', compute='_compute_related_fields', + help="Email of the related partner (if exist) or False") + is_active = fields.Boolean('Is Active', compute='_compute_related_fields', + help="If the related partner is active (if exist) or if related channel exist") def _invalidate_documents(self, vals_list=None): """ Invalidate the cache of the documents followed by ``self``. @@ -75,6 +81,18 @@ class Followers(models.Model): # Private tools methods to fetch followers data # -------------------------------------------------- + @api.depends('partner_id', 'channel_id') + def _compute_related_fields(self): + for follower in self: + if follower.partner_id: + follower.name = follower.partner_id.name + follower.email = follower.partner_id.email + follower.is_active = follower.partner_id.active + else: + follower.name = follower.channel_id.name + follower.is_active = bool(follower.channel_id) + follower.email = False + def _get_recipient_data(self, records, message_type, subtype_id, pids=None, cids=None): """ Private method allowing to fetch recipients data based on a subtype. Purpose of this method is to fetch all data necessary to notify recipients diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 4672cd4d5697..c83d4ae8705d 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -82,13 +82,15 @@ class MailThread(models.AbstractModel): message_is_follower = fields.Boolean( 'Is Follower', compute='_compute_is_follower', search='_search_is_follower') message_follower_ids = fields.One2many( - 'mail.followers', 'res_id', string='Followers') + 'mail.followers', 'res_id', string='Followers', groups='base.group_user') message_partner_ids = fields.Many2many( comodel_name='res.partner', string='Followers (Partners)', - compute='_get_followers', search='_search_follower_partners') + compute='_get_followers', search='_search_follower_partners', + groups='base.group_user') message_channel_ids = fields.Many2many( comodel_name='mail.channel', string='Followers (Channels)', - compute='_get_followers', search='_search_follower_channels') + compute='_get_followers', search='_search_follower_channels', + groups='base.group_user') message_ids = fields.One2many( 'mail.message', 'res_id', string='Messages', domain=lambda self: [('message_type', '!=', 'user_notification')], auto_join=True) @@ -258,17 +260,16 @@ class MailThread(models.AbstractModel): if self._context.get('tracking_disable'): return super(MailThread, self).create(vals_list) + threads = super(MailThread, self).create(vals_list) # subscribe uid unless asked not to if not self._context.get('mail_create_nosubscribe'): - default_followers = self.env['mail.followers']._add_default_followers( - self._name, [], self.env.user.partner_id.ids, customer_ids=[], - check_existing=False, existing_policy='skip')[0][0] - for values in vals_list: - message_follower_ids = values.get('message_follower_ids') or [] - message_follower_ids += [(0, 0, fol_vals) for fol_vals in default_followers] - values['message_follower_ids'] = message_follower_ids - - threads = super(MailThread, self).create(vals_list) + for thread in threads: + self.env['mail.followers']._insert_followers( + thread._name, thread.ids, self.env.user.partner_id.ids, + None, None, None, + customer_ids=[], + check_existing=False + ) # auto_subscribe: take values and defaults into account create_values_list = {} diff --git a/addons/mail/security/ir.model.access.csv b/addons/mail/security/ir.model.access.csv index eb52637ff2e2..2f21338e9f4f 100644 --- a/addons/mail/security/ir.model.access.csv +++ b/addons/mail/security/ir.model.access.csv @@ -6,9 +6,8 @@ access_mail_mail_all,mail.mail.all,model_mail_mail,,0,0,0,0 access_mail_mail_portal,mail.mail.portal,model_mail_mail,base.group_portal,0,0,0,0 access_mail_mail_user,mail.mail.user,model_mail_mail,base.group_user,0,0,0,0 access_mail_mail_system,mail.mail.system,model_mail_mail,base.group_system,1,1,1,1 -access_mail_followers_all,mail.followers.all,model_mail_followers,,1,0,0,0 -access_mail_followers_portal,mail.followers.portal,model_mail_followers,base.group_portal,1,1,1,0 -access_mail_followers_user,mail.followers.user,model_mail_followers,base.group_user,1,1,1,0 +access_mail_followers_all,mail.followers.all,model_mail_followers,,0,0,0,0 +access_mail_followers_user,mail.followers.user,model_mail_followers,base.group_user,1,0,0,0 access_mail_followers_system,mail.followers.system,model_mail_followers,base.group_system,1,1,1,1 access_mail_notification_portal,mail.notification.portal,model_mail_notification,base.group_portal,1,0,0,0 access_mail_notification_user,mail.notification.user,model_mail_notification,base.group_user,1,1,1,0 diff --git a/addons/mail/security/mail_security.xml b/addons/mail/security/mail_security.xml index 3ffe43e35eb4..3a98e1bddb2b 100644 --- a/addons/mail/security/mail_security.xml +++ b/addons/mail/security/mail_security.xml @@ -14,16 +14,6 @@ </record> </data> <data noupdate="1"> - <record id="mail_followers_read_write_own" model="ir.rule"> - <field name="name">mail.followers: write its own entries</field> - <field name="model_id" ref="model_mail_followers"/> - <field name="groups" eval="[(4, ref('base.group_user')), (4, ref('base.group_portal'))]"/> - <field name="domain_force">[('partner_id', '=', user.partner_id.id)]</field> - <field name="perm_create" eval="False"/> - <field name="perm_unlink" eval="False"/> - <field name="perm_read" eval="False"/> - </record> - <record id="ir_rule_mail_notifications_group_user" model="ir.rule"> <field name="name">mail.notifications: group_user: write its own entries</field> <field name="model_id" ref="model_mail_notification"/> diff --git a/addons/mail/static/src/js/followers.js b/addons/mail/static/src/js/followers.js index cbe20ba240e9..7179b159663d 100644 --- a/addons/mail/static/src/js/followers.js +++ b/addons/mail/static/src/js/followers.js @@ -6,6 +6,7 @@ var concurrency = require('web.concurrency'); var core = require('web.core'); var Dialog = require('web.Dialog'); var field_registry = require('web.field_registry'); +var session = require('web.session'); var _t = core._t; var QWeb = core.qweb; @@ -43,7 +44,6 @@ var Followers = AbstractField.extend({ this.subtypes = []; this.data_subtype = {}; this._isFollower = undefined; - var session = this.getSession(); this.partnerID = session.partner_id; this.dp = new concurrency.DropPrevious(); @@ -113,14 +113,14 @@ var Followers = AbstractField.extend({ $(QWeb.render('mail.Followers.add_more', {widget: this})).appendTo($followers_list); var $follower_li; _.each(this.followers, function (record) { - if(!record.active) { + if (!record.is_active) { record.title = _.str.sprintf(_t('%s \n(inactive)'), record.name); } else { record.title = record.name; } $follower_li = $(QWeb.render('mail.Followers.partner', { - 'record': _.extend(record, {'avatar_url': '/web/image/' + record.res_model + '/' + record.res_id + '/image_128'}), + 'record': record, 'widget': self}) ); $follower_li.appendTo($followers_list); @@ -199,28 +199,37 @@ var Followers = AbstractField.extend({ return str; }, _readFollowers: function () { - var self = this; var missing_ids = _.difference(this.value.res_ids, _.pluck(this.followers, 'id')); var def; if (missing_ids.length) { def = this._rpc({ route: '/mail/read_followers', - params: { follower_ids: missing_ids, res_model: this.model, context: {} } // empty context to be overridden in session.js with 'allowed_company_ids' + params: { follower_ids: missing_ids, context: {} } // empty context to be overridden in session.js with 'allowed_company_ids' }); } - return Promise.resolve(def).then(function (results) { + return Promise.resolve(def).then((results) => { if (results) { - self.followers = _.uniq(results.followers.concat(self.followers), 'id'); + // Preprocess records + _.each(results.followers, (record) => { + var resModel = record.partner_id ? 'res.partner' : 'mail.channel'; + var resId = record.partner_id ? record.partner_id : record.channel_id; + record.res_id = resId; + record.res_model = resModel; + record.avatar_url = '/web/image/' + resModel + '/' + resId + '/image_128'; + }); + this.followers = _.uniq(results.followers.concat(this.followers), 'id'); if (results.subtypes) { //read_followers will return False if current user is not in the list - self.subtypes = results.subtypes; + this.subtypes = results.subtypes; } } // filter out previously fetched followers that are no longer following - self.followers = _.filter(self.followers, function (follower) { - return _.contains(self.value.res_ids, follower.id); + this.followers = _.filter(this.followers, (follower) => { + return _.contains(this.value.res_ids, follower.id); + }); + var userFollower = _.filter(this.followers, (rec) => { + return this.partnerID === rec.partner_id; }); - var user_follower = _.filter(self.followers, function (rec) { return rec.is_uid; }); - self._isFollower = user_follower.length >= 1; + this._isFollower = userFollower.length >= 1; }); }, _reload: function () { @@ -361,7 +370,7 @@ var Followers = AbstractField.extend({ var follower_id = $currentTarget.data('follower-id'); // id of model mail_follower this._rpc({ route: '/mail/read_subscription_data', - params: {res_model: this.model, follower_id: follower_id}, + params: {follower_id: follower_id}, }) .then(function (data) { var res_id = $currentTarget.data('oe-id'); // id of model res_partner or mail_channel diff --git a/addons/mail/static/src/xml/followers.xml b/addons/mail/static/src/xml/followers.xml index 8a0914737a2c..8789b424af2e 100644 --- a/addons/mail/static/src/xml/followers.xml +++ b/addons/mail/static/src/xml/followers.xml @@ -30,12 +30,12 @@ Partner or channel following the record --> <t t-name="mail.Followers.partner"> - <div role="menuitem" t-attf-class="dropdown-item o_partner {{ !record.active ? 'o_inactive': '' }}"> + <div role="menuitem" t-attf-class="dropdown-item o_partner {{ !record.is_active ? 'o_inactive': '' }}"> <a class="o_mail_redirect text-truncate" href="#" t-att-title="record.title" - t-att-data-oe-model="record.res_model" - t-att-data-oe-id="record.res_id"> + t-att-data-oe-model="record.partner_id ? 'res.partner' : 'mail.channel'" + t-att-data-oe-id="record.partner_id ? record.partner_id : record.channel_id"> <img t-att-src="record.avatar_url" alt="Avatar" class="o_image_64_cover"/> <t t-esc="record.name"/> </a> @@ -45,8 +45,8 @@ aria-label="Edit subscription" role="img" t-att-data-follower-id="record.id" - t-att-data-oe-id="record.res_id" - t-att-data-oe-model="record.res_model"/> + t-att-data-oe-id="record.partner_id ? record.partner_id : record.channel_id" + t-att-data-oe-model="record.partner_id ? 'res.partner' : 'mail.channel'"/> <button t-if="widget.isEditable" class="btn btn-icon fa fa-remove o_remove_follower" aria-label="Remove this follower" diff --git a/addons/mail/static/tests/chatter_tests.js b/addons/mail/static/tests/chatter_tests.js index bc1ff44b746d..f26dd096e62a 100644 --- a/addons/mail/static/tests/chatter_tests.js +++ b/addons/mail/static/tests/chatter_tests.js @@ -2490,11 +2490,11 @@ QUnit.test('followers widget: follow/unfollow, edit subtypes', async function (a this.data.partner.records[0].message_follower_ids = [1]; followers.push({ id: 1, - is_uid: true, name: "Admin", email: "admin@example.com", - res_id: resID, - res_model: 'partner', + partner_id: partnerID, + channel_id: null, + is_active: true }); } return Promise.resolve(true); @@ -2558,18 +2558,18 @@ QUnit.test('followers widget: follow/unfollow confirmation dialog', async functi var partnerID = 2; var followers = [{ id: 1, - is_uid: true, name: "Admin", email: "admin@example.com", - res_id: resID, - res_model: 'res.partner', + partner_id: partnerID, + channel_id: null, + is_active: true }, { id: 2, - is_uid: true, name: "Demo", email: "demo@example.com", - res_id: 3, - res_model: 'res.partner', + partner_id: 1, + channel_id: null, + is_active: true }]; var form = await createView({ @@ -2624,12 +2624,14 @@ QUnit.test('followers widget: do not display follower duplications', async funct this.data.partner.records[0].message_follower_ids = [1]; var resID = 2; + var partnerID = 1; var followers = [{ id: 1, name: "Admin", email: "admin@example.com", - res_id: resID, - res_model: 'partner', + partner_id: partnerID, + channel_id: null, + is_active: true }]; var def; var form = await createView({ @@ -2657,17 +2659,18 @@ QUnit.test('followers widget: do not display follower duplications', async funct return this._super.apply(this, arguments); }, res_id: resID, - session: {partner_id: 1}, + session: {partner_id: partnerID}, }); followers.push({ id: 2, - is_uid: false, name: "A follower", email: "follower@example.com", res_id: resID, - res_model: 'partner', + partner_id: 555, + channel_id: null, + is_active: true }); this.data.partner.records[0].message_follower_ids.push(2); @@ -2695,23 +2698,23 @@ QUnit.test('followers widget: display inactive followers with a different style' id: 1, name: "Admin", email: "admin@example.com", - res_id: 101, - res_model: 'partner', - active: true, + partner_id: 101, + channel_id: false, + is_active: true, },{ id: 2, name: "Active_partner", email: "active_partner@example.com", - res_id: 102, - res_model: 'partner', - active: true, + partner_id: 102, + channel_id: false, + is_active: true, },{ id: 3, name: "Inactive_partner", email: "inactive_partner@example.com", - res_id: 103, - res_model: 'partner', - active: false, + partner_id: 103, + channel_id: false, + is_active: false, }]; var form = await createView({ @@ -3002,11 +3005,9 @@ QUnit.test('chatter: suggested partner auto-follow on message post', async funct var followers = []; followers.push({ id: 1, - is_uid: true, name: "Admin", email: "admin@example.com", - res_id: 5, - res_model: 'partner', + partner_id: 5, }); var form = await createView({ @@ -3045,11 +3046,11 @@ QUnit.test('chatter: suggested partner auto-follow on message post', async funct self.data.partner.records[0].message_follower_ids.push(2); followers.push({ id: 2, - is_uid: true, name: "Demo User", email: "demo-user@example.com", - res_id: 8, - res_model: 'partner', + partner_id: 8, + channel_id: false, + is_active: true }); // post a legit message so that it does not crashes @@ -3187,14 +3188,16 @@ QUnit.test('chatter: mention prefetched partners (followers & employees)', async id: 10, name: 'FollowerUser1', email: 'follower-user1@example.com', - res_model: 'res.partner', - res_id: 1, + partner_id: 1, + channel_id: null, + is_active: true }, { id: 20, name: 'FollowerUser2', email: 'follower-user2@example.com', - res_model: 'res.partner', - res_id: 2, + partner_id: 2, + channel_id: null, + is_active: true, }], subtypes: [], }); diff --git a/addons/test_mail/tests/test_mail_channel.py b/addons/test_mail/tests/test_mail_channel.py index 8869ac214422..2e3c7c2cb4b8 100644 --- a/addons/test_mail/tests/test_mail_channel.py +++ b/addons/test_mail/tests/test_mail_channel.py @@ -99,13 +99,16 @@ class TestChannelAccessRights(TestMailCommon): trigger_read = chell_pigs.name for message in chell_pigs.message_ids: trigger_read = message.subject - for partner in chell_pigs.message_partner_ids: + + with self.assertRaises(AccessError): + chell_pigs.message_partner_ids + + for partner in self.group_private.message_partner_ids: if partner.id == self.user_portal.partner_id.id: # Chell can read her own partner record continue - # TODO Change the except_orm to Warning - with self.assertRaises(except_orm): - trigger_read = partner.name + with self.assertRaises(AccessError): + trigger_read = partner.with_user(self.user_portal).name class TestChannelFeatures(TestMailCommon): diff --git a/addons/website_mail/controllers/main.py b/addons/website_mail/controllers/main.py index 6d00c0641497..822373eb4d6e 100644 --- a/addons/website_mail/controllers/main.py +++ b/addons/website_mail/controllers/main.py @@ -11,7 +11,12 @@ class WebsiteMail(http.Controller): # TDE FIXME: check this method with new followers res_id = int(id) is_follower = message_is_follower == 'on' - record = request.env[object].browse(res_id) + record = request.env[object].browse(res_id).exists() + if not record: + return False + + record.check_access_rights('read') + record.check_access_rule('read') # search partner_id if request.env.user != request.website.user_id: @@ -24,11 +29,9 @@ class WebsiteMail(http.Controller): partner_ids = request.env['res.partner'].sudo().create({'name': name, 'email': email}).ids # add or remove follower if is_follower: - record.check_access_rule('read') record.sudo().message_unsubscribe(partner_ids) return False else: - record.check_access_rule('read') # add partner to session request.session['partner_id'] = partner_ids[0] record.sudo().message_subscribe(partner_ids) @@ -48,14 +51,13 @@ class WebsiteMail(http.Controller): 'is_user': user != public_user, 'email': partner.email if partner else "", 'is_follower': False, - 'alias_name': False, } - record = request.env[model].sudo().browse(int(res_id)) - if record and partner: - values['is_follower'] = bool(request.env['mail.followers'].search_count([ + record_sudo = request.env[model].sudo().browse(int(res_id)) + if partner and record_sudo.exists(): + values['is_follower'] = bool(request.env['mail.followers'].sudo().search_count([ ('res_model', '=', model), - ('res_id', '=', record.id), + ('res_id', '=', record_sudo.id), ('partner_id', '=', partner.id) ])) return values -- GitLab