# Permissions in Embedding

You can control permissions in Zenlytic via access controls using both access filters (row-based) and access grants (column-based). Docs on those are [here](/data-modeling/access_grants.md).

## Setting up the access permissions

To start, you'll define the logic to determine when an access grant is allowed or not allowed. For example, with these definitions, which are found in the [model](/data-modeling/model.md) file:

```yaml
version: 1
type: model
name: demo
connection: demo_snowflake

access_grants:
- name: events_access
  user_attribute: events
  allowed_values:
  - has_events

- name: revenue_access
  user_attribute: revenue
  allowed_values:
  - has_revenue

- name: sessions_access
  user_attribute: sessions
  allowed_values:
  - has_sessions

...
```

In this example, if you pass the user attribute `{"revenue": "has_revenue"}` the session will have access to all tables governed by the `revenue_access` access grant. Similarly, if you pass the user attribute with any other value besides `"has_revenue"` the session will *not* have access to the tables governed by that access grant (e.g. `{"revenue": "no_revenue"}`).

When using access grants in embedding, pass an explicit value for every user attribute referenced by your grants. Do not omit the attribute for users who should be denied. If the attribute is missing, the grant is not triggered and does not block access. Instead, pass a non-granting value such as `"no_revenue"`.

You can restrict a view or a field with an access grant by name, by adding the property `required_access_grants` with an array of the grants the user must possess. If you list multiple grants, they must all pass for the user to have access, except that a missing user attribute on a grant is non-blocking for that grant:

```yaml
required_access_grants:
- revenue_access
```

## Full Example

Using the above model as our model, consider the following four views:

```yaml
name: orders
type: view
model_name: demo
default_date: order_created_at

required_access_grants:
- revenue_access

fields:
...
```

```yaml
name: events
type: view
model_name: demo
sql_table_name: DEMO_PROD.EVENTS
default_date: event_timestamp

required_access_grants:
- events_access
```

```yaml
name: pg_orders
type: view
model_name: pg_demo
sql_table_name: demo.public.orders
default_date: order_created_at

required_access_grants:
- revenue_access
```

```yaml
name: sessions
type: view
model_name: demo
sql_table_name: wcb.sessions
default_date: session_date

required_access_grants:
- sessions_access
```

When requesting the signed API for the session if you pass the set of user\_attributes:

```yaml
{
    "events": "has_events",
    "revenue": "no_revenue",
    "sessions": "no_sessions"
}
```

Which looks like this in Postman

![has-events-request](/files/P9gd6F7GRoPnINPpKfte)

The session that is generated will NOT have access to any of `pg_orders`, `orders`, or `sessions`. It will only have access to the `events` table (assuming these four tables are the only ones in our model). Zoë will not be able to see those three tables the user does not have access to, and will have no idea that they exist.

![zoe-just-events](/files/BDSnC1lSB6sZlgMADwjv)

Conversely, if you pass the following user\_attributes:

```yaml
{
    "events": "no_events",
    "revenue": "has_revenue",
    "sessions": "has_sessions"
}
```

![no-events-request](/files/Iayuama7yFlf5dLyRMPM)

The user will have access to the `pg_orders`, `sessions`, and `orders` tables, but will NOT have access to the `events` table.

![zoe-no-events](/files/6rDa9mha7baN5WKGHiMZ)

You can apply similar logic to fields as well to define more granular permissions inside of tables.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.zenlytic.com/embedding/permissions_in_embedding.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
