[MERGE] forward port of branch 8.0 up to 5e3e41b
This commit is contained in:
@@ -141,7 +141,7 @@ class mrp_repair(osv.osv):
|
||||
'location_id': fields.many2one('stock.location', 'Current Location', select=True, required=True, readonly=True, states={'draft': [('readonly', False)], 'confirmed': [('readonly', True)]}),
|
||||
'location_dest_id': fields.many2one('stock.location', 'Delivery Location', readonly=True, required=True, states={'draft': [('readonly', False)], 'confirmed': [('readonly', True)]}),
|
||||
'lot_id': fields.many2one('stock.production.lot', 'Repaired Lot', domain="[('product_id','=', product_id)]", help="Products repaired are all belonging to this lot", oldname="prodlot_id"),
|
||||
'guarantee_limit': fields.date('Warranty Expiration', help="The warranty expiration limit is computed as: last move date + warranty defined on selected product. If the current date is below the warranty expiration limit, each operation and fee you will add will be set as 'not to invoiced' by default. Note that you can change manually afterwards.", states={'confirmed': [('readonly', True)]}),
|
||||
'guarantee_limit': fields.date('Warranty Expiration', states={'confirmed': [('readonly', True)]}),
|
||||
'operations': fields.one2many('mrp.repair.line', 'repair_id', 'Operation Lines', readonly=True, states={'draft': [('readonly', False)]}, copy=True),
|
||||
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', help='Pricelist of the selected partner.'),
|
||||
'partner_invoice_id': fields.many2one('res.partner', 'Invoicing Address'),
|
||||
|
||||
@@ -306,12 +306,12 @@ class sale_order_line(osv.osv):
|
||||
return res
|
||||
|
||||
# set product uom in context to get virtual stock in current uom
|
||||
if res.get('value', {}).get('product_uom'):
|
||||
if 'product_uom' in res.get('value', {}):
|
||||
# use the uom changed by super call
|
||||
context.update({'uom': res['value']['product_uom']})
|
||||
context = dict(context, uom=res['value']['product_uom'])
|
||||
elif uom:
|
||||
# fallback on selected
|
||||
context.update({'uom': uom})
|
||||
context = dict(context, uom=uom)
|
||||
|
||||
#update of result obtained in super function
|
||||
product_obj = product_obj.browse(cr, uid, product, context=context)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from datetime import datetime
|
||||
import werkzeug.exceptions
|
||||
import werkzeug.urls
|
||||
import werkzeug.wrappers
|
||||
import simplejson
|
||||
@@ -188,6 +189,11 @@ class WebsiteForum(http.Controller):
|
||||
|
||||
@http.route(['''/forum/<model("forum.forum"):forum>/question/<model("forum.post", "[('forum_id','=',forum[0]),('parent_id','=',False)]"):question>'''], type='http', auth="public", website=True)
|
||||
def question(self, forum, question, **post):
|
||||
|
||||
# Hide posts from abusers (negative karma), except for moderators
|
||||
if not question.can_view:
|
||||
raise werkzeug.exceptions.NotFound()
|
||||
|
||||
# increment view counter
|
||||
question.sudo().set_viewed()
|
||||
if question.parent_id:
|
||||
|
||||
@@ -154,7 +154,7 @@ class Post(models.Model):
|
||||
|
||||
name = fields.Char('Title')
|
||||
forum_id = fields.Many2one('forum.forum', string='Forum', required=True)
|
||||
content = fields.Html('Content')
|
||||
content = fields.Html('Content', strip_style=True)
|
||||
plain_content = fields.Text('Plain Content', compute='_get_plain_content', store=True)
|
||||
|
||||
@api.one
|
||||
@@ -287,17 +287,21 @@ class Post(models.Model):
|
||||
can_downvote = fields.Boolean('Can Downvote', compute='_get_post_karma_rights')
|
||||
can_comment = fields.Boolean('Can Comment', compute='_get_post_karma_rights')
|
||||
can_comment_convert = fields.Boolean('Can Convert to Comment', compute='_get_post_karma_rights')
|
||||
can_view = fields.Boolean('Can View', compute='_get_post_karma_rights')
|
||||
|
||||
@api.one
|
||||
def _get_post_karma_rights(self):
|
||||
user = self.env.user
|
||||
post = self.sudo()
|
||||
|
||||
self.karma_accept = self.parent_id and self.parent_id.create_uid.id == self._uid and self.forum_id.karma_answer_accept_own or self.forum_id.karma_answer_accept_all
|
||||
self.karma_edit = self.create_uid.id == self._uid and self.forum_id.karma_edit_own or self.forum_id.karma_edit_all
|
||||
self.karma_close = self.create_uid.id == self._uid and self.forum_id.karma_close_own or self.forum_id.karma_close_all
|
||||
self.karma_unlink = self.create_uid.id == self._uid and self.forum_id.karma_unlink_own or self.forum_id.karma_unlink_all
|
||||
self.karma_comment = self.create_uid.id == self._uid and self.forum_id.karma_comment_own or self.forum_id.karma_comment_all
|
||||
self.karma_comment_convert = self.create_uid.id == self._uid and self.forum_id.karma_comment_convert_own or self.forum_id.karma_comment_convert_all
|
||||
is_creator = post.create_uid.id == self._uid
|
||||
|
||||
self.karma_accept = self.forum_id.karma_answer_accept_own if post.parent_id and post.parent_id.create_uid.id == self._uid else self.forum_id.karma_answer_accept_all
|
||||
self.karma_edit = self.forum_id.karma_edit_own if is_creator else self.forum_id.karma_edit_all
|
||||
self.karma_close = self.forum_id.karma_close_own if is_creator else self.forum_id.karma_close_all
|
||||
self.karma_unlink = self.forum_id.karma_unlink_own if is_creator else self.forum_id.karma_unlink_all
|
||||
self.karma_comment = self.forum_id.karma_comment_own if is_creator else self.forum_id.karma_comment_all
|
||||
self.karma_comment_convert = self.forum_id.karma_comment_convert_own if is_creator else self.forum_id.karma_comment_convert_all
|
||||
|
||||
self.can_ask = user.karma >= self.forum_id.karma_ask
|
||||
self.can_answer = user.karma >= self.forum_id.karma_answer
|
||||
@@ -309,6 +313,7 @@ class Post(models.Model):
|
||||
self.can_downvote = user.karma >= self.forum_id.karma_downvote
|
||||
self.can_comment = user.karma >= self.karma_comment
|
||||
self.can_comment_convert = user.karma >= self.karma_comment_convert
|
||||
self.can_view = user.karma >= self.karma_close or post.create_uid.karma > 0
|
||||
|
||||
@api.one
|
||||
@api.constrains('post_type', 'forum_id')
|
||||
|
||||
@@ -25,7 +25,8 @@ class WebsiteResPartner(osv.Model):
|
||||
_get_private, fnct_inv=_set_private, fnct_search=_search_private,
|
||||
type='boolean', string='Private Profile'),
|
||||
'website_description': fields.html(
|
||||
'Website Partner Full Description'
|
||||
'Website Partner Full Description',
|
||||
strip_style=True
|
||||
),
|
||||
'website_short_description': fields.text(
|
||||
'Website Partner Short Description'
|
||||
|
||||
@@ -146,7 +146,7 @@ class TestHtmlField(common.TransactionCase):
|
||||
% if object.some_field and not object.oriented:
|
||||
<table>
|
||||
% if object.other_field:
|
||||
<tr>
|
||||
<tr style="border: 10px solid black;">
|
||||
${object.mako_thing}
|
||||
<td>
|
||||
</tr>
|
||||
@@ -173,5 +173,11 @@ class TestHtmlField(common.TransactionCase):
|
||||
# sanitize should have closed tags left open in the original html
|
||||
self.assertIn('</table>', partner.comment, 'Error in HTML field: content does not seem to have been sanitized despise sanitize=True')
|
||||
self.assertIn('</td>', partner.comment, 'Error in HTML field: content does not seem to have been sanitized despise sanitize=True')
|
||||
self.assertIn('<tr style="', partner.comment, 'Style attr should not have been stripped')
|
||||
|
||||
self.partner._columns['comment'] = fields.html('Stripped Html', sanitize=True, strip_style=True)
|
||||
self.partner.write(cr, uid, [pid], {'comment': some_ugly_html}, context=context)
|
||||
partner = self.partner.browse(cr, uid, pid, context=context)
|
||||
self.assertNotIn('<tr style="', partner.comment, 'Style attr should have been stripped')
|
||||
|
||||
self.partner._columns = old_columns
|
||||
|
||||
+6
-1
@@ -1076,16 +1076,21 @@ class Text(_String):
|
||||
class Html(_String):
|
||||
type = 'html'
|
||||
sanitize = True # whether value must be sanitized
|
||||
strip_style = False # whether to strip style attributes
|
||||
|
||||
_column_sanitize = property(attrgetter('sanitize'))
|
||||
_related_sanitize = property(attrgetter('sanitize'))
|
||||
_description_sanitize = property(attrgetter('sanitize'))
|
||||
|
||||
_column_strip_style = property(attrgetter('strip_style'))
|
||||
_related_strip_style = property(attrgetter('strip_style'))
|
||||
_description_strip_style = property(attrgetter('strip_style'))
|
||||
|
||||
def convert_to_cache(self, value, record, validate=True):
|
||||
if value is None or value is False:
|
||||
return False
|
||||
if validate and self.sanitize:
|
||||
return html_sanitize(value)
|
||||
return html_sanitize(value, strip_style=self.strip_style)
|
||||
return value
|
||||
|
||||
|
||||
|
||||
@@ -317,11 +317,12 @@ class html(text):
|
||||
return None
|
||||
if not self._sanitize:
|
||||
return value
|
||||
return html_sanitize(value)
|
||||
return html_sanitize(value, strip_style=self._strip_style)
|
||||
|
||||
def __init__(self, string='unknown', sanitize=True, **args):
|
||||
def __init__(self, string='unknown', sanitize=True, strip_style=False, **args):
|
||||
super(html, self).__init__(string=string, **args)
|
||||
self._sanitize = sanitize
|
||||
self._strip_style = strip_style
|
||||
# symbol_set redefinition because of sanitize specific behavior
|
||||
self._symbol_f = self._symbol_set_html
|
||||
self._symbol_set = (self._symbol_c, self._symbol_f)
|
||||
|
||||
@@ -53,7 +53,7 @@ safe_attrs = clean.defs.safe_attrs | frozenset(
|
||||
])
|
||||
|
||||
|
||||
def html_sanitize(src, silent=True, strict=False):
|
||||
def html_sanitize(src, silent=True, strict=False, strip_style=False):
|
||||
if not src:
|
||||
return src
|
||||
src = ustr(src, errors='replace')
|
||||
@@ -69,7 +69,7 @@ def html_sanitize(src, silent=True, strict=False):
|
||||
|
||||
kwargs = {
|
||||
'page_structure': True,
|
||||
'style': False, # do not remove style attributes
|
||||
'style': strip_style, # True = remove style tags/attrs
|
||||
'forms': True, # remove form tags
|
||||
'remove_unknown_tags': False,
|
||||
'allow_tags': allowed_tags,
|
||||
|
||||
Reference in New Issue
Block a user