Before this revision, when you pass `context` in the arguments
of a JSON routes, this one gets automatically injected
in the environment context.
This is not the case for regular HTTP routes.
It makes sense to propagate the context for the JSONRPC protocol,
JSON routes used by the backend, such as `call_kw`,
but it doesn't make sense to pass this context automatically
for any other kind of routes, such as front-end routes
or routes used by custom Javascript widgets.
This change brings a more unified behavior for routes
of types HTTP and JSON.
In addition, most developers were not aware of this "feautre",
that passing `context` in the arguments of a JSON route leaded
to the injection of this context in the environment context.
This is actually reflected by the diff size this changes required,
only a dozens of routes needed to be adapted, to manually
add the context in their route arguments and to inject it
in their environment context.
closesodoo/odoo#121726
X-original-commit: a7a5655631e6d5b05fd2ba3d0c80617aae6d9cfe
Related: odoo/enterprise#41229
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
This commit fixes the totp tours which fail on a step in
the profile dialog. The step searches for an element
".o_dialog_container" that is removed since commit
e51112e0df7f5e05d3cdf2c01d236c6bbbf123a6
closesodoo/odoo#117451
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
This commit converts almost all odoo module by native module.
The goal is to deprecate odoo.define in favor of native module and then
simplify boot.js by removing the regexp that finds module dependencies.
task id: 3162300
closesodoo/odoo#117305
Related: odoo/enterprise#39118
Signed-off-by: Géry Debongnie <ged@odoo.com>
* The tours are now run by the `MacroEngine` defined in `macro.js`.
* This is accomplished by converting (at runtime) the user-defined tours to
`Macro`s. See `tour_compilers.js` for the step (and tour-to-macro) compilation.
* API is kept the same as much as possible. Basically, declaring tours stayed
the same with some exceptions:
* `allowInvisible` can be provided in a step to allow consuming the trigger
element even if it is invisible.
* `isCheck` can now be used to replace the no operation `run` that is
traditionally signals the runner to only perform a check.
* Before, multiple `run`s can be called simultaneously. Now, each `run` method
is awaited before proceeding to the next step.
* If the trigger element is `disabled`, the tour runner will *not* proceed on
calling the `run` method and the runner will stay on current step until the
trigger element becomes `enabled`.
* However, the tour runner is okay with `disabled` trigger element if the step
has `isCheck = true`. As long as the trigger element is found for `isCheck`
step, the tour runner will happily move to the next step.
* Some tours are adjusted to properly run with this new tour runner.
* When the tour failed:
* The dom string is not logged anymore.
* However, a warning message containing the relative location of the step will
be logged. This is better in helping the author in locating the failed step.
**Some guidelines learned during the development:**
* Each step may trigger a dom mutation. It's a good practice to insert an
intermediate step that *checks* the existence of an element that result from
the action of the previous step.
* Refrain from using the `run` method for assertions. `run`, in principle, is
provided to perform actions that are not offered by the helper. Use the
`trigger` for assertions.
* During dev, find `SHOW_POINTER_DURATION` and set it to `250`. This will show
the pointer (pointing to the trigger element) for 250ms when watching the
tour.
closesodoo/odoo#107618
Task-id: 3082036
Related: odoo/enterprise#37560
Signed-off-by: Géry Debongnie <ged@odoo.com>
Co-authored-by: Julien Mougenot <jum@odoo.com>
This commit is a security reinforcement.
It applies the same logic as for the password of the user to the totp_secret and signup_token
closesodoo/odoo#113753
Signed-off-by: Vranckx Florian (flvr) <flvr@odoo.com>
This is a step closer to a goal of avoiding dependence on asynchronous
modules. Starting from this commit, new tour definition should be
registered to `registry.category("web_tour.tours")` registry.
So, instead of the following:
```js
import tour from "web_tour.tour";
tour.register(name, options, steps);
```
We now do:
```js
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add(name, optionsWithSteps);
```
Notice the `options` and `steps` params are merged when registering
the tour definition. It should look something like so:
```js
registry.category("web_tour.tours").add("account_tour", {
test: true,
steps: [ ... ],
});
```
And if the `TourManager` instance is needed, one can get it from the
registry like so `registry.get("tourManager")`. Note however that
this instance is only available when the `TourManager` has been
instantiated -- so it's not available at top level of the module.
closesodoo/odoo#111103
Related: odoo/enterprise#36335
Signed-off-by: Géry Debongnie <ged@odoo.com>
request.geoip is no more a dictionnary cached in the session. It is now
a full blown object with lazy and smart geolocalisation capabilities.
Among other things, the previous dictionnary API is now deprecated. The
changes are:
* `request.geoip['country_name']` -> `request.geoip.country_name`
* `request.geoip['country_code']` -> `request.geoip.country_code`
* `request.geoip['city']` -> `request.geoip.city.name`
* `request.geoip['latitude']` -> `request.geoip.location.latitude`
* `request.geoip['longitude']` -> `request.geoip.location.longitude`
* `request.geoip['region']` -> `(request.geoip.subdivisions[0].iso_code if request.geoip.subdivisions else None)`
* `request.geoip['time_zone']` -> `request.geoip.location.time_zone`
It is safe to access all the attributes. Doing `request.geoip.city.name`
when the geolocalization failed (missing db, invalid address, ...)
evaluates to None. It does not raise an AttributeError.
Task: 2848206
Part-of: odoo/odoo#91337
Web:
Adding a css rule constraint to avoid the rule
from overwriting the o_field_highlight css class
applied on a field in a form view.
Base, auth_totp:
Adding the o_field_highlight class on the 2FA
form fields to display the input bottom border and
thereby more easily identify the fields.
Adding a placeholder to the 2FA password field.
Modifying the 2FA title and toggle font to keep
a consistency between the different page titles.
Task-3083540
closesodoo/odoo#108611
X-original-commit: c128a01490bbbcbf824781f5e8716aa30e65ba5b
Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
The recent switch from tables to css grids for form views `group` nodes
has introduced several inconsistencies/issues with several views accross
modules - these will not be the last fixes.
closesodoo/odoo#102174
X-original-commit: 836568dfd59886a6d52f15e0e2109709903b6803
Related: odoo/enterprise#32295
Signed-off-by: Bouvy Damien (dbo) <dbo@odoo.com>
Login is a noun and not a verb. The corresponding verb is Log in.
And indeed the translation in French was "Identifiant" instead of
"Se connecter".
closesodoo/odoo#99478
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
This commit fixes the style of the field, which was
pretty broken since the Owl conversion.
It also bring back the tooltip (as in legacy) when
the button is clicked.
The button now only shows the tooltip if the text
has been copied successfully to the clipboard, and
not appear when it is not allowed or not available
in the browser.
Tests have been added to assert those behaviors.
Enterprise PR to adapt a selector in tests:
https://github.com/odoo/enterprise/pull/30832closesodoo/odoo#98340
Related: odoo/enterprise#30832
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
The previous pass in #97567 missed a small window of race condition
in *closing the fecking dialog*. Apparently that's still not
instantaneous enough and it's possible to have the check trigger in
the interval between clicking the button and the dialog being
completely torn down.
Add an explicit test for this to the existing `closeProfileDialog`
utility function.
closesodoo/odoo#97969
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
When #96517 was merged, it was missed that if hr is *not* installed,
then the user profile opens in a dialog in edition mode (always, can't
be readonly).
Since half the tours of `auth_totp` end in the profile screen (to
check that the totp state is what we expect) this means they work fine
in most test contexts where `hr` is installed, but they fail as soon
as `hr` is *not* installed.
Fix this by adding a helper function which checks whether the profile
screen uses a dialog or not, and closes the dialog if so (otherwise it
does nothing as the "form" profile screen is not in edition mode).
While at it, improve a bunch of steps:
- fold check steps which were really `extra_triggers` (something we
wanted to check but not manipulate, in the same screen as something
we do want to manipulate)
- convert a few promise-based functions to `async` (tours don't
support promises but async functions work either way and lead to
simpler code here)
- make better use of the tour action helpers (no need for explicit
`_get_action_values` calls for the most part, and no need to
call the internal versions either)
- clarify a pair of fixmes as I'd completely forgotten what they meant
closesodoo/odoo#97567
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
The new list and form views were merged recently [1], but they
weren't activated because they weren't 100% ready yet. This is now
the case. This commit adds those views to the view registry. As a
consequence, a lot of qunit tests and tours needed to be adapted,
mostly for selector changes.
We also add legacy list and form views to the view registry, with
keys 'legacy_list' and 'legacy_form'. This allows to force those
legacy views when necessary. For instance, we did it in views
using complex custom legacy x2many field widgets that haven't been
converted yet (we have a compatibility layer but it isn't complete
and doesn't support every advanced usecases).
[1] odoo/odoo#92475
Part-of: odoo/odoo#78221
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>
Co-authored-by: luvi <luvi@odoo.com>
The trusted devices are valid for maximum 90 days (TRUSTED_DEVICE_AGE).
No need to keep them in the list of trusted device, it may even be
confusing.
closesodoo/odoo#95796
X-original-commit: 49130e60a3c43fa3df0adddbd3359e437f5bc0b2
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
Due to the removal of btn-block we need to change the display to grid
> Dropped .btn-block for utilities. Instead of using .btn-block on the
> .btn, wrap your buttons with .d-grid and a .gap-* utility to space
> them as needed
https://getbootstrap.com/docs/5.1/migration/#buttons
Task ID: 2766483
Part-of: odoo/odoo#95450
PR #75535 introduced trusted devices, but only made them visible in the
main user form (for admins) and in the portal.
It's quite useful for users to be able to view and manage their trusted
devices in their own user preferences as well.
This commit add them in the "Account Security" of the user profile.
In addition:
- improve the layout of the trusted devices by wrapping them in a
<group> to have them stand out from the surrounding prefs
- move the "Account is protected" label about the trusted devices, and
under main the 2FA toggle button, where it's supposed to be.
- removed the custom form view for trusted devices inside the one2many.
The point was to hide the extra `scope` field, but it's not worth it,
and the Cancel button wasn't even working, the default form view is
better.
- improve the confirmation message of the "Revoke All" button when it's
located on the user management form (for admins) to clarify that it's
not the admin's devices that will be revoked.
- change the 2FA label from "Your Account is protected" to "This account is
protected" when located on the user management form for admins.
Note: this is a manual partial fwd-port of #94111, as this part was
mistakenly dropped in the fwd-port chain at #94193closesodoo/odoo#94869
X-original-commit: d3a7910788ceff856fc6a843876579d379ce9caf
Signed-off-by: Olivier Dony <odo@odoo.com>
Adds a variant `_check_credentials_for_uid()` for auth_totp.device's
`_check_credentials()`. The new method will directly verify the device
key matches the given uid.
This spares the redundant uid comparison on the caller side, and
allows extension modules to customise the user/device matching logic.
closesodoo/odoo#94365
X-original-commit: 0e266eb3c73409950d1eb160c41eb6668d439856
Signed-off-by: Olivier Dony <odo@odoo.com>
When a login attempt is ignored, we add the user info for a better
understanding on the attack (brute force, credentials stuffing...).
closesodoo/odoo#91588
X-original-commit: 0f69448202244e808e1122a618be701806d606cf
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
Every request comes with a session, a dictionary that is persisted on
the filesystem and that saves various information such as the user
cart on the ecommerce.
When a user simply visits the website, a default session is created and
saved on disk, this bloats the filestore with many sessions. Creating
the session on-the-fly is cheaper than loading it from the filesystem.
With this work the default session is not saved on disk anymore unless
explicitly asked via `session.touch()`.
An exception to the statement "creating the session on-the-fly is
cheaper" is geoip, the ip geolocalization is not cheap. In this work,
geoip have been moved from http_routing/request.session.geoip to a
lazy property core/request.geoip. When requested the info is persisted
on the session. Like other keys from the default session, geoip will not
be persisted unless there is non-default stuff in the session.
Because the CSRF-TOKEN is based on the session-id, it is important the
session-id stays the same across multiples requests even when the
session is not persisted on disk. Even when a session is not persisted
on disk, the session-id cookie is still set so that the next session
created on-the-fly uses the same session-id.
Technical note regarding the session, it has been decided to drop the
session-snapshot protocol and to reintroduce a "modified" flag. It has
been decided not to use werkzeug's session (which natively comes with a
"modified" flag) and to keep our own session object. We decided to
extend MutableMapping instead of dict; using MutableMapping we only
have to override __setitem__ and __detitem__; using dict we would had to
override update()/pop()/... too.
Task: 2789035
Part-of: odoo/odoo#86015
This commit removes the multilang feature on the /web/login/totp controller,
it doesn't really add value since it triggers a redirect and that the page is
all the same translated.
It is a good practice by default for SEO, but in this case it brings
some bug with the IOS apps that doesn't follow the redirect, while we don't
need to optimize this page for Search Engine.
The bug into the IOS apps, create a loop when we request the totp screen.
Device request /web/login/totp
Server ask a redirect to /fr_FR/web/login/totp
Device redirect to /web/login/totp
Server ask a redirect to /fr_FR/web/login/totp
...
closesodoo/odoo#87810
X-original-commit: 4dea1b9b7cf0855095f9cfa37ff6a9a6db7cf55e
Signed-off-by: Adrien Dieudonné (adr) <adr@odoo.com>
Signed-off-by: Jérémy Kersten <jke@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>
Since PR odoo/odoo#78857 , the TOTP authentication support is broken
when used inside either Android or iOS mobile apps.
Due to our inability to update the iOS app (following review from
Apple), this commit aims at restoring the bare minimum requirements to
make the current mobile apps (specially iOS but also Android)
authentication workflow works.
As extended explanation:
- Set-Cookie header is expected to be sent even when session_id hasn't
changed (iOS specific).
- Successful credentials check on `/web/session/authenticate` expect a
successful response with a result containing `uid` set to `null` to
mark the need of an additional totp handshake (both platforms).
closesodoo/odoo#85463
Signed-off-by: Julien Castiaux <juc@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
Add the possibility to force the two-factor authentication for all users,
using a two-factor authentication by email
when the 2FA using an Authenticator app is not configured for the user.
Two possibilities:
- Force the 2FA only for employee users using the system parameter `auth_totp.policy=employee_required`
- Force the 2FA for all users, employees and portals, using the system parameter `auth_totp.policy=all_required`
closesodoo/odoo#83750
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
The action server is only available on view list. It is hard to find this.
closesodoo/odoo#83455
X-original-commit: 2fa29557d048e43bc9ed0a9fc9047de203b0c4f0
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Declared as an api.model in all the other modules except auth_totp
closesodoo/odoo#79726
X-original-commit: 61b319ea2b5ffc70e0fd80eb62b8a3f700be0f1f
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
Purpose
=======
Hide non-relevant fields for a portal user. E.G. we want to hide the
notification type, the menu customization... Because those fields
make no sense for a portal user.
Force the non-internal user to receive notifications by emails since
they can not open Discuss.
Task-2508521
Part-of: odoo/odoo#77766
Co-authored-by: nounoubensebia <neb@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
This commit removes all the 'extend' initially introduced to avoid code
repetition and ensure visual consistency across Bootstrap and Owl dropdowns.
Despite achieving the desired results, using 'extend' in this context
was seriously impacting the bundle generation time, probably due to an
underestimated amount of Apps' legacy-code applied on these elements.
In order to achieve the same results, the chosen strategy is to add
Bootstrap default classes directly into Owl dropdowns.
Also, it moves code related to bootstrap dropdown in 'webclient.scss',
leaving 'core/dropdown/dropdown.scss' for Owl code only.
Due to the discrepancies between Bootstrap and Owl html
structure, the '.dropdown-item' class could not have been added
directly to Owl's '.o_dropdown_item' itself, without refactoring
the Dropdown component structure.
// ==== Bootstrap 4.6 default Structure ================================
<div class="dropdown-menu">
<button class="dropdown-item" type="button">Action</button>
<a class="dropdown-item" href="#">Another action</a>
</div>
// ==== OWL default Structure before this commit =======================
<ul class="o_dropdown_menu">
<li class="o_dropdown_item">
<span>Action</span>
</li>
<li class="o_dropdown_item">
<a href="#">Another action</a>
</li>
</ul>
// ==== OWL Structure after this commit ================================
<div class="o-dropdown--menu dropdown-menu">
<span class="dropdown-item">Action</span>
<a class="dropdown-item" href="#">Another action</a>
</div>
// ==== web.assets_backend.css Bundle Generation Comparison ============
With all modules installed (enterprise edition over runbot):
Before this commit, bundle took ~2.5s and ~4s to generate and weighted ~322kB (~2.5MB uncompressed)
After this commit, it takes between ~1.2s and ~1.6s and weights ~257kB (~1.6MB uncompressed)
closesodoo/odoo#77649
X-original-commit: 84715436d87bb05b421bc9ccaacda67d07571690
Related: odoo/enterprise#21370
Signed-off-by: Géry Debongnie (ged) <ged@openerp.com>
Co-authored-by: Stefano Rigano <sri@odoo.com>
Co-authored-by: François Georis <fge@odoo.com>
Co-authored-by: Bruno Boi <boi@odoo.com>
Since mail dependancy has been extracted into a bridge module auth_totp_mail,
the test about "Invite to use 2FA" is misplaced in the wrong module.
This commit moves the test on 2FA invite button to the bridge module and fixes
the test on auth_totp module to use another indicator that 2FA has been disabled
for the currently tested user (see test file).
Task-2645206
Parent Task-2638538
COM PR: odoo/odoo#76381closesodoo/odoo#76579
X-original-commit: 305f94bf1b7ac7c106e05e60601640feca934005
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Original commit was adding the feature in stable but was replaced by
2dee29a7dc in 15.0
This is the forward port of 4736344a57e176 keeping only the test
closesodoo/odoo#76476
X-original-commit: f707d5887c168604b7b7571ae4adc47d64b4a55a
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
Since 29db699e9b, auth_top depends of mail module, which lead to delay auth_totp
installation - not during DB creation anymore. As mail module is not installed
during DB creation, once an app that depends on mail is installed after DB
creation, auth_top module is finally installed and the session token now depends
auth_top module. As a result, the user is automatically logged out.
This commit moves the invite mail (and the dependance to 'mail' module) to a
new bridge module. Auth_totp module will now be reinstalled during DB creation
automatically.
Task-2638538
Parent Task-2487630
COM PR: odoo/odoo#76022
UPG PR: odoo/upgrade#2808
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
+ Added the 'Trusted Devices' feature
+ Added 'Remember this Device' checkbox on /web/login/totp
+ Added trusted device's OS / browser on Profile > Account Security
Added '2FA Trusted Devices' feature to allow users to remember their
device to bypass the 2FA for the next connections. The trusted devices
are displayed in a 'Trusted Devices' One2Many under the 'Developer API
Keys'. It is possible to revoke all the trusted devices at once with a
special button. It is also possible to revoke one at a time on the
desired one.
Task-id 2523092
closesodoo/odoo#75535
Related: odoo/upgrade#2800
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
Co-authored-by: Martin Trigaux <mat@odoo.com>
Purpose
=======
Review the UX of the 2-factor authentication flow in order to make it more clear
and easy to use.
Specifications
==============
This commit applies multiple rewording of instructions, button, etc. Tests have
been adapted accordingly.
It also adds an 'invite to use two-factor authentication' flow that will
send an email to the selected used to redirect them their account security
settings.
- If portal is not installed yet, the user is redirected to his account security
settings in backend.
- If portal is installed, the user is redirected to /my/profile if them are
portal user. Otherwise, the redirection is still done at backend side.
As the backend view of auth_totp wizard is used at frontend side, copyclipboard
widget has to be rebuilt at frontend side (click event, style etc..).
As API key section is now displayed only on debug mode, test urls have been
adapted accordingly.
Task-2487630
Part-of: odoo/odoo#71142
The license is missing in most enterprise manifest so
the decision was taken to make it explicit in all cases.
When not defined, a warning will be triggered starting from
14.0 when falling back on the default LGPL-3.
closesodoo/odoo#74245
Related: odoo/design-themes#48
Related: odoo/enterprise#19862
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
Define `data-hotkey` on most used action buttons.
For the modals, the following keys are dedicated for "special"
actions:
- Alt+G: add
- Alt+V: save
- Alt+Z: cancel
closesodoo/odoo#73275
Taskid: 2588233
Related: odoo/enterprise#19464
Signed-off-by: Kevin Baptiste <kba@odoo.com>