This issue occurs when a customer imports or uploads a file, and that file
contains an image that is attached to the URL as text or HTML. then,
The error would be generated.
Step to Produce:-
- import CSV file (Ex.'product.product' model)
> that CSV file must have one URL Image(In that URL has content of text or
Html form)
- Click On the 'Test' Button.
Applying these changes will resolve this issue.
sentry:-4046190590
closesodoo/odoo#137611
X-original-commit: acbb5af7ee96cdc579850427bc2bca6d7bf184e4
Signed-off-by: Achraf Ben Azzouz (abz) <abz@odoo.com>
*: web_editor
When an HTML field sanitizes its attributes, it can still be filled with
HTML content (blocks, styling, power box commands) using the website
builder. This causes problems because those elements can then be broken
by the sanitizing.
It is possible to break elements so badly that the page cannot be
edited anymore to fix the problem.
This commit prevents the user from dropping snippet blocks inside the
content of such fields.
Steps to reproduce:
(Unless `slide.slide`'s `description` becomes
`sanitize_attributes=False` in the meantime.)
- Edit a single Course's slide.
- Drop a Carousel into the description field at the bottom.
- Save.
=> Carousel did not work.
Worse:
- Instead of the Carousel, drop a Countdown.
=> An error happens on each page reload, and the edit mode cannot be
reached anymore.
task-3293600
Part-of: odoo/odoo#120588
Before the task
when the default language for a website is not en_US, and users try to
edit_translations from the website, all terms are marked "translated"
because odoo adds
`data-oe-translation-state="to translate"` if the term is not extracted from
the en_US value and is the same as its en_US term
After this commit:
if the record's bounded website's default language is lang_base
odoo adds
`data-oe-translation-state="to translate"` if the term is not extracted from
the lang_base value and is the same as its lang_base term
closesodoo/odoo#127468
Task-id: 3344973
X-original-commit: 7c20510bda2f1312a9392df445ee38aea7b2267b
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
Signed-off-by: Chong Wang (cwg) <cwg@odoo.com>
'replace() argument 1 must be str, not bool' is generated if the user edit a
float or monetary section in the website view.
Steps to Reproduce
- Make debugger mode ON.
- Go to Settings > Translations > Languages.
- Remove the value of the 'Thousands Separator' field from the current user
language.
- Install the 'eCommerce' module.
- Go to the website.
- Go to the shop menu, and click any product from the product list.
- Click on the Edit button and try to edit any float or
monetary section like a product price (eg. change a product price from 750 to
70) and click on the Save button.
And traceback will be generated.
Applying this commit will resolve this issue.
sentry-4148693017
closesodoo/odoo#125684
X-original-commit: b895175cfc487f3db6e53351fd5774303f193698
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
*: base, web_editor
The Many2oneUserValueWidget does not allow the user to reset it
to blank if it already contains a selection. This commit makes it
possible to select an empty value by specifying a `null_text` option.
task-2406626
Part-of: odoo/odoo#67913
*: mass_mailing, website_blog, website_event, website_mail_group,
website_mass_mailing, website_payment, website_sale, website_twitter
The names of snippet blocks are not translatable because their name is
obtained from a their template name which is not a translatable item.
For markets that use a non-latin alphabet this is a no go.
This commit makes it possible to specify a `string` attribute in the
`t-snippet` blocks that makes their name inventoried by the translation
process.
closesodoo/odoo#118530
X-original-commit: a501d226d8674ed0c9b183c69a9e754c79682237
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Signed-off-by: Benoit Socias (bso) <bso@odoo.com>
Since [1] when the Dynamic Snippet was first introduced, it also
introduced a concept of "inherited" snippets. Specific snippets would
all `t-call` the same template for their rendering.
A mechanism was introduced to deduce the `data-snippet` from the caller
template, but it stored the obtained value in the `t-called` template
itself. Because of this if several "specific snippets" that used that
template had to be rendered, they would all have the `data-snippet`
value of the first one that got compiled.
We could compile the snippet template into something having a
dynamically obtained `data-snippet` value, but then that would be
equivalent to just using a `t-attf-data-snippet`.
All specific snippets already do set a `snippet_name` in the context
because it needs to be added in the classes.
This commit therefore adds a `t-att-data-snippet` attribute on the
base template, and populates with that same value in `onBuilt` for
stable versions.
During forward ports across stable versions, each new caller must be
patched as well - and all patches must be removed in master.
[1]: https://github.com/odoo/odoo/pull/53175
task-2922635
closesodoo/odoo#115566
X-original-commit: 73d2c9f87bf9a1a792f4318325c2e52fc81db5f2
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Signed-off-by: Benoit Socias (bso) <bso@odoo.com>
Before this commit, only the immediate parent of a selected node was
checked for HTML content support in order to determine the toolbar's
visibility. This led to incorrectly displaying the toolbar for fields
like the 'list-price' on an e-commerce product page, whose text content
is wrapped in an extra 'span' element inside the field's span element.
This commit fixes it by checking all of the node's ancestors up to the
editable root for the attributes that determine if a field supports HTML
content.
This commit also prevents a server error if the user somehow styles the
product's price (with ctrl+B for example. It's worth noting that such
style would not be kept in the saved version of the page).
lxml.HtmlElement's `text` property has `None` value if the span element
does not contain any text before its first child element
(see https://lxml.de/apidoc/lxml.html.html).
Therefore an element like `<span><strong>42.00</strong></span>` would result
in `None` when reading its `text` property.
The `text_content` method is more suitable for such task as it returns the
text content of an element and its children.
task-3188550
opw-3171669
closesodoo/odoo#114867
X-original-commit: 524ba7f89286aa03ed6a4da30177c9ce7018c59a
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
In commit [1] it was decided that the Snippet Menu would have its UI in
the user's language, while the Snippets' Content would be in the
language of the website they are currently editing. To do so, a new
context key was added: Snippet Lang.
Unfortunately, while Odoo handles the compilation according to a
language, website_id and more, it does not do so according to the
snippet lang.
It would not be an issue if the Snippets were compiled only in edit
mode, as a Website only has one default language. Unfortunately the
Snippet Content is also rendered in translate mode (Since the
SnippetMenu is one big XML template), therefore it can be rendered in
different Snippet Lang (though it's useless).
This commit fixes that by adding Snippet Lang as a cache key so that if
the key is present, it will re-compile the template.
Steps to reproduce:
- Create a new language
- Translate a snippet (e.g. search s_cover view and translate contact
us)
- Create a new website with 2 languages, the new language as default and
english
- Enter translate mode
- Leave it
- Enter edit mode via the "Edit master" button
- Drop the translated snippet
- It will not be translated because the Snippet Menu was rendered in
English first.
A commit introduced after this one will test these steps.
[1]: https://github.com/odoo/odoo/commit/55a978aa86967581956f855a1c5db33b7425bd15
X-original-commit: 6eba6203e9f1b8a730ab53f80fea8e7b78818bc7
Part-of: odoo/odoo#108643
Prior to this commit, the language of the snippet menu would be the same
as the snippet content. This would cause issues if the user's language
was not the same as the website they were editing.
This commit fixes that by displaying the snippet menu in the user's
selected language but getting snippet content in the website's language.
This commit also fixes SEO data not being saved according to the
website's displayed language. Prior, it was saved according to the
user's current display language.
This commit also introduces a test for a fix made at [1] that
targets a previous version of odoo.
[1]: https://github.com/odoo/odoo/commit/db5d1eae2086ff338d8211af70c2f88240393c36
task-2687506
closesodoo/odoo#102799
X-original-commit: 55a978aa86967581956f855a1c5db33b7425bd15
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
Avoid having multiple tooltips. We keep only one "t-field"
in the template. The other are replaced by a "t-out".
We also add a specific message when the datetime format is not
respected.
task-2942617
X-original-commit: a99d684507782cd0d9ff700dc7a12f7a46442403
Part-of: odoo/odoo#102545
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>
See previous commit(s) for more details about the new sanitize feature.
This commit implement a solution in the website builder to warn
restricted users when they can't edit a field due to the sanitizer
restriction.
Long story short: a HTML field can be flag as `sanitize_overridable`
which will allow users with the `base.group_sanitize_override` group to
not go through the sanitize process.
It means that such users can write some content which is not sanitize
friendly. A restricted user trying to add content in such fields would
then break the original content as the sanitizer would remove part of
the DOM.
In such cases, the field in the website builder is not detected as an
editable part and clicking on it will warn the user about it.
closesodoo/odoo#97398
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Add the possibility to flag a HTML field as `sanitize_overridable`.
The sanitizer will then be bypassed if the user doing the operation is
part of the new group `base.group_sanitize_override`.
The "Settings" users are part of that new group.
If such a user wrote some HTML that would have normally been removed by
the sanitizer, then users without the right to bypass the sanitizer
won't be able to write on that field anymore.
Otherwise, it would sanitize the previously written data.
Such cases are detected, and the modification prevented by the system,
which will warn the user about it.
For instance, with a `field.html(sanitize_overridable=True)`: one being
part of `group_sanitize_override` could write `<script></script>`.
Then, someone not part of the group trying to add an element inside that
field like appending a `<p/>` -> `<script></script><p>New Content</p>`
would not be able to because it would go through the sanitizer and
ultimately, removing part of the original value:
`<p>New Content</p>` (`<script></script>` would be removed).
== Real use case ==
In the website builder, there is 2 editor rights:
- group_website_publisher: restricted editor
- group_website_designer: editor & designer
The designer editor can edit pages and views, while the restricted
editor can't do anything unless he is part of other groups.
In edit mode, the restricted editor will only be able to edit fields of
record he has access to.
For instance, being a sales manager allows you to edit a product
description on the website.
Being an event manager -> edit event. Slide manager -> Slides etc.
As those restricted editor are able to edit those fields, they are
(almost) always sanitized to prevent them to introduce malicious code.
Since those fields are sanitized, even admins / designer editor are not
able to fully use the website builder in such fields.
Some clients don't really care about that sanitation, they'd prefer to
avoid it as they trust their manager and would prefer to have the full
builder capability instead.
This is typically the case in small project (butcher, hairdresser,
reseller etc) and in SMEs.
With the new `sanitize_overridable` feature, they will be able to do
that, as the "Designer & Editor" group now also receive the group
`base.group_sanitize_override` (done in next commit).
Part-of: odoo/odoo#97398
*: website, website_mass_mailing, website_payment
When an unsafe snippet is dropped into a sanitized HTML model field, its
unsafe content gets removed on save.
We need a way to mark snippets as being (in)compatible with
sanitization. It cannot be automatic, as, for example, the snippet
introduced at [1] contains an iframe but is compatible with
sanitization.
In 13.0, we will temporarily set up an automatic mechanism that marks
existing snippets containing forms as being incompatible with
sanitization.
In 14.0 a distinction between full sanitization and form-tolerant
sanitization introduced at [2] is added with this forward-ported commit.
This commit prevents unsafe snippets from being dropped into sanitized
HTML model fields.
The "Form Builder", "Product Search" and "Product Search Input" blocks
are now prevented from being dropped or moved into form-sanitized HTML
fields.
To do this, this commit introduces a new `t-forbid-sanitize` attribute
on the `t-snippet` tag. It can have the value `true` to prevent it from
being dropped into any sanitize fields, or `form` to specifically limit
to form-sanitized fields.
Steps to reproduce (in 13.0):
- Go to a product page
- Drop a "Product Search" snippet into the product-specific section of
the
product
- Save
=> The form was removed.
[1]: https://github.com/odoo/odoo/commit/c2e9bd0e60014b6a42931cf300e0f89f8cf7c225
[2]: https://github.com/odoo/odoo/commit/388c222c6c4bb7e2fe3e67009b248359ae0fd3db
task-2829961
closesodoo/odoo#96812
X-original-commit: 9eaba23781766730b06e936dbd9c5d0c28c909c6
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
When editing database fields via the web editor, their value are not checked.
Thus, stack traces can come up to the front-end user.
Step to reproduce the issue:
1) Install the E-Learning module and connect to the website
2) On the main website (not the backend), go to Courses > Edit
3) Edit the Next Rank treshold with any non integer string (e.g.: coucou)
A stracktrace will be shown upon save.
Solution: The issue is that there are no validation on the submitted fields,
this can cause stacktraces. A try-catch was used around the parsing of the
input value to catch and properly raise these exceptions to show clean errors.
On top of this, integers were not properly parsed, they were not taking into
account the `thousands_sep` of the user lang (e.g.: 35,000 for 35000).
NB: Generic fix of the following PR [1].
[1]: https://github.com/odoo/odoo/pull/85535
opw-2819392
closesodoo/odoo#96187
X-original-commit: edf76dbb0880c9b08354563a3c77e7c06a604802
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
Signed-off-by: Desausoi Laurent (lade) <lade@odoo.com>
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
Prior to this commit, when an exception occured during the save of an
ir.ui.view, the traceback was shown to the user and an alert directly
asks the user to reload or cancel the page.
While reloading, the changes that produced the traceback were not saved
and the other modifications were saved.
If the user choose to cancel the reload, the web editor UI was freezed
and there couldn't be any edition anymore.
This commit adds correctly the popover to target the invalid element and
shows the error rather than reloading the page.
The element which caused the error can still be edited. The other are no
more editable.
task-2700198
closesodoo/odoo#87350
X-original-commit: 10b97f37ab5d78b3a2b0f63fa019ee95bb78ea7d
Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
Signed-off-by: Thibault Libioulle (tle) <tle@odoo.com>
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
When working on qweb fields it is difficult to find some custom override as
they are never in the right file. Finding them is always a bit of random pick.
Task-2607416
Part-of: odoo/odoo#74171