diff --git a/addons/website/controllers/backend.py b/addons/website/controllers/backend.py
index 3d75facfc30..d9ca7981612 100644
--- a/addons/website/controllers/backend.py
+++ b/addons/website/controllers/backend.py
@@ -31,6 +31,7 @@ class WebsiteBackend(http.Controller):
if has_group_designer:
config = request.env['res.config.settings'].sudo().create({})
+ config.website_id = current_website
if config.has_google_analytics_dashboard:
dashboard_data['dashboards']['visits'] = dict(
ga_client_id=config.google_management_client_id or '', # void string instead of stringified False
@@ -39,7 +40,7 @@ class WebsiteBackend(http.Controller):
return dashboard_data
@http.route('/website/dashboard/set_ga_data', type='json', auth='user')
- def website_set_ga_data(self, ga_client_id, ga_analytics_key):
+ def website_set_ga_data(self, website_id, ga_client_id, ga_analytics_key):
if not request.env.user.has_group('base.group_system'):
return {
'error': {
@@ -54,10 +55,14 @@ class WebsiteBackend(http.Controller):
'message': 'The Google Analytics Client ID or Key you entered seems incorrect.',
}
}
+ Website = request.env['website']
+ current_website = website_id and Website.browse(website_id) or Website.get_current_website()
+
request.env['res.config.settings'].create({
'has_google_analytics': True,
'has_google_analytics_dashboard': True,
'google_management_client_id': ga_client_id,
'google_analytics_key': ga_analytics_key,
+ 'website_id': current_website,
}).execute()
return True
diff --git a/addons/website/models/__init__.py b/addons/website/models/__init__.py
index 8fa63d63d09..0ed659a8f3a 100644
--- a/addons/website/models/__init__.py
+++ b/addons/website/models/__init__.py
@@ -7,6 +7,7 @@ from . import ir_http
from . import ir_qweb
from . import ir_qweb_fields
from . import website
+from . import ir_rule
from . import ir_ui_view
from . import res_company
from . import res_partner
diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py
index 620e2cfd739..21c37801b96 100644
--- a/addons/website/models/ir_http.py
+++ b/addons/website/models/ir_http.py
@@ -267,6 +267,8 @@ class ModelConverter(ModelConverter):
def generate(self, uid, dom=None, args=None):
Model = request.env[self.model].sudo(uid)
+ # Allow to current_website_id directly in route domain
+ args.update(current_website_id=request.env['website'].get_current_website().id)
domain = safe_eval(self.domain, (args or {}).copy())
if dom:
domain += dom
diff --git a/addons/website/models/ir_rule.py b/addons/website/models/ir_rule.py
index 2a90dbfacfa..ba5e07128ee 100644
--- a/addons/website/models/ir_rule.py
+++ b/addons/website/models/ir_rule.py
@@ -8,5 +8,9 @@ class IrRule(models.Model):
@api.model
def _eval_context(self):
res = super(IrRule, self)._eval_context()
- res['website_id'] = self._context.get('website_id')
+ res['website_id'] = self.env['website'].get_current_website().id
return res
+
+ def _compute_domain_keys(self):
+ """ Return the list of context keys to use for caching ``_compute_domain``. """
+ return super(IrRule, self)._compute_domain_keys() + ['website_id']
diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py
index 3148bb984eb..c7a87da022e 100644
--- a/addons/website/models/ir_ui_view.py
+++ b/addons/website/models/ir_ui_view.py
@@ -297,3 +297,6 @@ class View(models.Model):
'url': '/website/pages',
'target': 'self',
}
+
+ def _read_template_keys(self):
+ return super(View, self)._read_template_keys() + ['website_id']
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index 3d2f379e322..1fd2ea4b5e5 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -694,18 +694,63 @@ class SeoMetadata(models.AbstractModel):
website_meta_keywords = fields.Char("Website meta keywords", translate=True)
+class WebsiteMultiMixin(models.AbstractModel):
+
+ _name = 'website.multi.mixin'
+
+ website_id = fields.Many2one('website', string='Website', help='Restrict publishing to this website.')
+
+ @api.multi
+ def can_access_from_current_website(self, website_id=False):
+ can_access = True
+ for record in self:
+ if (website_id or record.website_id.id) not in (False, request.website.id):
+ can_access = False
+ continue
+ return can_access
+
+
class WebsitePublishedMixin(models.AbstractModel):
_name = "website.published.mixin"
- website_published = fields.Boolean('Visible on current website',
- compute='_compute_website_published',
- inverse='_inverse_website_published',
- search='_search_website_published') # todo jov evaluate places where this is used, we can probably replace some with is_published
+ website_published = fields.Boolean('Visible on current website', related='is_published')
is_published = fields.Boolean('Is published')
- website_id = fields.Many2one('website', string='Website', help='Restrict publishing to this website.')
website_url = fields.Char('Website URL', compute='_compute_website_url', help='The full URL to access the document through the website.')
+ @api.multi
+ def _compute_website_url(self):
+ for record in self:
+ record.website_url = '#'
+
+ @api.multi
+ def website_publish_button(self):
+ self.ensure_one()
+ if self.env.user.has_group('website.group_website_publisher') and self.website_url != '#':
+ # Force website to land on record's website to publish/unpublish it
+ if 'website_id' in self and self.env.user.has_group('website.group_multi_website'):
+ self.website_id._force()
+ return self.open_website_url()
+ return self.write({'website_published': not self.website_published})
+
+ def open_website_url(self):
+ return {
+ 'type': 'ir.actions.act_url',
+ 'url': self.website_url,
+ 'target': 'self',
+ }
+
+
+class WebsitePublishedMultiMixin(WebsitePublishedMixin):
+
+ _name = 'website.published.multi.mixin'
+ _inherit = ['website.published.mixin', 'website.multi.mixin']
+
+ website_published = fields.Boolean(compute='_compute_website_published',
+ inverse='_inverse_website_published',
+ search='_search_website_published',
+ related=False)
+
@api.multi
@api.depends('is_published', 'website_id')
def _compute_website_published(self):
@@ -718,11 +763,8 @@ class WebsitePublishedMixin(models.AbstractModel):
@api.multi
def _inverse_website_published(self):
- current_website_id = self._context.get('website_id')
for record in self:
record.is_published = record.website_published
- if record.website_published and current_website_id:
- record.write({'website_id': current_website_id})
def _search_website_published(self, operator, value):
if not isinstance(value, bool) or operator not in ('=', '!='):
@@ -740,30 +782,11 @@ class WebsitePublishedMixin(models.AbstractModel):
else: # should be in the backend, return things that are published anywhere
return is_published
- @api.multi
- def _compute_website_url(self):
- for record in self:
- record.website_url = '#'
-
- @api.multi
- def website_publish_button(self):
- self.ensure_one()
- if self.env.user.has_group('website.group_website_publisher') and self.website_url != '#':
- return self.open_website_url()
- return self.write({'website_published': not self.website_published})
-
- def open_website_url(self):
- return {
- 'type': 'ir.actions.act_url',
- 'url': self.website_url,
- 'target': 'self',
- }
-
class Page(models.Model):
_name = 'website.page'
_inherits = {'ir.ui.view': 'view_id'}
- _inherit = 'website.published.mixin'
+ _inherit = 'website.published.multi.mixin'
_description = 'Page'
_order = 'website_id'
diff --git a/addons/website/static/src/js/backend/dashboard.js b/addons/website/static/src/js/backend/dashboard.js
index 393709b91db..b4fe22ba84e 100644
--- a/addons/website/static/src/js/backend/dashboard.js
+++ b/addons/website/static/src/js/backend/dashboard.js
@@ -112,6 +112,7 @@ var Dashboard = AbstractAction.extend(ControlPanelMixin, {
return this._rpc({
route: '/website/dashboard/set_ga_data',
params: {
+ 'website_id': self.website_id,
'ga_client_id': ga_client_id,
'ga_analytics_key': ga_analytics_key,
},
diff --git a/addons/website/views/website_views.xml b/addons/website/views/website_views.xml
index c0e1b4c842c..2c5d5dc4daa 100644
--- a/addons/website/views/website_views.xml
+++ b/addons/website/views/website_views.xml
@@ -75,7 +75,7 @@
current
-
+
website.redirect.form
diff --git a/addons/website_blog/controllers/main.py b/addons/website_blog/controllers/main.py
index f16f6ed761b..902b74dee90 100644
--- a/addons/website_blog/controllers/main.py
+++ b/addons/website_blog/controllers/main.py
@@ -48,13 +48,14 @@ class WebsiteBlog(http.Controller):
'/blog/page/',
], type='http', auth="public", website=True)
def blogs(self, page=1, **post):
+ domain = request.website.website_domain()
Blog = request.env['blog.blog']
- blogs = Blog.search([], limit=2)
+ blogs = Blog.search(domain, limit=2)
if len(blogs) == 1:
return werkzeug.utils.redirect('/blog/%s' % slug(blogs[0]), code=302)
BlogPost = request.env['blog.post']
- total = BlogPost.search([], count=True)
+ total = BlogPost.search_count(domain)
pager = request.website.pager(
url='/blog',
@@ -62,7 +63,7 @@ class WebsiteBlog(http.Controller):
page=page,
step=self._blog_post_per_page,
)
- posts = BlogPost.search([], offset=(page - 1) * self._blog_post_per_page, limit=self._blog_post_per_page)
+ posts = BlogPost.search(domain, offset=(page - 1) * self._blog_post_per_page, limit=self._blog_post_per_page)
blog_url = QueryURL('', ['blog', 'tag'])
return request.render("website_blog.latest_blogs", {
'posts': posts,
@@ -71,10 +72,10 @@ class WebsiteBlog(http.Controller):
})
@http.route([
- '/blog/',
- '/blog//page/',
- '/blog//tag/',
- '/blog//tag//page/',
+ '''/blog/''',
+ '''/blog//page/''',
+ '''/blog//tag/''',
+ '''/blog//tag//page/''',
], type='http', auth="public", website=True)
def blog(self, blog=None, tag=None, page=1, **opt):
""" Prepare all values to display the blog.
@@ -92,16 +93,19 @@ class WebsiteBlog(http.Controller):
- 'date': date_begin optional parameter, used in archives navigation
- 'blog_url': help object to create URLs
"""
+ if not blog.can_access_from_current_website():
+ raise werkzeug.exceptions.NotFound()
+
date_begin, date_end, state = opt.get('date_begin'), opt.get('date_end'), opt.get('state')
published_count, unpublished_count = 0, 0
+ domain = request.website.website_domain()
+
BlogPost = request.env['blog.post']
Blog = request.env['blog.blog']
- blogs = Blog.search([], order="create_date asc")
+ blogs = Blog.search(domain, order="create_date asc")
- # build the domain for blog post to display
- domain = []
# retrocompatibility to accept tag as slug
active_tag_ids = tag and [int(unslug(t)[1]) for t in tag.split(',')] or []
if active_tag_ids:
@@ -172,7 +176,7 @@ class WebsiteBlog(http.Controller):
response = request.render("website_blog.blog_post_short", values)
return response
- @http.route(['/blog//feed'], type='http', auth="public")
+ @http.route(['''/blog//feed'''], type='http', auth="public")
def blog_feed(self, blog, limit='15'):
v = {}
v['blog'] = blog
@@ -185,7 +189,7 @@ class WebsiteBlog(http.Controller):
return r
@http.route([
- '''/blog//post/''',
+ '''/blog//post/''',
], type='http', auth="public", website=True)
def blog_post(self, blog, blog_post, tag_id=None, page=1, enable_editor=None, **post):
""" Prepare all values to display the blog.
@@ -201,6 +205,9 @@ class WebsiteBlog(http.Controller):
- 'nav_list': a dict [year][month] for archives navigation
- 'next_post': next blog post, to direct the user towards the next interesting post
"""
+ if not blog.can_access_from_current_website():
+ raise werkzeug.exceptions.NotFound()
+
BlogPost = request.env['blog.post']
date_begin, date_end = post.get('date_begin'), post.get('date_end')
@@ -271,6 +278,12 @@ class WebsiteBlog(http.Controller):
@http.route('/blog//post/new', type='http', auth="public", website=True)
def blog_post_create(self, blog_id, **post):
+ # Use sudo so this line prevents both editor and admin to access blog from another website
+ # as browse() will return the record even if forbidden by security rules but editor won't
+ # be able to access it
+ if not request.env['blog.blog'].browse(blog_id).sudo().can_access_from_current_website():
+ raise werkzeug.exceptions.NotFound()
+
new_blog_post = request.env['blog.post'].create({
'blog_id': blog_id,
'website_published': False,
diff --git a/addons/website_blog/models/website_blog.py b/addons/website_blog/models/website_blog.py
index b1e0253b385..d9989c3d6a4 100644
--- a/addons/website_blog/models/website_blog.py
+++ b/addons/website_blog/models/website_blog.py
@@ -15,7 +15,7 @@ from odoo.tools import html2plaintext
class Blog(models.Model):
_name = 'blog.blog'
_description = 'Blogs'
- _inherit = ['mail.thread', 'website.seo.metadata']
+ _inherit = ['mail.thread', 'website.seo.metadata', 'website.multi.mixin']
_order = 'name'
name = fields.Char('Blog Name', required=True, translate=True)
@@ -108,7 +108,7 @@ class BlogTag(models.Model):
class BlogPost(models.Model):
_name = "blog.post"
_description = "Blog Post"
- _inherit = ['mail.thread', 'website.seo.metadata', 'website.published.mixin']
+ _inherit = ['mail.thread', 'website.seo.metadata', 'website.published.multi.mixin']
_order = 'id DESC'
_mail_post_access = 'read'
@@ -168,6 +168,8 @@ class BlogPost(models.Model):
visits = fields.Integer('No of Views', copy=False)
ranking = fields.Float(compute='_compute_ranking', string='Ranking')
+ website_id = fields.Many2one(related='blog_id.website_id', readonly=True)
+
@api.multi
@api.depends('content', 'teaser_manual')
def _compute_teaser(self):
diff --git a/addons/website_blog/views/website_blog_templates.xml b/addons/website_blog/views/website_blog_templates.xml
index 1853eaefaa8..069e5f93256 100644
--- a/addons/website_blog/views/website_blog_templates.xml
+++ b/addons/website_blog/views/website_blog_templates.xml
@@ -64,26 +64,26 @@
-
-
In
-
-
-
-
+
+
+
In
+
+
+
-
diff --git a/addons/website_blog/views/website_blog_views.xml b/addons/website_blog/views/website_blog_views.xml
index ddeee669d33..e9adbde891b 100644
--- a/addons/website_blog/views/website_blog_views.xml
+++ b/addons/website_blog/views/website_blog_views.xml
@@ -8,6 +8,7 @@
+
@@ -26,6 +27,7 @@
+
@@ -45,6 +47,7 @@
+
diff --git a/addons/website_event/controllers/main.py b/addons/website_event/controllers/main.py
index e50623b53fc..33e51724613 100644
--- a/addons/website_event/controllers/main.py
+++ b/addons/website_event/controllers/main.py
@@ -28,7 +28,6 @@ class WebsiteEventController(http.Controller):
searches.setdefault('type', 'all')
searches.setdefault('country', 'all')
- domain_search = {}
def sdn(date):
return fields.Datetime.to_string(date.replace(hour=23, minute=59, second=59))
@@ -64,6 +63,7 @@ class WebsiteEventController(http.Controller):
]
# search domains
+ domain_search = {'website_specific': request.website.website_domain()}
current_date = None
current_type = None
current_country = None
@@ -141,8 +141,11 @@ class WebsiteEventController(http.Controller):
return request.render("website_event.index", values)
- @http.route(['/event/
/page/'], type='http', auth="public", website=True, sitemap=False)
+ @http.route(['''/event//page/'''], type='http', auth="public", website=True, sitemap=False)
def event_page(self, event, page, **post):
+ if not event.can_access_from_current_website():
+ raise werkzeug.exceptions.NotFound()
+
values = {
'event': event,
'main_object': event
@@ -161,8 +164,11 @@ class WebsiteEventController(http.Controller):
return request.render(page, values)
- @http.route(['/event/'], type='http', auth="public", website=True)
+ @http.route(['''/event/'''], type='http', auth="public", website=True)
def event(self, event, **post):
+ if not event.can_access_from_current_website():
+ raise werkzeug.exceptions.NotFound()
+
if event.menu_id and event.menu_id.child_id:
target_url = event.menu_id.child_id[0].url
else:
@@ -171,8 +177,11 @@ class WebsiteEventController(http.Controller):
target_url += '?enable_editor=1'
return request.redirect(target_url)
- @http.route(['/event//register'], type='http', auth="public", website=True, sitemap=False)
+ @http.route(['''/event//register'''], type='http', auth="public", website=True, sitemap=False)
def event_register(self, event, **post):
+ if not event.can_access_from_current_website():
+ raise werkzeug.exceptions.NotFound()
+
values = {
'event': event,
'main_object': event,
@@ -195,6 +204,7 @@ class WebsiteEventController(http.Controller):
'date_begin': fields.Date.to_string(date_begin),
'date_end': fields.Date.to_string((date_begin + timedelta(days=(1)))),
'seats_available': 1000,
+ 'website_id': request.website.id,
}
return request.env['event.event'].with_context(context or {}).create(vals)
@@ -210,11 +220,12 @@ class WebsiteEventController(http.Controller):
country_code = request.session['geoip'].get('country_code')
result = {'events': [], 'country': False}
events = None
+ domain = request.website.website_domain()
if country_code:
country = request.env['res.country'].search([('code', '=', country_code)], limit=1)
- events = Event.search(['|', ('address_id', '=', None), ('country_id.code', '=', country_code), ('date_begin', '>=', '%s 00:00:00' % fields.Date.today()), ('state', '=', 'confirm')], order="date_begin")
+ events = Event.search(domain + ['|', ('address_id', '=', None), ('country_id.code', '=', country_code), ('date_begin', '>=', '%s 00:00:00' % fields.Date.today()), ('state', '=', 'confirm')], order="date_begin")
if not events:
- events = Event.search([('date_begin', '>=', '%s 00:00:00' % fields.Date.today()), ('state', '=', 'confirm')], order="date_begin")
+ events = Event.search(domain + [('date_begin', '>=', '%s 00:00:00' % fields.Date.today()), ('state', '=', 'confirm')], order="date_begin")
for event in events:
if country_code and event.country_id.code == country_code:
result['country'] = country
@@ -252,8 +263,11 @@ class WebsiteEventController(http.Controller):
registration[key] = value
return list(registrations.values())
- @http.route(['/event//registration/confirm'], type='http', auth="public", methods=['POST'], website=True)
+ @http.route(['''/event//registration/confirm'''], type='http', auth="public", methods=['POST'], website=True)
def registration_confirm(self, event, **post):
+ if not event.can_access_from_current_website():
+ raise werkzeug.exceptions.NotFound()
+
Attendees = request.env['event.registration']
registrations = self._process_registration_details(post)
@@ -270,7 +284,7 @@ class WebsiteEventController(http.Controller):
'iCal_url': urls.get('iCal_url')
})
- @http.route(['/event//ics'], type='http', auth="public", website=True)
+ @http.route(['''/event//ics'''], type='http', auth="public", website=True)
def make_event_ics_file(self, event, **kwargs):
if not event or not event.registration_ids:
return request.not_found()
diff --git a/addons/website_event/models/event.py b/addons/website_event/models/event.py
index 5bb045a320f..ae07f798939 100644
--- a/addons/website_event/models/event.py
+++ b/addons/website_event/models/event.py
@@ -32,9 +32,9 @@ class EventType(models.Model):
class Event(models.Model):
_name = 'event.event'
- _inherit = ['event.event', 'website.seo.metadata', 'website.published.mixin']
+ _inherit = ['event.event', 'website.seo.metadata', 'website.published.multi.mixin']
- website_published = fields.Boolean(track_visibility='onchange')
+ is_published = fields.Boolean(track_visibility='onchange')
is_participating = fields.Boolean("Is Participating", compute="_compute_is_participating")
@@ -45,7 +45,7 @@ class Event(models.Model):
def _compute_is_participating(self):
# we don't allow public user to see participating label
- if self.env.user != self.env.ref('base.public_user'):
+ if self.env.user != self.env['website'].get_current_website().user_id:
email = self.env.user.partner_id.email
for event in self:
domain = ['&', '|', ('email', '=', email), ('partner_id', '=', self.env.user.partner_id.id), ('event_id', '=', event.id)]
@@ -120,9 +120,9 @@ class Event(models.Model):
@api.multi
def _track_subtype(self, init_values):
self.ensure_one()
- if 'website_published' in init_values and self.website_published:
+ if 'is_published' in init_values and self.is_published:
return 'website_event.mt_event_published'
- elif 'website_published' in init_values and not self.website_published:
+ elif 'is_published' in init_values and not self.is_published:
return 'website_event.mt_event_unpublished'
return super(Event, self)._track_subtype(init_values)
diff --git a/addons/website_event/views/event_views.xml b/addons/website_event/views/event_views.xml
index 14339ac30d3..3c533e9e2ec 100644
--- a/addons/website_event/views/event_views.xml
+++ b/addons/website_event/views/event_views.xml
@@ -30,6 +30,9 @@
event.event
+
+
+
+
+ product.product.website.tree
+ product.product
+
+
+
+
+
+
+
+
+
+ product.template.website.tree
+ product.template
+
+
+
+
+
+
+
+
product.template.product.website.form
product.template
@@ -85,6 +107,7 @@
+
@@ -182,6 +205,7 @@
+
@@ -197,6 +221,7 @@
+
diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml
index 1f9a207d57b..cbc64b58754 100644
--- a/addons/website_sale/views/templates.xml
+++ b/addons/website_sale/views/templates.xml
@@ -271,7 +271,9 @@
-
+
+ (Unpublished)
+
diff --git a/addons/website_sale_delivery/models/delivery.py b/addons/website_sale_delivery/models/delivery.py
index 4884061ce86..2e0b878b8da 100644
--- a/addons/website_sale_delivery/models/delivery.py
+++ b/addons/website_sale_delivery/models/delivery.py
@@ -6,7 +6,7 @@ from odoo import fields, models
class DeliveryCarrier(models.Model):
_name = 'delivery.carrier'
- _inherit = ['delivery.carrier', 'website.published.mixin']
+ _inherit = ['delivery.carrier', 'website.published.multi.mixin']
website_description = fields.Text(related='product_id.description_sale', string='Description for Online Quotations')
website_published = fields.Boolean(default=False)
diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py
index 2ef722104b5..fb281276c85 100644
--- a/addons/website_slides/controllers/main.py
+++ b/addons/website_slides/controllers/main.py
@@ -57,7 +57,8 @@ class WebsiteSlides(http.Controller):
""" Returns a list of available channels: if only one is available,
redirects directly to its slides
"""
- channels = request.env['slide.channel'].search([], order='sequence, id')
+ domain = request.website.website_domain()
+ channels = request.env['slide.channel'].search(domain, order='sequence, id')
if not channels:
return request.render("website_slides.channel_not_found")
elif len(channels) == 1:
@@ -71,6 +72,7 @@ class WebsiteSlides(http.Controller):
def sitemap_slide(env, rule, qs):
Channel = env['slide.channel']
dom = sitemap_qs2dom(qs=qs, route='/slides/', field=Channel._rec_name)
+ dom += env['website'].get_current_website().website_domain()
for channel in Channel.search(dom):
loc = '/slides/%s' % slug(channel)
if not qs or qs.lower() in loc:
@@ -93,6 +95,9 @@ class WebsiteSlides(http.Controller):
'''/slides//category///page/'''],
type='http', auth="public", website=True, sitemap=sitemap_slide)
def channel(self, channel, category=None, tag=None, page=1, slide_type=None, sorting='creation', search=None, **kw):
+ if not channel.can_access_from_current_website():
+ raise werkzeug.exceptions.NotFound()
+
user = request.env.user
Slide = request.env['slide.slide']
domain = [('channel_id', '=', channel.id)]
@@ -164,8 +169,11 @@ class WebsiteSlides(http.Controller):
# SLIDE.SLIDE CONTOLLERS
# --------------------------------------------------
- @http.route('''/slides/slide/''', type='http', auth="public", website=True)
+ @http.route('''/slides/slide/''', type='http', auth="public", website=True)
def slide_view(self, slide, **kwargs):
+ if not slide.channel_id.can_access_from_current_website():
+ raise werkzeug.exceptions.NotFound()
+
values = self._get_slide_detail(slide)
if not values.get('private'):
self._set_viewed_slide(slide, 'slide')
diff --git a/addons/website_slides/data/website_slides_data.xml b/addons/website_slides/data/website_slides_data.xml
index 05d5f2d0aca..7ea95265642 100644
--- a/addons/website_slides/data/website_slides_data.xml
+++ b/addons/website_slides/data/website_slides_data.xml
@@ -2,9 +2,8 @@
-
- website_slides.google_app_key
- AIzaSyDOWlmDW-7DbLmOR9ZsT5AOEXf4n6TFwQA
+
+ AIzaSyDOWlmDW-7DbLmOR9ZsT5AOEXf4n6TFwQA
-
+
slide.channel.form
@@ -229,6 +231,7 @@
+
@@ -269,6 +272,7 @@
+
@@ -297,7 +301,7 @@
-
+
-
-
-
+
-
+
-
+
diff --git a/odoo/addons/base/models/ir_rule.py b/odoo/addons/base/models/ir_rule.py
index 32e03715eaa..afcf0ac197c 100644
--- a/odoo/addons/base/models/ir_rule.py
+++ b/odoo/addons/base/models/ir_rule.py
@@ -6,6 +6,7 @@ from collections import defaultdict
from odoo import api, fields, models, tools, SUPERUSER_ID, _
from odoo.exceptions import ValidationError
from odoo.osv import expression
+from odoo.tools import config
from odoo.tools.safe_eval import safe_eval
@@ -60,8 +61,16 @@ class IrRule(models.Model):
if any(rule.model_id.model == self._name for rule in self):
raise ValidationError(_('Rules can not be applied on the Record Rules model.'))
+ def _compute_domain_keys(self):
+ """ Return the list of context keys to use for caching ``_compute_domain``. """
+ return []
+
@api.model
- @tools.ormcache('self._uid', 'model_name', 'mode')
+ @tools.conditional(
+ 'xml' not in config['dev_mode'],
+ tools.ormcache('self._uid', 'model_name', 'mode',
+ 'tuple(self._context.get(k) for k in self._compute_domain_keys())'),
+ )
def _compute_domain(self, model_name, mode="read"):
if mode not in self._MODES:
raise ValueError('Invalid mode: %r' % (mode,))
diff --git a/odoo/addons/base/models/ir_ui_view.py b/odoo/addons/base/models/ir_ui_view.py
index 11a8fdb9a12..f46dd3eff39 100644
--- a/odoo/addons/base/models/ir_ui_view.py
+++ b/odoo/addons/base/models/ir_ui_view.py
@@ -1095,7 +1095,7 @@ actual arch.
def _read_template_keys(self):
""" Return the list of context keys to use for caching ``_read_template``. """
- return ['lang', 'inherit_branding', 'editable', 'translatable', 'edit_translations', 'website_id']
+ return ['lang', 'inherit_branding', 'editable', 'translatable', 'edit_translations']
# apply ormcache_context decorator unless in dev mode...
@api.model