From bb0404ea30af6aefc40d9ea92801dcf314bcb9f9 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 21 Sep 2017 23:42:45 +0200 Subject: [PATCH] [IMP] website_mail: simplify helpers for external post After removing the `sha_in` params a while ago, we get rid of the deprecated `token_field` option. - Make `token_field` a model attribute, so that each model can easily define the token field that should be used, and it does not need to be passed around all the time anymore. - Rename `_special_access_object()` to `_has_token_access()`, much more readable since it returns a bool - Do not forward the `attachment_ids` keyword arg to message_post, as it sometimes contains unrelated IDs (the helper is not meant to post attachments anyway) - Update callers accordingly --- addons/portal/controllers/mail.py | 17 ++++++++--------- addons/portal/models/mail_thread.py | 2 ++ addons/portal/static/src/js/portal_chatter.js | 10 ++++------ addons/portal/static/src/xml/portal_chatter.xml | 1 - addons/portal/views/portal_templates.xml | 3 +-- addons/sale/controllers/portal.py | 2 +- addons/website_quote/controllers/main.py | 4 ++-- .../views/website_quote_templates.xml | 1 - 8 files changed, 18 insertions(+), 22 deletions(-) diff --git a/addons/portal/controllers/mail.py b/addons/portal/controllers/mail.py index 4ee2414548a..3a59ecd70b3 100644 --- a/addons/portal/controllers/mail.py +++ b/addons/portal/controllers/mail.py @@ -8,13 +8,12 @@ from odoo.http import request from odoo.tools import consteq -def _special_access_object(res_model, res_id, token='', token_field=''): +def _has_token_access(res_model, res_id, token=''): record = request.env[res_model].browse(res_id).sudo() - if token and record and getattr(record, token_field, None) and consteq(getattr(record, token_field), token): - return True - return False + token_field = request.env[res_model]._mail_post_token_field + return (token and record and consteq(record[token_field], token)) -def _message_post_helper(res_model='', res_id=None, message='', token='', token_field='token', nosubscribe=True, **kw): +def _message_post_helper(res_model='', res_id=None, message='', token='', nosubscribe=True, **kw): """ Generic chatter function, allowing to write on *any* object that inherits mail.thread. If a token is specified, all logged in users will be able to write a message regardless of access rights; if the user is the public user, the message will be posted under the name @@ -27,15 +26,14 @@ def _message_post_helper(res_model='', res_id=None, message='', token='', token_ optional keywords arguments: :param string token: access token if the object's model uses some kind of public access using tokens (usually a uuid4) to bypass access rules - :param string token_field: name of the field that contains the token on the object (defaults to 'token') :param bool nosubscribe: set False if you want the partner to be set as follower of the object when posting (default to True) The rest of the kwargs are passed on to message_post() """ record = request.env[res_model].browse(res_id) author_id = request.env.user.partner_id.id if request.env.user.partner_id else False - if token_field and token: - access_as_sudo = _special_access_object(res_model, res_id, token=token, token_field=token_field) + if token: + access_as_sudo = _has_token_access(res_model, res_id, token=token) if access_as_sudo: record = record.sudo() if request.env.user == request.env.ref('base.public_user'): @@ -46,6 +44,7 @@ def _message_post_helper(res_model='', res_id=None, message='', token='', token_ else: raise Forbidden() kw.pop('csrf_token', None) + kw.pop('attachment_ids', None) return record.with_context(mail_create_nosubscribe=nosubscribe).message_post(body=message, message_type=kw.pop('message_type', "comment"), subtype=kw.pop('subtype', "mt_comment"), @@ -93,7 +92,7 @@ class PortalChatter(http.Controller): # Check access Message = request.env['mail.message'] if kw.get('token'): - access_as_sudo = _special_access_object(res_model, res_id, token=kw.get('token'), token_field=kw.get('token_field')) + access_as_sudo = _has_token_access(res_model, res_id, token=kw.get('token')) if not access_as_sudo: # if token is not correct, raise Forbidden raise Forbidden() Message = request.env['mail.message'].sudo() diff --git a/addons/portal/models/mail_thread.py b/addons/portal/models/mail_thread.py index 08cd54aa301..947839bc093 100644 --- a/addons/portal/models/mail_thread.py +++ b/addons/portal/models/mail_thread.py @@ -7,6 +7,8 @@ from odoo import api, fields, models class MailThread(models.AbstractModel): _inherit = 'mail.thread' + _mail_post_token_field = 'access_token' # token field for external posts, to be overridden + website_message_ids = fields.One2many('mail.message', 'res_id', string='Website Messages', domain=lambda self: [('model', '=', self._name), ('message_type', '=', 'comment')], auto_join=True, help="Website communication history") diff --git a/addons/portal/static/src/js/portal_chatter.js b/addons/portal/static/src/js/portal_chatter.js index 8e9868ad825..6e1dfdafb1f 100644 --- a/addons/portal/static/src/js/portal_chatter.js +++ b/addons/portal/static/src/js/portal_chatter.js @@ -135,12 +135,10 @@ var PortalChatter = Widget.extend({ 'offset': (this._current_page-1) * this.options['pager_step'], 'allow_composer': this.options['allow_composer'], }; - // add fields to allow to post comment without being logged - _.each(['token', 'token_field'], function(field){ - if(self.options[field]){ - data[field] = self.options[field]; - } - }); + // add token field to allow to post comment without being logged + if(self.options['token']){ + data['token'] = self.options['token']; + } // add domain if(this.get('domain')){ data['domain'] = this.get('domain'); diff --git a/addons/portal/static/src/xml/portal_chatter.xml b/addons/portal/static/src/xml/portal_chatter.xml index c4cfca119e0..71a7088c3cc 100644 --- a/addons/portal/static/src/xml/portal_chatter.xml +++ b/addons/portal/static/src/xml/portal_chatter.xml @@ -35,7 +35,6 @@ - diff --git a/addons/portal/views/portal_templates.xml b/addons/portal/views/portal_templates.xml index ce5ca4c2951..80b864183fd 100644 --- a/addons/portal/views/portal_templates.xml +++ b/addons/portal/views/portal_templates.xml @@ -346,11 +346,10 @@ :token string (optional): if you want your chatter to be available for non-logged user, you can use a token to verify the identity of the user; the message will be posted with the identity of the partner_id of the object - :token_field string (optional): name of the field that contains the token on the object (default to 'token') --> diff --git a/addons/sale/controllers/portal.py b/addons/sale/controllers/portal.py index baf3078d87a..01fa9c04121 100644 --- a/addons/sale/controllers/portal.py +++ b/addons/sale/controllers/portal.py @@ -221,7 +221,7 @@ class CustomerPortal(CustomerPortal): res_id=order_sudo.id, message=_('Order signed by %s') % (partner_name,), attachments=[('signature.png', base64.b64decode(signature))] if signature else [], - **({'token': access_token, 'token_field': 'access_token'} if access_token else {})) + **({'token': access_token} if access_token else {})) return { 'success': _('Your Order has been confirmed.'), 'redirect_url': '/my/orders/%s?%s' % (order_sudo.id, access_token and 'access_token=%s' % order_sudo.access_token or ''), diff --git a/addons/website_quote/controllers/main.py b/addons/website_quote/controllers/main.py index f34a8298160..d29c34180df 100644 --- a/addons/website_quote/controllers/main.py +++ b/addons/website_quote/controllers/main.py @@ -55,7 +55,7 @@ class sale_quote(http.Controller): if Order and request.session.get('view_quote') != now and request.env.user.share: request.session['view_quote'] = now body = _('Quotation viewed by customer') - _message_post_helper(res_model='sale.order', res_id=Order.id, message=body, token=token, token_field="access_token", message_type='notification', subtype="mail.mt_note", partner_ids=Order.user_id.sudo().partner_id.ids) + _message_post_helper(res_model='sale.order', res_id=Order.id, message=body, token=token, message_type='notification', subtype="mail.mt_note", partner_ids=Order.user_id.sudo().partner_id.ids) if not Order: return request.render('website.404') @@ -124,7 +124,7 @@ class sale_quote(http.Controller): Order.action_cancel() message = post.get('decline_message') if message: - _message_post_helper(message=message, res_id=order_id, res_model='sale.order', **{'token': token, 'token_field': 'access_token'} if token else {}) + _message_post_helper(message=message, res_id=order_id, res_model='sale.order', **{'token': token} if token else {}) return werkzeug.utils.redirect("/quote/%s/%s?message=2" % (order_id, token)) @http.route(['/quote/update_line'], type='json', auth="public", website=True) diff --git a/addons/website_quote/views/website_quote_templates.xml b/addons/website_quote/views/website_quote_templates.xml index c27bbf4fcd1..e231caea6c0 100644 --- a/addons/website_quote/views/website_quote_templates.xml +++ b/addons/website_quote/views/website_quote_templates.xml @@ -397,7 +397,6 @@ -