[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
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
<input type='hidden' name="token" t-att-value="widget.options['token']" t-if="widget.options['token']"/>
|
||||
<input type='hidden' name="sha_in" t-att-value="widget.options['sha_in']" t-if="widget.options['sha_in']"/>
|
||||
<input type='hidden' name="sha_time" t-att-value="widget.options['sha_time']" t-if="widget.options['sha_time']"/>
|
||||
<input type='hidden' name="token_field" t-att-value="widget.options['token_field']" t-if="widget.options['token_field']"/>
|
||||
<div class="alert alert-danger mt8 mb0 o_portal_chatter_composer_error" style="display:none;">
|
||||
Oops! Something went wrong. Try to reload the page and log in.
|
||||
</div>
|
||||
|
||||
@@ -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')
|
||||
-->
|
||||
<template id="message_thread">
|
||||
<div id="discussion" class="hidden-print o_portal_chatter"
|
||||
t-att-data-token="token" t-att-data-res_model="object._name" t-att-data-res_id="object.id" t-att-data-token_field="token_field" t-att-data-pager_step="message_per_page or 10" t-att-data-allow_composer="'0' if disable_composer else '1'">
|
||||
t-att-data-token="token" t-att-data-res_model="object._name" t-att-data-res_id="object.id" t-att-data-pager_step="message_per_page or 10" t-att-data-allow_composer="'0' if disable_composer else '1'">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -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 ''),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -397,7 +397,6 @@
|
||||
<!-- Options:Quotation Chatter: user can reply -->
|
||||
<t t-call="portal.message_thread">
|
||||
<t t-set="object" t-value="quotation"/>
|
||||
<t t-set="token_field" t-value="'access_token'"/>
|
||||
</t>
|
||||
</xpath>
|
||||
<xpath expr="//a[@data-target='#modaldecline']" position="before">
|
||||
|
||||
Reference in New Issue
Block a user