diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py index d4eb9ec7ec451..6ef57c2f77733 100644 --- a/addons/auth_signup/controllers/main.py +++ b/addons/auth_signup/controllers/main.py @@ -5,7 +5,7 @@ from odoo import http, _ from odoo.addons.auth_signup.models.res_users import SignupError -from odoo.addons.web.controllers.main import ensure_db, Home +from odoo.addons.web.controllers.main import ensure_db, Home, SIGN_UP_REQUEST_PARAMS from odoo.addons.base_setup.controllers.main import BaseSetup from odoo.exceptions import UserError from odoo.http import request @@ -101,7 +101,7 @@ def get_auth_signup_config(self): def get_auth_signup_qcontext(self): """ Shared helper returning the rendering context for signup and reset password """ - qcontext = request.params.copy() + qcontext = {k: v for (k, v) in request.params.items() if k in SIGN_UP_REQUEST_PARAMS} qcontext.update(self.get_auth_signup_config()) if not qcontext.get('token') and request.session.get('auth_signup_token'): qcontext['token'] = request.session.get('auth_signup_token') diff --git a/addons/http_routing/models/ir_http.py b/addons/http_routing/models/ir_http.py index 0d02fb084c414..ae8a6635e46ac 100644 --- a/addons/http_routing/models/ir_http.py +++ b/addons/http_routing/models/ir_http.py @@ -16,7 +16,7 @@ slugify_lib = None import odoo -from odoo import api, models, registry, exceptions, tools +from odoo import api, models, registry, exceptions, tools, http from odoo.addons.base.models.ir_http import RequestUID, ModelConverter from odoo.addons.base.models.qweb import QWebException from odoo.http import request @@ -653,8 +653,7 @@ def _handle_exception(cls, exception): @tools.ormcache('path') def url_rewrite(self, path): new_url = False - req = request.httprequest - router = req.app.get_db_router(request.db).bind('') + router = http.root.get_db_router(request.db).bind('') try: _ = router.match(path, method='POST') except werkzeug.exceptions.MethodNotAllowed: @@ -672,7 +671,7 @@ def url_rewrite(self, path): @api.model @tools.cache('path', 'query_args') def _get_endpoint_qargs(self, path, query_args=None): - router = request.httprequest.app.get_db_router(request.db).bind('') + router = http.root.get_db_router(request.db).bind('') endpoint = False try: endpoint = router.match(path, method='POST', query_args=query_args) diff --git a/addons/l10n_fr_fec/wizard/account_fr_fec.py b/addons/l10n_fr_fec/wizard/account_fr_fec.py index d80c07d57ec62..db7be2b388224 100644 --- a/addons/l10n_fr_fec/wizard/account_fr_fec.py +++ b/addons/l10n_fr_fec/wizard/account_fr_fec.py @@ -7,7 +7,7 @@ import io from odoo import api, fields, models, _ -from odoo.exceptions import UserError +from odoo.exceptions import UserError, AccessDenied from odoo.tools import float_is_zero, pycompat @@ -30,7 +30,7 @@ def _onchange_export_file(self): if not self.test_file: self.export_type = 'official' - def do_query_unaffected_earnings(self): + def _do_query_unaffected_earnings(self): ''' Compute the sum of ending balances for all accounts that are of a type that does not bring forward the balance in new fiscal years. This is needed because we have to display only one line for the initial balance of all expense/revenue accounts in the FEC. ''' @@ -103,6 +103,8 @@ def _get_company_legal_data(self, company): def generate_fec(self): self.ensure_one() + if not (self.env.is_admin() or self.env.user.has_group('account.group_account_user')): + raise AccessDenied() # We choose to implement the flat file instead of the XML # file for 2 reasons : # 1) the XSD file impose to have the label on the account.move @@ -147,7 +149,7 @@ def generate_fec(self): unaffected_earnings_line = True # used to make sure that we add the unaffected earning initial balance only once if unaffected_earnings_xml_ref: #compute the benefit/loss of last year to add in the initial balance of the current year earnings account - unaffected_earnings_results = self.do_query_unaffected_earnings() + unaffected_earnings_results = self._do_query_unaffected_earnings() unaffected_earnings_line = False sql_query = ''' diff --git a/addons/mail/static/src/models/messaging_notification_handler/messaging_notification_handler.js b/addons/mail/static/src/models/messaging_notification_handler/messaging_notification_handler.js index a42ede1c6ae6b..79bedaecbadba 100644 --- a/addons/mail/static/src/models/messaging_notification_handler/messaging_notification_handler.js +++ b/addons/mail/static/src/models/messaging_notification_handler/messaging_notification_handler.js @@ -750,7 +750,9 @@ function factory(dependencies) { notificationTitle = owl.utils.escape(authorName); } } - const notificationContent = htmlToTextContentInline(message.body).substr(0, PREVIEW_MSG_MAX_SIZE); + const notificationContent = owl.utils.escape( + htmlToTextContentInline(message.body).substr(0, PREVIEW_MSG_MAX_SIZE) + ); this.env.services['bus_service'].sendNotification(notificationTitle, notificationContent); messaging.update({ outOfFocusUnreadMessageCounter: increment() }); const titlePattern = messaging.outOfFocusUnreadMessageCounter === 1 diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index fdbb1e80a1813..725ee27e3a107 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -1041,12 +1041,12 @@ def _create_payment_transaction(self, vals): if payment_token and payment_token.acquirer_id != acquirer: raise ValidationError(_('Invalid token found! Token acquirer %s != %s') % ( payment_token.acquirer_id.name, acquirer.name)) - if payment_token and payment_token.partner_id != partner: - raise ValidationError(_('Invalid token found! Token partner %s != %s') % ( - payment_token.partner.name, partner.name)) else: acquirer = payment_token.acquirer_id + if payment_token and payment_token.partner_id != partner: + raise ValidationError(_('Invalid token found!')) + # Check an acquirer is there. if not acquirer_id and not acquirer: raise ValidationError(_('A payment acquirer is required to create a transaction.')) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index ab9168c8c6795..1f75df6045e11 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -128,9 +128,8 @@ def redirect_with_hash(*args, **kw): return http.redirect_with_hash(*args, **kw) def abort_and_redirect(url): - r = request.httprequest response = werkzeug.utils.redirect(url, 302) - response = r.app.get_response(r, response, explicit_session=False) + response = http.root.get_response(request.httprequest, response, explicit_session=False) werkzeug.exceptions.abort(response) def ensure_db(redirect='/web/database/selector'): @@ -647,6 +646,10 @@ def get_qweb_templates_checksum(cls, addons, db=None, debug=False): def get_qweb_templates(cls, addons, db=None, debug=False): return cls(addons, db, debug=debug)._get_qweb_templates()[0] +# Shared parameters for all login/signup flows +SIGN_UP_REQUEST_PARAMS = {'db', 'login', 'debug', 'token', 'message', 'error', 'scope', 'mode', + 'redirect', 'redirect_hostname', 'email', 'name', 'partner_id', + 'password', 'confirm_password', 'city', 'country_id', 'lang'} class GroupsTreeNode: """ @@ -934,7 +937,7 @@ def web_login(self, redirect=None, **kw): if not request.uid: request.uid = odoo.SUPERUSER_ID - values = request.params.copy() + values = {k: v for k, v in request.params.items() if k in SIGN_UP_REQUEST_PARAMS} try: values['databases'] = http.db_list() except odoo.exceptions.AccessDenied: @@ -1102,7 +1105,7 @@ def post(self, path): from werkzeug.wrappers import BaseResponse base_url = request.httprequest.base_url query_string = request.httprequest.query_string - client = Client(request.httprequest.app, BaseResponse) + client = Client(http.root, BaseResponse) headers = {'X-Openerp-Session-Id': request.session.sid} return client.post('/' + path, base_url=base_url, query_string=query_string, headers=headers, data=data) diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index d80bb9337fb11..112b5f75dfe31 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -2088,22 +2088,13 @@ var FieldBinaryFile = AbstractFieldBinary.extend({ this.filename_value = this.recordData[this.attrs.filename]; }, _renderReadonly: function () { - this.do_toggle(!!this.value); - if (this.value) { - this.$el.empty().append($("").addClass('fa fa-download')); - if (this.recordData.id) { - this.$el.css('cursor', 'pointer'); - } else { - this.$el.css('cursor', 'not-allowed'); - } - if (this.filename_value) { - this.$el.append(" " + this.filename_value); - } - } - if (!this.res_id) { - this.$el.css('cursor', 'not-allowed'); - } else { - this.$el.css('cursor', 'pointer'); + var visible = !!(this.value && this.res_id); + this.$el.empty().css('cursor', 'not-allowed'); + this.do_toggle(visible); + if (visible) { + this.$el.css('cursor', 'pointer') + .text(this.filename_value || '') + .prepend($(''), ' '); } }, _renderEdit: function () { diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 4ccdd292b4a72..d478a5bcdb837 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -2441,7 +2441,7 @@ QUnit.module('basic_fields', { }); QUnit.test('binary fields that are readonly in create mode do not download', async function (assert) { - assert.expect(2); + assert.expect(4); // save the session function var oldGetFile = session.get_file; @@ -2473,10 +2473,17 @@ QUnit.module('basic_fields', { await testUtils.fields.many2one.clickOpenDropdown('product_id'); await testUtils.fields.many2one.clickHighlightedItem('product_id'); - assert.containsOnce(form, 'a.o_field_widget[name="document"] > .fa-download', + assert.containsOnce(form, 'a.o_field_widget[name="document"]', 'The link to download the binary should be present'); + assert.containsNone(form, 'a.o_field_widget[name="document"] > .fa-download', + 'The download icon should not be present'); + + var link = form.$('a.o_field_widget[name="document"]'); + assert.ok(link.is(':hidden'), "the link element should not be visible"); - testUtils.dom.click(form.$('a.o_field_widget[name="document"]')); + // force visibility to test that the clicking has also been disabled + link.removeClass('o_hidden'); + testUtils.dom.click(link); assert.verifySteps([]); // We shouldn't have passed through steps diff --git a/addons/website/models/website.py b/addons/website/models/website.py index 54719351b989d..e4f485f4a77f6 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -12,7 +12,7 @@ from werkzeug.datastructures import OrderedMultiDict from werkzeug.exceptions import NotFound -from odoo import api, fields, models, tools +from odoo import api, fields, models, tools, http from odoo.addons.http_routing.models.ir_http import slugify, _guess_mimetype, url_for from odoo.addons.website.models.ir_http import sitemap_qs2dom from odoo.addons.portal.controllers.portal import pager @@ -794,7 +794,7 @@ def _enumerate_pages(self, query_string=None, force=False): :rtype: list({name: str, url: str}) """ - router = request.httprequest.app.get_db_router(request.db) + router = http.root.get_db_router(request.db) # Force enumeration to be performed as public user url_set = set() @@ -973,7 +973,7 @@ def _get_canonical_url_localized(self, lang, canonical_params): """ self.ensure_one() if request.endpoint: - router = request.httprequest.app.get_db_router(request.db).bind('') + router = http.root.get_db_router(request.db).bind('') arguments = dict(request.endpoint_arguments) for key, val in list(arguments.items()): if isinstance(val, models.BaseModel): diff --git a/addons/website/static/src/js/content/snippets.animation.js b/addons/website/static/src/js/content/snippets.animation.js index b4ab28dfd4e42..f765e1bb96293 100644 --- a/addons/website/static/src/js/content/snippets.animation.js +++ b/addons/website/static/src/js/content/snippets.animation.js @@ -608,7 +608,10 @@ registry.mediaVideo = publicWidget.Widget.extend({ var def = this._super.apply(this, arguments); if (this.$target.children('iframe').length) { - // There already is an