summaryrefslogtreecommitdiff
path: root/odoo/addons
diff options
context:
space:
mode:
authorJeremy Kersten <jke@odoo.com>2018-08-13 20:36:28 +0200
committerJeremy Kersten <jke@odoo.com>2018-08-13 20:36:28 +0200
commitfbbf24f58acbcd9488cfa8393bd2d4e3a8e4c053 (patch)
tree2994a4151cbc70ac62d1741d84f7758c049557d4 /odoo/addons
parent15df14b9e1863ca09115d920595a6eeb9f6514f1 (diff)
parent853e13800fb030f7ae7180558cb6c3c74b843cd1 (diff)
[MERGE] website: add multi-websites support
Diffstat (limited to 'odoo/addons')
-rw-r--r--odoo/addons/base/data/ir_module_category_data.xml2
-rw-r--r--odoo/addons/base/models/assetsbundle.py55
-rw-r--r--odoo/addons/base/models/ir_http.py13
-rw-r--r--odoo/addons/base/models/ir_rule.py11
-rw-r--r--odoo/addons/base/models/ir_ui_view.py2
-rw-r--r--odoo/addons/base/models/res_partner.py44
-rw-r--r--odoo/addons/base/models/res_users.py16
7 files changed, 96 insertions, 47 deletions
diff --git a/odoo/addons/base/data/ir_module_category_data.xml b/odoo/addons/base/data/ir_module_category_data.xml
index 64ae170d68a..53fe9a4ba27 100644
--- a/odoo/addons/base/data/ir_module_category_data.xml
+++ b/odoo/addons/base/data/ir_module_category_data.xml
@@ -170,7 +170,7 @@
<record model="ir.module.category" id="module_category_theme">
<field name="name">Theme</field>
- <field name="exclusive" eval="1"/>
+ <field name="exclusive" eval="0"/>
<field name="sequence">50</field>
</record>
diff --git a/odoo/addons/base/models/assetsbundle.py b/odoo/addons/base/models/assetsbundle.py
index 2cec27197e9..121ba2fd968 100644
--- a/odoo/addons/base/models/assetsbundle.py
+++ b/odoo/addons/base/models/assetsbundle.py
@@ -198,6 +198,24 @@ class AssetsBundle(object):
check = u"%s%s" % (json.dumps(self.files, sort_keys=True), self.last_modified)
return hashlib.sha1(check.encode('utf-8')).hexdigest()
+ def _get_asset_template_url(self):
+ return "/web/content/{id}-{unique}/{extra}{name}{page}{type}" # name contains inc
+
+ def _get_asset_url_values(self, id, unique, extra, name, page, type): # extra can contain direction or/and website
+ return {
+ 'id': id,
+ 'unique': unique,
+ 'extra': extra,
+ 'name': name,
+ 'page': page,
+ 'type': type,
+ }
+
+ def get_asset_url(self, id='%', unique='%', extra='', name='%', page='%', type='%'):
+ return self._get_asset_template_url().format(
+ **self._get_asset_url_values(id=id, unique=unique, extra=extra, name=name, page=page, type=type)
+ )
+
def clean_attachments(self, type):
""" Takes care of deleting any outdated ir.attachment records associated to a bundle before
saving a fresh one.
@@ -213,12 +231,14 @@ class AssetsBundle(object):
must exclude the current bundle.
"""
ira = self.env['ir.attachment']
+ url = self.get_asset_url(
+ extra='%s' % ('rtl/' if type == 'css' and self.user_direction == 'rtl' else ''),
+ name=self.name,
+ type=type
+ )
domain = [
- ('url', '=like', '/web/content/%-%/{0}{1}%.{2}'.format( # The wilcards are id, version and pagination number (if any)
- ('rtl/' if type == 'css' and self.user_direction == 'rtl' else ''),
- self.name,
- type)),
- '!', ('url', '=like', '/web/content/%-{}/%'.format(self.version))
+ ('url', '=like', url),
+ '!', ('url', '=like', self.get_asset_url(unique=self.version))
]
# force bundle invalidation on other workers
@@ -234,13 +254,13 @@ class AssetsBundle(object):
multiple time the same bundle in our `to_html` function, we group our ir.attachment records
by file name and only return the one with the max id for each group.
"""
- version = "%" if ignore_version else self.version
- url_pattern = '/web/content/%-{0}/{1}{2}{3}.{4}'.format(
- version,
- ('rtl/' if type == 'css' and self.user_direction == 'rtl' else ''),
- self.name,
- '.%' if type == 'css' else '',
- type
+ unique = "%" if ignore_version else self.version
+ url_pattern = self.get_asset_url(
+ unique=unique,
+ extra='%s' % ('rtl/' if type == 'css' and self.user_direction == 'rtl' else ''),
+ name=self.name,
+ page='.%' if type == 'css' else '',
+ type='.%s' % type
)
self.env.cr.execute("""
SELECT max(id)
@@ -270,7 +290,7 @@ class AssetsBundle(object):
values = {
'name': "/web/content/%s" % type,
'datas_fname': fname,
- 'mimetype' : mimetype,
+ 'mimetype': mimetype,
'res_model': 'ir.ui.view',
'res_id': False,
'type': 'binary',
@@ -279,7 +299,14 @@ class AssetsBundle(object):
}
attachment = ira.sudo().create(values)
- url = '/web/content/%s-%s%s/%s' % (attachment.id, self.version, ('/rtl' if type == 'css' and self.user_direction == 'rtl' else ''), fname)
+ url = self.get_asset_url(
+ id=attachment.id,
+ unique=self.version,
+ extra='%s' % ('rtl/' if type == 'css' and self.user_direction == 'rtl' else ''),
+ name=fname,
+ page='', # included in fname
+ type='' # included in fname
+ )
values = {
'name': url,
'url': url,
diff --git a/odoo/addons/base/models/ir_http.py b/odoo/addons/base/models/ir_http.py
index cfc4967e9b4..4ab82909c5b 100644
--- a/odoo/addons/base/models/ir_http.py
+++ b/odoo/addons/base/models/ir_http.py
@@ -171,9 +171,10 @@ class IrHttp(models.AbstractModel):
if serve:
return serve
- # Don't handle exception but use werkeug debugger if server in --dev mode
- if 'werkzeug' in tools.config['dev_mode']:
- raise
+ # Don't handle exception but use werkzeug debugger if server in --dev mode
+ if 'werkzeug' in tools.config['dev_mode'] and not isinstance(exception, werkzeug.exceptions.NotFound):
+ raise exception
+
try:
return request._handle_exception(exception)
except AccessDenied:
@@ -244,6 +245,10 @@ class IrHttp(models.AbstractModel):
return content_disposition(filename)
@classmethod
+ def _xmlid_to_obj(cls, env, xmlid):
+ return env.ref(xmlid, False)
+
+ @classmethod
def binary_content(cls, xmlid=None, model='ir.attachment', id=None, field='datas',
unique=False, filename=None, filename_field='datas_fname', download=False,
mimetype=None, default_mimetype='application/octet-stream',
@@ -277,7 +282,7 @@ class IrHttp(models.AbstractModel):
# get object and content
obj = None
if xmlid:
- obj = env.ref(xmlid, False)
+ obj = cls._xmlid_to_obj(env, xmlid)
elif id and model == 'ir.attachment' and access_token:
obj = env[model].sudo().browse(int(id))
if not consteq(obj.access_token, access_token):
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
diff --git a/odoo/addons/base/models/res_partner.py b/odoo/addons/base/models/res_partner.py
index f17c0cd209f..a423af7835d 100644
--- a/odoo/addons/base/models/res_partner.py
+++ b/odoo/addons/base/models/res_partner.py
@@ -596,29 +596,35 @@ class Partner(models.Model):
'target': 'new',
'flags': {'form': {'action_buttons': True}}}
+ def _get_name(self):
+ """ Utility method to allow name_get to be overrided without re-browse the partner """
+ partner = self
+ name = partner.name or ''
+
+ if partner.company_name or partner.parent_id:
+ if not name and partner.type in ['invoice', 'delivery', 'other']:
+ name = dict(self.fields_get(['type'])['type']['selection'])[partner.type]
+ if not partner.is_company:
+ name = "%s, %s" % (partner.commercial_company_name or partner.parent_id.name, name)
+ if self._context.get('show_address_only'):
+ name = partner._display_address(without_company=True)
+ if self._context.get('show_address'):
+ name = name + "\n" + partner._display_address(without_company=True)
+ name = name.replace('\n\n', '\n')
+ name = name.replace('\n\n', '\n')
+ if self._context.get('address_inline'):
+ name = name.replace('\n', ', ')
+ if self._context.get('show_email') and partner.email:
+ name = "%s <%s>" % (name, partner.email)
+ if self._context.get('html_format'):
+ name = name.replace('\n', '<br/>')
+ return name
+
@api.multi
def name_get(self):
res = []
for partner in self:
- name = partner.name or ''
-
- if partner.company_name or partner.parent_id:
- if not name and partner.type in ['invoice', 'delivery', 'other']:
- name = dict(self.fields_get(['type'])['type']['selection'])[partner.type]
- if not partner.is_company:
- name = "%s, %s" % (partner.commercial_company_name or partner.parent_id.name, name)
- if self._context.get('show_address_only'):
- name = partner._display_address(without_company=True)
- if self._context.get('show_address'):
- name = name + "\n" + partner._display_address(without_company=True)
- name = name.replace('\n\n', '\n')
- name = name.replace('\n\n', '\n')
- if self._context.get('address_inline'):
- name = name.replace('\n', ', ')
- if self._context.get('show_email') and partner.email:
- name = "%s <%s>" % (name, partner.email)
- if self._context.get('html_format'):
- name = name.replace('\n', '<br/>')
+ name = partner._get_name()
res.append((partner.id, name))
return res
diff --git a/odoo/addons/base/models/res_users.py b/odoo/addons/base/models/res_users.py
index e00738323a5..dcd8921ee21 100644
--- a/odoo/addons/base/models/res_users.py
+++ b/odoo/addons/base/models/res_users.py
@@ -545,6 +545,10 @@ class Users(models.Model):
# extra records will be deleted by the periodical garbage collection
self.env['res.users.log'].create({}) # populated by defaults
+ @api.model
+ def _get_login_domain(self, login):
+ return [('login', '=', login)]
+
@classmethod
def _login(cls, db, login, password):
if not password:
@@ -554,13 +558,11 @@ class Users(models.Model):
with cls.pool.cursor() as cr:
self = api.Environment(cr, SUPERUSER_ID, {})[cls._name]
with self._assert_can_auth():
- user = self.search([('login', '=', login)])
- if not user:
- raise AccessDenied()
-
- user = user.sudo(user.id)
- user._check_credentials(password)
- user._update_last_login()
+ user = self.search(self._get_login_domain(login))
+ if user:
+ user = user.sudo(user.id)
+ user._check_credentials(password)
+ user._update_last_login()
except AccessDenied:
_logger.info("Login failed for db:%s login:%s from %s", db, login, ip)
raise