Previously, when the odoo server was running on some Windows
installations, it was possible for javascript files loaded directly from
the static folder of an addon to fail to run because the Content-Type
header was set to text/plain instead of text/javascript. This is because
the mimetypes module from the standard library honors the mimetypes from
the OS, in the case of Windows it reads a key in the registry, which can
be misconfigured to text/plain for .js files.
This commit forces the mimetype of .js files to text/javascript to solve
this issue.
closesodoo/odoo#162313
X-original-commit: 64cbe389e698398eee93ebde9c61b2ee79756380
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
Signed-off-by: Samuel Degueldre (sad) <sad@odoo.com>
The conditionnal `isinstance(exc, NotFound)` is shadowed by the
conditionnal `isinstance(exc, HTTPException)` two lines above. Nobody
ever complained that the warning for NotFound error was gone. Since
werkzeug 1.0.0, the status code in the response log is colored, 404 is
colored yellow which should catch the eye. The explicit warning line
isn't really necessary.
closesodoo/odoo#159895
X-original-commit: 851b91f19b87446662421cb8d801a9472725bc72
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
The version of werkzeug installed can vary from one deployment
to another, as we recommend to use the operating system package,
and the version can therefore change according to the operating
system version.
e.g. the werkzeug version installed using
`apt install python3-werkzeug` varies between
Ubuntu 18.04, 20.04, 22.04, 23.10, ...
We want to keep under control the attributes
developers use on werkzeug.wrappers.Request,
to avoid compatibility issues from one
version to another.
Therefore, this revision aims
to subclass werkzeug.wrappers.Request to limit
the attributes which can be used.
task-3734305
Part-of: odoo/odoo#78857
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
Currently, when a worker (process/thread) has finished processing a request, it
will keep handles on resources held by the werkzeug `Request` object. This
includes open filhandles to temporary files, e.g. those of uploaded files. On
platforms supporting `O_TMPFILE`, these files are not visible in the
filesystem, but keep using up space in `TMPDIR` until werkzeug finally closes
the file handles when the next Request is being handled.
In some contexts, e.g. the upgrade platform, it can happen that there are
multiple workers that only handle rare requests that upload big files (multiple
GiB), kept open after the upload has finished:
```shell
lsof -nP | grep -E 'odoo\/tmp.*(deleted)' | grep -vE 'GeoIP'
python3 213853 odoo 13u REG 252,3 1064251 926275 /home/odoo/tmp/#926275 (deleted)
python3 213853 213865 python3 odoo 13u REG 252,3 1064251 926275 /home/odoo/tmp/#926275 (deleted)
```
This can pose problems, because often the filesystem on `TMPDIR` is not very
large and idle workers holding on to large files can increase the chance for
ENOSPC.
This patch changes the behavior such that the resources held by the werkzeug
`Request` object are being closed[^1] after the response has been sent out.
This also has the advantage that this work is done at potentially idle time
instead of within handling the next request.
[^1]: https://werkzeug.palletsprojects.com/en/2.0.x/wrappers/#werkzeug.wrappers.Request.closeclosesodoo/odoo#150029
X-original-commit: a920ddca57e7bf9353611396f1c0b1060c8cb044
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
In #126914 a limit on the request size has been enforced, that limit is
by default 128MiB and can be configured via an ir.config_parameter. When
restoring a backup larger than 128MiB via the database manager, the
default limit was used and the request was cancelled with a Request
Entity Too Large (code 413) HTTP error.
It is now possible to define a default max content length per route,
that per-route limit takes over the `web.max_file_upload_size` ICP.
Moved the code from `get_http_params` to `pre_dispatch` to better align
with the httpocalypse new http stack.
Fixes: #144144
opw-3643475
closesodoo/odoo#147506
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
The Content-Security-Policy[^1] http header was only set on the response
generated by controllers but it was missing from the `/<module>/static/`
route.
It is not strictly necessary to set that header on the responses comming
from that routes as it is not possible to add new static files or edit
existing ones via the interface (not even as admin). Only the developers
and system administrator can access those files.
It is also worth mentionning that using the Odoo internal web server to
deliver static files is suboptimal. Outside of a dev environment, those
files will typically be delivered via a web server[^2] and sysadmins
should configure their web server to set the CSP header on static images.
[^1]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
[^2]: https://www.odoo.com/documentation/master/administration/install/deploy.html#serving-static-files-and-attachmentsclosesodoo/odoo#146591
X-original-commit: 55e09d504df9bd134afb6e0b38f03457b5c71e8e
Related: odoo/documentation#6953
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
Install auth_oauth and via the /web/login, click the "Log in using
Odoo.com" button. You are redirected on odoo.com which ask you for your
odoo.com login and password. When the login form on odoo.com is
submited, you are redirected back on your local database.
The problem is that, in case a new account was created on-the-fly, then
the login fails with a cryptic error. The actual error is that
`request.env.user._is_internal` fails because `user` is an empty
recordset where it should had been the just-authenticated user.
The problem is an inconsistent transaction state between the cursor of
the request, the cursor used with `auth_oauth` (which created a new
user) and the cursor used with `authenticate` (which authenticated the
new user). Yes, there are 3 cursors. The newly created user just isn't
present in the transaction of the request's cursor.
Here is the lifetime of the 3 cursors:
* request.env.cr, it begins when the http request enters Odoo, it is
commited when a http response exits Odoo.
* /auth_oauth/signin, it begins roughly at the beginning of the
controller, it is commited once after the user is created (so before
the authenticate transaction begins but AFTER the request transaction
begun), it is commited again when the controller exits.
* authenticate, begins when authenticate is called, is commited when it
returns.
Because the request transaction started before, it cannot access user
created by /auth_oauth/signin.
Because the route is `auth='none'`, if system administrators append the
`auth_oauth` module via `--load` (cli) or `server_wide_modules` (odoorc)
then the controller can be accessed without database. This is the reason
for the explicit registry/cursor/environment inside this controller, we
needed to make sure we are connected to a database, we cannot rely on
request.
The new approach used in this work is to benefit from `ensure_db()`, the
function that is used by various web `auth='none'` controllers such as
/web and /web/login. It makes sure that the database we want to connect
to is already present on the request, otherwise it repeats the request
but this time connecting it to the database. Using this approach we can
have a `auth='none'` controller whose request.env is guaranteed to be
connected on the right database. We can avoid to create explicit new
registry/cursor/environment within the controller and just use request's
ones.
Because the /auth_oauth/signin controller now simply use the request
transaction, the above point:
> Because the request transaction started before, it cannot access user
> created by /auth_oauth/signin.
just doesn't stand anymore as the user is created within the same
transaction. The extra `cr.commit()` must still be present for
`authenticate` to see the newly created user.
opw-3421701
closesodoo/odoo#138051
X-original-commit: e165568f9795af213c8467a7f17948ed781b0799
Signed-off-by: Olivier Dony (odo) <odo@odoo.com>
Co-authored-by: Julien Castiaux <juc@odoo.com>
- `Response.charset` is deprecated since 2.3, `Response.set_cookie`
accesses the currently-extent internal `_charset` directly until
this too gets removed in Werkzeug 3.0. Add a `_charset` to
`FutureResponse` so this does not crash.
- Bytes response headers are deprecated since 2.3, and will get
removed in 3.0, passing bytes in websocket is completely unnecessary
happenstance which is trivially fixed.
closesodoo/odoo#137145
X-original-commit: 66e3040d4ad9e03aabefebd4799f699ad30fca45
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Purpose
=======
When a user tries to reach a course, an AccessError can occur when we
unslug the URL. Instead of the traditional error page, we want to
redirect the users to /slides, and the error will be displayed there.
Task-3477630
closesodoo/odoo#135926
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.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
One of the main issue with ormcache is that the invalidation clears
everything, meaning that some value, slow to compute but with a long
lifetime, can be removed from the cache because an easy to invalidate
value is cleared, like after writting or creating a product has an
example.
Most example in the code will try to invalidate the cache of the models
doing something like `env['ir.qweb'].clear_caches()` but it is
finally equivalent to `env.registry.clear_cache()`, and cross worker.
The idea is to have multiple cache, maybe with specific sizes for a
specific purpose.
Having one per model is maybe a bad idea because it will be difficult
to size the LRU correcly, and it is too dynamic. Checking invalidation
may be expensive.
The proposed solution is closed allow a limited number of named caches,
using onse sequence per cache. This is actually close to the
cache_longterm.
We want to discourage using a specific cache for one use case in
the buisness code. Adding a cache shouldn't be something easy, doable
in stable.
Note that we could also change the invalisation mecanism using an
insert only table. We an check the sequence of this table, but also
fetch all invalidation messages.
Another possible improvement, especially if we have more than x cache is
to have a global sequence, checking signaling would mean to check the
main sequence, and only the other ones if the main one changed.
Note that this poc is inspired from the long term cache but not all
use case where applie yet.
Part-of: odoo/odoo#119813
*: mail, mrp, test_website, web, web_editor
Before this commit '.webp' images could not be used in odoo.
After this commit '.webp' images can be uploaded to odoo.
- can be used in image field
- can be used in HTML field image
- can be used in mails and website
- can be transformed (shape mask, filter effect, crop, rotate, resize,
adjust quality)
task-2774352
Part-of: odoo/odoo#85494
Send a request to any json-rpc route with a HTTP header
`Content-Type: application/json-rpc` but send non-json or
non-jsonrpc data in the body. The application crashes with
a 500 Internal Server Error instead of a 400 Bad Request one
closes odoo/odoo#124571
Closes: #122048
X-original-commit: a1b83b07996f3fe4744474ff4023a3a2ce17ac7f
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
Before 16.0 and https://github.com/odoo/odoo/pull/78857 the session
cookie duration was set to 3 months, but the server-side garbage
collection of inactive session was reaping them after 7 days of
inactivity. The cookie lifetime was essentially superseded by the
server-side GC.
After https://github.com/odoo/odoo/pull/78857 these limits were made
consistent with each other, but the lifetime value was kept at 3 months,
which is a bit too long as a default.
This commit changes the default SESSION_LIFETIME back to 7 days for both
limits.
In addition, since the server-side GC is now implemented by a
database-specific cron job, this commit introduces an optional system
parameter `sessions.max_inactivity_seconds` that can be set to override
the default server-side GC threshold, to make it shorter.
Note 1: the ICP does not modify the cookie lifetime which will remain set
to the default 7 days. This means normal browser sessions won't stay
alive for longer than 7 days of inactivity. So `sessions.max_inactivity_seconds`
can't be effectively set to a longer expiration time.
This seems like a reasonably safe default.
Note 2: the session GC happens during the execution of the autovacuum
cron job ("Base: Auto-vacuum internal data") which is scheduled once per
day by default. When setting a small `sessions.max_inactivity_seconds`
value, it may be necessary to increase the frequency of that cron job
accordingly.
closesodoo/odoo#122964
X-original-commit: 05ff9a2db32c2fb1afa107ac005423218f452290
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
The 'frontend_lang' cookie is used to 'cache' the user's preferred lang.
We want to make sure that this language preference is preserved for a
longer period of time than just the life of the browser. This means that
even if you quit your browser and come back into the year, your
preferred language will be used, until you choose to remove your cookies.
The 'utm_*' cookies are used to 'track' where you are coming from on the
instance. The purpose of these cookies is to know the tracking value
to improve the overall user experience or compute the profitability of
some campaigns. Now we keep these cookies for 1 month.
closesodoo/odoo#122573
X-original-commit: 058e0abcf621796bf23d8dcaaf3b2297f632b5fd
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
Signed-off-by: Jérémy Kersten <jke@odoo.com>
Install and then uninstall the utm module via the web client, you get a
traceback because the ir.http override of the utm module is still
present in the registry altought the module is not installed anymore.
The problem affects all modules that override the _post_dispatch method
of ir.http, it is not limited to UTM.
The problem is that, after the uninstallation, a new registry (without
the uninstalled modules) is created but the old registry was still used
by the HTTP stack.
closes odoo/odoo#122519
Closes: #121755
X-original-commit: 979844600a0bc5ea8b63cf4d58c7aba5133e82f3
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
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>
The current profiler will add default value in the user session
using disk space without valid reason.
This commit makes those parameters optional in the session.
closesodoo/odoo#118762
X-original-commit: eb3bf03b119105f56806d7460fccd4c0133deaab
Signed-off-by: Jérémy Kersten <jke@odoo.com>
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
The geoip2 module is not installed in the iot so this one cannot launch Odoo.
This module is not used by the iot so it is not necessary
to install the module in the iot and therefore to make a new build
From this commit c59750d824closesodoo/odoo#118240
X-original-commit: 5f251f7c95adf9b67ef1c81ee0084b0b5c396cc3
Signed-off-by: Quentin Lejeune (qle) <qle@odoo.com>
With the special support for postmortem debugging removed, the
likelihood of needing / wanting the werkzeug remote debugger seems
even more remote (as it works in strictly less situations, only for
frontend non-json requests).
So remove that as well.
closesodoo/odoo#115176
X-original-commit: a2022783b652299155c460294c00dbced9b619ac
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Install a database with many langs, arab, french, english, ... Keep
english as the default lang. Start a shell and validate a sale-order
using the superuser. On the web client, the sale order has been
validated in arab instead of in english.
In 16.0 the `context_get` method was changed to ensure there was always
a lang set in the returned context. It used the following fallback
order: context > request. The solution was partial because in case there
was no request to extract a lang from, no lang was set on the context.
In a recent 16.0 fix (f2523c4a), the mechanism was changed to fix the
previous problem. The fallback order became: context > request > first
installed lang. This solution is sub-optimal because the first installed
lang isn't always the best pick. e.g. when you have a mostly english
company but that arab is installed for some website pages, arab is
selected instead of english (the langs are alphabetically sorted)
In this work, the fallback order is changed once again:
1. The lang set on the user's profile if activated
2. The best lang extracted from the user's browser if activated
3. (new) The lang of the user's current company if activated
4. (new) English if activated
5. The first lang (ordered by ISO code) if any
6. English
The 3rd should cover most of ill-cases. For the 4th step, we assume that
english is prioritaty to other installed langs when no lang standout.
closesodoo/odoo#113186
X-original-commit: 03134bf7cb1e3d63f3be435fbc734e6198ca029b
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
`handle_error`'s docstring states that it returns a `Response`, but in most case `HttpDispatcher.handle_error` returns an `HTTPException`.
After discussion, the implementation is correct, `handle_error` should be documented to return a WSGI Application (a callable taking an `environ` and a `start_response` callable) instead.
closesodoo/odoo#112889
Forward-port-of: odoo/odoo#112690
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
*: base, http_routing, mass_mailing, web, web_editor, website_slides
In some situations `werkzeug.wrappers.Response` are used instead of
`odoo.http.Reponse` that extends it.
This is a problem because since [1] the calls to `set_cookie` expect it
to accept the `cookie_type` parameter, which is not the case in the base
werkzeug implementation.
This commit replaces the `werkzeug.wrappers.Response` by
`odoo.http.Response`.
[1]: https://github.com/odoo/odoo/commit/2cbda6c98ee947cea1d06c09880eee8c758304a8closesodoo/odoo#112827
X-original-commit: 28da08292b7028575e628c5ad846fc05d30498f2
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
This commit fixes a change in behavior between 15.2 and 15.3.
Previously, if an unidentified user tried to reach a route that had auth='user', it would simply redirect to the login page.
Currently, it redirects and invalidates the session_id.
This is an issue in the latest version of master after this PR https://github.com/odoo/enterprise/pull/36521
This commit changes the route of service-worker.js to auth='user'.
This route is called on the login page, which rotates the sid and therefore invalidates the csrf token. Making it impossible for a user to log in.
This is a race condition, meaning it would only appear if the user stayed on the login page for a few seconds, hence why the automated testing did not block the commit.
closesodoo/odoo#112239
X-original-commit: d5d80d172616afe02bd41934930ea18dc273c739
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
Co-authored-by: Julien Castiaux <juc@odoo.com>
Doesn't seem like it could hurt, and should only make CORB more
reliable by avoiding sniffing. Worst case scenario requires fixing a
few mimetypes, but aside from CORB it looks like modern (non-IE)
browsers only try to guess document mimetypes in very limited
contexts.
closesodoo/odoo#107957
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
When overriding an existing controller route, developers can
easily c/p the route definition and call super() in the overridden method
when the route attributes are automatically deducted by odoo from the parent route.
Removing those redefined attributes simplifies the routes definition,
clearly highlighting what's changed by the override.
Also reduces unexpected behavior when modifying the base route without
noticing/considering the redefined attributes in a overridden route,
which overrides the changes made to the base route when the sub-module is installed.
This commit adds a test to catch routes attributes redefinition, and clean existing routes.
closesodoo/odoo#108512
Related: odoo/enterprise#35176
Signed-off-by: Victor Feyens (vfe) <vfe@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>
Start odoo-bin shell with `--geoip_country_db='/i/dont/exist'` and type
the following code:
from odoo.http import GeoIP
GeoIP('8.8.8.8').country_code
TypeError: The country method cannot be used with the GeoLite2-City
database
There are two "things" here: the raw country and city entries in the
databases and the rich python country and city objects returned when an
entry was found and parsed.
Then there are two "readers", a reader capable of reading and parsing
entries from the city database and **another** reader for the country.
The two readers are **only** compatible with their specific database:
the city reader cannot read or parse information from the country
database and vis-versa. That's the bug reported by the TypeError that
this commit fixes.
But, the two python instances created from parsing the entries of
respecting databases with respecting parsers **do** share a same API:
the city record class inherits from the country record class.
# Valid
city_db = geoip2.database.Reader(config['geoip_city_db'])
city_record = city_db.city('8.8.8.8')
city_record.country.name # works, a city record also
# holds country attributes
# Invalid
city_db = geoip2.database.Reader(config['geoip_city_db'])
country_record = city_db.country('8.8.8.8') # TypeError
closesodoo/odoo#109095
Signed-off-by: Julien Castiaux <juc@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
Maxmind offers multiple ip-geolocalization databases, historically we
have been using the City database which contains records on a
city-basis. Many years later it turns out we are primary using geoip to
know the country of the user. Geolocalization in the City database is
considered slow by our standard and we have been clever in order not to
geolocate each request by saving the info in the session.
On the other hand, the Country database that is offered by Maxmind is
much more lightweight and geoip using that country is considered a fast
operation by our standard.
In this work we make Odoo compatible with both the City and the Country
databases. Using multiple database at the same time, we can be smart and
only query each of the two on-demand. If a user ask for its country,
we'll use the fast Country db. If a user ask for its city/timezone we'll
use the slower City db.
By default it loads both database from the `/usr/share/GeoIP/` folder,
respectively the files `GeoLite2-City.mmdb` and `GeoLite2-Country.mmdb`,
you can provide alternative paths using the `--geoip-city-db` and
`--geoip-country-db` CLI options.
In the same mindset as #86015, geoip is still lazy. It is done on-demand
and the result is cached on the current request. The different with the
related PR is that as we know consider geoip to be fast, we no longer
cache the result in the session.
Task: 2848206
Part-of: odoo/odoo#91337
*: 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>
The main goal of this commit is to reduce the size of the registry by
removing the (almost) useless __last_update field.
Statistics # of fields with all modules installed:
before 30184 fields, 1299x last_update (4.30%)
Before this commit, the computed field __last_update was added on every model.
The idea behind this field was to have a computed field that had either
the write_date or the create_date if the write_date was empty. However,
the write_date is always written, even on creation, making it useless
to have the computed field __last_update
After this update, we completely remove from BaseModel:
* __last_update
* CONCURRENCY_CHECK_FIELD that was always defined as "__last_update"
* _compute_concurrency_field that was the compute function for __last_update
closesodoo/odoo#105739
Task-id: 3062140 (part of 3062137 improve registry load time)
Related: odoo/upgrade#4038
Related: odoo/enterprise#33939
Signed-off-by: Raphael Collet <rco@odoo.com>
The routing-map is a mapping that maps HTTP verbs and paths to python
controller methods (endpoints), e.g. it maps `GET /web/health/` to
`/web:Home.health`. The `_generate_routing_map` function is the function
responsible to generating the werkzeug routing-map in regard to the
controller inheritance mechanism. The mechanism makes it possible to
override an endpoint is various odoo modules to enrich it with new
features, e.g. `/web/login` is overriden in website to change the visual
of the page.
Implementation-wise, the informations from each `@route` decorator must
be merged with the other `@route` info for each endpoint override. When
a method is not overriden in a controller, there is not new info and
that controller should be skipped for that method.
The previous implementation attempted to skip such method using the
following idiom:
if not hasattr(controller, method_name):
continue
That idiom doesn't work as `hasattr` will perform a lookup on the full
controller's MRO instead of a lookup only on controller's own methods
and attributes. The controller's own methods and attributes are
actually found in `controller.__dict__`.
closesodoo/odoo#107064
X-original-commit: 42f52d26b6a81a68f1fe28e28971f0e7f4c97d11
Signed-off-by: Julien Castiaux <juc@odoo.com>
Define the following controller:
@route('/get-context', auth='public', type='json', website=True):
return request.env.context
Access that route via JSON-RPC providing a context:
this._rpc({
route: '/get-context',
params: {
context: {"a": 1}
}
})
Since httpocalypse, it replaces the context entirely instead of updating
it. i.e. before you would get along those lines:
{"a": 1, "lang": "en_US", "tz": "Europe/Brussels", "uid": 2}
but since you get instead (and that's wrong):
{"a": 1}
Note that after this commit, this merging-context behavior will be the
same whether or not website=True is defined (while it was only there for
website=True before).
Discovered via opw-2885948
X-original-commit: 7887cfc3f177d9e64f008aabb8bd710f54024dea
Part-of: odoo/odoo#107179
Move code to support only the redirect from url containing double '/' in
the middle of the path.
Keep same behavior than v15 and default Apache behavior.
domain.com//shop/product/1 -> 404
domain.com/shop//product/1 -> 301 -> /shop/product/1
opw-3063387
closesodoo/odoo#106137
X-original-commit: fdd6bf9942e2807b6d1460dba1ca5f61404c7b06
Signed-off-by: Julien Castiaux <juc@odoo.com>
Signed-off-by: Jérémy Kersten <jke@odoo.com>
Create a 15.0 database with website, access the home page via your
browser. Stop the server and migrate the database to 16.0. Restart the
server with a `--dbfilter` that rejects the database you created and
refresh your browser. 500 Internal server error, attribute error:
the `request` object as no `session`.
An error could occurs after a migration to 16.0 due to the presence of
the `geoip` key in the session. `request.session.geoip` has been made a
deprecated alias to `request.geoip` between 15.0 and 16.0, see 04e9726.
Because the session was created before 16.0, the session dict does
contain a `geoip` key. Upon logging the session out, the session dict
is cleared. The default implementation of `clear()`[^1] inside of
`collections.abc.MutableMapping` can be summarized for our usecase to:
for key in self:
value = self[key]
del self[key]
There is an extra `__getitem__` call due to `value = self[key]`, in the
case of the `geoip` key, it would access the alias. It is not possible
to accessing that alias inside of the `_get_dbname_and_session` method
of request as the session has not been set on `self` (the request) yet.
Yet inside of that method, we do `session.logout()` which `clear()` the
session which (wrongly) access the alias because `geoip` exists in the
internal dict (`'geoip' in self.keys() # True`).
The solution has been to implement the `clear()` function ourself
instead of using the mixin of `MutableMapping`.
[^1]: https://github.com/python/cpython/blob/b43496c01a554cf41ae654a0379efae18609ad39/Lib/_collections_abc.py#L925-L931closesodoo/odoo#105763
X-original-commit: b66e1ffa8e348eedf2de735babbc398290a8bffb
Signed-off-by: Julien Castiaux <juc@odoo.com>
The new `borrow_request()` function has been introduced to properly
separate the HTTP layer from the RPC layer. We forgot to protect some
RPC endpoints, mainly inside of `odoo.addons.web.controllers.database`.
This commit moves `odoo.service.dispatch_rpc` to `odoo.http` as we only
permorm RPC from the controllers and that we don't want to import
`borrow_request` inside of `odoo.service` (circular import).
X-original-commit: d0ee8615d8820e02232989c50a6e6ffbc66a9266
Part-of: odoo/odoo#105710
Install website then render a qweb template via xmlrpc, attribute error:
`request` has no `is_frontend` attribute.
Inside the qweb's `_prepare_environment` override of the http_routing
module (a dependency of website) is the following code snippet:
if (not irQweb.env.context.get('minimal_qcontext') and
request and request.is_frontend):
return irQweb._prepare_frontend_environment(values)
The conditionnal is about injecting extra informations in the qweb's
context in case we are serving a frontend request. By default, there is
no `is_frontend` attribute on the request object. That attribute is set
by the ir.http's `_match` override of the http_routing module (a website
dependency): it is set True when we don't match any endpoint or that we
match an endpoint that is `website=True`, it is set False otherwise.
The ir.http's `_match` method is called whenever we are serving a http
request whoose session is bound to a specific database. i.e. when there
is a valid database saved in the request's session. When there is not
database in the request's session (or that it is invalid) the matched
endpoint is directly called without going throught ir.http. Most
endpoints are only accessible via ir.http.
The two `/xmlrpc` and `/jsonrpc` endpoints are examples of endpoint that
do not require an established database connection to work. They perform
the request authentication and database connection themselves. It is
possible to call those two endpoints with no database saved in the
session, thus it is possible to call those two endpoints without going
throught ir.http. This is expected.
The two endpoints's duty is to execute public model methods and return
the xml/json serialized result. To do so, a registry is loaded on the
database with all the installed modules, including http_routing.
We fall in a situation where (1) there is a request, (2) we are using a
registry where http_routing is loaded, (3) there is no `is_frontend`
attribute on `request` as we didn't serve the endpoint via ir.http. This
situation is illegale.
To solve the problem, instead of working on the `if request.is_frontend`
bit of the above conditional, we decided to work on the `if request`
bit. ISO-model wise, RPC is an extra 8th layer built on top of HTTP.
HTTP is merely a transparent transport between a RPC client and a RPC
server, any other request-response capable procotol could fit. The
method executed via RPC must be independant from the usage of HTTP as
mean of transportation thus it should not be capable of using the
current request.
The proposed change is to temporary un-expose the current request from
the local-stack during the execution of the RPC method. This fixes the
problem as the code now run like it was executed from the shell or from
a cron. The other benefit is that the pattern used inside the condition:
`if request and request.is_frontend` doesn't need to change.
X-original-commit: f28863bfdaac3f644fcb274c856e0770783ed75c
Part-of: odoo/odoo#104567
When `make_json_response` was added in
034d01b2f3 and `_response` was updated
to use it, the `http_status` extracted from the error object was
removed.
But it's still set by `handle_error` and a local is defined for
it. Drop that.
closesodoo/odoo#104507
X-original-commit: b0ea1cd6a2628a6acd1e2d79cc862976c63b1565
Signed-off-by: Julien Castiaux <juc@odoo.com>
When calling a `auth=none` route with a non-existing DB name, the server
redirects to `/web/database/selector`. Such a route can be called
without database, therefore it is expected to work if the database
doesn't exist as well.
Before the HTTP refactoring, the fallback was `_dispatch_nodb` [1]. We
roll back to the same behavior since there is no good reason to redirect
to `/web/database/selector`.
Commits 4b330f3173 and de4e67dcc529163 are reintroduced as well.
[1] https://github.com/odoo/odoo/blob/b3199e949ae70307e8181ba0d6237871d6d07af7/odoo/http.py#L1529closesodoo/odoo#104174
X-original-commit: 1565e85890f1d14e067edd1c198c7199ab536307
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
Signed-off-by: Olivier Dony <odo@odoo.com>
* clean and improve docstrings in orm
* fix typos found with codespell
* rely on the Environment class docstring instead of doc content (and
therefore move part of the doc inside the class docstring)
closesodoo/odoo#102969
X-original-commit: 8250cd4b210005d223a4cdb8afa4014425ca6fa3
Related: odoo/documentation#2803
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
Both implementations of `set_cookie` in `http.py` and the one of
`setCookie` in `cookie_utils.js` are slightly different.
This commit unifies both Python implementations and replicates the same
behavior in JS:
- default the cookie type to "required"
- if setting that type is not allowed, delete that cookie if it was
previously set
task-2800976
closesodoo/odoo#102380
X-original-commit: fa8fdab2894607f1f89cdd195f62ec37af7b0342
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
*: im_livechat, survey, utm, website_crm_iap_reveal, website_forum,
website_livechat, website_sale, website_sale_comparison
Before this commit all cookies were considered essential.
This commit makes some of them optional. It also makes it possible for
the website visitor to only accept the essential cookies.
task-2800976
X-original-commit: 9a8a9463289a7446e9be0ef62ff895feb37a4de4
Part-of: odoo/odoo#101845
Co-authored-by: Benoit Socias <bso@odoo.com>
This commit avoid to have a dict by reference that will be global.
Now get_default_session return a new dict each time for the context key.
From this way the session.context['lang'] is not shared between several
users on the same worker.
To reproduce the bug, restart the server with 2 workers, make request in
lang A on these 2 workers. DEFAULT_SESSION['context']['lang'] now is set
to this lang A.
Now, make request to an url without lang in path and without cookies and
withtout session, you should be redirected to lang B (preferred lang
from the request header) but you will be redirect to lang A due to the
dict session.context that is shared for the worker...
When we initialize the new Session, we get the wrong lang A as value for
context.lang, so we don't recompute the expected lang for the end user.
X-original-commit: 62179de74862210fe2a055d15b367b1850c24263
fwd-port of #100102closesodoo/odoo#100910
X-original-commit: 42e46b2d89dde276f796b980f29e33cc216e7cb2
Signed-off-by: Jérémy Kersten <jke@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