[MERGE] trunk-fix-mail-mail-rules-tde: OpenChatter 'Rule Yur Daddy' Branch
Fixes some of access rights issues. This addons branch features : - message_is_follower field added in invisible in all views using Chatter - update of message_follower_ids, to use message_is_follower, and to properly handle users not having access to the res.partner model (ex: basic portal users, anonymous users) - misc access rights tuning bzr revid: abo@openerp.com-20120928173655-uh9rzio2zpl8vfpx
This commit is contained in:
@@ -278,6 +278,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
@@ -437,6 +438,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -243,6 +243,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
@@ -518,6 +519,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
@@ -301,6 +302,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -223,6 +223,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
@@ -525,6 +526,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -146,10 +146,10 @@
|
||||
<field name="priority"/>
|
||||
<field name="opportunity_id"/>
|
||||
</group>
|
||||
|
||||
<field name="description" placeholder="Description..."/>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -181,6 +181,7 @@
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
+12
-10
@@ -196,6 +196,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
@@ -246,12 +247,12 @@
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_module_vignette">
|
||||
<a type="open" class="oe_module_icon">
|
||||
<div class="oe_event_date "><t t-esc="record.date_begin.raw_value.getDate()"/></div>
|
||||
<div class="oe_event_month_year">
|
||||
<t t-esc="record.date_begin.raw_value.toString('MMM')"/>
|
||||
<t t-esc="record.date_begin.raw_value.getFullYear()"/>
|
||||
</div>
|
||||
<div class="oe_event_time"><t t-esc="record.date_begin.raw_value.toString('hh:mm tt')"/></div>
|
||||
<div class="oe_event_date "><t t-esc="record.date_begin.raw_value.getDate()"/></div>
|
||||
<div class="oe_event_month_year">
|
||||
<t t-esc="record.date_begin.raw_value.toString('MMM')"/>
|
||||
<t t-esc="record.date_begin.raw_value.getFullYear()"/>
|
||||
</div>
|
||||
<div class="oe_event_time"><t t-esc="record.date_begin.raw_value.toString('hh:mm tt')"/></div>
|
||||
</a>
|
||||
<div class="oe_module_desc">
|
||||
<h4><a type="open"><field name="name"/></a></h4>
|
||||
@@ -271,10 +272,10 @@
|
||||
</p>
|
||||
<t t-if="record.register_avail.raw_value != 0">
|
||||
<t t-if="!record.is_subscribed.raw_value">
|
||||
<input t-att-id="record.id.raw_value" type="text" name="subscribe" class="no_of_seats" value="1" onchange="document.getElementById('btn_sub' +this.id).setAttribute('data-context',JSON.stringify({'ticket':this.value}))"/>
|
||||
<button t-att-id="'btn_sub'+record.id.raw_value" type="object" name="subscribe_to_event" class="oe_mail_button_follow">
|
||||
<span >Subscribe</span>
|
||||
</button>
|
||||
<input t-att-id="record.id.raw_value" type="text" name="subscribe" class="no_of_seats" value="1" onchange="document.getElementById('btn_sub' +this.id).setAttribute('data-context',JSON.stringify({'ticket':this.value}))"/>
|
||||
<button t-att-id="'btn_sub'+record.id.raw_value" type="object" name="subscribe_to_event" class="oe_mail_button_follow">
|
||||
<span >Subscribe</span>
|
||||
</button>
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="record.is_subscribed.raw_value">
|
||||
@@ -478,6 +479,7 @@
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -121,6 +121,7 @@
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
@@ -158,6 +159,7 @@
|
||||
<field name="notes" nolabel="1" colspan="4" placeholder="Add a reason..."/>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -183,6 +183,7 @@
|
||||
<field name="description" placeholder="Feedback of interviews..."/>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
<field name="description"/>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
from osv import osv
|
||||
from osv import fields
|
||||
import tools
|
||||
@@ -91,7 +92,7 @@ class mail_notification(osv.Model):
|
||||
:param browse_record message: mail.message to notify
|
||||
"""
|
||||
notify_pids = []
|
||||
for partner in self.pool.get('res.partner').browse(cr, uid, partner_ids, context=context):
|
||||
for partner in self.pool.get('res.partner').browse(cr, SUPERUSER_ID, partner_ids, context=context):
|
||||
# Do not send an email to the writer
|
||||
if partner.user_ids and partner.user_ids[0].id == uid:
|
||||
continue
|
||||
|
||||
@@ -19,9 +19,10 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
from osv import osv
|
||||
from osv import fields
|
||||
from tools.translate import _
|
||||
|
||||
|
||||
class ir_ui_menu(osv.osv):
|
||||
""" Override of ir.ui.menu class. When adding mail_thread module, each
|
||||
@@ -38,13 +39,14 @@ class ir_ui_menu(osv.osv):
|
||||
|
||||
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
|
||||
""" Override to take off menu entries (mail.group) the user is not
|
||||
following. """
|
||||
following. Access are done using SUPERUSER_ID to avoid access
|
||||
rights issues for an internal back-end algorithm. """
|
||||
ids = super(ir_ui_menu, self).search(cr, uid, args, offset=0, limit=None, order=order, context=context, count=False)
|
||||
partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||
partner_id = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||
follower_obj = self.pool.get('mail.followers')
|
||||
for menu in self.browse(cr, uid, ids, context=context):
|
||||
if menu.mail_group_id:
|
||||
sub_ids = follower_obj.search(cr, uid, [
|
||||
sub_ids = follower_obj.search(cr, SUPERUSER_ID, [
|
||||
('partner_id', '=', partner_id), ('res_model', '=', 'mail.group'),
|
||||
('res_id', '=', menu.mail_group_id.id)
|
||||
], context=context)
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"
|
||||
options='{"thread_level": 1}'/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
|
||||
@@ -19,13 +19,12 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# import ast
|
||||
import base64
|
||||
import logging
|
||||
import tools
|
||||
|
||||
from osv import osv
|
||||
from osv import fields
|
||||
from openerp import SUPERUSER_ID
|
||||
from osv import osv, fields
|
||||
from tools.translate import _
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
@@ -134,7 +133,8 @@ class mail_mail(osv.Model):
|
||||
:return: True
|
||||
"""
|
||||
if mail.auto_delete:
|
||||
mail.unlink()
|
||||
# done with SUPERUSER_ID to avoid giving large unlink access rights
|
||||
self.unlink(cr, SUPERUSER_ID, [mail.id], context=context)
|
||||
return True
|
||||
|
||||
def send_get_mail_subject(self, cr, uid, mail, force=False, partner=None, context=None):
|
||||
|
||||
+129
-45
@@ -24,8 +24,9 @@ import openerp
|
||||
import tools
|
||||
|
||||
from email.header import decode_header
|
||||
from openerp import SUPERUSER_ID
|
||||
from operator import itemgetter
|
||||
from osv import osv, fields
|
||||
from osv import osv, orm, fields
|
||||
from tools.translate import _
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
@@ -62,14 +63,14 @@ class mail_message(osv.Model):
|
||||
continue
|
||||
try:
|
||||
result[message.id] = self._shorten_name(self.pool.get(message.model).name_get(cr, uid, [message.res_id], context=context)[0][1])
|
||||
except openerp.exceptions.AccessDenied, e:
|
||||
except (orm.except_orm, osv.except_osv):
|
||||
pass
|
||||
return result
|
||||
|
||||
def _get_unread(self, cr, uid, ids, name, arg, context=None):
|
||||
""" Compute if the message is unread by the current user. """
|
||||
res = dict((id, {'unread': False}) for id in ids)
|
||||
partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||
partner_id = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||
notif_obj = self.pool.get('mail.notification')
|
||||
notif_ids = notif_obj.search(cr, uid, [
|
||||
('partner_id', 'in', [partner_id]),
|
||||
@@ -87,7 +88,7 @@ class mail_message(osv.Model):
|
||||
read_cond = '(read = false or read is null)'
|
||||
else:
|
||||
read_cond = 'read = true'
|
||||
partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||
partner_id = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||
cr.execute("SELECT message_id FROM mail_notification "\
|
||||
"WHERE partner_id = %%s AND %s" % read_cond,
|
||||
(partner_id,))
|
||||
@@ -140,7 +141,8 @@ class mail_message(osv.Model):
|
||||
return []
|
||||
|
||||
def _get_default_author(self, cr, uid, context=None):
|
||||
return self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||
# remove context to avoid possible hack in browse with superadmin using context keys that could trigger a specific behavior
|
||||
return self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=None).partner_id.id
|
||||
|
||||
_defaults = {
|
||||
'type': 'email',
|
||||
@@ -154,16 +156,17 @@ class mail_message(osv.Model):
|
||||
#------------------------------------------------------
|
||||
|
||||
def vote_toggle(self, cr, uid, ids, user_ids=None, context=None):
|
||||
''' Toggles voting '''
|
||||
''' Toggles voting. Done as SUPERUSER_ID because of write access on
|
||||
mail.message not always granted. '''
|
||||
if not user_ids:
|
||||
user_ids = [uid]
|
||||
for message in self.read(cr, uid, ids, ['vote_user_ids'], context=context):
|
||||
for user_id in user_ids:
|
||||
has_voted = user_id in message.get('vote_user_ids')
|
||||
if not has_voted:
|
||||
self.write(cr, uid, message.get('id'), {'vote_user_ids': [(4, user_id)]}, context=context)
|
||||
self.write(cr, SUPERUSER_ID, message.get('id'), {'vote_user_ids': [(4, user_id)]}, context=context)
|
||||
else:
|
||||
self.write(cr, uid, message.get('id'), {'vote_user_ids': [(3, user_id)]}, context=context)
|
||||
self.write(cr, SUPERUSER_ID, message.get('id'), {'vote_user_ids': [(3, user_id)]}, context=context)
|
||||
return True
|
||||
|
||||
#------------------------------------------------------
|
||||
@@ -171,17 +174,31 @@ class mail_message(osv.Model):
|
||||
#------------------------------------------------------
|
||||
|
||||
def _message_dict_get(self, cr, uid, msg, context=None):
|
||||
""" Return a dict representation of the message browse record. """
|
||||
""" Return a dict representation of the message browse record. A read
|
||||
is performed to because of access rights issues (reading many2one
|
||||
fields allow to have the foreign record name without having
|
||||
to check external access rights).
|
||||
"""
|
||||
has_voted = False
|
||||
vote_ids = self.pool.get('res.users').name_get(cr, uid, [user.id for user in msg.vote_user_ids], context=context)
|
||||
vote_ids = self.pool.get('res.users').name_get(cr, SUPERUSER_ID, [user.id for user in msg.vote_user_ids], context=context)
|
||||
for vote in vote_ids:
|
||||
if vote[0] == uid:
|
||||
has_voted = True
|
||||
break
|
||||
attachment_ids = [{'id': attach[0], 'name': attach[1]} for attach in self.pool.get('ir.attachment').name_get(cr, uid, [x.id for x in msg.attachment_ids], context=context)]
|
||||
author_id = self.pool.get('res.partner').name_get(cr, uid, [msg.author_id.id], context=context)[0]
|
||||
author_user_id = self.pool.get('res.users').name_get(cr, uid, [msg.author_id.user_ids[0].id], context=context)[0]
|
||||
partner_ids = self.pool.get('res.partner').name_get(cr, uid, [x.id for x in msg.partner_ids], context=context)
|
||||
try:
|
||||
attachment_ids = [{'id': attach[0], 'name': attach[1]} for attach in self.pool.get('ir.attachment').name_get(cr, uid, [x.id for x in msg.attachment_ids], context=context)]
|
||||
except (orm.except_orm, osv.except_osv):
|
||||
attachment_ids = []
|
||||
try:
|
||||
author_id = self.pool.get('res.partner').name_get(cr, uid, [msg.author_id.id], context=context)[0]
|
||||
is_author = uid in msg.author_id.user_ids
|
||||
except (orm.except_orm, osv.except_osv):
|
||||
author_id = False
|
||||
is_author = False
|
||||
try:
|
||||
partner_ids = self.pool.get('res.partner').name_get(cr, uid, [x.id for x in msg.partner_ids], context=context)
|
||||
except (orm.except_orm, osv.except_osv):
|
||||
partner_ids = []
|
||||
return {
|
||||
'id': msg.id,
|
||||
'type': msg.type,
|
||||
@@ -193,7 +210,7 @@ class mail_message(osv.Model):
|
||||
'subject': msg.subject,
|
||||
'date': msg.date,
|
||||
'author_id': author_id,
|
||||
'author_user_id': author_user_id,
|
||||
'is_author': is_author,
|
||||
'partner_ids': partner_ids,
|
||||
'child_ids': [],
|
||||
'vote_user_ids': vote_ids,
|
||||
@@ -246,7 +263,7 @@ class mail_message(osv.Model):
|
||||
limit = limit or self._message_read_limit
|
||||
context = context or {}
|
||||
if not ids:
|
||||
ids = self.search(cr, uid, domain, context=context, limit=limit)
|
||||
ids = self.search(cr, SUPERUSER_ID, domain, context=context, limit=limit)
|
||||
messages = self.browse(cr, uid, ids, context=context)
|
||||
|
||||
result = []
|
||||
@@ -294,41 +311,99 @@ class mail_message(osv.Model):
|
||||
cr.execute("""CREATE INDEX mail_message_model_res_id_idx ON mail_message (model, res_id)""")
|
||||
|
||||
def check_access_rule(self, cr, uid, ids, operation, context=None):
|
||||
""" mail.message access rule check
|
||||
- message received (a notification exists) -> ok
|
||||
- check rules of related document if exists
|
||||
- fallback on normal mail.message check """
|
||||
""" Access rules of mail.message:
|
||||
- read: if
|
||||
- notification exist (I receive pushed message) OR
|
||||
- author_id = pid (I am the author) OR
|
||||
- I can read the related document if res_model, res_id
|
||||
- Otherwise: raise
|
||||
- create: if
|
||||
- I am in the document message_follower_ids OR
|
||||
- I can write on the related document if res_model, res_id
|
||||
- Otherwise: raise
|
||||
- write: if
|
||||
- I can write on the related document if res_model, res_id
|
||||
- Otherwise: raise
|
||||
- unlink: if
|
||||
- I can write on the related document if res_model, res_id
|
||||
- Otherwise: raise
|
||||
"""
|
||||
if uid == SUPERUSER_ID:
|
||||
return
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
partner_id = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=None)['partner_id'][0]
|
||||
|
||||
# check messages for which you have a notification
|
||||
partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||
not_obj = self.pool.get('mail.notification')
|
||||
not_ids = not_obj.search(cr, uid, [
|
||||
('partner_id', '=', partner_id),
|
||||
('message_id', 'in', ids),
|
||||
], context=context)
|
||||
notified_ids = [notification.message_id.id for notification in not_obj.browse(cr, uid, not_ids, context=context)
|
||||
if notification.message_id.id in ids]
|
||||
|
||||
# check messages linked to an existing document
|
||||
# Read mail_message.ids to have their values
|
||||
model_record_ids = {}
|
||||
document_ids = []
|
||||
cr.execute('SELECT DISTINCT id, model, res_id FROM mail_message WHERE id = ANY (%s)', (ids,))
|
||||
for id, rmod, rid in cr.fetchall():
|
||||
if not (rmod and rid):
|
||||
continue
|
||||
document_ids.append(id)
|
||||
model_record_ids.setdefault(rmod, set()).add(rid)
|
||||
message_values = dict.fromkeys(ids)
|
||||
cr.execute('SELECT DISTINCT id, model, res_id, author_id FROM "%s" WHERE id = ANY (%%s)' % self._table, (ids,))
|
||||
for id, rmod, rid, author_id in cr.fetchall():
|
||||
message_values[id] = {'res_model': rmod, 'res_id': rid, 'author_id': author_id}
|
||||
if rmod:
|
||||
model_record_ids.setdefault(rmod, set()).add(rid)
|
||||
|
||||
# Read: Check for received notifications -> could become an ir.rule, but not till we do not have a many2one variable field
|
||||
if operation == 'read':
|
||||
not_obj = self.pool.get('mail.notification')
|
||||
not_ids = not_obj.search(cr, SUPERUSER_ID, [
|
||||
('partner_id', '=', partner_id),
|
||||
('message_id', 'in', ids),
|
||||
], context=context)
|
||||
notified_ids = [notification.message_id.id for notification in not_obj.browse(cr, SUPERUSER_ID, not_ids, context=context)]
|
||||
else:
|
||||
notified_ids = []
|
||||
# Read: Check messages you are author -> could become an ir.rule, but not till we do not have a many2one variable field
|
||||
if operation == 'read':
|
||||
author_ids = [mid for mid, message in message_values.iteritems()
|
||||
if message.get('author_id') and message.get('author_id') == partner_id]
|
||||
else:
|
||||
author_ids = []
|
||||
|
||||
# Create: Check message_follower_ids
|
||||
if operation == 'create':
|
||||
doc_follower_ids = []
|
||||
for model, mids in model_record_ids.items():
|
||||
fol_obj = self.pool.get('mail.followers')
|
||||
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
|
||||
('res_model', '=', model),
|
||||
('res_id', 'in', list(mids)),
|
||||
('partner_id', '=', partner_id),
|
||||
], context=context)
|
||||
fol_mids = [follower.res_id for follower in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context)]
|
||||
doc_follower_ids += [mid for mid, message in message_values.iteritems()
|
||||
if message.get('res_model') == model and message.get('res_id') in fol_mids]
|
||||
else:
|
||||
doc_follower_ids = []
|
||||
|
||||
# Calculate remaining ids, and related model/res_ids
|
||||
model_record_ids = {}
|
||||
other_ids = set(ids).difference(set(notified_ids), set(author_ids), set(doc_follower_ids))
|
||||
for id in other_ids:
|
||||
if message_values[id]['res_model']:
|
||||
model_record_ids.setdefault(message_values[id]['res_model'], set()).add(message_values[id]['res_id'])
|
||||
|
||||
# CRUD: Access rights related to the document
|
||||
document_related_ids = []
|
||||
for model, mids in model_record_ids.items():
|
||||
model_obj = self.pool.get(model)
|
||||
mids = model_obj.exists(cr, uid, mids)
|
||||
model_obj.check_access_rights(cr, uid, operation)
|
||||
model_obj.check_access_rule(cr, uid, mids, operation, context=context)
|
||||
if operation in ['create', 'write', 'unlink']:
|
||||
model_obj.check_access_rights(cr, uid, 'write')
|
||||
model_obj.check_access_rule(cr, uid, mids, 'write', context=context)
|
||||
else:
|
||||
model_obj.check_access_rights(cr, uid, operation)
|
||||
model_obj.check_access_rule(cr, uid, mids, operation, context=context)
|
||||
document_related_ids += [mid for mid, message in message_values.iteritems()
|
||||
if message.get('res_model') == model and message.get('res_id') in mids]
|
||||
|
||||
# fall back on classic operation for other ids
|
||||
other_ids = set(ids).difference(set(notified_ids), set(document_ids))
|
||||
super(mail_message, self).check_access_rule(cr, uid, other_ids, operation, context=None)
|
||||
# Calculate remaining ids: if not void, raise an error
|
||||
other_ids = set(ids).difference(set(notified_ids), set(author_ids), set(doc_follower_ids), set(document_related_ids))
|
||||
if not other_ids:
|
||||
return
|
||||
raise orm.except_orm(_('Access Denied'),
|
||||
_('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))
|
||||
|
||||
def create(self, cr, uid, values, context=None):
|
||||
if not values.get('message_id') and values.get('res_id') and values.get('model'):
|
||||
@@ -337,6 +412,13 @@ class mail_message(osv.Model):
|
||||
self.notify(cr, uid, newid, context=context)
|
||||
return newid
|
||||
|
||||
def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'):
|
||||
""" Override to explicitely call check_access_rule, that is not called
|
||||
by the ORM. It instead directly fetches ir.rules and apply them. """
|
||||
res = super(mail_message, self).read(cr, uid, ids, fields=fields, context=context, load=load)
|
||||
self.check_access_rule(cr, uid, ids, 'read', context=context)
|
||||
return res
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
# cascade-delete attachments that are directly attached to the message (should only happen
|
||||
# for mail.messages that act as parent for a standalone mail.mail record).
|
||||
@@ -360,12 +442,14 @@ class mail_message(osv.Model):
|
||||
partners_to_notify |= set(partner.id for partner in message.partner_ids)
|
||||
# add all followers and set add them in partner_ids
|
||||
if message.model and message.res_id:
|
||||
record = self.pool.get(message.model).browse(cr, uid, message.res_id, context=context)
|
||||
record = self.pool.get(message.model).browse(cr, SUPERUSER_ID, message.res_id, context=context)
|
||||
extra_notified = set(partner.id for partner in record.message_follower_ids)
|
||||
missing_notified = extra_notified - partners_to_notify
|
||||
if missing_notified:
|
||||
message.write({'partner_ids': [(4, p_id) for p_id in missing_notified]})
|
||||
self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(4, p_id) for p_id in missing_notified]}, context=context)
|
||||
partners_to_notify |= extra_notified
|
||||
# # remove uid from partners
|
||||
self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(3, uid)]}, context=context)
|
||||
self.pool.get('mail.notification').notify(cr, uid, list(partners_to_notify), newid, context=context)
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
</record>
|
||||
|
||||
<record id="action_mail_my_feeds" model="ir.actions.client">
|
||||
<field name="name">My Feeds</field>
|
||||
<field name="name">My Posts</field>
|
||||
<field name="tag">mail.wall</field>
|
||||
<field name="params" eval=""{'domain': [('author_id.user_ids', 'in', [uid])],
|
||||
'context': {'default_model': 'res.users', 'default_res_id': uid} }""/>
|
||||
|
||||
+19
-10
@@ -30,6 +30,7 @@ import xmlrpclib
|
||||
|
||||
from email.message import Message
|
||||
from mail_message import decode
|
||||
from openerp import SUPERUSER_ID
|
||||
from osv import osv, fields
|
||||
from tools.safe_eval import safe_eval as eval
|
||||
|
||||
@@ -118,26 +119,27 @@ class mail_thread(osv.AbstractModel):
|
||||
|
||||
def _get_message_data(self, cr, uid, ids, name, args, context=None):
|
||||
res = dict((id, dict(message_unread=False, message_summary='')) for id in ids)
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
partner_id = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||
|
||||
# search for unread messages, by reading directly mail.notification, as SUPERUSER
|
||||
notif_obj = self.pool.get('mail.notification')
|
||||
notif_ids = notif_obj.search(cr, uid, [
|
||||
notif_ids = notif_obj.search(cr, SUPERUSER_ID, [
|
||||
('partner_id.user_ids', 'in', [uid]),
|
||||
('message_id.res_id', 'in', ids),
|
||||
('message_id.model', '=', self._name),
|
||||
('read', '=', False)
|
||||
], context=context)
|
||||
for notif in notif_obj.browse(cr, uid, notif_ids, context=context):
|
||||
for notif in notif_obj.browse(cr, SUPERUSER_ID, notif_ids, context=context):
|
||||
res[notif.message_id.res_id]['message_unread'] = True
|
||||
|
||||
for thread in self.browse(cr, uid, ids, context=context):
|
||||
cls = res[thread.id]['message_unread'] and ' class="oe_kanban_mail_new"' or ''
|
||||
res[thread.id]['message_summary'] = "<span%s><span class='oe_e'>9</span> %d</span> <span><span class='oe_e'>+</span> %d</span>" % (cls, len(thread.message_comment_ids), len(thread.message_follower_ids))
|
||||
res[thread.id]['message_is_follower'] = user.partner_id.id in [follower.id for follower in thread.message_follower_ids]
|
||||
for thread in self.read(cr, uid, ids, ['message_follower_ids', 'message_comment_ids', 'message_ids'], context=context):
|
||||
cls = res[thread['id']]['message_unread'] and ' class="oe_kanban_mail_new"' or ''
|
||||
res[thread['id']]['message_summary'] = "<span%s><span class='oe_e'>9</span> %d</span> <span><span class='oe_e'>+</span> %d</span>" % (cls, len(thread['message_comment_ids']), len(thread['message_follower_ids']))
|
||||
res[thread['id']]['message_is_follower'] = partner_id in thread['message_follower_ids']
|
||||
return res
|
||||
|
||||
def _search_unread(self, cr, uid, obj=None, name=None, domain=None, context=None):
|
||||
partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||
partner_id = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||
res = {}
|
||||
notif_obj = self.pool.get('mail.notification')
|
||||
notif_ids = notif_obj.search(cr, uid, [
|
||||
@@ -196,6 +198,13 @@ class mail_thread(osv.AbstractModel):
|
||||
fol_obj.unlink(cr, uid, fol_ids, context=context)
|
||||
return super(mail_thread, self).unlink(cr, uid, ids, context=context)
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
default = default or {}
|
||||
default['message_ids'] = []
|
||||
default['message_comment_ids'] = []
|
||||
default['message_follower_ids'] = []
|
||||
return super(mail_thread, self).copy(cr, uid, id, default=default, context=context)
|
||||
|
||||
#------------------------------------------------------
|
||||
# mail.message wrappers and tools
|
||||
#------------------------------------------------------
|
||||
@@ -620,7 +629,7 @@ class mail_thread(osv.AbstractModel):
|
||||
""" Wrapper on message_subscribe, using users. If user_ids is not
|
||||
provided, subscribe uid instead. """
|
||||
if not user_ids: user_ids = [uid]
|
||||
partner_ids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, uid, user_ids, context=context)]
|
||||
partner_ids = [user['partner_id'][0] for user in self.pool.get('res.users').read(cr, uid, user_ids, ['partner_id'], context=context)]
|
||||
return self.message_subscribe(cr, uid, ids, partner_ids, context=context)
|
||||
|
||||
def message_subscribe(self, cr, uid, ids, partner_ids, context=None):
|
||||
@@ -631,7 +640,7 @@ class mail_thread(osv.AbstractModel):
|
||||
""" Wrapper on message_subscribe, using users. If user_ids is not
|
||||
provided, unsubscribe uid instead. """
|
||||
if not user_ids: user_ids = [uid]
|
||||
partner_ids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, uid, user_ids, context=context)]
|
||||
partner_ids = [user['partner_id'][0] for user in self.pool.get('res.users').read(cr, uid, user_ids, ['partner_id'], context=context)]
|
||||
return self.message_unsubscribe(cr, uid, ids, partner_ids, context=context)
|
||||
|
||||
def message_unsubscribe(self, cr, uid, ids, partner_ids, context=None):
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//sheet" position="after">
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"
|
||||
options='{"thread_level": 1}'/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_mail_global,mail.mail,model_mail_mail,base.group_system,1,1,1,1
|
||||
access_mail_message_all,mail.message.all,model_mail_message,,1,0,0,0
|
||||
access_mail_message_all,mail.message.all,model_mail_message,,1,0,1,0
|
||||
access_mail_message_group_user,mail.message.group.user,model_mail_message,base.group_user,1,1,1,1
|
||||
access_mail_thread,mail.thread,model_mail_thread,base.group_user,1,1,1,0
|
||||
access_mail_followers_all,mail.followers.all,model_mail_followers,,1,1,1,1
|
||||
access_mail_notification_all,mail.notification.all,model_mail_notification,,1,1,1,1
|
||||
access_mail_group,mail.group,model_mail_group,base.group_user,1,1,1,1
|
||||
access_mail_mail_all,mail.mail.all,model_mail_mail,,0,0,1,0
|
||||
access_mail_mail_system,mail.mail.system,model_mail_mail,base.group_system,1,1,1,1
|
||||
access_mail_followers_all,mail.followers.all,model_mail_followers,,0,0,0,0
|
||||
access_mail_followers_system,mail.followers.system,model_mail_followers,base.group_system,1,1,1,1
|
||||
access_mail_notification_all,mail.notification.all,model_mail_notification,,1,0,0,0
|
||||
access_mail_notification_aystem,mail.notification.system,model_mail_notification,base.group_system,1,1,1,1
|
||||
access_mail_group_all,mail.group.all,model_mail_group,,1,0,0,0
|
||||
access_mail_group_user,mail.group.user,model_mail_group,base.group_user,1,1,1,1
|
||||
access_mail_alias_all,mail.alias.all,model_mail_alias,,1,0,0,0
|
||||
access_mail_alias_user,mail.alias,model_mail_alias,base.group_user,1,1,1,0
|
||||
access_mail_alias_system,mail.alias,model_mail_alias,base.group_system,1,1,1,1
|
||||
access_mail_mail_user,mail.mail,model_mail_mail,base.group_user,1,1,1,0
|
||||
access_mail_mail_manager,mail.mail,model_mail_mail,group_mail_manager,1,1,1,1
|
||||
access_mail_vote_all,mail.vote.all,model_mail_vote,,1,1,1,1
|
||||
|
||||
|
@@ -2,20 +2,6 @@
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- CATEGORY -->
|
||||
<record model="ir.module.category" id="module_category_social">
|
||||
<field name="name">Home</field>
|
||||
<field name="parent_id" ref="base.module_category_tools"/>
|
||||
<field name="sequence">26</field>
|
||||
</record>
|
||||
|
||||
<!-- GROUPS -->
|
||||
<record id="group_mail_manager" model="res.groups">
|
||||
<field name="name">Mail manager</field>
|
||||
<field name="comment"></field>
|
||||
<field name="category_id" ref="module_category_social"/>
|
||||
</record>
|
||||
|
||||
<!-- RULES -->
|
||||
<record id="group_rule_public_and_joined" model="ir.rule">
|
||||
<field name="name">Mail.group: access only public and joined groups</field>
|
||||
@@ -24,5 +10,18 @@
|
||||
<field name="domain_force">['|', '|', ('public', '=', 'public'), ('message_follower_ids', 'in', [user.id]), '&', ('public','=','groups'), ('group_public_id','in', [x.id for x in user.groups_id])]</field>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
This rule can not be uncommented, because we have a more wide method in mail.message. When we implement a many2one_variable field, we will be able to uncomment this.
|
||||
|
||||
<record id="mail_message_read_partner_or_author" model="ir.rule">
|
||||
<field name="name">mail.message: read if notified or author</field>
|
||||
<field name="model_id" ref="model_mail_message"/>
|
||||
<field name="domain_force">['|', ('partner_ids', 'in', user.partner_id.id), ('author_id', '=', user.partner_id.id)]</field>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_unlink" eval="False"/>
|
||||
</record>
|
||||
-->
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -124,6 +124,14 @@
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* Followers
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
.openerp div.oe_mail_recthread_aside h4 {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* Thread
|
||||
/* ------------------------------------------------------------ */
|
||||
@@ -224,7 +232,7 @@
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content a {
|
||||
.openerp .oe_chatter a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -258,30 +266,6 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* mail.vote
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
.openerp .oe_mail_msg_content button.oe_mail_msg_vote {
|
||||
height:21px;
|
||||
width: 30px;
|
||||
padding: 1px;
|
||||
background: #8A89BA;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content button.oe_mail_msg_vote_true {
|
||||
background:#DC5F59;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content button.oe_mail_msg_vote span {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content span.oe_mail_vote_count{
|
||||
color: #807FB4;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* mail.compose.message form view & OpenERP hacks
|
||||
|
||||
@@ -56,11 +56,6 @@ openerp.mail = function(session) {
|
||||
return session.origin + '/web/binary/saveas?session_id=' + session.session_id + '&model=ir.attachment&field=datas&filename_field=datas_fname&id=' + attachment['id'];
|
||||
},
|
||||
|
||||
/** Check if the current user is the message author */
|
||||
is_author: function (widget, message_user_id) {
|
||||
return (widget.session && widget.session.uid != 0 && widget.session.uid == message_user_id);
|
||||
},
|
||||
|
||||
/** Replaces some expressions
|
||||
* - :name - shortcut to an image
|
||||
*/
|
||||
@@ -301,6 +296,7 @@ openerp.mail = function(session) {
|
||||
// TDE TODO: check for deferred, not sure it is correct
|
||||
this._super.apply(this, arguments);
|
||||
this.bind_events();
|
||||
this.display_user_avatar();
|
||||
// fetch and display message, using message_ids if set
|
||||
var display_done = $.when(this.message_fetch(true, [], {})).then(this.proxy('do_customize_display'));
|
||||
// add message composition form view
|
||||
@@ -313,7 +309,6 @@ openerp.mail = function(session) {
|
||||
/** Customize the display
|
||||
* - show_header_compose: show the composition form in the header */
|
||||
do_customize_display: function() {
|
||||
this.display_user_avatar();
|
||||
if (this.options.show_header_compose) {
|
||||
this.$el.find('div.oe_mail_thread_action').eq(0).show();
|
||||
}
|
||||
@@ -491,8 +486,7 @@ openerp.mail = function(session) {
|
||||
* - record.date: formatting according to the user timezone
|
||||
* - record.timerelative: relative time givein by timeago lib
|
||||
* - record.avatar: image url
|
||||
* - record.attachment_ids[].url: url of each attachment
|
||||
* - record.is_author: is the current user the author of the record */
|
||||
* - record.attachment_ids[].url: url of each attachment */
|
||||
display_record: function (record) {
|
||||
// formatting and additional fields
|
||||
record.date = session.web.format_value(record.date, {type:"datetime"});
|
||||
@@ -506,7 +500,6 @@ openerp.mail = function(session) {
|
||||
var attach = record.attachment_ids[l];
|
||||
attach['url'] = mail.ChatterUtils.get_attachment_url(this.session, attach);
|
||||
}
|
||||
record.is_author = mail.ChatterUtils.is_author(this, record.author_user_id[0]);
|
||||
// add to internal storage
|
||||
this.records[record.id] = record;
|
||||
// render, add the expand feature
|
||||
@@ -649,12 +642,15 @@ openerp.mail = function(session) {
|
||||
// update domain
|
||||
var domain = this.options.domain.concat([['model', '=', this.view.model], ['res_id', '=', this.view.datarecord.id]]);
|
||||
// create and render Thread widget
|
||||
var show_header_compose = this.view.is_action_enabled('edit') ||
|
||||
(this.getParent().fields.message_is_follower && this.getParent().fields.message_is_follower.get_value());
|
||||
this.$el.find('div.oe_mail_recthread_main').empty();
|
||||
var thread = new mail.Thread(self, domain, this.options.context,
|
||||
{ 'thread_level': this.options.thread_level,
|
||||
'use_composer': true,
|
||||
'show_header_compose': show_header_compose,
|
||||
'use_composer': show_header_compose,
|
||||
'show_dd_delete': true,
|
||||
'show_reply_by_email': true });
|
||||
'show_reply_by_email': show_header_compose });
|
||||
return thread.appendTo(this.$el.find('div.oe_mail_recthread_main'));
|
||||
},
|
||||
});
|
||||
|
||||
@@ -45,8 +45,8 @@ openerp_mail_followers = function(session, mail) {
|
||||
},
|
||||
|
||||
reinit: function() {
|
||||
this.$el.find('button.oe_mail_button_follow').hide();
|
||||
this.$el.find('button.oe_mail_button_unfollow').hide();
|
||||
this.message_is_follower == undefined;
|
||||
this.display_buttons();
|
||||
},
|
||||
|
||||
bind_events: function() {
|
||||
@@ -55,7 +55,7 @@ openerp_mail_followers = function(session, mail) {
|
||||
.mouseover(function () { $(this).html('Unfollow').removeClass('oe_mail_button_mouseout').addClass('oe_mail_button_mouseover'); })
|
||||
.mouseleave(function () { $(this).html('Following').removeClass('oe_mail_button_mouseover').addClass('oe_mail_button_mouseout'); });
|
||||
this.$el.on('click', 'button.oe_mail_button_follow', function () { self.do_follow(); });
|
||||
this.$el.on('click', 'button.oe_mail_button_invite', function(event) {
|
||||
this.$el.on('click', 'a.oe_mail_invite', function(event) {
|
||||
action = {
|
||||
type: 'ir.actions.act_window',
|
||||
res_model: 'mail.wizard.invite',
|
||||
@@ -74,41 +74,65 @@ openerp_mail_followers = function(session, mail) {
|
||||
|
||||
read_value: function() {
|
||||
var self = this;
|
||||
return this.ds_model.read_ids([this.view.datarecord.id], ['message_follower_ids']).pipe(function (results) {
|
||||
return results[0].message_follower_ids;
|
||||
}).pipe(this.proxy('set_value'));
|
||||
return this.ds_model.read_ids([this.view.datarecord.id], ['message_is_follower', 'message_follower_ids']).then(function (results) {
|
||||
self.set_value(results[0].message_follower_ids, results[0].message_is_follower);
|
||||
});
|
||||
},
|
||||
|
||||
set_value: function(value_) {
|
||||
set_value: function(value_, message_is_follower) {
|
||||
this.reinit();
|
||||
if (! this.view.datarecord.id ||
|
||||
session.web.BufferedDataSet.virtual_id_regex.test(this.view.datarecord.id)) {
|
||||
this.$el.find('div.oe_mail_recthread_aside').hide();
|
||||
this.$('div.oe_mail_recthread_aside').hide();
|
||||
return;
|
||||
}
|
||||
return this.fetch_followers(value_ || this.get_value());
|
||||
return this.fetch_followers(value_ || this.get_value(), message_is_follower);
|
||||
},
|
||||
|
||||
fetch_followers: function (value_) {
|
||||
return this.ds_follow.call('read', [value_, ['name', 'user_ids']]).pipe(this.proxy('display_followers'));
|
||||
fetch_followers: function (value_, message_is_follower) {
|
||||
this.value = value_;
|
||||
this.message_is_follower = message_is_follower || (this.getParent().fields.message_is_follower && this.getParent().fields.message_is_follower.get_value());
|
||||
return this.ds_follow.call('read', [value_, ['name', 'user_ids']]).pipe(this.proxy('display_followers'), this.proxy('display_generic'));
|
||||
},
|
||||
|
||||
|
||||
/* Display generic info about follower, for people not having access to res_partner */
|
||||
display_generic: function (error, event) {
|
||||
event.preventDefault();
|
||||
var node_user_list = this.$('ul.oe_mail_followers_display').empty();
|
||||
// format content: Followers (You and 0 other) // Followers (3)
|
||||
var content = this.options.title;
|
||||
if (this.message_is_follower) {
|
||||
content += ' (You and ' + (this.value.length-1) + ' other)';
|
||||
}
|
||||
else {
|
||||
content += ' (' + this.value.length + ')'
|
||||
}
|
||||
this.$('div.oe_mail_recthread_followers h4').html(content);
|
||||
this.display_buttons();
|
||||
return $.when();
|
||||
},
|
||||
|
||||
/** Display the followers, evaluate is_follower directly */
|
||||
display_followers: function (records) {
|
||||
var self = this;
|
||||
this.message_is_follower = _.indexOf(_.flatten(_.pluck(records, 'user_ids')), this.session.uid) != -1;
|
||||
var node_user_list = this.$el.find('ul.oe_mail_followers_display').empty();
|
||||
this.$el.find('div.oe_mail_recthread_followers h4').html(this.options.title + ' (' + records.length + ')');
|
||||
var node_user_list = this.$('ul.oe_mail_followers_display').empty();
|
||||
this.$('div.oe_mail_recthread_followers h4').html(this.options.title + ' (' + records.length + ')');
|
||||
_(records).each(function (record) {
|
||||
record.avatar_url = mail.ChatterUtils.get_image(self.session, 'res.partner', 'image_small', record.id);
|
||||
$(session.web.qweb.render('mail.followers.partner', {'record': record})).appendTo(node_user_list);
|
||||
});
|
||||
if (this.message_is_follower) {
|
||||
this.$el.find('button.oe_mail_button_follow').hide();
|
||||
this.$el.find('button.oe_mail_button_unfollow').show(); }
|
||||
else {
|
||||
this.$el.find('button.oe_mail_button_follow').show();
|
||||
this.$el.find('button.oe_mail_button_unfollow').hide(); }
|
||||
this.display_buttons();
|
||||
},
|
||||
|
||||
display_buttons: function () {
|
||||
this.$('button.oe_mail_button_follow').hide();
|
||||
this.$('button.oe_mail_button_unfollow').hide();
|
||||
this.$('span.oe_mail_invite_wrapper').hide();
|
||||
if (! this.view.is_action_enabled('edit')) return;
|
||||
this.$('span.oe_mail_invite_wrapper').show();
|
||||
if (this.message_is_follower) { this.$('button.oe_mail_button_unfollow').show(); }
|
||||
else if (this.message_is_follower == false) { this.$('button.oe_mail_button_follow').show(); }
|
||||
},
|
||||
|
||||
do_follow: function () {
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
<li t-if="options.show_record_name and record.record_name and record.subject and options.thread_level > 0">
|
||||
<a t-attf-href="#model=#{record.model}&id=#{record.res_id}"><t t-raw="record.record_name"/></a>
|
||||
</li>
|
||||
<li><a t-attf-href="#model=res.partner&id=#{record.author_id[0]}"><t t-raw="record.author_id[1]"/></a></li>
|
||||
<li t-if="record.author_id"><a t-attf-href="#model=res.partner&id=#{record.author_id[0]}"><t t-raw="record.author_id[1]"/></a></li>
|
||||
<li><span t-att-title="record.date"><t t-raw="record.timerelative"/></span></li>
|
||||
<t t-call="mail.thread.message.vote"/>
|
||||
<li t-if="options.show_reply"><a class="oe_mail_msg_reply">Reply</a></li>
|
||||
@@ -185,7 +185,7 @@
|
||||
<t t-if='record.vote_user_ids.length > 0'>
|
||||
<span class="oe_left oe_mail_vote_count"><t t-esc="record.vote_user_ids.length"/> votes</span>
|
||||
</t>
|
||||
<button t-attf-class="oe_mail_msg_vote oe_mail_msg_vote_#{record.has_voted}" t-attf-data-msg_id="{record.id}">
|
||||
<button t-attf-class="oe_mail_msg_vote oe_tag" t-attf-data-msg_id="{record.id}">
|
||||
<t t-if="! record.has_voted"><span>+1</span></t>
|
||||
<t t-if="record.has_voted"><span>-1</span></t>
|
||||
</button>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
-->
|
||||
<div t-name="mail.followers" class="oe_mail_recthread_aside oe_semantic_html_override">
|
||||
<div class="oe_mail_recthread_actions">
|
||||
<button type="button" class="oe_mail_button_invite">Invite</button>
|
||||
<button type="button" class="oe_mail_button_follow">Follow</button>
|
||||
<button type="button" class="oe_mail_button_unfollow oe_mail_button_mouseout">Following</button>
|
||||
</div>
|
||||
@@ -18,7 +17,7 @@
|
||||
</div>
|
||||
<div class="oe_mail_recthread_followers">
|
||||
<t t-if="widget.options.title">
|
||||
<h4><t t-raw="widget.options.title"/></h4>
|
||||
<h4><t t-raw="widget.options.title"/></h4><span class="oe_mail_invite_wrapper"> · <a class="oe_mail_invite" >Invite partners</a></span>
|
||||
</t>
|
||||
<ul class="oe_mail_followers_display"></ul>
|
||||
</div>
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from . import test_mail
|
||||
from . import test_mail, test_mail_access_rights
|
||||
|
||||
checks = [
|
||||
test_mail,
|
||||
test_mail_access_rights,
|
||||
]
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Business Applications
|
||||
# Copyright (c) 2012-TODAY OpenERP S.A. <http://openerp.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.addons.mail.tests import test_mail
|
||||
from osv.orm import except_orm
|
||||
|
||||
|
||||
class test_mail_access_rights(test_mail.TestMailMockups):
|
||||
|
||||
def setUp(self):
|
||||
super(test_mail_access_rights, self).setUp()
|
||||
cr, uid = self.cr, self.uid
|
||||
self.mail_group = self.registry('mail.group')
|
||||
self.mail_message = self.registry('mail.message')
|
||||
self.mail_notification = self.registry('mail.notification')
|
||||
self.res_users = self.registry('res.users')
|
||||
self.res_groups = self.registry('res.groups')
|
||||
self.res_partner = self.registry('res.partner')
|
||||
|
||||
# create a 'pigs' group that will be used through the various tests
|
||||
self.group_pigs_id = self.mail_group.create(self.cr, self.uid,
|
||||
{'name': 'Pigs', 'description': 'Fans of Pigs, unite !'})
|
||||
|
||||
# Find Employee group
|
||||
group_employee_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'base', 'group_user')
|
||||
self.group_employee_id = group_employee_ref and group_employee_ref[1] or False
|
||||
|
||||
# Create Bert (without groups) and Raoul( employee)
|
||||
self.user_bert_id = self.res_users.create(cr, uid, {'name': 'Bert Tartopoils', 'login': 'bert', 'groups_id': [(6, 0, [])]})
|
||||
self.user_raoul_id = self.res_users.create(cr, uid, {'name': 'Raoul Grosbedon', 'login': 'raoul', 'groups_id': [(6, 0, [self.group_employee_id])]})
|
||||
self.user_bert = self.res_users.browse(cr, uid, self.user_bert_id)
|
||||
self.partner_bert_id = self.user_bert.partner_id.id
|
||||
self.user_raoul = self.res_users.browse(cr, uid, self.user_raoul_id)
|
||||
self.partner_raoul_id = self.user_raoul.partner_id.id
|
||||
|
||||
def test_00_mail_message_read_access_rights(self):
|
||||
""" Test basic mail_message read access rights. """
|
||||
cr, uid = self.cr, self.uid
|
||||
partner_bert_id, partner_raoul_id = self.partner_bert_id, self.partner_raoul_id
|
||||
user_bert_id, user_raoul_id = self.user_bert_id, self.user_raoul_id
|
||||
|
||||
# Prepare groups: Pigs (employee), Jobs (public)
|
||||
self.mail_group.message_post(cr, uid, self.group_pigs_id, body='Message')
|
||||
self.group_jobs_id = self.mail_group.create(cr, uid, {'name': 'Jobs', 'public': 'public'})
|
||||
|
||||
# ----------------------------------------
|
||||
# CASE1: Bert, basic mail.message read access
|
||||
# ----------------------------------------
|
||||
|
||||
# Do: create a new mail.message
|
||||
message_id = self.mail_message.create(cr, uid, {'body': 'My Body'})
|
||||
# Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc
|
||||
self.assertRaises(except_orm, self.mail_message.read,
|
||||
cr, user_bert_id, message_id)
|
||||
# Do: message is pushed to Bert
|
||||
notif_id = self.mail_notification.create(cr, uid, {'message_id': message_id, 'partner_id': partner_bert_id})
|
||||
# Test: Bert reads the message, ok because notification pushed
|
||||
self.mail_message.read(cr, user_bert_id, message_id)
|
||||
# Do: remove notification
|
||||
self.mail_notification.unlink(cr, uid, notif_id)
|
||||
# Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc
|
||||
self.assertRaises(except_orm, self.mail_message.read,
|
||||
cr, self.user_bert_id, message_id)
|
||||
# Do: Bert is now the author
|
||||
self.mail_message.write(cr, uid, [message_id], {'author_id': partner_bert_id})
|
||||
# Test: Bert reads the message, ok because Bert is the author
|
||||
self.mail_message.read(cr, user_bert_id, message_id)
|
||||
# Do: Bert is not the author anymore
|
||||
self.mail_message.write(cr, uid, [message_id], {'author_id': partner_raoul_id})
|
||||
# Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc
|
||||
self.assertRaises(except_orm, self.mail_message.read,
|
||||
cr, user_bert_id, message_id)
|
||||
# Do: message is attached to a document Bert can read, Jobs
|
||||
self.mail_message.write(cr, uid, [message_id], {'model': 'mail.group', 'res_id': self.group_jobs_id})
|
||||
# Test: Bert reads the message, ok because linked to a doc he is allowed to read
|
||||
self.mail_message.read(cr, user_bert_id, message_id)
|
||||
# Do: message is attached to a document Bert cannot read, Pigs
|
||||
self.mail_message.write(cr, uid, [message_id], {'model': 'mail.group', 'res_id': self.group_pigs_id})
|
||||
# Test: Bert reads the message, crash because not notification/not in doc followers/not read on doc
|
||||
self.assertRaises(except_orm, self.mail_message.read,
|
||||
cr, user_bert_id, message_id)
|
||||
|
||||
def test_05_mail_message_search_access_rights(self):
|
||||
""" Test mail_message search override about access rights. """
|
||||
self.assertTrue(1 == 1, 'Test not implemented, do not replace by return True')
|
||||
|
||||
def test_10_mail_flow_access_rights(self):
|
||||
""" Test a Chatter-looks alike flow. """
|
||||
cr, uid = self.cr, self.uid
|
||||
partner_bert_id, partner_raoul_id = self.partner_bert_id, self.partner_raoul_id
|
||||
user_bert_id, user_raoul_id = self.user_bert_id, self.user_raoul_id
|
||||
|
||||
# Prepare groups: Pigs (employee), Jobs (public)
|
||||
self.mail_group.message_post(cr, uid, self.group_pigs_id, body='Message')
|
||||
self.group_jobs_id = self.mail_group.create(cr, uid, {'name': 'Jobs', 'public': 'public'})
|
||||
|
||||
# ----------------------------------------
|
||||
# CASE1: Bert, without groups
|
||||
# ----------------------------------------
|
||||
# Do: Bert creates a group, should crash because perm_create only for employees
|
||||
self.assertRaises(except_orm,
|
||||
self.mail_group.create,
|
||||
cr, user_bert_id, {'name': 'Bert\'s Group'})
|
||||
# Do: Bert reads Jobs basic fields, ok because public = read access on the group
|
||||
self.mail_group.read(cr, user_bert_id, self.group_jobs_id, ['name', 'description'])
|
||||
# Do: Bert browse Pigs, ok (no direct browse of partners)
|
||||
self.mail_group.browse(cr, user_bert_id, self.group_jobs_id)
|
||||
# Do: Bert reads Jobs messages, ok because read access on the group => read access on its messages
|
||||
jobs_message_ids = self.mail_group.read(cr, user_bert_id, self.group_jobs_id, ['message_ids'])['message_ids']
|
||||
self.mail_message.read(cr, user_bert_id, jobs_message_ids)
|
||||
# Do: Bert reads Jobs followers, ko because partner are accessible to employees or partner manager
|
||||
jobs_followers_ids = self.mail_group.read(cr, user_bert_id, self.group_jobs_id, ['message_follower_ids'])['message_follower_ids']
|
||||
self.assertRaises(except_orm,
|
||||
self.res_partner.read,
|
||||
cr, user_bert_id, jobs_followers_ids)
|
||||
# Do: Bert comments Jobs, ko because no write access on the group and not in the followers
|
||||
self.assertRaises(except_orm,
|
||||
self.mail_group.message_post,
|
||||
cr, user_bert_id, self.group_jobs_id, body='I love Pigs')
|
||||
# Do: add Bert to jobs followers
|
||||
self.mail_group.message_subscribe(cr, uid, [self.group_jobs_id], [partner_bert_id])
|
||||
# Do: Bert comments Jobs, ok because he is now in the followers
|
||||
self.mail_group.message_post(cr, user_bert_id, self.group_jobs_id, body='I love Pigs')
|
||||
|
||||
# Do: Bert reads Pigs, should crash because mail.group security=groups only for employee group
|
||||
self.assertRaises(except_orm,
|
||||
self.mail_group.read,
|
||||
cr, user_bert_id, self.group_pigs_id)
|
||||
|
||||
# ----------------------------------------
|
||||
# CASE1: Raoul, employee
|
||||
# ----------------------------------------
|
||||
# Do: Bert read Pigs, ok because public
|
||||
self.mail_group.read(cr, user_raoul_id, self.group_pigs_id)
|
||||
# Do: Bert read Jobs, ok because group_public_id = employee
|
||||
self.mail_group.read(cr, user_raoul_id, self.group_jobs_id)
|
||||
@@ -409,8 +409,9 @@
|
||||
</page>
|
||||
</notebook>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
@@ -799,6 +800,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -189,6 +189,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -117,8 +117,11 @@
|
||||
<field name="stage_id" domain="[('user_id','=',uid)]" widget="statusbar" clickable="1"/>
|
||||
</header>
|
||||
<field name="memo" widget="html"/><!-- editor_width="100%%" editor_height="60%%" -->
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field class="oe_chatter" name="message_ids" widget="mail_thread"/>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<!-- Mail group for the company's news -->
|
||||
<record id="company_news_feed" model="mail.group">
|
||||
<field name="name">Company's news</field>
|
||||
<field name="public">public</field>
|
||||
</record>
|
||||
|
||||
<record id="action_news" model="ir.actions.act_window">
|
||||
@@ -17,6 +18,7 @@
|
||||
<!-- Mail group for the company's jobs -->
|
||||
<record id="company_jobs" model="mail.group">
|
||||
<field name="name">Company's jobs</field>
|
||||
<field name="public">public</field>
|
||||
</record>
|
||||
|
||||
<record id="action_jobs" model="ir.actions.act_window">
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<field name="password">portal</field>
|
||||
<!-- Avoid auto-including this user in any default group -->
|
||||
<field name="groups_id" eval="[(5,)]"/>
|
||||
<field name="partner_id" eval="ref('base.res_partner_1')"/>
|
||||
<field name="supplier" eval="False"/>
|
||||
<field name="customer" eval="True"/>
|
||||
<field name="email">demo@portal.wrong.address</field>
|
||||
</record>
|
||||
|
||||
<!-- Add the demo user to the portal (and therefore to the portal member group) -->
|
||||
|
||||
@@ -1,8 +1,2 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_mail_message,mail.message,mail.model_mail_message,group_portal,1,0,1,1
|
||||
access_mail_message_all,mail.message.all,mail.model_mail_message,group_portal,1,0,0,0
|
||||
access_mail_thread,mail.thread,mail.model_mail_thread,group_portal,1,0,0,0
|
||||
access_mail_followers,mail.followers,mail.model_mail_followers,group_portal,1,0,1,1
|
||||
access_mail_notification,mail.notification,mail.model_mail_notification,group_portal,1,0,1,0
|
||||
access_mail_group,mail.group,mail.model_mail_group,group_portal,1,0,0,0
|
||||
access_mail_alias,mail.alias,mail.model_mail_alias,group_portal,1,0,0,0
|
||||
access_mail_message_portal,mail.message.portal,mail.model_mail_message,group_portal,1,0,1,1
|
||||
|
||||
|
@@ -21,15 +21,18 @@
|
||||
|
||||
from openerp.addons.mail.tests import test_mail
|
||||
from openerp.tools import append_content_to_html
|
||||
from osv.orm import except_orm
|
||||
|
||||
|
||||
class test_portal(test_mail.TestMailMockups):
|
||||
|
||||
def setUp(self):
|
||||
super(test_portal, self).setUp()
|
||||
cr, uid = self.cr, self.uid
|
||||
self.ir_model = self.registry('ir.model')
|
||||
self.mail_group = self.registry('mail.group')
|
||||
self.mail_mail = self.registry('mail.mail')
|
||||
self.mail_message = self.registry('mail.message')
|
||||
self.res_users = self.registry('res.users')
|
||||
self.res_partner = self.registry('res.partner')
|
||||
|
||||
@@ -37,7 +40,42 @@ class test_portal(test_mail.TestMailMockups):
|
||||
self.group_pigs_id = self.mail_group.create(self.cr, self.uid,
|
||||
{'name': 'Pigs', 'description': 'Fans of Pigs, unite !'})
|
||||
|
||||
def test_00_mail_invite(self):
|
||||
# Find Portal group
|
||||
group_portal_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'portal', 'group_portal')
|
||||
self.group_portal_id = group_portal_ref and group_portal_ref[1] or False
|
||||
|
||||
# Create Chell (portal user)
|
||||
self.user_chell_id = self.res_users.create(cr, uid, {'name': 'Chell Gladys', 'login': 'chell', 'groups_id': [(6, 0, [self.group_portal_id])]})
|
||||
self.user_chell = self.res_users.browse(cr, uid, self.user_chell_id)
|
||||
self.partner_chell_id = self.user_chell.partner_id.id
|
||||
|
||||
def test_00_access_rights(self):
|
||||
""" Test basic mail_message and mail_group access rights for portal users. """
|
||||
cr, uid = self.cr, self.uid
|
||||
partner_chell_id = self.partner_chell_id
|
||||
user_chell_id = self.user_chell_id
|
||||
|
||||
# Prepare group: Pigs (portal)
|
||||
self.mail_group.message_post(cr, uid, self.group_pigs_id, body='Message')
|
||||
self.mail_group.write(cr, uid, [self.group_pigs_id], {'name': 'Jobs', 'public': 'groups', 'group_public_id': self.group_portal_id})
|
||||
|
||||
# ----------------------------------------
|
||||
# CASE1: Chell will use the Chatter
|
||||
# ----------------------------------------
|
||||
|
||||
# Do: Chell reads Pigs messages, ok because restricted to portal group
|
||||
message_ids = self.mail_group.read(cr, user_chell_id, self.group_pigs_id, ['message_ids'])['message_ids']
|
||||
self.mail_message.read(cr, user_chell_id, message_ids)
|
||||
# Do: Chell posts a message on Pigs, crash because can not write on group or is not in the followers
|
||||
self.assertRaises(except_orm,
|
||||
self.mail_group.message_post,
|
||||
cr, user_chell_id, self.group_pigs_id, body='Message')
|
||||
# Do: Chell is added to Pigs followers
|
||||
self.mail_group.message_subscribe(cr, uid, [self.group_pigs_id], [partner_chell_id])
|
||||
# Test: Chell posts a message on Pigs, ok because in the followers
|
||||
self.mail_group.message_post(cr, user_chell_id, self.group_pigs_id, body='Message')
|
||||
|
||||
def test_50_mail_invite(self):
|
||||
cr, uid = self.cr, self.uid
|
||||
user_admin = self.res_users.browse(cr, uid, uid)
|
||||
self.mail_invite = self.registry('mail.wizard.invite')
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<record id="portal_stock_picking_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Claims</field>
|
||||
<field ref="crm_claim.model_crm_claim" name="model_id"/>
|
||||
<field name="domain_force">[('partner_id','child_of',user.partner_id.id)]</field>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -40,32 +40,51 @@ class crm_contact_us(osv.TransientModel):
|
||||
r = self.pool.get('res.company').search(cr, uid, [], context=context)
|
||||
return r
|
||||
|
||||
def _get_current_user_email(self, cr, uid, context=None):
|
||||
def _get_user_name(self, cr, uid, context=None):
|
||||
"""
|
||||
If the user is logged in (i.e. not anonymous), get the user's email to
|
||||
pre-fill the email_from field.
|
||||
If the user is logged in (i.e. not anonymous), get the user's name to
|
||||
pre-fill the partner_name field.
|
||||
Same goes for the other _get_user_attr methods.
|
||||
|
||||
@return current user's email if the user isn't "anonymous", None otherwise
|
||||
@return current user's name if the user isn't "anonymous", None otherwise
|
||||
"""
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
user = self.pool.get('res.users').read(cr, uid, uid, ['login'], context)
|
||||
|
||||
if (user.login != 'anonymous'):
|
||||
return user.email
|
||||
if (user['login'] != 'anonymous'):
|
||||
return self.pool.get('res.users').name_get(cr, uid, uid, context)[0][1]
|
||||
else:
|
||||
return None
|
||||
|
||||
def _get_user_email(self, cr, uid, context=None):
|
||||
user = self.pool.get('res.users').read(cr, uid, uid, ['login', 'email'], context)
|
||||
|
||||
if (user['login'] != 'anonymous' and user['email']):
|
||||
return user['email']
|
||||
else:
|
||||
return None
|
||||
|
||||
def _get_user_phone(self, cr, uid, context=None):
|
||||
user = self.pool.get('res.users').read(cr, uid, uid, ['login', 'phone'], context)
|
||||
|
||||
if (user['login'] != 'anonymous' and user['phone']):
|
||||
return user['phone']
|
||||
else:
|
||||
return None
|
||||
|
||||
_defaults = {
|
||||
'email_from' : _get_current_user_email,
|
||||
'company_ids' : _get_companies,
|
||||
'partner_name': _get_user_name,
|
||||
'email_from': _get_user_email,
|
||||
'phone': _get_user_phone,
|
||||
'company_ids': _get_companies,
|
||||
}
|
||||
|
||||
def create(self, cr, uid, values, context=None):
|
||||
"""
|
||||
Since they potentially sensitive, we don't want any user to be able to
|
||||
read datas generated through this module. That's why we'll write those
|
||||
information in the crm.lead table and leave blank entries in the
|
||||
portal_crm.crm_contact_us table. This is why the create() method is
|
||||
overwritten.
|
||||
Since they are potentially sensitive, we don't want any user to be able
|
||||
to read datas generated through this module. That's why we'll write
|
||||
those information directly in the crm.lead table and leave blank
|
||||
entries in the portal_crm.crm_contact_us table.
|
||||
This is why the create() method is overwritten.
|
||||
"""
|
||||
crm_lead = self.pool.get('crm.lead')
|
||||
|
||||
@@ -88,11 +107,20 @@ class crm_contact_us(osv.TransientModel):
|
||||
|
||||
def submit(self, cr, uid, ids, context=None):
|
||||
""" When the form is submitted, redirect the user to a "Thanks" message """
|
||||
return {'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'view_type': 'form',
|
||||
'res_model': self._name,
|
||||
'res_id': ids[0],
|
||||
'view_id': self.pool.get('ir.model.data').get_object_reference(cr, uid, 'portal_crm', 'wizard_contact_form_view_thanks')[1],
|
||||
'target': 'inline'
|
||||
}
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'view_type': 'form',
|
||||
'res_model': self._name,
|
||||
'res_id': ids[0],
|
||||
'view_id': self.pool.get('ir.model.data').get_object_reference(cr, uid, 'portal_crm', 'wizard_contact_form_view_thanks')[1],
|
||||
'target': 'inline',
|
||||
}
|
||||
|
||||
def _needaction_domain_get(self, cr, uid, context=None):
|
||||
"""
|
||||
This model doesn't need the needactions mechanism inherited from
|
||||
crm_lead, so simply override the method to return an empty domain
|
||||
and, therefore, 0 needactions.
|
||||
"""
|
||||
return False
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_event,event,event.model_event_event,portal.group_portal,1,0,0,0
|
||||
access_registration,registration,event.model_event_registration,portal.group_portal,1,0,0,0
|
||||
access_registration,registration,event.model_event_registration,portal.group_portal,1,1,1,1
|
||||
|
||||
|
@@ -12,7 +12,7 @@
|
||||
<record id="portal_registration_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Registrations</field>
|
||||
<field ref="event.model_event_registration" name="model_id"/>
|
||||
<field name="domain_force">[('partner_id','child_of',user.partner_id.id)]</field>
|
||||
<field name="domain_force">[('user_id','=',user.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<record id="portal_task_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Task</field>
|
||||
<field ref="project.model_project_task" name="model_id"/>
|
||||
<field name="domain_force">[('partner_id','child_of',user.partner_id.id)]</field>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<record id="portal_issue_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Issues</field>
|
||||
<field ref="project_issue.model_project_issue" name="model_id"/>
|
||||
<field name="domain_force">[('partner_id','child_of',user.partner_id.id)]</field>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -5,43 +5,43 @@
|
||||
<!-- Sale Portal Access Rules -->
|
||||
<record id="portal_sale_order_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Quotations/Sales Orders</field>
|
||||
<field ref="sale.model_sale_order" name="model_id"/>
|
||||
<field name="domain_force">[('partner_id','child_of',user.partner_id.id)]</field>
|
||||
<field name="model_id" ref="sale.model_sale_order"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_stock_picking_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Delivery Orders</field>
|
||||
<field name="model_id" ref="stock.model_stock_picking"/>
|
||||
<field name="domain_force">[('partner_id','child_of',[user.partner_id.id])]</field>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_stock_picking_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Delivery Orders Out</field>
|
||||
<field ref="stock.model_stock_picking_out" name="model_id"/>
|
||||
<field name="domain_force">[('partner_id','child_of',[user.partner_id.id])]</field>
|
||||
<field name="model_id" ref="stock.model_stock_picking_out"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_account_invoice_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Account Invoices</field>
|
||||
<field ref="account.model_account_invoice" name="model_id"/>
|
||||
<field name="domain_force">[('partner_id','child_of',user.partner_id.id)]</field>
|
||||
<field name="model_id" ref="account.model_account_invoice"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_personal_payment" model="ir.rule">
|
||||
<field name="name">Portal Personal Payments</field>
|
||||
<field ref="account_voucher.model_account_voucher" name="model_id"/>
|
||||
<field name="domain_force">[('partner_id','child_of',user.partner_id.id)]</field>
|
||||
<field name="model_id" ref="account_voucher.model_account_voucher"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_personal_contact" model="ir.rule">
|
||||
<field name="name">Portal Personal Contacts</field>
|
||||
<field ref="base.model_res_partner" name="model_id"/>
|
||||
<field name="domain_force">[('id','child_of',user.partner_id.id)]</field>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -203,6 +203,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -150,6 +150,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers" help="Follow this project to automatically follow all related tasks and issues."/>
|
||||
</div>
|
||||
@@ -467,6 +468,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
</record>
|
||||
|
||||
<record id="crm_case_programnotgivingproperoutput0" model="project.issue">
|
||||
<field eval="time.strftime('%Y-%m-15 12:50:00')" name="date"/>
|
||||
<field eval="time.strftime('%Y-%m-15 12:50:00')" name="date"/>
|
||||
<field name="priority">3</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_1"/>
|
||||
|
||||
@@ -161,6 +161,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -285,6 +285,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -102,8 +102,9 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
||||
@@ -310,6 +310,7 @@
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
@@ -917,6 +917,7 @@
|
||||
</xpath>
|
||||
<xpath expr="/form/sheet" position="after">
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
@@ -1043,6 +1044,7 @@
|
||||
</xpath>
|
||||
<xpath expr="/form/sheet" position="after">
|
||||
<div class="oe_chatter">
|
||||
<field name="message_is_follower" invisible="1"/>
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user