All you need to know about db filtering in Odoo

Trong Blog của chúng tôi

First have a look at the official deployment documentation, which has a good introduction paragraph about db filtering.

Odoo is a multi-tenant system: a single Odoo system may run and serve a number of database instances.

Examples

Let's take some examples to illustrate how does the code works:

dbfilter is a regex that is built dynamically: you can use variables %d and %h to adapt its content depending on the HOST header of the http request.

Concretely:

So, if you define dbfilter = ^%d.*\Z, a user accessing https://demo.example.com will have access to databases matching ^demo.*\Z, e.g.:

  • demo
  • demo_backup_20180404

Beware

re.match is used: dbs = [i for i in dbs if re.match(r, i)]

So it's easy to write a regex more permissive than expected. If you define dbfilter = demo_* for example, it will also match demoinefromage_prod.

dbfilter_from_header module

You can't always match databases names with domain names.

For example, you might have a single Odoo instance to serve 2 databases:

  • customer1_prod
  • customer2_prod

But each of these customers wants its own custom domain, respectively:

  • https://back.customer1.com
  • https://app.customer2.com

To support this case, you can use OCA's dbfilter_from_header module.

Installation

$ git clone https://github.com/OCA/server-tools -b 9.0 --no-checkout --single-branch --depth 1
$ cd server-tools
$ git config core.sparsecheckout true
$ echo "dbfilter_from_header" > .git/info/sparse-checkout
$ git read-tree -mu HEAD

Configuration

On Nginx side, you need to define a dedicated dbfilter for each virtual host.

In our case, for https://back.customer1.com:

server_name back.customer1.com;

(...)

location / {

(...)

    proxy_set_header X-Odoo-dbfilter ^customer1_.*\Z;

2 things to note:

  • before passing the request to Odoo, Nginx takes all HTTP headers, lowercase them and converts dashes to underscores;
  • we use \Z instead of $ to match end of string, because nginx cannot escape $

2 levels of filtering

dbfilter_from_header respects the dbfilter defined at Odoo level, so we can setup 2 levels of filtering:

  • dbfilter = ^.+prod.*$
  • proxy_set_header X-Odoo-dbfilter ^.*customer1.*\Z;