summaryrefslogtreecommitdiff
path: root/addons/website_mail/controllers/main.py
diff options
context:
space:
mode:
authorJérome Maes <jem@openerp.com>2016-12-26 11:32:25 +0100
committerJérome Maes <jem@openerp.com>2017-06-30 11:06:32 +0200
commitd79678fdd5faccffff65a439653fa5d639a3d3c4 (patch)
tree7cb3f4a849289dbae3983daefea02c6cbbd21467 /addons/website_mail/controllers/main.py
parent890e665b882b27184003cc5de6ad365f2910815d (diff)
[IMP] website_mail: make the frontend chatter lazy
Message are now fetched and display using javascript to optimize performance. Also the chatter is completely rewrite : add pager, filter possiblity, ... This commit is mainly technical: posting feature does not change. Only the display with pager is new. The goal is also to prepare frontend chatter for a better integration with rating widget. The mail.thread mixin is extended to manage the field website_message_ids (display all messages that can be seen on frontend by user (employee or not). When fetching or posting message, a check is done to see if we need to do it as sudo(). website_mail implement posting messages with token or sha_in (using in website_quote). The same verification is now done when fetching messages, via '_special_access_object' method.
Diffstat (limited to 'addons/website_mail/controllers/main.py')
-rw-r--r--addons/website_mail/controllers/main.py92
1 files changed, 65 insertions, 27 deletions
diff --git a/addons/website_mail/controllers/main.py b/addons/website_mail/controllers/main.py
index 546def6890a..c0e8354610d 100644
--- a/addons/website_mail/controllers/main.py
+++ b/addons/website_mail/controllers/main.py
@@ -1,11 +1,18 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from hashlib import sha1
-from time import time
-from werkzeug.exceptions import NotFound
+
+from werkzeug.exceptions import NotFound, Forbidden
from odoo import http
from odoo.http import request
+from odoo.tools import consteq
+
+
+def _special_access_object(res_model, res_id, token='', token_field=''):
+ 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
def _message_post_helper(res_model='', res_id=None, message='', token='', token_field='token', nosubscribe=True, **kw):
""" Generic chatter function, allowing to write on *any* object that inherits mail.thread.
@@ -27,13 +34,17 @@ def _message_post_helper(res_model='', res_id=None, message='', token='', token_
"""
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 and record and token == getattr(record.sudo(), token_field, None):
- record = record.sudo()
- if request.env.user == request.env.ref('base.public_user'):
- author_id = record.partner_id.id if hasattr(record, 'partner_id') else author_id
+ if token_field and token:
+ access_as_sudo = _special_access_object(res_model, res_id, token=token, token_field=token_field)
+ if access_as_sudo:
+ record = record.sudo()
+ if request.env.user == request.env.ref('base.public_user'):
+ author_id = record.partner_id.id if hasattr(record, 'partner_id') else author_id
+ else:
+ if not author_id:
+ raise NotFound()
else:
- if not author_id:
- raise NotFound()
+ raise Forbidden()
kw.pop('csrf_token', None)
return record.with_context(mail_create_nosubscribe=nosubscribe).message_post(body=message,
message_type=kw.pop('message_type', "comment"),
@@ -98,25 +109,52 @@ class WebsiteMail(http.Controller):
]))
return values
- @http.route(['/website_mail/post/json'], type='json', auth='public', website=True)
- def chatter_json(self, res_model='', res_id=None, message='', **kw):
- try:
- msg = _message_post_helper(res_model, int(res_id), message, **kw)
- except Exception:
- return False
- data = {
- 'id': msg.id,
- 'body': msg.body,
- 'date': msg.date,
- 'author': msg.author_id.name,
- 'image_url': '/mail/%s/%s/avatar/%s' % (msg.model, msg.res_id, msg.author_id.id)
- }
- return data
-
@http.route(['/website_mail/post/post'], type='http', methods=['POST'], auth='public', website=True)
- def chatter_post(self, res_model='', res_id=None, message='', redirect=None, **kw):
+ def website_chatter_post(self, res_model, res_id, message, **kw):
url = request.httprequest.referrer
if message:
- message = _message_post_helper(res_model, int(res_id), message, **kw)
- url = url + "#message-%s" % (message.id,)
+ _message_post_helper(res_model, int(res_id), message, **kw)
+ url = url + "#discussion"
return request.redirect(url)
+
+ @http.route('/website_mail/init', type='json', auth='public', website=True)
+ def website_chatter_init(self, res_model, res_id, domain=False, limit=False, **kwargs):
+ is_user_public = bool(request.env.user == request.website.user_id)
+ message_data = self.website_message_fetch(res_model, res_id, domain=domain, limit=limit, **kwargs)
+ display_composer = False
+ if kwargs.get('allow_composer'):
+ display_composer = kwargs.get('token') or not is_user_public
+ return {
+ 'messages': message_data['messages'],
+ 'options': {
+ 'message_count': message_data['message_count'],
+ 'is_user_public': is_user_public,
+ 'is_user_publisher': request.env.user.has_group('website.group_website_publisher'),
+ 'display_composer': display_composer,
+ 'partner_id': request.env.user.partner_id.id
+ }
+ }
+
+ @http.route('/website_mail/fetch', type='json', auth='public', website=True)
+ def website_message_fetch(self, res_model, res_id, domain=False, limit=10, offset=0, **kw):
+ if not domain:
+ domain = []
+ # Only search into website_message_ids, so apply the same domain to perform only one search
+ # extract domain from the 'website_message_ids' field
+ field_domain = request.env[res_model]._fields['website_message_ids'].domain
+ domain += field_domain(request.env[res_model]) if callable(field_domain) else field_domain
+ domain += [('res_id', '=', res_id)]
+ # None published can see only the published messages
+ if not request.env.user.has_group('website.group_website_publisher'):
+ domain += [('website_published', '=', True)]
+ # 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'))
+ if not access_as_sudo: # if token is not correct, raise Forbidden
+ raise Forbidden()
+ Message = request.env['mail.message'].sudo()
+ return {
+ 'messages': Message.search(domain, limit=limit, offset=offset).website_message_format(),
+ 'message_count': Message.search_count(domain)
+ }