summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2018-08-07 16:54:18 +0200
committerChristophe Simonis <chs@odoo.com>2018-08-07 16:54:18 +0200
commit0c5cbbe0bb4209dd6924494cd0c4d07dd3892b9e (patch)
tree62472770e4559486ed8ead37d29af0642f8a482c /addons
parent1f92477cf46af9580d6cb4b2a430254875e83ed1 (diff)
parent692a32e78098d57507c6ca2a5ac956af0f652446 (diff)
[MERGE] forward port branch 10.0 up to 692a32e7809
Diffstat (limited to 'addons')
-rw-r--r--addons/auth_signup/models/res_partner.py12
-rw-r--r--addons/auth_signup/models/res_users.py12
-rw-r--r--addons/crm/tests/test_lead2opportunity.py2
-rw-r--r--addons/event_sale/models/sale_order.py9
-rw-r--r--addons/mail/models/mail_template.py12
-rw-r--r--addons/mail/views/mail_template_views.xml7
-rw-r--r--addons/point_of_sale/static/src/js/screens.js3
-rw-r--r--addons/report/models/report.py2
-rw-r--r--addons/sale/models/sale.py2
-rw-r--r--addons/web/controllers/main.py5
-rw-r--r--addons/website/models/ir_attachment.py6
-rw-r--r--addons/website_mail/controllers/main.py5
-rw-r--r--addons/website_mail/models/mail_message.py6
13 files changed, 58 insertions, 25 deletions
diff --git a/addons/auth_signup/models/res_partner.py b/addons/auth_signup/models/res_partner.py
index a1d9f7d3ec5..1f79b89e992 100644
--- a/addons/auth_signup/models/res_partner.py
+++ b/addons/auth_signup/models/res_partner.py
@@ -26,9 +26,9 @@ def now(**kwargs):
class ResPartner(models.Model):
_inherit = 'res.partner'
- signup_token = fields.Char(copy=False)
- signup_type = fields.Char(string='Signup Token Type', copy=False)
- signup_expiration = fields.Datetime(copy=False)
+ signup_token = fields.Char(copy=False, groups="base.group_erp_manager")
+ signup_type = fields.Char(string='Signup Token Type', copy=False, groups="base.group_erp_manager")
+ signup_expiration = fields.Datetime(copy=False, groups="base.group_erp_manager")
signup_valid = fields.Boolean(compute='_compute_signup_valid', string='Signup Token is Valid')
signup_url = fields.Char(compute='_compute_signup_url', string='Signup URL')
@@ -36,15 +36,17 @@ class ResPartner(models.Model):
@api.depends('signup_token', 'signup_expiration')
def _compute_signup_valid(self):
dt = now()
- for partner in self:
+ for partner in self.sudo():
partner.signup_valid = bool(partner.signup_token) and \
(not partner.signup_expiration or dt <= partner.signup_expiration)
@api.multi
def _compute_signup_url(self):
""" proxy for function field towards actual implementation """
- result = self._get_signup_url_for_action()
+ result = self.sudo()._get_signup_url_for_action()
for partner in self:
+ if any(u.has_group('base.group_user') for u in partner.user_ids if u != self.env.user):
+ self.env['res.users'].check_access_rights('write')
partner.signup_url = result.get(partner.id, False)
@api.multi
diff --git a/addons/auth_signup/models/res_users.py b/addons/auth_signup/models/res_users.py
index f5c0a6f2d88..c170b7ab8a4 100644
--- a/addons/auth_signup/models/res_users.py
+++ b/addons/auth_signup/models/res_users.py
@@ -132,10 +132,20 @@ class ResUsers(models.Model):
template = self.env.ref('auth_signup.reset_password_email')
assert template._name == 'mail.template'
+ template_values = {
+ 'email_to': '${object.email|safe}',
+ 'email_cc': False,
+ 'auto_delete': True,
+ 'partner_to': False,
+ 'scheduled_date': False,
+ }
+ template.write(template_values)
+
for user in self:
if not user.email:
raise UserError(_("Cannot send email: user %s has no email address.") % user.name)
- template.with_context(lang=user.lang).send_mail(user.id, force_send=True, raise_exception=True)
+ with self.env.cr.savepoint():
+ template.with_context(lang=user.lang).send_mail(user.id, force_send=True, raise_exception=True)
_logger.info("Password reset email sent for user <%s> to <%s>", user.login, user.email)
@api.model
diff --git a/addons/crm/tests/test_lead2opportunity.py b/addons/crm/tests/test_lead2opportunity.py
index 861444b3f7c..e4847b5bf45 100644
--- a/addons/crm/tests/test_lead2opportunity.py
+++ b/addons/crm/tests/test_lead2opportunity.py
@@ -38,7 +38,7 @@ class TestLead2opportunity2win(TestCrmCases):
crm_case_3.message_post(subject='Test note', body='Détails envoyés par le client sur ​​le FAX pour la qualité')
# I convert mass lead into opportunity customer.
- mass = CrmLead2OpportunityPartnerMass.with_context({'active_model': 'crm.lead', 'active_ids': [crm_case_13.id, crm_case_2.id], 'active_id': crm_case_13.id}).create({
+ mass = CrmLead2OpportunityPartnerMass.sudo(self.crm_salemanager.id).with_context({'active_model': 'crm.lead', 'active_ids': [crm_case_13.id, crm_case_2.id], 'active_id': crm_case_13.id}).create({
'user_ids': [(6, 0, self.env.ref('base.user_root').ids)],
'team_id': self.env.ref("sales_team.team_sales_department").id
})
diff --git a/addons/event_sale/models/sale_order.py b/addons/event_sale/models/sale_order.py
index 7baca444240..2ea7d127cc8 100644
--- a/addons/event_sale/models/sale_order.py
+++ b/addons/event_sale/models/sale_order.py
@@ -8,11 +8,12 @@ class SaleOrder(models.Model):
@api.multi
def action_confirm(self):
- self.ensure_one()
res = super(SaleOrder, self).action_confirm()
- self.order_line._update_registrations(confirm=True)
- if any(self.order_line.filtered(lambda line: line.event_id)):
- return self.env['ir.actions.act_window'].with_context(default_sale_order_id=self.id).for_xml_id('event_sale', 'action_sale_order_event_registration')
+ for order in self:
+ order.order_line._update_registrations(confirm=True)
+ if any(order.order_line.filtered(lambda line: line.event_id)):
+ return self.env['ir.actions.act_window'].with_context(default_sale_order_id=order.id).for_xml_id(
+ 'event_sale', 'action_sale_order_event_registration')
return res
diff --git a/addons/mail/models/mail_template.py b/addons/mail/models/mail_template.py
index 01f26f3d048..5fdf370bf65 100644
--- a/addons/mail/models/mail_template.py
+++ b/addons/mail/models/mail_template.py
@@ -262,22 +262,22 @@ class MailTemplate(models.Model):
def unlink_action(self):
for template in self:
if template.ref_ir_act_window:
- template.ref_ir_act_window.sudo().unlink()
+ template.ref_ir_act_window.unlink()
if template.ref_ir_value:
- template.ref_ir_value.sudo().unlink()
+ template.ref_ir_value.unlink()
return True
@api.multi
def create_action(self):
- ActWindowSudo = self.env['ir.actions.act_window'].sudo()
- IrValuesSudo = self.env['ir.values'].sudo()
+ ActWindow = self.env['ir.actions.act_window']
+ IrValues = self.env['ir.values']
view = self.env.ref('mail.email_compose_message_wizard_form')
for template in self:
src_obj = template.model_id.model
button_name = _('Send Mail (%s)') % template.name
- action = ActWindowSudo.create({
+ action = ActWindow.create({
'name': button_name,
'type': 'ir.actions.act_window',
'res_model': 'mail.compose.message',
@@ -288,7 +288,7 @@ class MailTemplate(models.Model):
'view_id': view.id,
'target': 'new',
})
- ir_value = IrValuesSudo.create({
+ ir_value = IrValues.create({
'name': button_name,
'model': src_obj,
'key2': 'client_action_multi',
diff --git a/addons/mail/views/mail_template_views.xml b/addons/mail/views/mail_template_views.xml
index 483c80ae394..4306f1fe8d1 100644
--- a/addons/mail/views/mail_template_views.xml
+++ b/addons/mail/views/mail_template_views.xml
@@ -9,7 +9,9 @@
<sheet>
<div class="oe_button_box" name="button_box">
<field name="ref_ir_act_window" invisible="1"/>
- <button class="oe_stat_button" name="create_action" type="object"
+ <button class="oe_stat_button"
+ groups="base.group_system"
+ name="create_action" type="object"
attrs="{'invisible':[('ref_ir_act_window','!=',False)]}" icon="fa-plus"
help="Display an option on related documents to open a composition wizard with this template">
<div class="o_form_field o_stat_info">
@@ -17,7 +19,8 @@
<span class="o_stat_text">Context Action</span>
</div>
</button>
- <button name="unlink_action" type="object"
+ <button name="unlink_action" type="object"
+ groups="base.group_system"
class="oe_stat_button" icon="fa-minus"
attrs="{'invisible':[('ref_ir_act_window','=',False)]}"
help="Remove the contextual action to use this template on related documents" widget="statinfo">
diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js
index e64e12ffd38..b37dc13ff95 100644
--- a/addons/point_of_sale/static/src/js/screens.js
+++ b/addons/point_of_sale/static/src/js/screens.js
@@ -1317,6 +1317,9 @@ var ClientListScreenWidget = ScreenWidget.extend({
reload_partners: function(){
var self = this;
return this.pos.load_new_partners().then(function(){
+ // partners may have changed in the backend
+ self.partner_cache = new DomCache();
+
self.render_list(self.pos.db.get_partners_sorted(1000));
// update the currently assigned client if it has been changed in db.
diff --git a/addons/report/models/report.py b/addons/report/models/report.py
index 0f0d3e13a0b..e7afee3e0e1 100644
--- a/addons/report/models/report.py
+++ b/addons/report/models/report.py
@@ -526,7 +526,7 @@ class Report(models.Model):
:specific_paperformat_args: a dict containing prioritized wkhtmltopdf arguments
:returns: list of string representing the wkhtmltopdf arguments
"""
- command_args = []
+ command_args = ['--disable-local-file-access']
if paperformat.format and paperformat.format != 'custom':
command_args.extend(['--page-size', paperformat.format])
diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py
index db883fb3080..e94ba3eac75 100644
--- a/addons/sale/models/sale.py
+++ b/addons/sale/models/sale.py
@@ -1014,13 +1014,13 @@ class SaleOrderLine(models.Model):
@api.onchange('product_id', 'price_unit', 'product_uom', 'product_uom_qty', 'tax_id')
def _onchange_discount(self):
- self.discount = 0.0
if not (self.product_id and self.product_uom and
self.order_id.partner_id and self.order_id.pricelist_id and
self.order_id.pricelist_id.discount_policy == 'without_discount' and
self.env.user.has_group('sale.group_discount_per_so_line')):
return
+ self.discount = 0.0
product = self.product_id.with_context(
lang=self.order_id.partner_id.lang,
partner=self.order_id.partner_id.id,
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index ff6dac34c05..3a4ca384657 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -711,6 +711,8 @@ class Database(http.Controller):
@http.route('/web/database/restore', type='http', auth="none", methods=['POST'], csrf=False)
def restore(self, master_pwd, backup_file, name, copy=False):
try:
+ data_file = None
+ db.check_super(master_pwd)
with tempfile.NamedTemporaryFile(delete=False) as data_file:
backup_file.save(data_file)
db.restore_db(name, data_file.name, str2bool(copy))
@@ -719,7 +721,8 @@ class Database(http.Controller):
error = "Database restore error: %s" % (str(e) or repr(e))
return self._render_template(error=error)
finally:
- os.unlink(data_file.name)
+ if data_file:
+ os.unlink(data_file.name)
@http.route('/web/database/change_password', type='http', auth="none", methods=['POST'], csrf=False)
def change_password(self, master_pwd, master_pwd_new):
diff --git a/addons/website/models/ir_attachment.py b/addons/website/models/ir_attachment.py
index 215b182bfb8..eb81cd6702c 100644
--- a/addons/website/models/ir_attachment.py
+++ b/addons/website/models/ir_attachment.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from odoo import fields, models
+from odoo import api, fields, models
class Attachment(models.Model):
@@ -10,3 +10,7 @@ class Attachment(models.Model):
# related for backward compatibility with saas-6
website_url = fields.Char(string="Attachment URL", related='local_url', deprecated=True)
+
+ @api.model
+ def get_serving_groups(self):
+ return super(Attachment, self).get_serving_groups() + ['website.group_website_designer']
diff --git a/addons/website_mail/controllers/main.py b/addons/website_mail/controllers/main.py
index 4e85c240767..44ccb232d1f 100644
--- a/addons/website_mail/controllers/main.py
+++ b/addons/website_mail/controllers/main.py
@@ -40,7 +40,7 @@ def _message_post_helper(res_model='', res_id=None, message='', token='', token_
optional keywords arguments:
:param string token: access token if the object's model uses some kind of public access
using tokens (usually a uuid4) to bypass access rules
- :param string token_field: name of the field that contains the token on the object (defaults to 'token')
+ :param string token_field: name of the field that contains the token on the object (deprecated, use _mail_post_token_field)
:param string sha_in: Deprecated, use `token` and `token_field` instead
:param str sha_time: Deprecated, use `token` and `token_field` instead
:param bool nosubscribe: set False if you want the partner to be set as follower of the object when posting (default to True)
@@ -49,7 +49,7 @@ 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):
+ if token and record and token == getattr(record.sudo(), record._mail_post_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
@@ -57,6 +57,7 @@ def _message_post_helper(res_model='', res_id=None, message='', token='', token_
if not author_id:
raise NotFound()
kw.pop('csrf_token', None)
+ kw.pop('attachment_ids', None)
return record.with_context(mail_create_nosubscribe=nosubscribe).message_post(body=message,
message_type=kw.pop('message_type', "comment"),
subtype=kw.pop('subtype', "mt_comment"),
diff --git a/addons/website_mail/models/mail_message.py b/addons/website_mail/models/mail_message.py
index d5e12e41b0b..e60392f62bd 100644
--- a/addons/website_mail/models/mail_message.py
+++ b/addons/website_mail/models/mail_message.py
@@ -56,3 +56,9 @@ class MailMessage(models.Model):
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)
+
+
+class MailThread(models.AbstractModel):
+ _inherit = 'mail.thread'
+
+ _mail_post_token_field = 'access_token' # token field for external posts, to be overridden