...when voip addon is installed.
We want to avoid predictable rpcs that are systematically done at
webclient startup. In particular, the voip service needs to know if
the user has group "base.group_user", which produces a rpc when
the service is started.
To avoid this, this commit adds the information in the page
directly. As this information is also useful at other places
(even though it's not at startup), we directly add it to the
groupCache of the user service (and we do the same for the
"base.group_system" group, which we also receive in the page).
closesodoo/odoo#139477
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Currently, when a user has access to a branch of a company, but not to
the company itself, the branch will not show up in the company switcher.
As a result, the user is not able to switch back to that branch when
logged in to another company.
To fix this, we now show the whole hierarchy of the branches you have
access to, disabling the companies/branches you don't have access to.
task-3503204
Part-of: odoo/odoo#138942
Before this commit, formatters like `formatMonetary` and `formatFloat`
weren't loaded in the assets front-end.
This commit introduces `formatAmount` ( `formatMonetary` calls
`formatAmount` but makes some prior processing to deduce the currency
from the field) and makes `formatAmount` and `formatFloat` accessible
from any front-end application.
Note: The currencies were added in the front-end session info because
they are needed in `formatAmount`.
closesodoo/odoo#133824
Related: odoo/enterprise#46658
Signed-off-by: Valentin Chevalier <vcr@odoo.com>
The limit was only enforced by the front-end, meaning that anybody could
forge a request with a huge file and get it processed by Odoo. According
to the documentation of werkzeug[^1], such limit should be enforced by
the server server instead of the wsgi application. It is the case for
Odoo Online but on-premise customers might not configure their servers.
The `web.max_file_upload_size` system paramter is now enforced upon
parsing the content of the request. It defaults at 128 MiB which is
enough for most documents and images. We do not want to host large
files (e.g. videos) in the Odoo filestore.
[^1]: https://werkzeug.palletsprojects.com/en/2.0.x/request_data/Fixes: #124646
Part-of: odoo/odoo#126914
In order to manage different branches, the usability of the company
selector is being improved
* display in a hierarchic manner
* when selecting a company, select all the available children with it
task-3371677
Part-of: odoo/odoo#125642
This commit moves and adapt the res.users.settings model from mail to base and
and allows to access and modify its content with web's user service.
This allows to access user settings without needing the mail module.
closesodoo/odoo#116005
Related: odoo/enterprise#38360
Signed-off-by: Michaël Mattiello (mcm) <mcm@odoo.com>
Some cookies were left around even when the user logged out
The next user should log into the default company instead of the company
of the last user.
task-3077421
closesodoo/odoo#108998
Related: odoo/enterprise#35685
Signed-off-by: Julien Castiaux <juc@odoo.com>
*: 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).
closesodoo/odoo#108063
X-original-commit: 7b9bd9d37731fae724dc5d91da656dab70aa9ad4
Related: odoo/enterprise#35012
Signed-off-by: Julien Castiaux <juc@odoo.com>
Only server wide modules are being taken into account when calculating translations hash.
So user probably can't get translations of new installed modules unless it is forced by hard page reload (Ctrl+Shift+R).
Problem exists since https://github.com/odoo/odoo/commit/80d74e7ee0eab83dc5100e0776df09d04b882fec and the cause in that `mods = odoo.conf.server_wide_modules or []` string was unpaired with the following `if` statement during refactoring.
This commit restores computation of hash based on all loaded modules.
closesodoo/odoo#105466
X-original-commit: 859cd0463aec4533df30e4839367832fef0685fd
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
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>
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
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
closesodoo/odoo#88134
Task: 2801675
Related: odoo/documentation#2083
Related: odoo/enterprise#26191
Signed-off-by: Julien Castiaux <juc@odoo.com>
The odoo.addons.web.controllers.main python module have been splitted
over multiple files on the basis 1 controller = 1 file. In this work we
adapt all modules to use the new imports.
A non-exhaustive list of where stuff have been moved:
* main.Home --> home.Home
* main.Session --> session.Session
* main.WebClient --> webclient.WebClient
* main.clean_action --> action.clean_action
* main.ensure_db --> home.ensure_db
The complete list is accessible in odoo.addons.web.controllers.main.
closesodoo/odoo#87571
Related: odoo/enterprise#25746
Signed-off-by: Raphael Collet <rco@odoo.com>
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.
closesodoo/odoo#85340
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
This commit is the 12th commit of a comprehensive refactor of our HTTP
framework. See odoo/odoo#78857 for complete historic, discussions and
rationnals.
The web module is twofold, on one side there are many controllers: /,
/web, /web/login, /web/database/selector, /web/dataset/call_kw, etc, on
the other side there is `session_info`: the method responsible to create
the web client's environ.
This module is kinda an exception as it is (with base) a server wide
module. In the case of the HTTP framework, it means that the controllers
of web are always accessible, i.e. going to / or /web/login will never
return a 404 Not Found even if the user is not connected to a database.
This is both a blessing and a curse. It is a blessing because the
controllers are always accessible it means that a new users can freely
access those routes. It is a curse because *any* user can access them,
even user who don't have a session yet thus who are not connected to a
database yet. From a developer standpoint, we have to put extra care to
correct serve users with and without a database. An example is the
/web/login route, the login/password pair is stored in a database,
without database it is impossible to validate a user login but users can
still access this route without db.
To solve this problem, there is the `ensure_db` function. This function
attempts to find a database using various sources (?db= query-string,
session db, mono db) and to save it on the user session. In case no db
is found, the user is redirected to the database selector. In a way,
this function grants a database to the user in a seamingly experience.
In a way, this function brings a welcome differentiation between
`auth='none'` with a database and `auth='none'` without a database. Such
differentiation only matters for the server wide modules as "regular"
module controllers are only accessible via the ir.http routing map, i.e.
it is not possible to declare a nodb controller outside of server wide
modules.
An important changement is the `session.authenticate` method, before it
was possible to call the method when the cursor was not yet initialized,
authenticate would open a cursor against the given database, setup a
registry and an environment and ultimately save everything on the
current request. Because the cursor is now greedily created, it is no
more possible to update the request environment when authenticating on
another database.
PR: odoo#78857
Task: 2571224
Avoid to base64 encode, then decode to process assets and images for a ~25% speed improvement.
Change image processing tool to work on images, rather than base64 encoded strings.
Performance is ~25% faster on assets & images:
/web/assets/...frontend.min.css: 13ms to 7ms, base64 enc/dec: 2 -> 0
/web/image/XML_ID: 10ms to 8ms, base64 enc/dec: 3 -> 0
/web/image/res.users/2/avatar_128: 40ms to 20ms, base64 enc/dec: 6 -> 2
closesodoo/odoo#82851
Related: odoo/enterprise#23537
Signed-off-by: Fabien Pinckaers <fp@odoo.com>
As JS is not taking the properties in the order they are written,
the order in the rendering was always following the property name
sorting order (=id).
Previous to this commit:
- The companies were ordered by their id in the company switcher as
JS is not tacking the object properties order into account.
After this commit:
- The companies will be sorted by their sequence prior to be used in the
rendering.
task-2722235
closesodoo/odoo#81893
X-original-commit: 39c678a1ccb50d3a1871a4049a8df26427b27a3c
Signed-off-by: Laurent Stukkens (ltu) <ltu@odoo.com>
Purpose
=======
Avoid counting requests from social bots (twitter, facebook, linkedin...)
when tracking a link.
Specifications
=============
Social media platforms have a specific user agent in the HTTP headers that
can be used to detect them and to not increment the click count in that case.
Task-2578902
closesodoo/odoo#78806
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Following-up to previous commit, this one makes the
`get_translations_for_webclient()` more defensive with regards to the
absence of a `lang` key in the context, rather than relying on callers
to protect it. The rest of the logic was already fine with this.
This allows simplification of the `session_info` logic and removal of
the conditional for `translation_hash`.
Further cleanups in `session_info()`:
- removed a duplicate calls to `session.get_context()`
- removed duplicated resolutions of `request.session.uid`
closesodoo/odoo#79182
X-original-commit: 3eca1a2e58b8c644c0701d33d0c9d0330bdc234f
Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
Signed-off-by: Romeo Fragomeli (rfr) <rfr@odoo.com>
Since [1] and [2], the mobile app gets this error when trying to login
on v15, while it was working fine in v14 with TOTP enabled.
The 'authenticate' JSON-RPC route tries to authenticate the user and
then call `session_info()`. As no UID is defined, some methods in
`session_info()` raise an exception and an unexpected error is sent:
* `_is_public()` -> "Expected singleton: res.users()"
* `get_web_translations_hash()` -> "lang"
In this fix, this exception is avoided and the proper result is sent,
allowing the authentication process to continue.
Steps to reproduce:
* Try to connect to an account with TOTP on the mobile app (v15+) => BUG
Refs:
[1] odoo/odoo@80d74e7ee0
[2] odoo/odoo@401fc7efe9
X-original-commit: 65dca67ecdcc2228d90781a9f5ccd99f290ada6c
Part-of: odoo/odoo#79182
The show_effect was either "True" or false which is inconsistent.
This was caused by the fact that the string value came from the backend
and the boolean came from the default value of get_param.
By wrapping the result of get_param in a bool constructor, we make sure
the type is always consistent.
closesodoo/odoo#78742
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
With the introduction of the guest feature, a lot of fields are now
accessed through a controller so that they can be available to guests,
with additional checking in the controllers.
Avatar is one such field, however the extra checks were too restrictive:
we only allowed people to see the avatar if the user whose avatar was
requested was also a member of the channel. This breaks the avatar on
previous messages if a user leaves a channel.
This commit relaxes this restriction for internal users (they can now
see all avatars through this route), and adds a fallback to the avatar
placeholder for people who do not have acces (ie: guests) so that the
UI doesn't look broken.
closesodoo/odoo#76341
X-original-commit: b849fd426806332c1ecc1bbba7b568384a021c65
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
* = crm_livechat, hr, hr_holidays, im_livechat, mail_bot, purchase, sms,
snailmail, survey, test_discuss_full, test_mail, web_editor, website,
website_livechat
- Create new model `mail.guest` for guests.
- Rewrite some RPCs to target routes rather than model methods so that
guests are able to use them.
- Patch JS and python models to support guests.
- Create a stand-alone page and boot the channel in it.
task-2494829
closesodoo/odoo#75496
Related: odoo/enterprise#20417
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
The frontend code was still using the legacy RainbowMan, with the wowl
webclient, we rewrote this RainbowMan and started using that one
instead, but because the frontend code had no access to the wowl
environment, the legacy version was still used in the frontend. Since
the frontend now has access to the wowl environment, the old code can be
removed and the calls can go through the new effect service.
closesodoo/odoo#74148
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is the first phase of the conversion of the web/ JS
codebase to the owl framework. The impact of this commit is two-fold.
First, it rewrites the framework part of web with a new system of
services and registries. Services allow to execute code (e.g. do rpcs,
setup things) before launching the application. They can also expose
an API to be used by other parts of the application (e.g. a notification
service would expose a function to display notifications). Services are
often a good extension point for external modules that want to execute
code at webclient startup. Registries offer another way to extend the
application. They provide well designed extension points to add
elements/behaviors from the outside (for instance, to add a systray item,
an error handler...).
Second, this commit initiates the conversion of the webclient to owl
with a top-down approach, around those notions of services and registries.
The root of the web application is now an owl application. Among others,
the WebClient, ActionManager, Navbar, UserMenu, DebugManager, Dialogs,
services (e.g. notification, ajax...) have been converted to the new
framework/architecture.
Legacy views and client actions are still supported (and used). They
will be converted in the next months, and at some point, the support
will be dropped.
Co-authored-by: Aaron Bohy <aab@odoo.com>
Co-authored-by: Bruno Boi <boi@odoo.com>
Co-authored-by: Géry Debongnie <ged@odoo.com>
Co-authored-by: Samuel Degueldre <sad@odoo.com>
Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com>
Co-authored-by: Simon Genin (ges) <ges@odoo.com>
Co-authored-by: Francois (fge) <fge@odoo.com>
Co-authored-by: Michael Mattiello (mcm) <mcm@odoo.com>
Co-authored-by: Julien Mougenot <jum@odoo.com>
Co-authored-by: Lucas Perais (lpe) <lpe@odoo.com>
Co-authored-by: Jorge Pinna Puissant <jpp@odoo.com>
Also make this a configurable value, from the server.
This is the limit of the SAAS servers.
closesodoo/odoo#72143
X-original-commit: bcd1c8aade6123dd20d7aebaae8a0f204f258604
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Signed-off-by: William André (wan) <wan@odoo.com>
The profiling tools can be useful to profile a test of some execution
point but this is not convenient to identify a problem on a running
instance.
With this commit, an option available in the debug menu allows to add a
flag on the user sessions to enable profiling of all requests. Each
request will be saved in a different 'ir.profile' entry, but will be
grouped under the same session.
The profiling can be activated on all sessions, even for a public user,
but only if profiling is enabled on the database globally.
This commits also adds a speedscope view to visualize saved results in
the web client.
closesodoo/odoo#66590
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
Previously, lazy-loading xml templates was only possible by fetching the
xml file directly, this meant that it was impossible to lazy-load an
entire bundle's templates with a single request. Additionally,
requesting the xml files directly meant that no inheritance was applied,
causing the need for a separate inheritance system using t-jquery on the
client-side.
This commit alters the /web/webclient/qweb route so that it now takes a
bundle id, meaning that it is now possible to lazy-load the xml from
arbitrary bundles.
task-2497943
closesodoo/odoo#70084
Signed-off-by: Géry Debongnie (ged) <ged@openerp.com>
This commit changes the way assets are declared in Odoo modules.
Before: assets were declared in template files. Template bundles were
generated from primary templates, so technically any qweb template could
have been called as an asset bundle, with the 't-call-assets' directive.
Being standard qweb templates, they had access to standard HTML tags
(script, link, with or without raw scripts or style definition), qweb
directives (t-call, t-raw, etc.) and could be inherited by other
templates.
Now: assets are defined in the module's manifest and generated by the
't-call-assets' directive.
More information on the new system can be found on the updated user
documentation (see the "JavaScript Reference" section).
Task: 2352566
Co-authored-by: Bruno Boi <boi@odoo.com>
Co-authored-by: Julien Mougenot <jum@odoo.com>
Co-authored-by: Lucas Perais <lpe@odoo.com>
Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
Co-authored-by: Simon Genin <ges@odoo.com>
This commit's primary objective is to ensure that the timesheet uom is working in accordance
with the company settings in a multi company environment.
Prior to this commit:
- The timesheet preferences sent to the front end were always those of the default
company of the user.
- The timesheet related widgets initialisation process (adding the correct ones in
the fieldRegistry) was performed before the front end treatment of cids and coockies
which prevented applying the front end selected company settings.
After this commit:
- A dictionnary is used in the session in order to structure the companies info.
- The company timesheet preferences are sent to the front end through the company dict.
- The uom info is sent to the front end through the session.
- The timesheet uom is now managed from the frontend and is now in sync with the settings.
- Timesheet widgets are initialised during the AbstractWebClient init and are in sync with
the multicompany front end settings
task-2168337
Closes: #66551
This commit allows the user to apply actions to all records
matching the current domain in list views. It also ensures that
the user is aware of the set of records actually selected.
The number of selected records is now displayed in the control
panel, and the user can, with an additional click, select all
records matching the current domain instead of the ones of the
current page.
Task 2185145
Before this commit, we compute the hash on each request, to know if we need to
download the file from the frontend or if we can use cache.
Now we store the hash computed in cache. The cache will be invalidated when we
touch one of these translations (openerp-web in the comments) or when you
install a new lang (already the case).
+ avoid to use read on a record, since it will not use the cache from record.
Related to #47257
task-2211013
X-original-commit: d5aaecbc51de19ef1d8d9988b691177fc73a4b86
This information is necessary for tours going from the backend to
the frontend (or the other way around) to run properly:
Some tour steps may be flagged with 'community' or 'enterprise',
meaning they must only be executed in the corresponding edition.
The TourManager filters the steps according to the edition. When
a tour is executed (either in test mode, automatically, or in an
onboarding situation, manually), the index of the current step is
stored in the local storage. So, the list of filtered steps must
be the same in the backend and in the frontend, which couldn't be
guaranteed as the frontend didn't have the information (thus always
considered being in community).
Part of task 2180175
closesodoo/odoo#45398
Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com>
The `session_info` dictionnary is used to bootstrap some JS code client
side (usually in the backend). It includes relevant information, such
as some parameters key for the OdooBot onboarding, the Enterprise
subscription expiration alert, etc. to avoid triggering a lot of RPC
calls upon webclient start.
`session_info` is also called by the remote authentication mechanism
located at `/web/session/authenticate`, which can be used by external
mechanism to obtain a valid session remotely.
Revision odoo/odoo@8a28cc2 introduced the concept of cache keys for
some oft-requested data (such as menus, translations and dynamic qweb
templates) to avoid requesting them on each webclient start, since they
tend not to change often. Unfortunately, it introduced a read on the
ir.ui.menu model that raised an `AccessError` if the authenticating user
was not a member of the `base.group_user` group ('Internal' user type).
While fixing that issue, it became apparent that `session_info`
returns a whole lot of information through this remote connection route
which is entirely unnecessary if not used in the context of a webclient
start, such a currencies, the state of the enterprise subscription, etc.
This commit fixes the access right issue by removing this non-relevant
information from the returned dict (including cache keys) if the user
is not an internal one.
closesodoo/odoo#40770
X-original-commit: 6e99ac2c6cd5ca9af87b4fc7a3a1394359e30b02
Related: odoo/enterprise#6860
Signed-off-by: Damien Bouvy (dbo) <dbo@odoo.com>
SHA-1 is a cryptographic hash function that have weaknesses known since
2005, it has been deprecated by the NIST [1] about 10 years ago in 2011
and Google [2] have been able to perform a collision attack in 2017.
We use SHA-1 in order to generate unique URL for resources that can be
cached by the browser: assets bundle, translations, qweb templates and
qweb images.
Although practical attacks still requires quite a lot of computational
resources, it is time to upgrade SHA-1 to SHA-2.
We have selected the SHA-512/256 variant of the SHA-2 algorithm as
replacement for SHA-1 for the following reasons:
* On 64 bits platform, SHA-512 is the fastest SHA-2 variant, it is only
~1.5x slower than SHA-1. [3]
* Keeping only the 256 foremost bits protects against both collision
attacks and length extension attacks.
* The hexadecimal digest is only 24 chars longer than SHA-1 which is
nice to have somewhat short URLs.
We have not used SHA-3 because:
* At the moment of writing, it is too slow (~3x slower than SHA-1) [3]
* It is not guaranteed to be available with the Python 3.5 `hashlib`
module.
* One of the author of SHA-3 is Belgian.
[1] https://csrc.nist.gov/projects/hash-functions/nist-policy-on-hash-functions
[2] https://shattered.io/
[3] http://bench.cr.yp.to/results-hash.html
[4] http://www.commitstrip.com/en/2017/02/27/the-sha-1-alternative/
QWeb templates that show up in the 'qweb' key of a module's manifest
now support server side inheritance and xpath evaluation
QWeb templates that show up in the xmlDependencies of a JS widget are not
impacted at all by theses changes, as they are served through the
Werkzeug sharedMiddleware
A similar syntax than ir.ui.view has been implemented in the QWeb templates
- each template must have a root node, whatever tag works
- the root node of a template must have a t-name containing the name of the template
The name -- without the module's name -- may contain dots pretty much anywhere
Though what is recommended is only underscores in template names
- if a template is to inherit from a parent, the root node has a t-inherit directive
containing either the full name of the template it inherits from which is module_name.template_name
or the name of the template, no module name necessary, if the parent template is in the same module
- there are 2 modes of inheriting
primary: copy the behavior of the parent into the template
extension: modifies the parent in place
Task: 1999528
closesodoo/odoo#33892
Signed-off-by: VincentSchippefilt <VincentSchippefilt@users.noreply.github.com>
Co-authored-by: Julien Mougenot <jum@odoo.com>
Co-authored-by: Lucas Perais <lpe@odoo.com>
cache_hashes was introduced at 8a28cc22fd to reduce the number of reload
The cache is correctly reseted when the translations content changed but did
not contain all the translation-related parameters that are, however, stored
in the session_info
This commit fixes two bugs:
Language parameters invalidation:
1. Access the webclient in a specific language
2. Modify the language parameters (e.g. thousands separator)
3. Refresh the page
--> webclient is still using old language parameters (from cache)
No translation flag after installing a language:
1. Load a database in English in mono-language
2. Load a second language
3. Access a record with a translated field
--> translation button not present on translated field (multi_lang is still
false in cache value)
To fix it, this commit adds all the information that are returns by the
/web/webclient/translations call to make sure the hash represent the reality
closesodoo/odoo#34266
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
* add a json_scriptsafe module, which re-exports the stdlib's json but
provides a script-safe `dumps` function, because of the way it works
the script-safe version is fine / safe to use outside script
contexts, so there's no need to provide different functions to qweb
contexts
* make the json.dumps in qweb contexts <script>-safe (should be
rendered using t-raw)
* update callsites to properly dump json:
- dump in template, not in the python code
- dump the entire structure at once, not bits and bobs inside a JSON
literal
Task 1999158
closesodoo/odoo#33682
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This commit goal is to encapsulate every tour-test into a separate assets
bundle that would be called only during tests (command line) or by URL
(debug=tests). That way, a lot of .js files would not be loaded anymore
uselessly outside test mode and will speed up the page loads (especially in the
frontend as the backend do not reload the page anyway).
In order to do that, we needed to propagate the `debug` state from page to
page.
Otherwise, every page change during a test would simply lose the debug mode and
the test would stop as the test assets would not be loaded.
As we could not add the `&debug=tests` on every link (either hardcoded or
preprocess during the rendering), it has been decided to store it in session.
Technical summary:
1. `debug` state (currently only stored in URL) will be stored in session.
Either when adding the `debug` param in URL (handled with _dispatch) or by
starting Odoo with `test-enable` or `test-file` (handled by session init).
2. Once activated (and so set in session), debug mode will remain activated
even if not visible in URL (after a page navigation eg).
To deactivate it, set its value to nothing, `debug=`. That will exit debug mode
(whatever mode it is: debug, assets, tests).
3. As tour-test files are now in a separate bundle, every layout (when needed)
should `t-call="web.conditional_assets_tests"`.
As it would be redundant and verbose, no `t-if` is needed on the t-call to
load it only in test debug mode. That will be handled by
`compiled_assets_tests` that will actually do the conditionnal t-call-assets
to web.assets_tests, if tests debug mode is activated.
4. In addition to separating the tour-tests files in a separate bundle, we also
moved those files to a specific folder under /static/tests/tours next to
QUnit tests.
5. Also, tour files will be moved in a specific folder /static/src/js/tours for
cleanness purpose (those files will still be kept in their 'normal' assets
as needed outside test mode since it is tours).
This will be done in the next commit.
6. It is possible to enable multiple debug mode, such as 'tests' and 'assets'
together. Simply separate debug modes with a comma, eg '?debug=assets,tests'
task-1934445
Comes with https://github.com/odoo/enterprise/pull/4281Closes#33213
* http_routing, portal, rating, survey, website, website_survey,
website_slides_survey
Before this commit, the final base layout of website was a fully
overridden layout of the one in portal, which was somehow a duplicated
one of the login one in web, which... so lots of duplicated code.
This commit is a first step towards a better organization:
1) The web app defines a frontend layout (to include base frontend
assets), with a base company logo as header.
2) The portal app modifies that layout in place to include the base
header, footer, ... It also uses a primary extension of it for
portal pages.
The survey app simply uses the above layout instead of defining its
own (by primary extension to include its own assets for its own
pages)
Same goes for the rating app and pages.
3) The website app modifies that layout in place to include the UI
assets, to add website UI, ... This allows to create frontend apps
which do not depend on website, with a non duplicated layout that
will be automatically adapted if website is ever installed (this
therefore allows to get rid of website_survey definitely)
This commit also fixes the session info system and the translation URL
on the frontend side to not require to redefine the whole session_info
for portal, website, ... Now the frontend session_info is defined in web
and http_routing extends it to add translation informations, then
website extends it again to add its own elements (not to redefine them
all as before). Note: before, http_routing defined the translation route
but only portal was adding it in its layout...
This is an adaptation of the work that was done with commit
https://github.com/odoo/odoo/commit/99821fdcf89aa66ac9561a972c6823135ebf65c0
Note 1: Many frontend but non-website apps (not only survey / rating)
could probably use this too but this would be the topic of another task.
Note 2: survey currently depends on http_routing but does not add itself
in the list of frontend apps to translate, it probably should.
Note 3: web_editor does currently not depend on http_routing but does
add itself in the list of frontend apps to translate, it thus uses a
function it does not really depend on... to check after its work-in-
progress refactoring.
task-1961045
closesodoo/odoo#33825
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Generate a unique URL for translations and cache them forever in the
browser. This reduces the number of requests, in exchange for computing
the hash of the translations when the session object is added to the page
Today, some resources that varies very infrequentely are requested on
every page load: the menus, the translations and the qweb templates
After this commit, there will be 2 improvements that will make the
loading of the webclient faster:
1. cache almost static resources forever
when loading the /web/ page, the user session will
contain the cache key to be used to fetch these resources. As the content
of the resource itself it used to compute the hash, the request can be
put in cache by the browser forever (for a year).
The up side is that in general less requests are needed to load the web client
The down side is that the load time and number of queries of /web page
has increased to include what is needed to compute the hash of translations,
menus and qweb templates
2. trigger the loading of the menus before the download (and startup) of
the JS and CSS assets:
The menus contains the definition of the action, wich is the first thing
needed to load a page in odoo. Starting the loading of the menu much
earlier means that when they are not yet in the browser cache (see point 1),
the browser does not need to wait for the entire assets to be downloaded
and parsed before starting the 'load_menu' request, but instead start it
immediately and hold onto a promise to be used instead of the rpc 'load_menu'.
Because the request is done before anything else is loaded, including
JQuery, it is made in vanilla JS.
Co-authored-by: Julien Mougenot <jum@odoo.com>