> ## 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.Cube.restrictions

#### *property* Cube.restrictions *: [MutableMapping](https://docs.python.org/3/library/collections.abc.html#collections.abc.MutableMapping)\[[str](https://docs.python.org/3/library/stdtypes.html#str), MembershipCondition\[LevelIdentifier, 'IN', [bool](https://docs.python.org/3/library/functions.html#bool) | [int](https://docs.python.org/3/library/functions.html#int) | [float](https://docs.python.org/3/library/functions.html#float) | date | datetime | time | [str](https://docs.python.org/3/library/stdtypes.html#str)] | RelationalCondition\[LevelIdentifier, 'EQ', [bool](https://docs.python.org/3/library/functions.html#bool) | [int](https://docs.python.org/3/library/functions.html#int) | [float](https://docs.python.org/3/library/functions.html#float) | date | datetime | time | [str](https://docs.python.org/3/library/stdtypes.html#str)] | LogicalCondition\[MembershipCondition\[LevelIdentifier, 'IN', [bool](https://docs.python.org/3/library/functions.html#bool) | [int](https://docs.python.org/3/library/functions.html#int) | [float](https://docs.python.org/3/library/functions.html#float) | date | datetime | time | [str](https://docs.python.org/3/library/stdtypes.html#str)] | RelationalCondition\[LevelIdentifier, 'EQ', [bool](https://docs.python.org/3/library/functions.html#bool) | [int](https://docs.python.org/3/library/functions.html#int) | [float](https://docs.python.org/3/library/functions.html#float) | date | datetime | time | [str](https://docs.python.org/3/library/stdtypes.html#str)], 'AND']]*

Mapping from role to the corresponding restriction.

Restrictions limit the data accessible to users based on their roles.

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

<Warning>
  - These restrictions do not secure tables, consider configuring [`atoti.tables.Tables.restrictions`](./atoti.tables.Tables.restrictions#atoti.tables.Tables.restrictions) or changing [`atoti.tables.Tables.readers`](./atoti.tables.Tables.readers#atoti.tables.Tables.readers) instead.
  - A [`QueryCube`](./atoti.distribution.query_cube#atoti.QueryCube) only enforces its own restrictions, it ignores the ones of the contributing data cubes.
</Warning>

### 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"]}}
>>> session.security.individual_roles["Rose"] = {"ROLE_USER"}
>>> password = "abcdef123456"
>>> session.security.basic_authentication.credentials["Rose"] = password
>>> rose_session = tt.Session.connect(
...     session.url,
...     authentication=tt.BasicAuthentication("Rose", password),
... )
>>> rose_cube = rose_session.cubes[cube.name]
```

ROLE\_USER has no restrictions so all the countries and currencies are accessible 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"]}}
>>> cube.restrictions["ROLE_FRANCE"] = l["Country"] == "France"
>>> cube.restrictions["ROLE_FRANCE"]
l['Restrictions example', 'Geography', 'Country'] == 'France'
>>> session.security.individual_roles["Rose"] |= {"ROLE_FRANCE"}
>>> rose_cube.query(
...     m["contributors.COUNT"], include_totals=True, levels=[l["Country"]]
... )
                  contributors.COUNT
Continent Country
Total                              1
Europe                             1
          France                   1
```

Unlike [`atoti.tables.Tables.restrictions`](./atoti.tables.Tables.restrictions#atoti.tables.Tables.restrictions), cube restrictions have no impact on tables:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> rose_table = rose_session.tables[table.name]
>>> 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
```

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

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> cube.restrictions["ROLE_GERMANY"] = l["Country"] == "Germany"
>>> session.security.basic_authentication.credentials["Lena"] = password
>>> session.security.individual_roles["Lena"] = {
...     "ROLE_GERMANY",
...     "ROLE_USER",
... }
>>> lena_session = tt.Session.connect(
...     session.url,
...     authentication=tt.BasicAuthentication("Lena", password),
... )
>>> lena_cube = lena_session.cubes[cube.name]
>>> 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"}
>>> cube.restrictions
{'ROLE_FRANCE': l['Restrictions example', 'Geography', 'Country'] == 'France', 'ROLE_GERMANY': l['Restrictions example', 'Geography', 'Country'] == 'Germany'}
>>> 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"]}}
>>> cube.restrictions["ROLE_NORDIC"] = l["Country"].isin("Norway", "Sweden")
>>> session.security.individual_roles["Rose"] |= {"ROLE_NORDIC"}
>>> 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"]}}
>>> cube.restrictions["ROLE_ASIA"] = l["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"]}}
>>> cube.restrictions["ROLE_EUR"] = l["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_cube.query(m["contributors.COUNT"], levels=[l["Country"]])
Empty DataFrame
Columns: [contributors.COUNT]
Index: []
```

A [`QuerySession`](./atoti.distribution.query_session#atoti.QuerySession) has cubes but no tables so there is nothing to merge cube restrictions with.
However, data cubes have their restrictions merged with the ones from the session’s [`tables`](./atoti.Session.tables#atoti.Session.tables):

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> session.tables.restrictions.update(
...     {
...         "ROLE_SEK": table["Currency"] == "SEK",
...         "ROLE_JPY": table["Currency"] == "JPY",
...     }
... )
>>> session.security.individual_roles["Rose"] = {
...     "ROLE_ASIA",  # Cube restriction
...     "ROLE_NORDIC",  # Cube restriction
...     "ROLE_SEK",  # Tables restriction
...     "ROLE_JPY",  # Tables restriction
...     "ROLE_USER",
... }
>>> rose_table.query().set_index(["Continent", "Country"]).sort_index()
                  Currency
Continent Country
Asia      Japan        JPY
Europe    Sweden       SEK
>>> rose_cube.query(
...     m["contributors.COUNT"], levels=[l["Country"], l["Currency"]]
... )
                           contributors.COUNT
Continent Country Currency
Asia      Japan   JPY                       1
Europe    Sweden  SEK                       1
```

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> cube.restrictions.clear()
>>> cube.restrictions
{}
```

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