From 1e2b70012a690d7c4536cecfb45edd9282774aca Mon Sep 17 00:00:00 2001 From: Radhika Shyara Date: Mon, 30 May 2022 06:20:17 +0000 Subject: [PATCH] [FIX] mail: check if the user can access to the thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this commit, when the user creates a private task and assign another user to that task and then removes himself and save the task, the current user should no longer access to that task since the task becomes this private task of the other user assigned on it. So when the current user changes anything in that task, it will have a `Access Error`. However if the user tries to remove a follower on that task he will also have a traceback because no thread is found. The reason why no thread is found is because the user has no longer access to the record and so he has no longer access to the chatter. This commit checks if a thread is found before continuing the process. If no thread is found then the user has no access to the chatter instead of throwing a traceback because no thread is found. task-2857229 closes odoo/odoo#94665 X-original-commit: 2c68e397b3c12657024e70016808183c89260168 Signed-off-by: Sébastien Theys (seb) Co-authored-by: Prakash Prajapati --- addons/mail/models/mail_thread.py | 6 +++++- addons/mail/static/src/models/chatter.js | 2 +- addons/mail/static/src/models/thread.js | 7 ++++++- addons/mail/static/tests/helpers/mock_server.js | 3 ++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index f732c314ef2..49cd4487ed7 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -3148,8 +3148,12 @@ class MailThread(models.AbstractModel): return self.env['ir.attachment'].search([('res_id', '=', self.id), ('res_model', '=', self._name)], order='id desc') def _get_mail_thread_data(self, request_list): + res = {'hasWriteAccess': False, 'hasReadAccess': True} + if not self: + res['hasReadAccess'] = False + return res + self.ensure_one() - res = {'hasWriteAccess': False} try: self.check_access_rights("write") self.check_access_rule("write") diff --git a/addons/mail/static/src/models/chatter.js b/addons/mail/static/src/models/chatter.js index 75e2d28d1a7..cf6a33b4970 100644 --- a/addons/mail/static/src/models/chatter.js +++ b/addons/mail/static/src/models/chatter.js @@ -237,7 +237,7 @@ registerModel({ * @returns {boolean} */ _computeIsDisabled() { - return Boolean(!this.thread || this.thread.isTemporary); + return Boolean(!this.thread || this.thread.isTemporary || !this.thread.hasReadAccess); }, /** * @private diff --git a/addons/mail/static/src/models/thread.js b/addons/mail/static/src/models/thread.js index 4169aaaac95..0c979d1f844 100644 --- a/addons/mail/static/src/models/thread.js +++ b/addons/mail/static/src/models/thread.js @@ -526,6 +526,7 @@ registerModel({ followers: followersData, hasWriteAccess, mainAttachment, + hasReadAccess, suggestedRecipients: suggestedRecipientsData, } = await this.messaging.rpc({ route: '/mail/thread/data', @@ -538,7 +539,7 @@ registerModel({ if (!this.exists()) { return; } - const values = { hasWriteAccess, mainAttachment }; + const values = { hasWriteAccess, mainAttachment, hasReadAccess }; if (activitiesData) { Object.assign(values, { activities: insertAndReplace(activitiesData.map(activityData => @@ -1873,6 +1874,10 @@ registerModel({ guestMembers: many('Guest', { sort: '_sortGuestMembers', }), + /** + * States whether the current user has read access for this thread. + */ + hasReadAccess: attr(), /** * States whether `this` has activities (`mail.activity.mixin` server side). */ diff --git a/addons/mail/static/tests/helpers/mock_server.js b/addons/mail/static/tests/helpers/mock_server.js index 2bef3499a3b..17e4c374b74 100644 --- a/addons/mail/static/tests/helpers/mock_server.js +++ b/addons/mail/static/tests/helpers/mock_server.js @@ -512,10 +512,11 @@ patch(MockServer.prototype, 'mail', { async _mockRouteMailThreadData(thread_model, thread_id, request_list) { const res = { 'hasWriteAccess': true, // mimic user with write access by default + 'hasReadAccess': true, }; const thread = this.pyEnv[thread_model].searchRead([['id', '=', thread_id]])[0]; if (!thread) { - console.warn(`mock server: reading data "${request_list}" from invalid thread "${thread_model}_${thread_id}"`); + res['hasReadAccess'] = false; return res; } if (request_list.includes('activities')) {