Skip to content

Commit

Permalink
[IMP] website_mail: make the frontend chatter lazy
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jem-odoo committed Jun 30, 2017
1 parent 890e665 commit d79678f
Show file tree
Hide file tree
Showing 10 changed files with 497 additions and 195 deletions.
2 changes: 1 addition & 1 deletion addons/website_mail/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
'data/mail_channel_data.xml',
],
'qweb': [
'static/src/xml/chatter_message.xml'
'static/src/xml/website_mail.xml'
],
'installable': True,
'auto_install': True,
Expand Down
92 changes: 65 additions & 27 deletions addons/website_mail/controllers/main.py
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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"),
Expand Down Expand Up @@ -98,25 +109,52 @@ def is_follower(self, model, res_id, **post):
]))
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)
}
12 changes: 12 additions & 0 deletions addons/website_mail/models/mail_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,15 @@ def check_access_rule(self, operation):
if self.env.cr.fetchall():
raise AccessError(_('The requested operation cannot be completed due to security restrictions. Please contact your system administrator.\n\n(Document type: %s, Operation: %s)') % (self._description, operation))
return super(MailMessage, self).check_access_rule(operation=operation)

@api.multi
def website_message_format(self):
message_values = self.read([
'id', 'body', 'date', 'author_id', 'email_from', # base message fields
'message_type', 'subtype_id', 'subject', # message specific
'model', 'res_id', 'record_name', # document related
'website_published',
])
message_tree = dict((m.id, m) for m in self.sudo())
self._message_read_dict_postprocess(message_values, message_tree)
return message_values
4 changes: 0 additions & 4 deletions addons/website_mail/static/src/css/website_mail.css

This file was deleted.

38 changes: 38 additions & 0 deletions addons/website_mail/static/src/css/website_mail.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.js_follow[data-follow='on'] .js_follow_btn ,
.js_follow[data-follow='off'] .js_unfollow_btn {
display: none;
}

.o_website_mail_chatter {
padding: 10px;

.o_website_mail_avatar{
width: 45px;
height: 45px;
}

.o_website_mail_header {
margin-bottom: 15px;
}

.o_website_mail_composer {
margin-bottom: 15px;
}

.o_website_mail_messages {
margin-bottom: 15px;

.o_website_mail_message_title {
p {
font-size:85%;
color:@odoo-main-color-muted;
margin: 0px;
}
}

}

.o_website_mail_pager {
text-align: center;
}
}
80 changes: 0 additions & 80 deletions addons/website_mail/static/src/js/message_post.js

This file was deleted.

Loading

0 comments on commit d79678f

Please sign in to comment.