> ## Documentation Index
> Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# atoti.tables.Tables.restrictions

#### *property* Tables.restrictions *: [MutableMapping](https://docs.python.org/3/library/collections.abc.html#collections.abc.MutableMapping)\[[str](https://docs.python.org/3/library/stdtypes.html#str), DatabaseRestrictionCondition]*

Mapping from role to corresponding restriction.

Restrictions limit the data accessible to users based on their roles.
Restrictions apply on table columns and are inherited by all hierarchies based on these columns.

* Restrictions on different columns/hierarchies are intersected.
* Restrictions on the same column/hierarchy are unioned.

### Example

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> session_config = tt.SessionConfig(security=tt.SecurityConfig())
>>> session = tt.Session.start(session_config)
>>> df = pd.DataFrame(
...     [
...         ("Asia", "Korea", "KRW"),
...         ("Asia", "Japan", "JPY"),
...         ("Europe", "France", "EUR"),
...         ("Europe", "Germany", "EUR"),
...         ("Europe", "Norway", "NOK"),
...         ("Europe", "Sweden", "SEK"),
...     ],
...     columns=["Continent", "Country", "Currency"],
... )
>>> table = session.read_pandas(
...     df,
...     keys={"Continent", "Country", "Currency"},
...     table_name="Restrictions example",
... )
>>> cube = session.create_cube(table)
>>> h, l, m = cube.hierarchies, cube.levels, cube.measures
>>> cube.hierarchies["Geography"] = [
...     table["Continent"],
...     table["Country"],
... ]
>>> for level_name in cube.hierarchies["Geography"]:
...     del cube.hierarchies[level_name]
```

Adding a user to the session:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> password = "abcdef123456"
>>> session.security.individual_roles["Rose"] = {"ROLE_USER"}
>>> session.security.basic_authentication.credentials["Rose"] = password
>>> rose_session = tt.Session.connect(
...     session.url,
...     authentication=tt.BasicAuthentication("Rose", password),
... )
>>> rose_table = rose_session.tables[table.name]
>>> rose_cube = rose_session.cubes[cube.name]
```

ROLE\_USER has no restrictions so all the countries and currencies are accessible from the table:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> rose_table.query().set_index(["Continent", "Country"]).sort_index()
                  Currency
Continent Country
Asia      Japan        JPY
          Korea        KRW
Europe    France       EUR
          Germany      EUR
          Norway       NOK
          Sweden       SEK
```

And from the cube:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> rose_cube.query(
...     m["contributors.COUNT"], levels=[l["Country"], l["Currency"]]
... )
                           contributors.COUNT
Continent Country Currency
Asia      Japan   JPY                       1
          Korea   KRW                       1
Europe    France  EUR                       1
          Germany EUR                       1
          Norway  NOK                       1
          Sweden  SEK                       1
```

Assigning a role to Rose to limit her access to France only:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> session.tables.restrictions["ROLE_FRANCE"] = (
...     table["Country"] == "France"
... )
>>> session.security.individual_roles["Rose"] |= {"ROLE_FRANCE"}
>>> rose_table.query()
  Continent Country Currency
0    Europe  France      EUR
>>> rose_cube.query(
...     m["contributors.COUNT"], include_totals=True, levels=[l["Country"]]
... )
                  contributors.COUNT
Continent Country
Total                              1
Europe                             1
          France                   1
```

Adding Lena with ROLE\_GERMANY limiting her access to Germany only:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> session.tables.restrictions["ROLE_GERMANY"] = (
...     table["Country"] == "Germany"
... )
>>> session.security.individual_roles["Lena"] = {
...     "ROLE_GERMANY",
...     "ROLE_USER",
... }
>>> session.security.basic_authentication.credentials["Lena"] = password
>>> lena_session = tt.Session.connect(
...     session.url,
...     authentication=tt.BasicAuthentication("Lena", password),
... )
>>> lena_table = lena_session.tables[table.name]
>>> lena_cube = lena_session.cubes[cube.name]
>>> lena_table.query()
  Continent  Country Currency
0    Europe  Germany      EUR
>>> lena_cube.query(m["contributors.COUNT"], levels=[l["Country"]])
                  contributors.COUNT
Continent Country
Europe    Germany                  1
```

Assigning ROLE\_GERMANY to Rose lets her access the union of the restricted countries:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> session.security.individual_roles["Rose"] |= {"ROLE_GERMANY"}
>>> session.tables.restrictions
{'ROLE_FRANCE': t['Restrictions example']['Country'] == 'France', 'ROLE_GERMANY': t['Restrictions example']['Country'] == 'Germany'}
>>> rose_table.query().set_index(["Continent", "Country"]).sort_index()
                  Currency
Continent Country
Europe    France       EUR
          Germany      EUR
>>> rose_cube.query(m["contributors.COUNT"], levels=[l["Country"]])
                  contributors.COUNT
Continent Country
Europe    France                   1
          Germany                  1
```

Restrictions can include multiple elements:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> session.tables.restrictions["ROLE_NORDIC"] = table["Country"].isin(
...     "Norway", "Sweden"
... )
>>> session.security.individual_roles["Rose"] |= {"ROLE_NORDIC"}
>>> rose_table.query().set_index(["Continent", "Country"]).sort_index()
                  Currency
Continent Country
Europe    France       EUR
          Germany      EUR
          Norway       NOK
          Sweden       SEK
>>> rose_cube.query(m["contributors.COUNT"], levels=[l["Country"]])
                  contributors.COUNT
Continent Country
Europe    France                   1
          Germany                  1
          Norway                   1
          Sweden                   1
```

Since Country and Continent are part of the same Geography hierarchy, restrictions on these two levels are unioned:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> session.tables.restrictions["ROLE_ASIA"] = table["Continent"] == "Asia"
>>> session.security.individual_roles["Rose"] |= {"ROLE_ASIA"}
>>> rose_cube.query(m["contributors.COUNT"], levels=[l["Country"]])
                  contributors.COUNT
Continent Country
Asia      Japan                    1
          Korea                    1
Europe    France                   1
          Germany                  1
          Norway                   1
          Sweden                   1
```

Currency is part of a different hierarchy so restrictions on it are intersected with the ones from Geography:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> session.tables.restrictions["ROLE_EUR"] = table["Currency"] == "EUR"
>>> session.security.individual_roles["Rose"] |= {"ROLE_EUR"}
>>> rose_cube.query(
...     m["contributors.COUNT"], levels=[l["Country"], l["Currency"]]
... )
                           contributors.COUNT
Continent Country Currency
Europe    France  EUR                       1
          Germany EUR                       1
```

Removing the ROLE\_FRANCE and ROLE\_GERMANY roles leaves no remaining accessible countries:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> session.security.individual_roles["Rose"] -= {
...     "ROLE_FRANCE",
...     "ROLE_GERMANY",
... }
>>> rose_table.query()
Empty DataFrame
Columns: [Continent, Country, Currency]
Index: []
>>> rose_cube.query(m["contributors.COUNT"], levels=[l["Country"]])
Empty DataFrame
Columns: [contributors.COUNT]
Index: []
```

<Callout icon="link">
  **See also**:
  [`owners`](./atoti.tables.Tables.owners#atoti.tables.Tables.owners), [`readers`](./atoti.tables.Tables.readers#atoti.tables.Tables.readers), and [`atoti.Cube.restrictions`](./atoti.Cube.restrictions#atoti.Cube.restrictions).
</Callout>
