Commit Graph
1216 Commits
Author SHA1 Message Date
Géry Debongnie 286cc97dd4 [IMP] web: allow lang to be overriden by url query params
With this commit, it is possible to load the web client in a language
different than the user by using the `lang=` query string in the url:
For example, `/web?lang=en_US`

This is useful when we need to quickly check something, without changing
the current user settings. Note that it will only work if the url lang
has been installed on the database (if lang does not exist, it will fall
back to en_us).

closes odoo/odoo#128121

Taskid: #3420252
Signed-off-by: Samuel Degueldre (sad) <sad@odoo.com>
2023-07-25 10:35:41 +02:00
Mathieu Duckerts-AntoineandOliver Dony afdb546e44 [FIX] web: domain field: quick save after debug edit
When a domain field value is edited via the debug textarea, no
search_count is done for performance reasons. A single exception is done
when saving the record. Then we check the validity of the domain created
in the debug textarea in order to avoid to save an invalid domain in db
(and get tracebacks,..). The problem is that a search_count can take a
very long time to be executed if the domain is valid. Here we introduce
a route /web/domain/validate in order to quickly check the validity of a
domain and use it in domain field in order to fix the above mentionned
performance issue. Note that the search_count is still done if it useful
but does not have to be waited anymore.

X-original-commit: 40288221c39ff8fba41cd6ac231ab33600dc0cd4
Part-of: odoo/odoo#128913
Co-authored-by: Oliver Dony <odo@odoo.com>
Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com>
2023-07-19 11:40:09 +02:00
Xavier-Do 595aa24843 [IMP] registry: multiple ormcache
One of the main issue with ormcache is that the invalidation clears
everything, meaning that some value, slow to compute but with a long
lifetime, can be removed from the cache because an easy to invalidate
value is cleared, like after writting or creating a product has an
example.

Most example in the code will try to invalidate the cache of the models
doing something like `env['ir.qweb'].clear_caches()` but it is
finally equivalent to `env.registry.clear_cache()`, and cross worker.

The idea is to have multiple cache, maybe with specific sizes for a
specific purpose.

Having one per model is maybe a bad idea because it will be difficult
to size the LRU correcly, and it is too dynamic. Checking invalidation
may be expensive.

The proposed solution is closed allow a limited number of named caches,
using onse sequence per cache. This is actually close to the
cache_longterm.

We want to discourage using a specific cache for one use case in
the buisness code. Adding a cache shouldn't be something easy, doable
in stable.

Note that we could also change the invalisation mecanism using an
insert only table. We an check the sequence of this table, but also
fetch all invalidation messages.
Another possible improvement, especially if we have more than x cache is
to have a global sequence, checking signaling would mean to check the
main sequence, and only the other ones if the main one changed.

Note that this poc is inspired from the long term cache but not all
use case where applie yet.

Part-of: odoo/odoo#119813
2023-07-18 11:42:26 +02:00
Nasreddin Boulif (bon) 189017d10c [FIX] web: allow exporting record with properties when grouped
Steps to reproduce:

  - Install `CRM` for test purpose
  - Go to `CRM > Pipeline` and open any lead
  - Add a new property and set a value
  - Go back and open list view
  - Group by `Salesperson`
  - Select all records and click on `Export` in action menu
  - Add 'Properties' field
  - Export

Issue:

  Traceback raised. No issue if not grouped.

Cause:

  The properties value is a list of dict. When grouped, the properties
  value is not converted to string (like it is done for list and tuples
  in the non-grouped flow).

Solution:

  Move the code that convert list and tuples to string in the
  non-grouped flow directly to the `write_cell` method so that it is
  applied in both cases.

opw-3338564

closes odoo/odoo#128682

X-original-commit: f380c56bb13773eee0e19462ba7283b04d54183b
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
2023-07-17 12:06:33 +02:00
Julien Castiaux cc6b60f72f [IMP] web: default robots.txt
Web lacked a default route for /robots.txt meaning that if you didn't
installed website (which comes with a full fledged robots.txt) you would
get a 404 page not found.

closes odoo/odoo#127402

Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
2023-07-07 06:15:46 +02:00
Martin Trigaux 604a47ead8 [IMP] *: remove global ACL
THese are rarely intended for all users but often intended only for
employees.

account:
account.incoterms: only used within internal business models
account.journal.group: same as account.journal, add sudo in computed field

account_edi: need access to accounting objects

base_address_extended:
res.city: only employees should access address data

board: only employees uses this (old) module

crm:
crm.stage: internal users business object

hr_recruitment: employees can read

im_livechat: apply same as for the steps

l10n_ar: used on partner, not only invoices
l10n_ec: accessed only through account.move
l10n_latam: accessed on res.partner

mail:
publisher.warrenty.contract: no data, only static models
mail.channel: group_user has already his own rule
mail.group: group_user has already his own rule
mail.message.subtype: group_user has already his own rule
mail.message.all: remove, already has a portal and employee rule

partner_autocomplete: no interaction with public

project:
project.tags: only needed for project sharing

sale_management:
sale.order.option: same as sale.order

utm: employee already has write access

web_editor: test models that have nothing to do here
web_tour: only employees uses tours

website_sale:
product.ribbon: add sudo for access

base:
ir.default: only employees uses set (could probably be converted to group_system)
ir.ui.view.custom: same as ir.ui.view, add sudo when needed
report.*: portal users don't configure reports
res.users.log: create in sudo, no access needed (adapt test to use another model)
res.lang: still needed for public

closes odoo/odoo#118701

Related: odoo/enterprise#41285
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
2023-06-12 22:39:26 +02:00
Michele 724df8a570 [IMP] core: new neutralize flag on database restore and database duplicate dialog
Before this PR:
The only way to neutralize the database is running cli command neutralize

After this PR:
There is a new checkbox "neutralize database" in Duplicate database and Restore database dialog that neutralize the database after duplication/restore.
I also moved the neutralization code to the external module so it can be called also outside the cli .

closes odoo/odoo#122185

X-original-commit: 616740e9d09b3d0376be43ed1489e390f6f5823e
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
2023-05-24 11:53:38 +02:00
Denis Ledoux 58ea5e7b43 [IMP] http.py: do not inject context by default in JSON routes
Before this revision, when you pass `context` in the arguments
of a JSON routes, this one gets automatically injected
in the environment context.

This is not the case for regular HTTP routes.

It makes sense to propagate the context for the JSONRPC protocol,
JSON routes used by the backend, such as `call_kw`,
but it doesn't make sense to pass this context automatically
for any other kind of routes, such as front-end routes
or routes used by custom Javascript widgets.

This change brings a more unified behavior for routes
of types HTTP and JSON.
In addition, most developers were not aware of this "feautre",
that passing `context` in the arguments of a JSON route leaded
to the injection of this context in the environment context.
This is actually reflected by the diff size this changes required,
only a dozens of routes needed to be adapted, to manually
add the context in their route arguments and to inject it
in their environment context.

closes odoo/odoo#121726

X-original-commit: a7a5655631e6d5b05fd2ba3d0c80617aae6d9cfe
Related: odoo/enterprise#41229
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
2023-05-22 11:43:04 +02:00
flvr-odoo a5f8788332 [FIX] web : adding csp for automated scanner
Due to numerous client complaining about their automated scanner not
seeing the CSP header on the http request, we add it for good mesures

opw-2793379

closes odoo/odoo#121098

X-original-commit: 70a54ac604cf2aeef33d11b95851e35dd463727f
Signed-off-by: Vranckx Florian (flvr) <flvr@odoo.com>
2023-05-11 00:33:48 +02:00
Julien CastiauxandRaphaël Collet 5a998694a6 [IMP] core: merge subqueries WHERE clauses
Rationale
---------

Given the following domain:

    ['|',
        ('company_id.name', 'like', 'BE'),
        ('company_id.city', 'like', 'Brussels')]

The ORM would generate the following SQL query:

    SELECT "res_partner"."id"
    FROM "res_partner"
    WHERE "res_partner"."company_id" IN (
        SELECT "res_company"."id"
        FROM "res_company"
        WHERE "res_company"."name" like 'BE'
    ) OR "res_partner"."company_id" IN (
        SELECT "res_company"."id"
        FROM "res_company"
        WHERE "res_company"."email" like 'help@odoo.com'
    );

Which is sub-optiomal as the WHERE clause of the two subqueries could be
regrouped inside of a single query like so:

    SELECT "res_partner"."id"
    FROM "res_partner"
    WHERE "res_partner"."company_id" IN (
        SELECT "res_company"."id"
        FROM "res_company" WHERE (
            "res_company"."name" like 'BE'
            OR "res_company"."email" like 'help@odoo.com'
        )
    );

Postgres-wise, it is faster to execute the latter query than the former
one. This commit is about optimizing the ORM so that it generates
queries where the WHERE clause of compatible subqueries are grouped
together.

Technical solution
------------------

The solution explored by this work is to replace the regular relational
field accesses (over a dotted path) by a new `any` operator that look as
follow:

    (relational_field, 'any', domain)

For instance, the above `('company_id.name', 'like', 'BE')` leaf becomes
`('company_id', 'any', [('name', 'like', 'BE')]` using `any`.

Having a domain as right-hand-side allow for the combination of the
domains of same compatible relations:

    [('company_id', 'any', ['|',
        ('name', 'like', 'BE'),
        ('city', 'like', 'Brussels')])

Having combined domains allows for generating better SQL queries with
minimal changes to the expression parsing algorithm, which can only
translate a single leaf at a time to SQL. With the new `any` operator,
it is still a single leaf but the right-hand-side contains the merged
domain, thus the combined SQL WHERE clause is immediately generated.

task-id-3234671

Part-of: odoo/odoo#118067
Co-authored-by: Raphaël Collet <rco@odoo.com>
2023-04-27 10:12:57 +02:00
Rémy Voet (ryv) 234db70d86 [IMP] *: Use the new API of _read_group for backend use
Part-of: odoo/odoo#110737
2023-04-19 21:58:27 +02:00
niyasraphy bcb245e749 [FIX] web: traceback on accessing home page
before this commit, after running an older version,
 lets say odoo 14 and trying to access 16 in the
 same browser return traceback without redirecting
  to db selector page

 and this happens due to the missing env in request,
 which returns as None.

 after this commit, no traceback wont be shown and
 will open the db selector page

closes odoo/odoo#118851

X-original-commit: 900303c18243e3b97414b3dbf5eb7ee5b8c9c080
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
2023-04-18 17:25:43 +02:00
valeriobelcastro a33dbdb5c7 [IMP] handle query parameters on /web route
closes odoo/odoo#117987

Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
2023-04-09 12:57:40 +02:00
Mohit Beniwal 66cac3a7ed [FIX] inventory: invalid literal for base 10:'false' in inventory
This issue was occurring while printing the count sheets in the 'update
quantity' section of products in 'Inventory' module.

Steps to Reproduce:
- Open Inventory module and go to any product.
- Click on update quantity button.
- Click create button, select the new record without saving it.
  Then click Print > Count Sheet

To fix this we check whether it is integer or not, if it is integer then
only it will print the report.

sentry-3880400776

closes odoo/odoo#115186

X-original-commit: 2600c17859363f5ec8c1f50a73e9d1990aa762ba
Signed-off-by: Ivan Elizaryev (iel) <iel@odoo.com>
2023-03-14 14:39:22 +01:00
Petar Najman e71fe9820a [FIX] web: Locale not loaded for Serbian lang
In Serbia there are two language codes and those are `sr_RS` (Cyrillic) and `sr@latin` (Latin). Inside of the `web/static/lib/moment/locale` folder, the two langs are registered as `sr-cyrl.js` and `sr.js` respectively. The `load_locale` controller wasn't loading the right langs for neither case.

X-original-commit: 65d5ab801f22b42a0f94fe4b86f68ace451ea184
Part-of: odoo/odoo#114565
2023-03-13 10:53:00 +01:00
nda-odoo f5e8d8ea92 [FIX] web: faster asset search
Help postgres planner avoiding a scan over the entire table.

On a database with 5.5M ir_attachment but only a few url:
before: https://explain.dalibo.com/plan/g45f7492a78d6e19#raw
after: https://explain.dalibo.com/plan/1f5868ba6909b5df#raw

from 1156.316 ms to 2.334 ms

opw-3134913

closes odoo/odoo#113389

X-original-commit: 1549c4dc81f1f5f327b9115944faa87255c31624
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
2023-02-22 17:48:58 +01:00
Benoit Socias fb9efde4f3 [FIX] *: replace werkzeug's Response by odoo's Response
*: base, http_routing, mass_mailing, web, web_editor, website_slides

In some situations `werkzeug.wrappers.Response` are used instead of
`odoo.http.Reponse` that extends it.
This is a problem because since [1] the calls to `set_cookie` expect it
to accept the `cookie_type` parameter, which is not the case in the base
werkzeug implementation.

This commit replaces the `werkzeug.wrappers.Response` by
`odoo.http.Response`.

[1]: https://github.com/odoo/odoo/commit/2cbda6c98ee947cea1d06c09880eee8c758304a8

closes odoo/odoo#112827

X-original-commit: 28da08292b7028575e628c5ad846fc05d30498f2
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
2023-02-16 09:01:07 +01:00
Julien (jula) 926d8c6c5d [FIX] web, stock: escape JSON error when downloading report
__Description of the issue:__

When something goes wrong while downloading a report file, a 500 error
is sent as JSON. However the frontend interprets this response as HTML
and then try to parse the text content as JSON.

Most of the time this works, but if the response contains any HTML tags,
like `<lambda>` from a Python stacktrace, the JSON response will get
misinterpreted as HTML instead of regular text, causing the subsequent
JSON interpretation to fail.

The end result for the user is that empty tracebacks will be displayed
instead of User Errors or actual tracebacks.

__Desired behavior:__

The JSON response is HTML escaped before being sent and will therefore
be correctly parsed and displayed to the user.

This basically restore what was done prior of #104594.

Enterprise: odoo/enterprise#36523
X-original-commit: 5999a7d336553053c5638f69344cdfbc84a8c681
Part-of: odoo/odoo#112453
2023-02-12 14:14:41 +01:00
Aaron Bohy b2e267872f [REM] web: remove legacy views benchmark page
Those views are no longer used and about to be removed. This
commit also removes the benchmark lib as it is no longer used.

Part of task 3168640

Part-of: odoo/odoo#111809
2023-02-08 13:27:57 +01:00
Ivan Yelizariev 85f5006018 [FIX] web: fix export m2m fields on using group_by
Export tool is based on ORM method `_export_rows`. The method has special
processing of m2m fields when user checked *Import compatible* option [1].
Before this commit the negative value of `import_compatible` parameter wasn't
passed when data are exported in grouping mode. This led to empty values in m2m
fields.

STEPS:
* Order some products via website and pay via wire transfer
* Open Orders menu in backend
* group order by any field
* expand group with the order
* add field *Transactions/Acquirer/Display Name*

[1]: https://github.com/odoo/odoo/blob/b28c44a38698018ebbbc420f6567c17b2b97c279/odoo/models.py#L894-L914

opw-2864737

closes odoo/odoo#110151

X-original-commit: 6647ac83467207f4f4ef23aac96ebaf5333b967b
Signed-off-by: Ivan Elizaryev (iel) <iel@odoo.com>
2023-01-17 16:47:24 +01:00
Victor Feyens 1a1ce16265 [IMP] core,*: check routes decorators
When overriding an existing controller route, developers can
easily c/p the route definition and call super() in the overridden method
when the route attributes are automatically deducted by odoo from the parent route.

Removing those redefined attributes simplifies the routes definition,
clearly highlighting what's changed by the override.
Also reduces unexpected behavior when modifying the base route without
noticing/considering the redefined attributes in a overridden route,
which overrides the changes made to the base route when the sub-module is installed.

This commit adds a test to catch routes attributes redefinition, and clean existing routes.

closes odoo/odoo#108512

Related: odoo/enterprise#35176
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
2023-01-16 19:45:57 +01:00
Xavier-Do bc61ab4fb2 [FIX] web: format set_profiling output nicely
JSON content can be rendered nicely by browsers when using the
appropriate mimetype

closes odoo/odoo#107708

X-original-commit: 70153bbe233bb81d51752c5f1ed1766414eb875b
Signed-off-by: Olivier Dony (odo) <odo@odoo.com>
2022-12-23 12:10:52 +01:00
Julien Castiaux 5502313853 [FIX] web, *: multi-db /web/session/authenticate
*: base_setup, hr_timesheet, mail, partner_autocomplete, web_tour

Start odoo without -d and with a --dbfilter that allows multiple
databases. Via JSON-RPC access the /web/session/authenticate route
providing a non-filtered database and valid credentials. Traceback,
`request.env` is None.

Since httpocalypse the initialization of the ORM (cursor, registry,
environment) is greedy. It means that the connection to the database is
established very early during the request routing or skip altogether in
case no dbname was known at that time. This contrast with prepocalypse
where the various ORM thingies were lazily setup the first time they
were accessed.

This changement has an important implication regarding authentication.

In prepocalypse, thanks to the lazy approache, a cursor/registry/env
would be setup on the database you just login upon using the
`request.env` for the first time. This was very nice in this regard but
had other problems.

Since httpocalypse such operation is no more possible. Devs must
initialize and use their own cursor/registry/env in case they
authenticate on another database than the one `request.cr` is (maybe)
connected to.

The `/web/session/authenticate` controller is an example of such case.
It crates its own cr/registry/environment after authentication. The
problem the controller uses `ir.http.session_info` and that not all
overrides were updated to use `self.env` (=the env created in the web
controller) instead of `request.env` (=the missing env of the request).

closes odoo/odoo#108063

X-original-commit: 7b9bd9d37731fae724dc5d91da656dab70aa9ad4
Related: odoo/enterprise#35012
Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-12-15 15:45:07 +01:00
Olivier Dony 4fb4964fc3 [FIX] web, website: /web/login should simulate auth=public
The /web/login route is historically defined to be auth=none, which
means that it is available even when no database is selected (yet), and
no db_filter is set to automatically select one.
This is done mainly to be able to redirect users to the database
selection screen (cfr ensure_db()) instead of showing them a 404 until
they manually go to the /web/database/selector page.

The conversion of this mechanism in odoo/odoo#87571 can cause
problems because the user environment used to render the login page uses
the superuser ID. In certain configurations of installed modules, it was
possible to have the /web/login page showing "OdooBot" as the logged in
user, despite no user being actually logged in at all.

To fix this, we override the env that was set by auth=none:
- with the current session user, if there is one (like `/web` does)
- with the public user otherwise (as auth=public would do)

closes odoo/odoo#107613

X-original-commit: 6e42a07d7637070d45be81dcbf7261eda08425b4
Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-12-09 19:45:47 +01:00
Victor Piryns (pivi) 21f78b1ae0 [FIX] web, stock: rollback database when crashing on report generation
Current behaviour:
When we are printing a report and then the report fails to generate
(for ex. wkhtmltopdf memory limit/timeout),
the incorrect state is committed to the database.

Expected behaviour:
We should rollback when generating reports fails, since it is an error state.

Steps to reproduce:
To reproduce the behaviour, we need to force an error state.
- In odoo/addons/base/models/ir_actions_report.py:`_run_wkhtmltopdf()`,
raise an exception before spawning the subprocess (for ex. adding a 1/0).
- In addons/web/controllers/main.py:`report_download()`#L2126,
add this little code snippet:
```python
ids = [int(x) for x in docids.split(",")]
report = request.env['ir.actions.report']._get_report_from_name(reportname)
obj = request.env[report.model].browse(ids)
if getattr(obj, 'message_post'):
    obj.message_post(body='This report was committed!')
```
- Install Inventory
- Pick a delivery order and try to print it, there should be an error
(whatever exception you decided to raise in `_run_wkhtmltopdf()`)
- See that in the message board we got a message that the report has been committed,
which isn't the case, it failed to generate.

Reason for the problem:
Controllers are catching the exception when generating reports,
but never reset the state of the database.

Fix:
Raise an InternalServerError with an error code of 500 to trigger
a database rollback.

Affected versions:
- 14.0
- 15.0
- saas-15.2
- saas-15.3
- 16.0
- master

opw-3001950

closes odoo/odoo#106172

X-original-commit: ec185fcf7f32da05c83733af36bebe10ac22e2ad
Related: odoo/enterprise#34193
Signed-off-by: Julien Castiaux <juc@odoo.com>
Signed-off-by: Piryns Victor (pivi) <pivi@odoo.com>
2022-11-21 15:57:11 +01:00
Hubert Van de Walle (huvw) fdd60894ae [FIX] web: rtl assets in ltr language in debug mode
Steps to reproduce:

  - Switch to `?debug=assets`
  - Change the user language to Arabic and back to English
  -> The page is still displayed in rtl mode

Cause of the issue:

  The css is retrieved like this

  ```py
  >>> self.env['ir.attachment'].sudo().search([('url', '=like', '/web/assets/%/web.assets_common.css')])
  ir.attachment(212, 189)

  >>> self.env['ir.attachment'].sudo().search([('url', '=like', '/web/assets/%/web.assets_common.css')]).mapped('url')
  ['/web/assets/212-5d47380/rtl/web.assets_common.css', '/web/assets/189-5d47380/web.assets_common.css']
  ```
  Only the second one should be matched.

Solution:

  Check for the absence of an extra parameter in the url

opw-2892012

closes odoo/odoo#105127

X-original-commit: 539427fa2a099b29adf099c2b48d4f1d2fd4ebd2
Signed-off-by: Julien Castiaux <juc@odoo.com>
Signed-off-by: Hubert Van De Walle <huvw@odoo.com>
2022-11-17 10:57:10 +01:00
Julien Castiaux ebe2516a44 [FIX] base: unlink request.cr after rpc db drop
Start odoo on a specific database, e.g. 'db-example'. Drop it via JSON
or XML RPC. The database is successfully dropped but the RPC fails with
a traceback because it attempts to commit on a database that doesn't
exist anymore.

    import requests

    admin_passwd = ...
    requests.post(
        'http://127.0.0.1:8069/jsonrpc',
        json={'params': {
            'service': 'db',
            'method': 'drop',
            'args': [
                admin_passwd, 'db-example'
            ]
        }}
    )

Closes odoo#104527

closes odoo/odoo#105710

X-original-commit: b6e195ccb3a6c37b0d980af159e546bdc67b1e42
Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-11-15 00:17:59 +01:00
Julien Castiaux 6b0e54ca4c [FIX] base, web: missing borrow_request() for db
The new `borrow_request()` function has been introduced to properly
separate the HTTP layer from the RPC layer. We forgot to protect some
RPC endpoints, mainly inside of `odoo.addons.web.controllers.database`.

This commit moves `odoo.service.dispatch_rpc` to `odoo.http` as we only
permorm RPC from the controllers and that we don't want to import
`borrow_request` inside of `odoo.service` (circular import).

X-original-commit: d0ee8615d8820e02232989c50a6e6ffbc66a9266
Part-of: odoo/odoo#105710
2022-11-15 00:17:59 +01:00
Rémy Voet (ryv)andJulien Castiaux e967e25095 [IMP] *: remove bad usage of search_read.
Reading only 'id' with `search_read` is equivalent to use `search` but
complexify the result usage. Fix all these bad usages.

Part-of: odoo/odoo#104838
Co-authored-by: Julien Castiaux <juc@odoo.com>
2022-11-07 11:26:32 +01:00
xmo-odoo e806427d23 [REM] web: deprecated dataset methods
Part-of: odoo/odoo#98138
2022-10-26 19:03:46 +02:00
MerlinGuillaume 20434b5c7a [FIX] web: show decimal part of floats in exported xlsx
If the decimal separator of the currently selected language is a comma,
exporting data in an xlsx would use a wrong float format

Steps to reproduce:
1. Install Invoicing
2. Go to Settings > Languages, add 'French / Français' language and
   switch to it
3. Go to Facturation > Fournisseurs > Factures
4. Export the data (there should be at least one amount with a decimal
   part)
5. The decimal part of the amounts is not displayed

Solution:
Always use the same decimal separator to print in the xlsx as we can
only use a dot as a decimal separator (the comma is used as the thousand
separator). The value will then be displayed to the user according to
his OS regional settings (see https://xlsxwriter.readthedocs.io/format.html#number-formats-in-different-locales)

Problem:
When using a comma for the float format, we actually specify the format
of the integral part of the number (the thousands) without displaying
the decimal part (which is represented with the dot)

opw-2965984

closes odoo/odoo#102255

X-original-commit: 21efa4f18266a5c5c57157035c2357ed3e147a69
Signed-off-by: Julien Castiaux <juc@odoo.com>
Signed-off-by: Guillaume Merlin (megu) <megu@odoo.com>
2022-10-06 00:37:25 +02:00
Jeremy Kersten 5490fcc27f [FIX] http: convert DEFAULT_SESSION as a function get_default_session
This commit avoid to have a dict by reference that will be global.
Now get_default_session return a new dict each time for the context key.
From this way the session.context['lang'] is not shared between several
users on the same worker.

To reproduce the bug, restart the server with 2 workers, make request in
lang A on these 2 workers. DEFAULT_SESSION['context']['lang'] now is set
to this lang A.
Now, make request to an url without lang in path and without cookies and
withtout session, you should be redirected to lang B (preferred lang
from the request header) but you will be redirect to lang A due to the
dict session.context that is shared for the worker...
When we initialize the new Session, we get the wrong lang A as value for
context.lang, so we don't recompute the expected lang for the end user.

X-original-commit: 62179de74862210fe2a055d15b367b1850c24263

fwd-port of #100102

closes odoo/odoo#100910

X-original-commit: 42e46b2d89dde276f796b980f29e33cc216e7cb2
Signed-off-by: Jérémy Kersten <jke@odoo.com>
2022-09-23 09:21:38 +02:00
ef00294e71 [IMP] core: store translated fields as JSONB columns
Translated fields no longer use the model ir.translation.  Instead they store
all their values as JSON, and store them into JSONB columns in the model's
table.  The field's column value is either NULL or a JSON dict mapping language
codes to text (the field's value in the corresponding language), and must
contain an entry for key 'en_US' (as it is used as a fallback for all other
languages).  Empty text is allowed in translation values, but not NULL.

Here are examples for a field with translate=True:

    NULL
    {"en_US": "Foo"}
    {"en_US": "Foo", "fr_FR": "Bar", "nl_NL": "Baz"}
    {"en_US": "Foo", "fr_FR": "", "nl_NL": "Baz"}

Like before, writing False to the field makes it NULL, i.e., False in all
languages.  However, writing "" to the field makes its value empty in the
current language, but does not discard the values in the other languages.

Here are examples for a field with translate=xml_translate:

    NULL
    {"en_US": "<div>Foo<p>Bar</p></div>", "fr_FR": "<div>Fou<p>Barre</p></div>"}

Change for callable(translate) fields: one can now write any value in any
language on such a field.  The new value will be adapted in all languages, based
on the mapping of terms between languages in the old values.  Basically the
structure of the value must remain the same in all languages, like before.

Reading a translated field is now both simpler and faster than the former
implementation.  We fetch the value of the field in the current language by
coalescing its value with the 'en_US' value of the field:

    SELECT id, COALESCE(name->>'fr_FR', name->>'en_US') AS name ...

The raw cache of the field contains either None or a dict which is conceptually
a subset of the JSON value in database (except for missing languages).  For the
sake of simplicity, most cache operations deal with the dict and return the text
value in the current language.

Trigram indexes have been adapted to the new storing strategy, and should enable
to search in any language.  Before this change, only the source value of the
field ('en_US') could be indexed.

Computed stored translated fields are not supported by the framework, because of
the complexity of the computation itself: the field would need to be computed in
all active languages.  We chose to not provide any hook to compute a field in
all languages at once, and the framework always invokes a compute method once to
recompute it.

Code translations are no longer stored into the database.  They become static,
and are extracted from the PO files when needed.  The worker simply uses a cache
with extracted code translations for performance.  This is reasonable, since
fr_FR code translations for all modules takes around 2MB of memory, and the
cache can be shared among all registries in the worker.  Changing code
translations requires to update the corresponding PO file and reloading the
worker(s).

Performance summary:
 (+) reading 'model' translated fields is faster
 (+) reading 'model_terms' translated fields is much faster (no need to inject
     translations into the source value)
 (+) searching translated fields with operator 'ilike' is much faster when the
     field is indexed with 'trigram'
 (+) updating translated fields requires less ORM flushing
 (-) importing translations from PO files is 2x slower

Some extra fixes:
 - make field 'name' of ir.actions.actions translated; because of the PG
   inheritance, this is necessary to make the column definition consistent in
   all models that inherit from ir.actions.actions.
 - add some backend API for the web/website client for editing translations
 - move methods get_field_string() to model ir.model.fields
 - move _load_module_terms to model ir.module.module
 - adapt tests in test_impex, test_new_api
 - because env.lang is injected into SQL queries, its returned value is
   now guaranteed to correspond to a valid active language or None
 - remove wizard to insert missing translations (no longer makes sense)

task-id: 2081307

Co-authored-by: Fabien Pinckaers <fp@openerp.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
2022-09-15 22:37:50 +02:00
Yolann Sabaux 19ed75ddab [FIX] mail: revert upload_attachment fix
Cookies should be used internally by the web UI. The server-side is not supposed to be aware of it at all.

Reverts:
odoo#88745

Based on odoo#93812
discussion. It has been decided to revert the fix to avoid further unattended behaviours.

closes odoo/odoo#100178

X-original-commit: bdde7dda7356744d459e3991a7f382fee42bf8c5
Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
Signed-off-by: Yolann Sabaux (yosa) <yosa@odoo.com>
2022-09-15 10:03:09 +02:00
Gorash 5410b7c238 [IMP] base/web: XML templates are added into the asset bundles.
XML files are now declared in python module manifests. During the qweb
't-call-asset' directive, assetbundle will fetch the declared xml files,
apply the inheritance (t-inherit) and create a javascript service (for
eg: 'web.assets_backend.bundle.xml') which is added at the end of the
*.js mimifier file.

When the debug mode is activated, comments are added in the template
indicating which file the template comes from as well as the
inheritances applied to it.

****

JavaScript:

assets.js (module @web/core/assets) takes care of loading libraries,
javascripts and styles.
`loadJS(url)` (loads the javascript and returns a resolved promise when
the templates are also loaded via the '*.bundle.xml' service)
`loadCSS(url)` (loads the style a resolved promise when the file is
loaded)
`loadXML(xml, app=assets.defaultApp)` (load template into
application/owl, used by the `*.bundle.xml` services)
`getBundle(bundleName)` (get the bundle descriptor)
`loadBundle(desc)` (load the files and bundle from a descriptor)

templates (XML element content all owl templates)

A new `ready(serviceName)` method on boot.js lets you know when a
service is loaded are the require.

The xmlDependencies attribute no longer exists.

Python:

The xmls taken into account by assetbundle.py, applying `t-inherit`
inheritances and adding an `name_of_the_bundle.bundle.xml` service in
the generated JavaScript file.

****

Every manifest changes is into the next commit, except 'web_tour' in
this current commit as example.

Part-of: odoo/odoo#95500
2022-09-14 20:25:01 +02:00
Gorash 48c267e9a5 [IMP] web/http: Added support for immutable property to serve files
When a file is immutable the different network layers can cache it.
Services receiving this header should never invalidate these files.

Part-of: odoo/odoo#95500
2022-09-14 20:25:00 +02:00
Pierre-Yves Dufays 390c36f42f [FIX] web: makes the logo route return the correct image
Emails got always the odoo logo even if the company logo has been changed. This
solves the problem.

Technical note: the problem was caused by an exception in the controller due to
invalid parameters used for send_file method causing web/static/img/nologo.png
to be returned.

Task-2920690

closes odoo/odoo#99073

Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-09-09 16:23:40 +02:00
Xavier Morel b3b85cae9b [IMP] *: owlify password meter and convert change password to real wizard
The changes in `auth_password_policy` are largely the owlification of
the password meter widget:

- modernize the password policy module and convert it to an
  odoo-module (note: now exports a pseudo-abstract class which is
  really a policy, for the sake of somewhat sensibly typing
  `recommendations`)
- replace the implementation of the Meter and PasswordField widgets by
  owl versions

The changes to web and base stem from taking a look at converting the
ChangePassword wizard, and finding that it would be a pain in the ass
but also... unnecessary? It seems to have been done as a wizard
completely in javascript despite being backend-only for legacy
reasons: apparently one of the very old web clients (v5 or v6
probably) implemented it as a "native action" which was directly part
of the client's UI, and so it had to be implemented entirely in the
client.

Over time it was moved back into the regular UI (and moved around
quite a bit), hooked as a client action to maintain access to the
existing UI / dialog.

But since it's been an action opened via a button for years it can
just... be a normal wizard, with password fields, which
auth_password_policy can then set the widget of.

So did that:

- removed the old unnecessary JS, and its dedicated endpoint (which is
  *not* used by portal, portal has its own endpoint)
- used check_identity for the "old password check"
- split out `change_password` with an internal bit so we can have a
  safer (and logged) "set user password" without needing to provide
  the old password, which is now used for the bulk password change
  wizard as well
- added a small wizard which just takes a new password (and
  confirmation), for safety a given change password wizard is only
  accessible to their creator (also the wizard is restricted to
  employees though technically it would probably be fine for portal
  users as well)

Rather than extensive messy rewrite / monkeypatching (the original
wizard was 57 LOC, though also 22 LOC of template, the auth_policy
hooking / patching was 33, plus 8 lines of CSS),
`auth_password_policy` just sets the widget of the `new_password`
field in the new wizard, much as it did the bulk wizard.

Also improve the "hide meter if field is empty" feature by leveraging
`:placeholder-shown`. This requires setting a placeholder, and while
empty works fine in firefox, it doesn't work in chrome. So the
placeholder needs to be a single space. Still, seems better than
updating a fake attribute or manipulating a class for the sake of
trivial styling.

Notes on unlink + transient vacuum

Although the wizard object is only created when actually calling
`change_password`, and is deleted on success, it is possible for the
user to get an error and fail to continue (it should be unlikely
without overrides since the passwords are checked while creating /
saving but...).

While in that case the `new_password` in the database is not the
user's own, it could be their *future* password, or give evidence as
to their password-creation scheme, or some other signal useful to
attack that front of the user's life and behavior. As such, quickly
removing leftovers from the database (by setting a very low transient
lifetime) seems like a good idea.

This is compounded by the `check_identity` having a grace period of 10
minutes. 0.1 is 6 minutes, but because the cron runs every 10 the user
effectively has 6~10 minutes between the moment they create an
incorrect / incomplete version of the wizard and the moment where it
is destroyed if they just leave it.

closes odoo/odoo#99458

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2022-09-08 18:31:18 +02:00
MerlinGuillaume 719e028640 [FIX] web: number format in exported group header for float values
Exporting data incorrectly formats the float values of group headers

Steps to reproduce:
1. Install Planning
2. Open Planning and trigger the list view
3. Remove the default filter and add a group_by on employees
4. Export the data
5. The file produced doesn't have the same format for Allocated Hours in
   the group headers and in the line details

Solution:
Create formats for float and monetary values using the user's
preferences in decimal separator and decimal precision. For monetary
format, we use the biggest decimal precision used in the company
currencies.

opw-2864273

closes odoo/odoo#98813

X-original-commit: 718e8eea7862ad307479190336baf5b5e7092ae4
Signed-off-by: Julien Castiaux <juc@odoo.com>
Signed-off-by: Guillaume Merlin (megu) <megu@odoo.com>
2022-08-25 04:21:14 +02:00
Martin Trigaux ffc525419a [IMP] base: avoid render with env mixup
The render API was confusing as mixing the access to the report and
the rendering env.

The ambiguity was present for code such as
`report.sudo()._render(record_ids)` where it was not clear if the
`sudo()` is needed to access to `report` or to `record_ids`. For low
priviledge users (such as portal or public), it was common to use
`report.with_user(SUPERUSER_ID)._render(record_ids)`.

This PR changes the render methods signature to be `api.model`. The
`report_ref` can be:
- ir.actions.report external id
- ir.actions.report id
- ir.actions.report recod
- `report_name` value

This will allow to call the report methods with any user and no longer
need to use `with_user(1)` to render reports as public user.

Task-id 2670865

closes odoo/odoo#91341

Related: odoo/upgrade#3650
Related: odoo/enterprise#27323
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
2022-08-02 11:48:46 +02:00
Fabio Barbero 9765879130 [IMP] auth_signup: redirect activated user to login on signup link
Purpose
=======
When a user receives an email to activate their account, allow them to
click on the "Activate Account" button after the account has already
been activated instead of showing a "Invalid signup token" error.

Specifications
=============
Add a parameter p_id to the sign up url to check if the partner has
already activated their account (if their user_ids state is not new) and
redirect them to login otherwise.

Task-2680414

closes odoo/odoo#79936

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2022-07-18 18:40:59 +02:00
2d44f2792d [IMP] website, *: handle url redirections from website iframe
*: auth_signup, portal, web, website_knowledge

When navigating in the iframe, only same origin redirections should be
open in the iframe contentWindow. External redirections should be done
in the top window.

Some internal pages had to be served with X-Frame-Options header set to
SAMEORIGIN, and Content-Security-Policy to "frame-ancestors 'self'" (see
[1]).

All the links that are redirecting to another host, and the client
actions, are opened in the top window.
Exemples that will be opened in the iframe's top window:
- Clicking on a link google.be that should not open in a new tab
- Clicking on the language selector and adding a new one, or
clicking on "logout".

[1]: https://github.com/odoo/odoo/pull/78298#discussion_r898853383

See merge commit for more information.

task-2687506

Co-authored-by: Arthur Detroux <ard@odoo.com>
Co-authored-by: qsm-odoo <qsm@odoo.com>
2022-06-24 10:28:04 +02:00
Florian Charlier dae28c4b46 [IMP] base: add _is_internal method to res.users
No method was readily available to know if a user is `internal` (has
group `base.group_user`), which was inconsistent with other base groups.

_is_internal is now used in the codebase where it is clear that
`.has_group('base.group_user')` is called on a single record.

Part-of: odoo/odoo#85703
2022-06-14 09:35:57 +02:00
Florian Charlier b5f3433adc [IMP] auth_signup,portal,web: welcome external users w/o portal
When portal is not installed and `auth_signup.invitation_scope` is "b2c",
visitors can create an account, leading to a blank page. Still, accounts can be
required for several use cases in apps that do not require portal (such as
survey).

We here add a landing page for users that created an account but have no
requested redirections and cannot be redirected to a customer portal either.

auth_signup_uninvited is also updated in model to be consistent with config
data.

Tests are added to check this behavior.

Task-2762102

Part-of: odoo/odoo#85703
2022-06-14 09:35:57 +02:00
Julien Castiaux 4960665043 [FIX] web: missing cache of /web/assets
Fine tuning of da8def8e41

closes odoo/odoo#93407

X-original-commit: 7efa8743b1bbe9efc4b81a10331f096e8de1e52d
Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-06-13 13:31:47 +02:00
Julien Castiaux fc115ebdf7 [FIX] web: invalid image placeholder resizing
Access `/web/image/82303?height=16`, traceback because the placeholder
image cannot be resized to `"16"`.

closes odoo/odoo#92891

Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-06-03 18:34:49 +02:00
Julien Castiaux da8def8e41 [IMP] core, web: Delegate delivery of static files
Rationnals
----------

Web servers can serve some resources (e.g. static files) right away
without any interaction with the web application. The network model of
most web servers makes them capable of handling thousands of
simultaneous requests when it comes to intensive IO operations such as
streaming data from a file. The network model of Odoo is different: it
is capable of a lot of processing power but can only serve a handful of
requests at a time, i.e. Odoo (with some help from postgres) is
optimized for CPU operations, not IO.

Some users don't configure their web server, they use a basic
configuration that relay all requests to Odoo. The result is that many
Odoo HTTP Workers can be busy streaming static files instead of
processing other requests. This can lead to a worker starvation, i.e.
all workers are busy streaming files and cannot process new requests.

X-Sendfile
----------

In this work, we add the support for the [X-Sendfile] header family,
they are multiples http headers that can be used by the web application
to communicate with the web server in order to delegate the delivery of
files stored on the file system. Odoo still receives the request but it
does no more stream the file content from within its HTTP worker,
instead it skips the response body altogether and sets the `X-Sendfile`
special header with the path of the file on the filesystem. The web
server intercepts that special header, open the file and stream it.

Using those headers, we can use the best of both the web application and
the web server. The web application is still responsible to locate the
resource and verify the access rights, the web server is still
responsible of streaming the content.

Using X-Sendfile is opt-in via the `--x-sendfile` CLI flag. We set both
`X-Sendfile` (apache) and `X-Accel-Redirect` (nginx). If you are using
apache, make sure `mod_xsendfile` is enabled. If you are using NGINX
you have to add the following location block:

    location /web/filestore {  # custom path, hardcoded within Odoo
        # Prevent access from the outside world, i.e. makes this
        # route only accessible via X-Accel. MANDATORY!!!
        internal;

        # Give access to the filestore using this server's
        # permissions. Odoo is in charge of verifying the access
        # rights.
        alias /path/to/odoo/data-dir/filestore;
    }

The Odoo [deployment documentation] has been updated accordingly.

[X-Sendfile]: https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/
[deployment documentation]: https://www.odoo.com/documentation/master/administration/install/deploy.html#serving-static-files-and-attachments

Changes to the API
------------------

To benefit most from X-Sendfile, all APIs related to streaming content
over HTTP has to be adapted. They are: (1) `request._serve_static`,
(2) `ir.http._serve_fallback`, (3) `/web/content` and (4) `/web/image`.

Each used it own way to deliver content: (1) `_serve_static` was using
`send_file` (flask's send_file that as been vendored with odoo 10
years ago and not maintenained since then), (2) _serve_fallback was
handcrafting a `werkzeug.wrappers.Response`, (3) /web/content-image were
using the "binary server" `ir.http.binary_content` API.

I has been decided to remove all 3 APIs and to merge the code inside of
the new `http.Stream` object and the `ir.binary` helper model.

A Stream wraps what is going to be sent to the browser, it can be a path
to a file on the locale filesystem, a blob of raw data or an URL to an
external resource. The Stream also holds various metadata that are
mainly used for caching. The preferred way to create a Stream is via one
of its three factories so that all the metadata are set. The factories
are: `from_path`, `from_attachment` and `from_binary_field`. A stream
instance exposes a single method `get_response()` used to create the
corresponding HTTP response object out of the stream.

Inside of `ir.http` were a few methods that were not related to the http
routing and formed what was called the "binary server". All those
methods have been removed and the feature have been refactored inside of
the new `ir.binary` model. The removed methods are:

- `_xmlid_to_obj`
- `_get_record_and_check`
- `_binary_ir_attachment_redirect_content`
- `_binary_record_content`
- `_binary_set_headers`
- `binary_content`
- `_response_by_status`
- `_get_content_common`
- `_content_image`
- `_content_image_get_response`
- `_placeholder_image_get_response`

The new `ir.binary` abstract model exposes the following utilities:

**`_find_record`**

Find an attachment or a record with a binary-field out of an xmlid or
out of a pair record-model/record-id. Check the access rights and the
access token.

**`_get_stream_from`**

Create a Stream from an attachment or a record with a binary-field.

**`_get_image_stream_from`**

Same as `_get_stream_from` but adapted for images. It sets a sensible
ETag on the stream and has image resizing support.

**`_placeholder`**

Get the image placeholder blob.

Testing
-------

It is possible to test the web server configuration using the
`test_http` module. Install the module then run the unittest using the
`webserver` test-tag. By default it attempts to connect to a web-server
running on `http://localhost:80`, you can change this URL by setting the
`WEB_SERVER_URL` environment variable.

    odoo-bin -i test_http --stop-after-init
    WEB_SERVER_URL='http://localhost:80' odoo-bin --test-tags webserver --stop-after-init

closes odoo/odoo#88134

Task: 2801675
Related: odoo/documentation#2083
Related: odoo/enterprise#26191
Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-06-01 02:53:59 +02:00
Paul Morelle f7494a914d [IMP] web: add stacklevel to DeprecationWarning
bcf665a291 introduced this deprecation warning without a stacklevel
argument. Adding it makes the error highlighted precisely where the
deprecated import occurred.

closes odoo/odoo#92420

X-original-commit: 9c01ab0deec4b82c60d8f942c39f2ca33aa42afd
Signed-off-by: Julien Castiaux <juc@odoo.com>
Signed-off-by: Paul Morelle <pmo@odoo.com>
2022-05-30 13:24:23 +02:00
Yolann Sabaux dc8cf87fc8 [FIX] web: fetch right company_id
Steps to reproduce:
- Have two companies set up
- In settings, check for company 2 the Files Centralization
- For a Product, upload a document

Issue:
The document will not appear in Documents.
It will only appear if the option is checked for company 1

Cause:
The company_id is not fetched correctly throughout the process.
There is a similar solution for the specific `documents` upload route:
https://github.com/odoo/enterprise/blob/bdf712d66c3e5cee70a6b424b69a618fe655a39f/documents/controllers/main.py#L147-L149

Solution:
Get the id directly from the cookies

opw-2774365

closes odoo/odoo#91751

X-original-commit: 46db92d5211c215d07448676e619154390b7147f
Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
Signed-off-by: yosa-odoo <yosa@odoo.com>
2022-05-19 13:45:05 +02:00
Simon Genin (ges) 959f3ad8b0 [FIX] web: fix record prefix for export dialog
closes odoo/odoo#91173

Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-05-12 13:43:30 +02:00