Commit Graph
1509 Commits
Author SHA1 Message Date
Gorash 0452d0701f [IMP] website: remove cache from website.page
The cache placed on the pages is no longer useful thanks to the use of
the new directive t-cache.

closes odoo/odoo#88276

Related: odoo/enterprise#27582
Related: odoo/documentation#2056
Related: odoo/upgrade#3451
Signed-off-by: Vincent Schippefilt (vsc) <vsc@odoo.com>
2022-06-03 16:40:40 +02:00
Gorash b0a2a41d78 [IMP] all/website: using lazy values and t-cache in templates
Using lazy values allows you to not do query when the content is not
displayed or if it is already cached. Adding `t-cache` only reduces
render time, but combining it with lazy values saves browses, computes
and query.
Thus for the `/shop` page the page is displayed in 60ms (before: 250ms).

Part-of: odoo/odoo#88276
2022-06-03 16:40:40 +02:00
Gorash 9af92b7374 [IMP] base: Qweb add t-cache and t-nocache directive
The `t-cache` directive allows you to keep the rendered result
of a template part. The supplied key must be a tuple. This tuple
can contain recordset in this case the zone will be invalidated
each time the write_date of these records changes.

The `t-nocache` directive makes it possible to force rendering
of a part even if it is in a `t-cache`. The values available in
the `t-nocache` are the one provided when calling the template
(and therefore ignores any t-set that could have been done).

Part-of: odoo/odoo#88276
2022-06-03 16:40:40 +02:00
Gorash 8c869769e9 [IMP] base: add a cache for company_ids on res.user
Part-of: odoo/odoo#88276
2022-06-03 16:40:39 +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
Raphael Collet 6cf8db906f [REF] *: adapt code to new flush API
closes odoo/odoo#87527

Related: odoo/upgrade#3497
Related: odoo/enterprise#26939
Signed-off-by: Raphael Collet <rco@odoo.com>
2022-05-25 18:00:47 +02:00
Huy Le 504ff2a674 [FIX] website: exclude non installable theme on configurator
Exclude non installable theme from the configurator suggested themes.
Also, exclude themes which are found in the database (sql) but not in
the manifest (files/sources). This was reported after migration where
`theme_beauty_sale` was still in the database but did not exists
anymore.

Note that in prior versions, this was causing a `KeyError`.

closes odoo/odoo#92167

X-original-commit: 6e4faeb136e123e09d74cde06c47f7c822b1fd19
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-05-24 16:00:14 +02:00
Christophe Monniez 65c8814a2f [FIX] various: replace deprecated currentThread method
CurrentThread is now really deprecated in Python 3.10 ... Time to
change.

Part-of: odoo/odoo#91927
2022-05-23 08:29:52 +02:00
Ivan Yelizariev 08605c506e [FIX] website: make search by "Visited Pages" work again
Field `website.visitor::page_ids` was storable initially [1], but then it was
refactored [2] and hence the search by "Visited Pages" [3] became broken.

Fix it by adding `search=` attribute

[1]: https://github.com/odoo/odoo/commit/6bec0e4d29e6b33b74962b2893a7a405667ef58c
[2]: https://github.com/odoo/odoo/commit/e33172e83210a5e0044a6fb92e315b84deefc440
[3]: https://github.com/odoo/odoo/blob/c6c7605cdae803aca4f441ef4e622a1b79f17019/addons/website/views/website_visitor_views.xml#L248-L257

opw-2622141

closes odoo/odoo#91829

X-original-commit: 792e07b8ff43ecb0499f4add27f5465c28e716cf
Signed-off-by: Ivan Elizaryev (iel) <iel@odoo.com>
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-05-19 19:04:55 +02:00
Jeremy Kersten cccd6eb01d [IMP] website[_event,_sale]: add plausible as Analytics solution
This commit add the way to specify the Plausible shared key auth token and
the plausible domain on your website to have the Plausible Dashboard integrated
in your Website > Dashboard > Analytics menu.

Some custom event are already pre-configured as:

Push an event 'Shop' on confirmation on ecommerce (with amount bucket +/- 50)
Push an event 'Lead Generation' on:
    'Thank you' page of contactus
    Confirmation of subscription for an event

From this way, the end user can just add a goal 'Lead Generation'
or 'Shop' on Plausible to have the Goal values visible.

closes odoo/odoo#91058

Related: odoo/documentation#2007
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-05-18 20:33:34 +02:00
Huy 6768e77f9b [FIX] website: allow editor users to edit theme views
Currently, "Editor and Designer" can't edit the views which originate
from a theme (which are copies from the theme `theme.ir.ui.view`
records).

This error is caused by [1], which is preventing the `arch_updated`
field to be set to `True`, as this field is supposed to be set to `True`
only on manual user change, not during module update.

Indeed, restricted users don't have access to the themes records, making
the overide raising an error.

But there were actually no reason for this code to be executed outside
module operation.

Steps to reproduce:
- Create any view in a theme module.
  For example: create a custom footer view.
- As a "Editor and Designer" user, edit this view through the website
  builder.
- An access right error is raised.

[1]: https://github.com/odoo/odoo/commit/1eb7c577ecb31c2f0876b6dd76769e2b47802cb0

closes odoo/odoo#91255

X-original-commit: d2be8dc99eb99321be1172af447d5f2536c17364
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-05-13 13:18:53 +02:00
Julien Castiaux 1de40dd85e [FIX] website: wrong canonical URL after reroute
A reroute in an internal redirection, the URL on the current request is
changed. The actual changes occurs on the "WSGI environment", a
dictionnary that is populated with the request information by the WSGI
server (werkzeug in our case). Among all the properties there are
PATH_INFO, RAW_URI and REQUEST_URI.

* PATH_INFO is the standard value, it contains a RFC-3986 path.
  `request.httprequest.path` is based on that value.
* RAW_URI and REQUEST_PATH are two custom values set by werkzeug to
  mimic other popular wsgi servers (gunicorn, uwsgi, mod_wsgi), they
  also only contain a RFC-3986 path.

When rerouting only PATH_INFO and RAW_URI are updated. REQUEST_URI is
left as-is in order to keep the original path somewhere. When building
the cannonical path, one must use the original path instead of the
rerouted one.

X-original-commit: 779486c4dff23b946b4b14e3dca164ecca4f85a8
Part-of: odoo/odoo#91034
2022-05-12 13:42:57 +02:00
Denis Ledoux b03c227e88 [REF] models: refactor fields_view_get, load_views
Refactor the `load_views` API so it no longer sends multiple times the same
fields description.

e.g.
When `load_views` is called to get the kanban, tree and form views,
the list of fields of the model was sent 4 times:
- Once for each view, with only the fields used in the view,
  in `['fields_views']['kanban']['fields']` for instance
- Once globally, with all the fields of the model, in `['fields']`

The goal of this revision is to change that so it sends the list of all fields
only once.

In addition, if a view contains x2many fields,
the fields description of the comodel is also sent.
It was sent in the `views` key of the view fields dict.
e.g.
When calling `load_views` of `res.partner` to get the kanban,
tree and form views,
the `res.partner` fields description was actually sent 6 times:
- Once for each view
- Once globally
- Once for each view of the many2many field `child_ids` of the form view, in
  - `['fields_views']['form']['fields']['child_ids']['views']['kanban']['fields']`
  - `['fields_views']['form']['fields']['child_ids']['views']['form']['fields']`

The change suggested in this revision is to:
- Remove the fields description for each view in `['fields_views']`.
  As it no longer contains the fields,
  the key becomes `['views']` instead of `['fields_views']`.
- Replace the dict key `['fields']` by `['models']`,
  which is a dict with as key the model name and as values
  the model fields description. It contains the fields description
  for all models implied in the view:
  the model of the main view and the model of all one2many and many2many fields.

With this change, the fields description will only be sent once by model
implied in the view.

In addition, the web client was getting the information about the fields
sometimes in the global fields description list (e.g. `['fields']`),
sometimes in the fields description list of the view type
(e.g. `['fields_views']['form']['fields']`),
making it a pain to try to make changes / performance gain
in these field description dictionaries, because you never knew in which dict
the web client was getting its info.
Now, as there is only one place to get the fields description from,
it's clearer and cleaner.

- one2many and many2many fields views are passed directly in the main view
  architecture rather than being put in the `views` key
  of the field description.
  This is actually easier to treat by the web client,
  and this will allow in a future work to cache an entire view in one block
  of text rather than having to combine multiple cached blocks of text
  to return one view.
- one2many and many2many fields which do not have directly embedded views
  have their views directly injected in the architecture,
  so the web client doesn't have to do RPC calls to `load_views`
  for each one2many and many2many fields not having embedded views.
  For instance, this allow to reduce the number of RPC calls to `load_views`
  from 8 to 1 when loading the form of `product.product`.
  Currently, this behavior is limited to 1 level deep but we consider making it
  go all the way down in future works. We did not do it for the moment because
  in certain cases it rises the processing time and the size (bytes) too much.
  e.g. the sale.order view can be 5 levels deep,
  meaning you can reach 4 dialogs on top the main view.
  ```
  sale.order form > order_line > sale.order.line form > invoice_lines >
  account.move.line form > asset_ids > account.asset form >
  depreciation_move_ids > account.move form.
  ```
  This will also benefit in future works to cache an entire view in one block
  of text rather to having to combine multiple cached block of text
  to get one view.
- `fields_view_get` becomes `get_view`.
  As it no longer returns the fields description,
  keeping the `fields` in the name `fields_view_get` no longer makes sense.
  Hence removing `fields` from the method name, it becomes `view_get`.
  As it gets renamed anyway, we take the opportunity to rename it `get_view`,
  which is more in line with the general getter/setter guidelines
  in the model object world.
- `_fields_view_get` becomes `_get_view`. For the same reasons than above.
- `load_views` becomes `get_views`.
  This is not mandatory, there is no technical reason to rename `load_views` as
  it practically sends the same info as before,
  the view architectures and their fields description. Just in another way.
  We just take the opportunity of this pull request to suggest a cleaner API:
  `_get_view`, `get_view` and `get_views`.
- Arguments `toolbar=False, submenu=False` fo the methods
  `_fields_view_get` and `fields_view_get` are converted to a kwargs `**options`
  in `_get_view` and `get_view`.
  The rationale is that submenu was already no longer used (deprecated)
  and the mobile options is introduced.
  The mobile options is necessary to tell the server to send the mobile views
  for x2many fields (kanban instead of tree).
  Instead of adding a new argument each time we add a new option to
  `fields_view_get`, it seems wiser to have a kwargs `**options` to avoid
  to re-write all overrides each time a new option is introduced.
- `_fields_view_get` returned a dict containing the arch in text and some of the
  view information. Now, `get_view` returns a tuple with the view architecture
  as an `etree` node, and the view as a browse record. The rationale is that all
  overrides of `_fields_view_get` were about modifying the arch only
  (e.g. changing the address format/re-organizing the address related field
  nodes of the partner according to the company country).
  To do so, all these overrides were doing `etree.fromstring` to parse the arch
  which was sent in text to convert it to an `etree`,
  then operations were done on the `etree`,
  and then `etree.tostring` was called to convert back the arch to string.
  With this change of signature to send the arch as an `etree`,
  all these back and forth `etree.fromstring` -> `etree.tostring` are avoided,
  allowing some performance gain and less code in the end.
- A cleanup of the keys returned in the dict of `fields_view_get`
  has been performed in `get_view`:
  - `fields` is removed, as explained above,
  - `view_id` is renamed `id`,
  - `name` is removed, it was unused by the web client,
  - `type` is removed, it was unused by the web client,
  - `field_parent` is removed, it was unused by the web client,
  - `base_model` is removed, it was unused by the web client.
- `filters` is moved from the global dict returned by `load_views`
  (now `get_views`) to the dict returned by `fields_view_get` (now `get_view`)
  as it applies only to the `search` view type.
- Retro-compatible methods for the 3 methods
  `fields_view_get`, `_fields_view_get` and `load_views` are provided,
  with deprecation warnings in them.

- The web client could cache the model fields description
  (as it already caches the views),
  so it doesn't need to fetch them again if it asks for another view of a model
  for which he already has the fields description.
  If we do so, `get_views` could return only the list of models used by
  the views, without the fields description as of now,
  and the web client would then call `fields_get` independently only for
  the models for which it doesn't have yet the fields description.
  This would avoid the server to return the fields description
  and to call `fields_get`, which is costly, for each `get_views`,
  therefore gaining performances.
- Inject the views of the one2many and many2many fields all the way down,
  unlimited depth level, as explained above.
- Cache with `ormcache` the architecture of back-end views.
  This is already done for qweb views, it's not done for back-end views.
  Therefore the postprocessing of the views is performed for each `get_views`,
  which is costly, while the view architecture doesn't change for users
  belonging to the same groups, according to the groups implied by the view.

This pull request is co-authored by
Aaron Bohy (aab) for the web client part and
Denis Ledoux (dle) for the server part.

Part-of: odoo/odoo#87522
2022-04-29 09:57:44 +02:00
Pierre-Yves Dufays aef2d27053 [IMP] website: add X-Disable-Tracking header to improve tracking
In this commit we add a request header X-Disable-Tracking that enables the
client to ask the server not to track a request.

This is useful for example when the client prefetches pages to be able to work
offline. In that case, the prefetched pages must not be considered as viewed
by the user. In such scenario and without such header, it is not possible to
get an accurate page tracking.

Task-2476513

Part-of: odoo/odoo#86031
2022-04-29 08:09:58 +02:00
William Braeckman fb86ae3371 [FIX] website,website_sale: fix unable to save in multi company settings
This commit is a follow-up to https://github.com/odoo/odoo/pull/89707
The above PR fixed most issues with the configuration but since the
default value was not set anymore for `auth_signup_uninvited` a
configuration with no website attached would make the config not
saveable (required field not set).

closes odoo/odoo#89938

X-original-commit: 5fab73f7730a10636642ba96b1fdd7a7455fe6f9
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
Signed-off-by: William Braeckman (wbr) <wbr@odoo.com>
2022-04-27 21:28:32 +02:00
William Braeckman 7e945db634 [FIX] website,website_sale: fix user sign up config
This commit aims to fix multiple issues with the "Customer Account"
parameter in the backend config.

 - Hide the parameter from general and sales settings if website is
   installed.
 - Properly compute the right value once website is installed, as it was
   not using the website's value.
 - Fix a traceback when clicking on "Default Access Rights".

TaskId-2825096

closes odoo/odoo#89806

X-original-commit: 8b162f507f881619061d61530cc03b4b4654c1fe
Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
Signed-off-by: William Braeckman (wbr) <wbr@odoo.com>
2022-04-27 12:16:28 +02:00
Victor Feyens 7d422a2cd4 [FIX] *: unnecessary semicolon (W0301)
+ empty spaces removal
+ added space after comma (C0326 - bad-whitespace)

Part-of: odoo/odoo#86332
2022-04-27 07:51:23 +02:00
Romain Derie 346360cc27 [FIX] website: give unlink access right on assets to website editor
Commit [1] was not enough, expecting that the unlink right was not
needed. But it is.

A recent test highlighted that issue.

[1]: https://github.com/odoo/odoo/commit/e3515a7b73c3e173a3ddf0bc48e4a888024c8817

closes odoo/odoo#89211

X-original-commit: 19a97fcaf1fd2f762522d171e98d9942fb45e9d1
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-04-20 22:56:12 +02:00
Romain Derieandroen-odoo b8bd897fe4 [FIX] website: allow user to access HTML/CSS editor
Current behavior:
When an admin user modified a file with the HTML/CSS/JS editor in a
website, users that had "editor and designer" right couldn't access
the HTML/CSS/JS editor anymore.

Steps to reproduce:
- Have user 1 (U1) admin
- Have user 2 (U2) with website access set to "Editor and Designer"
- U1 modify the css user_custom_rules.scss with the HTML/CSS Editor
- U2 can't open the editor of that website because he is not in the
setting groups or the one that created it

opw-2733109

X-original-commit: d20468c3463927a54c34688769a22b3949c5c465
Part-of: odoo/odoo#89211
Co-authored-by: roen-odoo <roen@odoo.com>
2022-04-20 22:56:11 +02:00
Benoit Socias 998dc0bbe2 [FIX] website: avoid traceback during edition of menu missing URL
Before this commit if a menu had been saved without URL, a string +
boolean concatenation error could happen when updating the menu.

After this commit the False boolean is replaced by an empty string to
avoid the problem.

task-2781260

closes odoo/odoo#89147

X-original-commit: 0288e0e91a071c7ec4b8adb0474d82a46dea9c9c
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-04-20 18:49:07 +02:00
Benoit Socias 38872576e5 [FIX] website, web_tour: send parent menu id as integer in menu update
Since [1] nested menus were not saved anymore because model ids do not
support `str` anymore.

After this commit the menus update data contain an integer `parent_id`
making them understood again by the model.
The `parent_id`s returned by `nestedSortable()` are the ones obtained
through a regex match, and therefore are strings.

Steps to reproduce:
- go to the 'Home' web page
- click on 'Edit Menu' in the 'Pages' menu
- drag and drop a menu item to nest it (e.g. put 'Contact Us' inside
'Home')
- click on 'Save'
=> nested entry disappeared from the menu instead of being nested under
its parent

[1]: https://github.com/odoo/odoo/commit/534087fa8d3c9947a918aa109f4030b5628a80d1

task-2781260

X-original-commit: d7bfb935580d6cc70dc213657c1a6dbc85dfa756
Part-of: odoo/odoo#89147
2022-04-20 18:49:07 +02:00
roen-odoo d8568944b4 [FIX] website, website_blog: remove stars from blog description
Current behavior:
When adding a "Heading" in the first 200 characters of a blog with
/Heading, the short description of the blog preview would have
unwanted stars (*) around the heading

Steps to reproduce:
- Create a blog article
- In the first 200 characters of the blog use a heading (e.g. /Heading1)
- Go back to the blog list, the description of the new article contains
  unwanted stars (*)

opw-2798595

closes odoo/odoo#88352

X-original-commit: 6cb57d2f1ffb0adceaa3199cc0bf5140589d9328
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-04-14 14:07:05 +02:00
Benoit Socias e9ea0692bb [FIX] website: not split fuzzy matching candidates on hyphen
Since [1] when the fuzzy search was introduced, the candidate words used
for the fuzzy matching were split on non-'\w' (all non alphanumeric
characters + underscore).

This commit adds '-' (hyphen) to the list of characters that should be
considered part of the same word.

Steps to reproduce:
- Specify a product with name 'micro-vis'
- search for 'micro-vis' or 'microvis'
=> Was not returning any match
=> Now returns fuzzy match even for 'micro-vs'

opw-2801704

[1]: https://github.com/odoo/odoo/commit/c6ba756e4b4704089d02434871788a82d90cb195

closes odoo/odoo#88591

X-original-commit: 10d54d3c6ba46afa86abac5275a02c4b5ec7d5a1
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-04-13 11:55:37 +02:00
Benoit Socias 768db8390d [FIX] website, website_payment: exclude Donation snippet from cache
Since [1] the CSRF token used by the donation snippet's form did end up
being cached for new visitors that did not have a session id yet.
This made the validation of the token fail when using the form because
the token from the very first new visitor on the worker was reused.

After this commit pages that contain a Donation snippet are not cached
anymore in order to always get a fresh CSRF token - similarly to what is
done for the form snippet.

When using incognito mode the csrf token is sometimes not recognized
during navigation to the donation payment page.
Simple sequence to reproduce it:
- drop a Donation snippet on the Home page
- use Firefox and do not log in
- in normal browser, select 25 then press Donate Now
- open an incognito browser, select 50 then press Donate Now
=> 400 Bad Request
Alternative (any browser):
- open page with Donation snippet in incognito window
- remove session id from cookies using developer tools
- close window
- reopen page in a new incognito window
- try to donate
=> 400 Bad Request

[1]: https://github.com/odoo/odoo/commit/7fccbac004628093da49016f75370a84bba49465

opw-2774065

closes odoo/odoo#88184

X-original-commit: 16c9b103195f342f8bcca928a53121dbe4480d58
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-04-07 13:24:20 +02:00
Romain Derie 5a8d6c351b [IMP] website, test_website: avoid a query on res_company_user_rel
Manual forward port, commit was lost from 15.2 to master. Either it
seemed not needed after the httpocalypse refactoring, or was simply
lost during the rebase.

-----

We can remove an useless SQL Query for public user on every single page
serve, if we directly set the website's company_id in the available
company_ids of the public user.

Indeed, the public user from a website always have the same company_id
as the website.

We can then do that directly and bypass the next line which will
always be true in the case of the public user, making a read for
nothing.

task-2774979

closes #85419

X-original-commit: c95ab6f

[1]: https://github.com/odoo/odoo/commit/728ade674cb12c64718efda56b0d5d542e319cba

closes odoo/odoo#87856

Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-04-06 19:32:44 +02:00
Mathieu Walravens 1ba130a4aa [FIX] website: published link redirect does not check if domain exists
Since commit [1], we should use domain instead of _get_http_domain().
However _get_http_domain() checks if the domain exists which is not the
case in commit [2]. It only impacts databases having multiple websites.

[1]: https://github.com/odoo/odoo/commit/7d8a8ddea0b363732f2177ad589a3e0e10e2fb6c
[2]: https://github.com/odoo/odoo/commit/ee71cdff0786d5c41fbcc50894cd06811d3d8d5b

Steps to reproduce:
  1. Install the eCommerce app
  2. Add a second website
  3. Keep the domain field of the website empty
  4. Set the website field of a product to the website.
  4. Click 'Go to Website'

Current behavior before PR:
  - RPC_ERROR: Odoo Server Error

Desired behavior after PR is merged:
  - Redirected to the product's page

closes odoo/odoo#88067

X-original-commit: 18c8a97ac986753728462b374a1c327bc9597a37
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-04-06 15:30:51 +02:00
Julien Castiaux c46f4b908a [IMP] *: request.session.geoip -> request.geoip
Commit "[IMP] core: don't save visitor default session" moved the geoip
from the session to the request with a deprecation warning. This commit
adapts the remaining modules to use `request.geoip` instead of
`request.session.geoip`.

Geoip is always set on the request but it can be an empty dictionnary in
case the geolocalization failed.

closes odoo/odoo#86015

Task: 2789035
Related: odoo/enterprise#25192
Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-04-05 14:13:54 +02:00
Martin Trigaux f41ec39abe [IMP] base: get_view_id becomes private
Add new helper get_view
Remove dangerous documented comment

Part-of: odoo/odoo#85110
2022-03-29 10:56:16 +02:00
Gorash 880954ebfc [IMP] *: remove _render from ir.ui.view and simplify report
There were inconsistencies in the calls to `_render`.
* the view context could contain information that misled developers.
Indeed, the context and value of the view are not supposed to be found
in the rendering. Thus by calling `ir.qweb` with the name of the
template, we ensure that there is no unwanted information and in
addition the cache key is that of the name of the template which saves
a query.
* the context used for rendering was modified by a method on
`ir.ui.view`, except this is not information used by this model. There
is now a `_prepare_environment` method residing on `ir.qweb`. This
method allows to modify the value dictionary as well as the context in
which the rendering will be done. This preparation of the data as well
as my security check is done only once per rendering. This also saves
some queries
* Freeze options for rendering were inconsistent. It could be that
options on which rendering depends were not part of the cache key. Thus,
depending on the user who generated the generation of the rendering
function, there was or was not information in the template. For example
for automatic branding. This is no longer possible, because it is the
context that is used. The options serving as a cache key are only
recorded for information (for the profiling system for example). A
simplification of the `ir.qweb.field` models could be made.

The report rendering and call `ir.qweb` instead of `ir.ui.view`.

Part-of: odoo/odoo#85110
2022-03-29 10:56:15 +02:00
Fabio Barbero 47041f2d45 [IMP] base: allow user to activate multiple languages at once
Purpose
=======
Add "Activate" button when selecting multiple languages, select multiple
languages when clicking on "Add languages" in settings.

Specifications
=============
`lang` variable in `base.language.install` changed from Selection to
Many2many to allow multiple languages being activated at once.
Hide globe icon for language fields from view mode (only visible when
editing). Remove state in base.language.install since it's no longer
need to keep track of the installation step.

Task-2662548

closes odoo/odoo#78287

Related: odoo/upgrade#2921
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2022-03-14 08:42:58 +00:00
Rémy Voet (ryv) e1785e820a [IMP] base: add prefetching group feature
The field prefetching mechanism was poorly customizable.  Before this,
we could only tell if a field was prefetched with other fields or not at
all.  We have no way to inform the framework, like: "When I need data of
that field, prefetch these other fields, which are likely be used in the
same transaction".

From now on, the `prefetch` attribute is used as a grouping key for
prefetching fields.  When a field is fetched, all the fields with the
same value for `prefetch` are taken for prefetching.

For example, consider a small set of fields that are rarely used, except
for one flow A using them.  You want to prefetch those fields only in
the flow A, and you want to fetch them in a single query.  With the new
feature, simply set `prefetch=A` for some string `A` on those fields,
and they will be grouped for prefetching.

closes odoo/odoo#85220

Signed-off-by: Rémy Voet <ryv@odoo.com>
2022-03-03 11:03:55 +00:00
Rémy Voet (ryv) d2b68d186e [FIX] website: remove force prefetch for translate fields
Issue
-----
When website is installed, the rendering of template uses a side effect
of the ORM cache (cache shared between sudoed env vs non-sudoed env) and
the fields prefetching feature to work correctly.

The `self.visibility` in (`_handle_visibility`, website/ir_ui_view.py)
is done in sudo mode, then it will fetch all prefetchable fields and put
them in the cache (that will be read in non-sudo mode in the render of
the template).  Another example of issue related to this:
https://github.com/odoo/odoo/pull/83341.

Because of this, the fields of mixin `website.seo.metadata` were forced
to be prefetchable (the default for translate is to be not prefetchable
since https://github.com/odoo/odoo/pull/82896), which causes a useless
LEFT JOIN on "ir_translation" in most of business flow.

Fix
---
Remove the `prefetch=True` on mixin fields, and add a extra read to fill
the cache in case of website rendering.  It also allows to read these
fields at the same time.

Part-of: odoo/odoo#85220
2022-03-03 11:03:55 +00:00
alt-odoo 4e542fbdac [FIX] website: wrong fw-port of commit 971f324c419
Since commit [1], we should use domain instead of _get_http_domain()
that was removed.

[1]: https://github.com/odoo/odoo/commit/7d8a8ddea0b363732f2177ad589a3e0e10e2fb6c

closes odoo/odoo#85692

X-original-commit: 82341e9bd0cad8320fd1b95f3369cf2074978cb0
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
Signed-off-by: Alex Thuyls (alt) <alt@odoo.com>
2022-03-02 23:08:17 +00:00
Vincent Schippefilt 05fc9a6733 [IMP] *: use _read_group instead of read_group
This commit modifies most of the usages of read_group and uses
_read_group instead. _read_group doesn't join automatically on the
many2one fields when no order_by is specified, making it more performant
when the "name" of the many2one is not relevant, which is the case for
most back-end cases

closes odoo/odoo#84908

Task-id: 2479334
Related: odoo/enterprise#24877
Signed-off-by: Raphael Collet <rco@odoo.com>
2022-03-02 17:10:48 +00:00
Romain Derie 826c0a9119 [IMP] website: fetch all pages and views at once
When serving a page, fetch the requested page and the menu's pages in
one go.

This will only impact pages that do not have a menu entry, which is the
most common form of pages.

So, instead of:
- read page
- read page's view
and later:
- read menu pages
- read menu pages' views

Fetch everything together:
- read served page + menu pages
- read served page's menu + menu pages' views

task-2774979

closes odoo/odoo#85456

X-original-commit: 16bf7cca8e8d452ce9131d9d86ff5b23789da4e1
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-02-28 13:53:20 +00:00
Romain Derie a61ba018a7 [IMP] website: avoid query on website table when serving empty page
Getting the `res.company` record by browsing the `company_id` cached
value from `website` instead of reading it directly on the website
record will avoid a read on the website table.

While this might seems unusual and not elegant, since this is a very
low level method used to render every view, it seems fine.

task-2774979

X-original-commit: bc643a573a7339c82661cbcff2cc59bdd0eec3e3
Part-of: odoo/odoo#85456
2022-02-28 13:53:19 +00:00
Romain Derie 28b9a6490c [IMP] website: don't query website table when serving homepage
We can easily avoid a read on the website table when serving the
homepage by simply caching the website.homepage_id value and then
browsing the record (no query needed) instead of reading it on the
website record.

While this code is not really elegant, it seems like a good tradeoff to
gain a query on this particular homepage serve controller, which is the
main entry point of a website and generally the page the more often
served.

task-2774979

X-original-commit: 69b443b85656c895c66a1f83b235f5d1e53727d4
Part-of: odoo/odoo#85456
2022-02-28 13:53:19 +00:00
Julien Castiaux 8639f9b257 [FIX] website: restore debug mode in website pages
Install website, create a custom web page, we'll call it page_1. Ensure
you are not in debug mode (go to /web/health?debug=0 to disable it).
Open the web page enabling the debug-mode /page_1?debug=1, the page
opens but the debug mode is disabled.

Because web pages are served using another routing mechanism than
controlers we have to ensure we load the debug query-string in those
mechanisms too.

closes odoo/odoo#85340

Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-02-28 13:53:09 +00:00
Julien Castiaux 2e9c6f22d5 [FIX] website: nonexisting record id in URL =>404
Install the website_sale and open '/shop/whatever-9999' in your browser,
the response is a 500 Internal Error instead of a 404 Page not Found.

Because `request.endpoint` has been murdered by the httpocalypse, we
must re-match to get the endpoint later used to re-build the URL. When
an URL contains a record-id but that record does not exists, matching
the URL will raise a `odoo.exceptions.MissingError`.

Part-of: odoo/odoo#85340
2022-02-28 13:53:08 +00:00
qsm-odoo 1ab7210ae3 [REF] web_editor, website: review the web_editor.assets model
- Three controllers were actually useless as the relevant public methods
  of the web_editor.assets can be called directly via RPC in the related
  usecases.

- Review the web_editor.assets model methods organization in the model
  declaration.

closes odoo/odoo#85392

Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-02-28 12:56:05 +00:00
Younn Olivier 2eccc43669 [FIX] website: add scss variables to the disable snippets assets cron
Commit [1] introduced a cron that disables outdated js and scss snippets
assets. For example, if a new version of the masonry snippet is defined
with new assets: data-vcss="001" and data-vjs="001", the previous assets
have to be disabled (000.scss and 000.js).

That cron was not handling the scss variables files at all, so when
an outdated snippet was still used in the db and the cron was run, the
000.scss file was activated, but not the 000_variables.scss and it was
crashing the assets.

Now, the XXX_variables.scss assets files are handled alongside the
XXX.scss files.

Also, the regex used in the _is_snippet_used method was only returning
the first match of a snippet in an html field. So if a view had a
snippet up to date and then an outdated snippet of the same type, the
old assets were not activated. The 'g' flag was added to return all the
occurences of the snippet in an html field.

[1]: https://github.com/odoo/odoo/commit/fa1c05e7bb2959c6025a806a4348f69ed225b4ec

task-2775188

closes odoo/odoo#85360

X-original-commit: 644067e80d4ca3f41707cddd15ed8f2807a1e410
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
2022-02-24 19:41:45 +00:00
Julien Castiaux c0647b5c52 [REF] core: HTTPocalypse (14) changes all addons
This commit is the 14th commit of a comprehensive refactor of our HTTP
framework. See odoo/odoo#78857 for complete historic, discussions and
rationnals.

* `request.uid = x` => `request.update_env(user=x)`.
* `request.context = x` => `request.update_env(context=x)`.
* `request.context = dict(request.context, x=y)`
   => `request.update_context(x=y)`.
* `request.cr = None` => `request.cr.close()`.
* `http.mono_db()` => `request.db`.
* `http.dispatch_rpc()` => `service.dispatch_rpc()`.
* `@service.model.check` => `service.model.retrying()`.
* `request.endpoint`
   => `env['ir.http']._match(request.httprequest.path)[0].endpoint`.
* `request.routing_iteration `=> `removed`.
* `request.jsonrequest` => `request.dispatcher.jsonrequest`.

Note that `request.params` is now set much later in the process. If you
are in a situation where you values from the query string or the
http body you can use `request.get_http_params()`.

Note that using the new `request.future_response`, it is possible to
add headers and cookies on the response object before the response
object is initialized. Please note that headers/cookies saved on
the future response will NOT be injected in case of error.

PR: odoo#78857
Task: 2571224
2022-02-24 13:30:51 +00:00
Julien Castiaux 06cc322e7e [REF] core: HTTPocalypse (13) http_routing/website
This commit is the 13th commit of a comprehensive refactor of our HTTP
framework. See odoo/odoo#78857 for complete historic, discussions and
rationnals.

Here be dragons.

First and foremost, `http_routing` is a technical module that aim to
provide the minimum viable compatibility code between portal and
website. Its primary job is to take care of the lang inserted in the
path of URLs, e.g. `en` in `/en/my_blog`. Both when routing a request
with a lang in the URL and when rendering templates with multilang
support.

Next to `http_routing` is website, the module used by customers to
create pretty web page accessible online. Website uses a different
routing logic than the backend, webpages are **not** registered in the
routing map of werkzeug but instead delivered by website dedicated
code. It means that **all** request targeting a website page thrown at
the werkzeug router **fail** with a HTTP 404 error. The reality is that
website abuses the fallback mechanism (`_serve_fallback`) to deliver
its pages.

Using `_serve_fallback` as the standard way to deliver pages is broken
by design. It is the least crappy way to deliver content as long as
website page don't have a dedicated path prefix. Using a path prefix
(e.g. `p` in `/p/fr/mon_blog`) it would have been possible to route the
request to a dedicated endpoint using the same router as the backend and
with no change to the HTTP dispatching code. Sadly, the business does
not want such prefix so we have to stick with a broken design.

It is broken because prior to serving a page, website needs to setup A
LOT of stuff on the system. It needs to ensure a proper user is set on
the environment, it needs to setup the GeoIP database, it also needs
to determine the lang the user requested the page and it also needs to
save multiple attributes on the request objet itself (`is_frontend`,
`is_frontend_multilang`, `routing_iteration`, `website`, `lang`,
`rerouting` and `website_routing`). Since `base/ir.http@_match()` will
fail, everything must be set either prior to calling this method or in
`website/ir.http@_serve_fallback`.

---

The original implementation was overriding the `_dispatch` method which
was responsible to call the four `_match()`, `_authenticate()`,
`_postprocess_args` and finally `WebRequest._dispatch()`. The override
was very special, here is an attempt to explain it:

1) try to match an endpoint using the backend router, 404-errors are
   ignored.
2) include the geoip stuff.
3) authenticate using the `auth` @route argument if an endpoint matched
   in (1), otherwise authenticate with the public user.
4) if not endpoint matched or if a frontend endpoint matched in (1):
  a) call `_add_dispatch_parameters` which sets many arguments on the
     `request` object, including the lang found in the request cookies
  b) try to extract a lang from the URL: abort with a redirection when
     the lang is missing or wrong, remove the lang from the request
     path when it is set (updating both `request.lang` and the cookie).
5) return the result of `super()._dispatch()`

Note that `_serve_fallback()` is called during `super()._dispatch()`
when the path still does not route to an endpoint. Thanks to the
`_dispatch` overrides in http_routing and website, it is garanteed that
the system is setup prior to calling `_serve_fallback`.

---

Because it is now `http.py@Request._serve_ir_http()` that is responsible
of calling the four`_match()`, `_authenticate()`, `_pre_dispatch` and
finally `_(http|json)_dispatch()` it is no more possible to override it
to take over the dispatching to perform the http_routing/website magic.
The prior implementation can not work with the new design thus is has
been refactored too.

To render a website page, there must be a user configured on the
environment (not None) and the various special attributes must be set on
the request object. The special `lang` attribute is popped from the
request path but backend endpoints must be delivered in priority.

Using the new design, it has been decided to override the `_match`
method to implement the lang-in-path logic, to override both
`_pre_dispatch` and `_serve_fallback` to call `_add_dispatch_parameters`
which have been renamed `_frontend_pre_dispatch` and to also grant the
public user in the `_serve_fallback` override.

The `_handle_error` override in website has similar needs, the function
is called upon error (4xx/5xx) in order to render a pretty
website-looking page. Because such error can occurs as early as in
`_match()` (page not found and no fallback), when nothing has been setup
yet, website is yet again responsible for setuping everything: request,
orm, frontend.

Many other small improvement are not described here. Hopefully the added
comments in the source code are enought.

PR: odoo#78857
Task: 2571224
2022-02-24 13:30:50 +00:00
Julien Castiaux 66b691dc32 Revert "[FIX] website: remove force prefetch for translate fields"
This reverts commit a1a30f52a3.

closes odoo/odoo#85199

Related: odoo/enterprise#24660
Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-02-23 12:59:52 +00:00
Julien Castiaux e655e8da8a Revert "[IMP] base: add prefetching group feature"
This reverts commit 041fe5e21e.

Part-of: odoo/odoo#85199
2022-02-23 12:59:52 +00:00
Rémy Voet (ryv) 041fe5e21e [IMP] base: add prefetching group feature
The field prefetching mechanism was poorly customizable.  Before this,
we could only tell if a field was prefetched with other fields or not at
all.  We have no way to inform the framework, like: "When I need data of
that field, prefetch these other fields, which are likely be used in the
same transaction".

From now on, the `prefetch` attribute is used as a grouping key for
prefetching fields.  When a field is fetched, all the fields with the
same value for `prefetch` are taken for prefetching.

For example, consider a small set of fields that are rarely used, except
for one flow A using them.  You want to prefetch those fields only in
the flow A, and you want to fetch them in a single query.  With the new
feature, simply set `prefetch=A` for some string `A` on those fields,
and they will be grouped for prefetching.

Part-of: odoo/odoo#83818
2022-02-23 10:01:59 +00:00
Rémy Voet (ryv) a1a30f52a3 [FIX] website: remove force prefetch for translate fields
Issue
-----
When website is installed, the rendering of template uses a side effect
of the ORM cache (cache shared between sudoed env vs non-sudoed env) and
the fields prefetching feature to work correctly.

The `self.visibility` in (`_handle_visibility`, website/ir_ui_view.py)
is done in sudo mode, then it will fetch all prefetchable fields and put
them in the cache (that will be read in non-sudo mode in the render of
the template).  Another example of issue related to this:
https://github.com/odoo/odoo/pull/83341.

Because of this, the fields of mixin `website.seo.metadata` were forced
to be prefetchable (the default for translate is to be not prefetchable
since https://github.com/odoo/odoo/pull/82896), which causes a useless
LEFT JOIN on "ir_translation" in most of business flow.

Fix
---
Remove the `prefetch=True` on mixin fields, and add a extra read to fill
the cache in case of website rendering.  It also allows to read these
fields at the same time.

Part-of: odoo/odoo#83818
2022-02-23 10:01:58 +00:00
Arthur Detroux (ard) 2e44cb41ea [FIX] website: fix editor not starting after creating a website
Commit [1] introduced an automatic start of edit mode when
selecting a theme but didn't take into account wether the frontend lang
of the user was matching that of the website that is supposed to enter
in edit mode.

Steps to reproduce:
- Create an empty database and install website.
- Add an extra lang on website (e.g FR) and visit the website in that
lang.
- Go in settings an create a new website, skiper the configurator,
  select a theme.
- Redirect is with enable_editor but nothing happens.

The editor isn't started if not in the source's lang.

This commit redirect the user to the default_lang of the website
so that editor can always be started. It also introduces a tour
to test out the flow.

[1]: https://github.com/odoo/odoo/commit/f474eac4543712ae5b1c7d614f9eff9367445107

task-2687416

closes odoo/odoo#85058

X-original-commit: 02e08af7278cd66d768fe6a4f23aa17eb816be3c
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-02-22 15:19:34 +00:00
Benoit Socias 07290bfe8d [FIX] website: disable fuzzy search if search term contains numbers
Since [1] when fuzzy search was introduced, fuzzy search was also used
when the search term contained numbers.
This is a problem for companies where the shop search is used on
references: the fuzzy search does not match against the whole database
and therefore the exact match might not be found.

After this commit the exact search is used whenever the search term is
made of 80% of numbers or more - because it is very likely to be a
reference or an identifier.

[1]: https://github.com/odoo/odoo/commit/7559626c54e34b41e1549e28276a650accec6986

opw-2715647

closes odoo/odoo#84943

X-original-commit: 7b44907c322a7b78ef4a5cb46627df4f72b21240
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-02-18 21:04:54 +00:00
Arthur Detroux (ard) 283219f64e [FIX] website: use default website lang for configurator
The configurator introduced at [1] uses a frontend controller to
display its content. However this results in inconsistent language
translation as the python code uses the users's language but the
localization services uses the frontend's language when on a frontend
page.

Steps to reproduce:
- Create a database with the only language being french
- Install website
- In the configurator, all the pages will be in french except
  "Pages and Features"

With this commit, the language for the configurator will always be
the language of the website it's configuring. A test also make sure
that this is the current behavior.

[1]: https://github.com/odoo/odoo/commit/e8a5af2e28a4724f86783746706cb59175f086bf

task-2687416

closes odoo/odoo#84810

X-original-commit: a0f8fdc65566fafe98dab21f5c2dbab9505c3d5c
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2022-02-18 14:28:53 +00:00