From 4ce3d4283abb54ae6b21e9052f7d52e876be8cdf Mon Sep 17 00:00:00 2001
From: "mintlify[bot]" <109931778+mintlify[bot]@users.noreply.github.com>
Date: Tue, 5 May 2026 16:05:16 +0000
Subject: [PATCH 1/2] docs: document conditional row-level access and allow_all
in access policies
---
docs-mintlify/docs.json | 6 +
.../data-modeling/data-access-policies.mdx | 11 +-
.../conditional-row-level-access.mdx | 284 ++++++++++++++++++
.../data-modeling/data-access-policies.mdx | 120 +++++++-
4 files changed, 419 insertions(+), 2 deletions(-)
create mode 100644 docs-mintlify/recipes/access-control/conditional-row-level-access.mdx
diff --git a/docs-mintlify/docs.json b/docs-mintlify/docs.json
index ab131e9bacec3..7348d54411761 100644
--- a/docs-mintlify/docs.json
+++ b/docs-mintlify/docs.json
@@ -648,6 +648,12 @@
"recipes/configuration/custom-data-model-per-tenant"
]
},
+ {
+ "group": "Access Control",
+ "pages": [
+ "recipes/access-control/conditional-row-level-access"
+ ]
+ },
{
"group": "Core Data API",
"pages": [
diff --git a/docs-mintlify/docs/data-modeling/data-access-policies.mdx b/docs-mintlify/docs/data-modeling/data-access-policies.mdx
index cf65f076bfa3d..9cd3816bc63f1 100644
--- a/docs-mintlify/docs/data-modeling/data-access-policies.mdx
+++ b/docs-mintlify/docs/data-modeling/data-access-policies.mdx
@@ -492,6 +492,14 @@ view(`orders_view`, {
+### Conditional row-level filters
+
+You can switch which `row_level` filter applies based on the
+[security context][ref-sec-ctx] — for example, to scope a group to its region
+or to let admins bypass row filters with `row_level.allow_all: true`. See the
+[conditional row-level access recipe][ref-recipe-conditional-row-level] for
+worked examples in YAML and JavaScript.
+
### Mandatory filters
You can apply mandatory row-level filters to specific groups to ensure they only see data matching certain criteria:
@@ -621,4 +629,5 @@ cube(`orders`, {
[ref-ref-dap-role]: /reference/data-modeling/data-access-policies#role
[ref-ref-dap-masking]: /reference/data-modeling/data-access-policies#member-masking
[ref-ref-mask-dim]: /reference/data-modeling/dimensions#mask
-[ref-core-data-apis]: /reference/core-data-apis
\ No newline at end of file
+[ref-core-data-apis]: /reference/core-data-apis
+[ref-recipe-conditional-row-level]: /recipes/access-control/conditional-row-level-access
\ No newline at end of file
diff --git a/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx b/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx
new file mode 100644
index 0000000000000..9bf3352bd9a31
--- /dev/null
+++ b/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx
@@ -0,0 +1,284 @@
+---
+title: Conditional row-level access
+description: Switch row-level filters based on the security context, and let an admin policy grant unrestricted row access on top of more restrictive policies.
+---
+
+## Use case
+
+You want different row-level filters to apply to the same group depending on
+who the user is. For example:
+
+- Users in different regional groups should see only rows for their region.
+- Admins should bypass row filters entirely, even when other policies restrict
+the same role.
+
+You can express both patterns with [`access_policy`][ref-ref-dap] by combining
+[`conditions`][ref-ref-dap-conditions], [`row_level.allow_all`][ref-ref-dap-row-level],
+and the [_OR_ semantics across policies][ref-dap-rls] that match the same group.
+
+## Data modeling
+
+### Region-based switching
+
+Define one policy per region, and gate each policy with a `conditions` entry
+that checks the user's [security context][ref-sec-ctx]. Only the policy whose
+condition evaluates to `true` contributes its `row_level` filter to the query —
+the others are skipped.
+
+In the following example, users in the `analyst` group see rows for their
+region: members of the `emea` group are restricted to EMEA orders, and members
+of the `amer` group are restricted to AMER orders.
+
+
+
+```yaml title="YAML"
+cubes:
+ - name: orders
+ # ...
+
+ access_policy:
+ - group: analyst
+ conditions:
+ - if: "{ security_context.groups and 'emea' in security_context.groups }"
+ row_level:
+ filters:
+ - member: region
+ operator: equals
+ values: ["EMEA"]
+
+ - group: analyst
+ conditions:
+ - if: "{ security_context.groups and 'amer' in security_context.groups }"
+ row_level:
+ filters:
+ - member: region
+ operator: equals
+ values: ["AMER"]
+```
+
+```javascript title="JavaScript"
+cube(`orders`, {
+ // ...
+
+ access_policy: [
+ {
+ group: `analyst`,
+ conditions: [
+ { if: securityContext.groups && securityContext.groups.includes(`emea`) }
+ ],
+ row_level: {
+ filters: [
+ {
+ member: `region`,
+ operator: `equals`,
+ values: [`EMEA`]
+ }
+ ]
+ }
+ },
+ {
+ group: `analyst`,
+ conditions: [
+ { if: securityContext.groups && securityContext.groups.includes(`amer`) }
+ ],
+ row_level: {
+ filters: [
+ {
+ member: `region`,
+ operator: `equals`,
+ values: [`AMER`]
+ }
+ ]
+ }
+ }
+ ]
+})
+```
+
+
+
+In JavaScript, you can also express the same pattern by making `row_level`
+itself a function of `securityContext` and returning different filters
+depending on the caller:
+
+
+
+```yaml title="YAML"
+cubes:
+ - name: orders
+ # ...
+
+ access_policy:
+ - group: analyst
+ conditions:
+ - if: "{ security_context.groups and ('emea' in security_context.groups or 'amer' in security_context.groups) }"
+ row_level:
+ filters:
+ - member: region
+ operator: equals
+ values:
+ - "{ 'EMEA' if 'emea' in security_context.groups else 'AMER' }"
+```
+
+```javascript title="JavaScript"
+cube(`orders`, {
+ // ...
+
+ access_policy: [
+ {
+ group: `analyst`,
+ row_level: {
+ filters: [
+ {
+ member: `region`,
+ operator: `equals`,
+ values: [
+ securityContext.groups && securityContext.groups.includes(`emea`)
+ ? `EMEA`
+ : `AMER`
+ ]
+ }
+ ]
+ }
+ }
+ ]
+})
+```
+
+
+
+### Admin override with `allow_all`
+
+To let admins bypass row-level filters that apply to a role, add a second
+policy for the same group that grants [`row_level.allow_all`][ref-ref-dap-row-level]
+when `securityContext.is_admin` is true. Because policies that match the same
+group are combined with _OR_ semantics, the admin policy unlocks every row
+regardless of the more restrictive analyst policy:
+
+
+
+```yaml title="YAML"
+cubes:
+ - name: orders
+ # ...
+
+ access_policy:
+ # Region-restricted access for regular analysts
+ - group: analyst
+ row_level:
+ filters:
+ - member: region
+ operator: equals
+ values: ["{ security_context.region }"]
+
+ # Admin override: full row access when the user is an admin
+ - group: analyst
+ conditions:
+ - if: "{ security_context.is_admin }"
+ row_level:
+ allow_all: true
+```
+
+```javascript title="JavaScript"
+cube(`orders`, {
+ // ...
+
+ access_policy: [
+ {
+ // Region-restricted access for regular analysts
+ group: `analyst`,
+ row_level: {
+ filters: [
+ {
+ member: `region`,
+ operator: `equals`,
+ values: [securityContext.region]
+ }
+ ]
+ }
+ },
+ {
+ // Admin override: full row access when the user is an admin
+ group: `analyst`,
+ conditions: [
+ { if: securityContext.is_admin }
+ ],
+ row_level: {
+ allow_all: true
+ }
+ }
+ ]
+})
+```
+
+
+
+### Composing boolean logic with `conditions`
+
+`conditions` accept full boolean logic, so you can switch which `row_level`
+applies based on combined checks against the security context and user
+attributes. In YAML, use `and`, `or`, `not`, and parentheses inside
+`{ ... }`. In JavaScript, use `&&`, `||`, and `!`. Multiple `conditions`
+entries on a single policy are combined with _AND_ semantics; multiple
+matching policies are combined with _OR_ semantics.
+
+In the following example, full-time analysts who are _either_ admins _or_
+owners and are _not_ contractors get unrestricted row access; everyone else
+in the `analyst` group falls back to the region-restricted policy above.
+
+
+
+```yaml title="YAML"
+cubes:
+ - name: orders
+ # ...
+
+ access_policy:
+ - group: analyst
+ conditions:
+ - if: "{ user_attributes.is_full_time_employee and user_attributes.tenure_years >= 2 }"
+ - if: "{ user_attributes.is_admin or user_attributes.is_owner }"
+ - if: "{ not (security_context.groups and 'contractors' in security_context.groups) }"
+ row_level:
+ allow_all: true
+```
+
+```javascript title="JavaScript"
+cube(`orders`, {
+ // ...
+
+ access_policy: [
+ {
+ group: `analyst`,
+ conditions: [
+ { if: userAttributes.is_full_time_employee && userAttributes.tenure_years >= 2 },
+ { if: userAttributes.is_admin || userAttributes.is_owner },
+ { if: !(securityContext.groups && securityContext.groups.includes(`contractors`)) }
+ ],
+ row_level: {
+ allow_all: true
+ }
+ }
+ ]
+})
+```
+
+
+
+## Result
+
+With these policies in place:
+
+- Regional analysts see only rows for the region attached to their security
+context, because only the policy whose `conditions` match contributes its
+`row_level` filter.
+- Admins see all rows, because the admin policy's `row_level.allow_all: true`
+combines with the regional policy via _OR_ semantics.
+- Users without any matching policy are denied access by default.
+
+
+[ref-ref-dap]: /reference/data-modeling/data-access-policies
+[ref-ref-dap-conditions]: /reference/data-modeling/data-access-policies#conditions
+[ref-ref-dap-row-level]: /reference/data-modeling/data-access-policies#row-level
+[ref-dap-rls]: /docs/data-modeling/access-control/data-access-policies#row-level-access
+[ref-sec-ctx]: /docs/data-modeling/access-control/context
diff --git a/docs-mintlify/reference/data-modeling/data-access-policies.mdx b/docs-mintlify/reference/data-modeling/data-access-policies.mdx
index 5698a33e556a5..5ab02668a91e1 100644
--- a/docs-mintlify/reference/data-modeling/data-access-policies.mdx
+++ b/docs-mintlify/reference/data-modeling/data-access-policies.mdx
@@ -208,6 +208,61 @@ cube(`orders`, {
+#### Boolean logic in `if` expressions
+
+`if` expressions support full boolean logic so you can compose checks against
+the [security context][ref-sec-ctx] and user attributes:
+
+- In YAML, expressions inside `{ ... }` use Jinja-style operators: `and`, `or`,
+`not`, and parentheses for grouping.
+- In JavaScript, expressions use native operators: `&&`, `||`, and `!`.
+- Multiple `conditions` entries on a single policy are combined with _AND_
+semantics — every entry must evaluate to `true` for the policy to take effect.
+- Multiple policies that match the same group are combined with _OR_ semantics —
+if any matching policy grants access, the user gets access.
+
+In the following example, a single policy combines three `conditions` entries
+that each use a different boolean operator:
+
+
+
+```yaml title="YAML"
+cubes:
+ - name: orders
+ # ...
+
+ access_policy:
+ - group: manager
+ conditions:
+ - if: "{ user_attributes.is_full_time_employee and user_attributes.tenure_years >= 2 }"
+ - if: "{ user_attributes.is_admin or user_attributes.is_owner }"
+ - if: "{ not (security_context.groups and 'contractors' in security_context.groups) }"
+ member_level:
+ includes: "*"
+```
+
+```javascript title="JavaScript"
+cube(`orders`, {
+ // ...
+
+ access_policy: [
+ {
+ group: `manager`,
+ conditions: [
+ { if: userAttributes.is_full_time_employee && userAttributes.tenure_years >= 2 },
+ { if: userAttributes.is_admin || userAttributes.is_owner },
+ { if: !(securityContext.groups && securityContext.groups.includes(`contractors`)) }
+ ],
+ member_level: {
+ includes: `*`
+ }
+ }
+ ]
+})
+```
+
+
+
### `member_level`
The optional `member_level` parameter, when present, configures [member-level
@@ -452,6 +507,68 @@ REST (JSON) API][ref-rest-query-filters] queries, allowing to use the same set o
You can also use `and` and `or` parameters to combine multiple filters into
[boolean logical operators][ref-rest-boolean-ops].
+#### `allow_all`
+
+Use the `allow_all` parameter to make the row-level intent of a policy explicit
+without listing any filters:
+
+- `allow_all: true` grants the policy access to all rows. It is equivalent to
+omitting `row_level` (or omitting `filters`) and is useful when you want the
+policy to clearly state that no row-level restriction applies.
+- `allow_all: false` denies the policy access to all rows. Other matching
+policies (if any) still apply on top — see [row-level access][ref-dap-rls].
+
+
+
+```yaml title="YAML"
+cubes:
+ - name: orders
+ # ...
+
+ access_policy:
+ - group: admin
+ row_level:
+ allow_all: true
+
+ - group: guest
+ row_level:
+ allow_all: false
+```
+
+```javascript title="JavaScript"
+cube(`orders`, {
+ // ...
+
+ access_policy: [
+ {
+ group: `admin`,
+ row_level: {
+ allow_all: true
+ }
+ },
+ {
+ group: `guest`,
+ row_level: {
+ allow_all: false
+ }
+ }
+ ]
+})
+```
+
+
+
+#### Conditional `row_level`
+
+You can make `row_level` conditional so that different filters apply depending
+on the [security context][ref-sec-ctx] or user attributes. In YAML, attach
+[`conditions`](#conditions) to a policy so its `row_level` is skipped when the
+conditions don't match. In JavaScript, you can additionally make `row_level` a
+function of `securityContext` and return different filters at evaluation time.
+When a policy's `row_level` is skipped, other matching policies still apply;
+if no policy matches, access is denied by default. See the [conditional
+row-level access recipe][ref-recipe-conditional-row-level] for worked examples.
+
Note that access policies also respect [row-level security][ref-rls] restrictions
configured via the `query_rewrite` configuration option. See [row-level access][ref-dap-rls] to
learn more about policy evaluation.
@@ -513,4 +630,5 @@ cube(`orders`, {
[ref-mask-dim]: /reference/data-modeling/dimensions#mask
[ref-rest-query-filters]: /reference/rest-api/query-format#filters-format
[ref-rest-query-ops]: /reference/rest-api/query-format#filters-operators
-[ref-rest-boolean-ops]: /reference/rest-api/query-format#boolean-logical-operators
\ No newline at end of file
+[ref-rest-boolean-ops]: /reference/rest-api/query-format#boolean-logical-operators
+[ref-recipe-conditional-row-level]: /recipes/access-control/conditional-row-level-access
\ No newline at end of file
From 4b859f98c21529aecb0e0bb3c8928035bb0c34aa Mon Sep 17 00:00:00 2001
From: AvilaJulio
Date: Thu, 2 Jul 2026 09:46:07 -0500
Subject: [PATCH 2/2] docs: correct conditional row-level access & allow_all
claims
Fixes invalid claims in the conditional row-level access docs, validated
against Cube 1.6.65 (Docker + Postgres) and the schema-compiler source:
- YAML `{ ... }` expressions are parsed as Python and only support
and/or/not, parentheses, member access, and method calls. Replaced
`in` and `>=` (which throw "Unsupported Python multiple children node"
and can silently deny access) with `.includes(...)` and boolean
attributes; documented the unsupported operators.
- Removed the "make `row_level` a function of securityContext" guidance
(rejected by CubeValidator: rowLevel is object-only; the core change
was reverted in #10767). Replaced with the working pattern of computing
a filter's member/values from securityContext in JavaScript.
- Removed `allow_all: false` (invalid: allowAll only accepts `true`,
xor with filters); documented deny-by-default instead.
- Fixed broken link to the data-access-policies guide (dropped the
non-existent `/access-control/` path segment).
Co-Authored-By: Claude Opus 4.8 (1M context)
Claude-Session: https://claude.ai/code/session_01T11gd3wgtSz7WGVnZ2ewPW
---
.../conditional-row-level-access.mdx | 62 +++++++++----------
.../data-modeling/data-access-policies.mdx | 59 +++++++++---------
2 files changed, 58 insertions(+), 63 deletions(-)
diff --git a/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx b/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx
index 9bf3352bd9a31..9c51d741bcf70 100644
--- a/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx
+++ b/docs-mintlify/recipes/access-control/conditional-row-level-access.mdx
@@ -39,7 +39,7 @@ cubes:
access_policy:
- group: analyst
conditions:
- - if: "{ security_context.groups and 'emea' in security_context.groups }"
+ - if: "{ security_context.groups and security_context.groups.includes('emea') }"
row_level:
filters:
- member: region
@@ -48,7 +48,7 @@ cubes:
- group: analyst
conditions:
- - if: "{ security_context.groups and 'amer' in security_context.groups }"
+ - if: "{ security_context.groups and security_context.groups.includes('amer') }"
row_level:
filters:
- member: region
@@ -97,28 +97,9 @@ cube(`orders`, {
-In JavaScript, you can also express the same pattern by making `row_level`
-itself a function of `securityContext` and returning different filters
-depending on the caller:
-
-
-
-```yaml title="YAML"
-cubes:
- - name: orders
- # ...
-
- access_policy:
- - group: analyst
- conditions:
- - if: "{ security_context.groups and ('emea' in security_context.groups or 'amer' in security_context.groups) }"
- row_level:
- filters:
- - member: region
- operator: equals
- values:
- - "{ 'EMEA' if 'emea' in security_context.groups else 'AMER' }"
-```
+In JavaScript, you can collapse the two policies into one by computing the
+filter `values` from `securityContext` at evaluation time — the `values` array
+is evaluated per request, so a ternary can pick the region for the caller:
```javascript title="JavaScript"
cube(`orders`, {
@@ -145,7 +126,14 @@ cube(`orders`, {
})
```
-
+
+This single-policy form is JavaScript-only. YAML `{ ... }` expressions don't
+support inline conditionals (Python `if`/`else`) or comparison operators, so in
+YAML use one policy per region as shown above. Note that `row_level` itself is
+always a static object — only the `member` and `values` inside a filter are
+evaluated against `securityContext`; you can't replace `row_level` with a
+function.
+
### Admin override with `allow_all`
@@ -215,16 +203,16 @@ cube(`orders`, {
### Composing boolean logic with `conditions`
-`conditions` accept full boolean logic, so you can switch which `row_level`
+`conditions` accept boolean logic, so you can switch which `row_level`
applies based on combined checks against the security context and user
attributes. In YAML, use `and`, `or`, `not`, and parentheses inside
`{ ... }`. In JavaScript, use `&&`, `||`, and `!`. Multiple `conditions`
entries on a single policy are combined with _AND_ semantics; multiple
matching policies are combined with _OR_ semantics.
-In the following example, full-time analysts who are _either_ admins _or_
-owners and are _not_ contractors get unrestricted row access; everyone else
-in the `analyst` group falls back to the region-restricted policy above.
+In the following example, full-time senior analysts who are _either_ admins
+_or_ owners and are _not_ contractors get unrestricted row access; everyone
+else in the `analyst` group falls back to the region-restricted policy above.
@@ -236,9 +224,9 @@ cubes:
access_policy:
- group: analyst
conditions:
- - if: "{ user_attributes.is_full_time_employee and user_attributes.tenure_years >= 2 }"
+ - if: "{ user_attributes.is_full_time_employee and user_attributes.is_senior }"
- if: "{ user_attributes.is_admin or user_attributes.is_owner }"
- - if: "{ not (security_context.groups and 'contractors' in security_context.groups) }"
+ - if: "{ not (security_context.groups and security_context.groups.includes('contractors')) }"
row_level:
allow_all: true
```
@@ -251,7 +239,7 @@ cube(`orders`, {
{
group: `analyst`,
conditions: [
- { if: userAttributes.is_full_time_employee && userAttributes.tenure_years >= 2 },
+ { if: userAttributes.is_full_time_employee && userAttributes.is_senior },
{ if: userAttributes.is_admin || userAttributes.is_owner },
{ if: !(securityContext.groups && securityContext.groups.includes(`contractors`)) }
],
@@ -265,6 +253,14 @@ cube(`orders`, {
+
+YAML `{ ... }` expressions are parsed as Python and support `and`, `or`, `not`,
+parentheses, member access, and method calls like `.includes(...)`. They do
+**not** support comparison operators (`==`, `>=`, `in`) or inline `if`/`else`
+conditionals — use boolean [user attributes][ref-sec-ctx] or method calls
+instead. The JavaScript form has no such restriction.
+
+
## Result
With these policies in place:
@@ -280,5 +276,5 @@ combines with the regional policy via _OR_ semantics.
[ref-ref-dap]: /reference/data-modeling/data-access-policies
[ref-ref-dap-conditions]: /reference/data-modeling/data-access-policies#conditions
[ref-ref-dap-row-level]: /reference/data-modeling/data-access-policies#row-level
-[ref-dap-rls]: /docs/data-modeling/access-control/data-access-policies#row-level-access
+[ref-dap-rls]: /docs/data-modeling/data-access-policies#row-level-access
[ref-sec-ctx]: /docs/data-modeling/access-control/context
diff --git a/docs-mintlify/reference/data-modeling/data-access-policies.mdx b/docs-mintlify/reference/data-modeling/data-access-policies.mdx
index 5ab02668a91e1..bc4b9130dc421 100644
--- a/docs-mintlify/reference/data-modeling/data-access-policies.mdx
+++ b/docs-mintlify/reference/data-modeling/data-access-policies.mdx
@@ -210,12 +210,16 @@ cube(`orders`, {
#### Boolean logic in `if` expressions
-`if` expressions support full boolean logic so you can compose checks against
+`if` expressions support boolean logic so you can compose checks against
the [security context][ref-sec-ctx] and user attributes:
-- In YAML, expressions inside `{ ... }` use Jinja-style operators: `and`, `or`,
-`not`, and parentheses for grouping.
-- In JavaScript, expressions use native operators: `&&`, `||`, and `!`.
+- In YAML, expressions inside `{ ... }` are parsed as Python and support the
+`and`, `or`, and `not` operators, parentheses for grouping, member access, and
+method calls such as `.includes(...)`. Comparison operators (`==`, `>=`, `in`)
+and inline `if`/`else` conditionals are **not** supported — use boolean user
+attributes or method calls instead.
+- In JavaScript, expressions use native operators: `&&`, `||`, `!`, and any
+valid JavaScript expression.
- Multiple `conditions` entries on a single policy are combined with _AND_
semantics — every entry must evaluate to `true` for the policy to take effect.
- Multiple policies that match the same group are combined with _OR_ semantics —
@@ -234,9 +238,9 @@ cubes:
access_policy:
- group: manager
conditions:
- - if: "{ user_attributes.is_full_time_employee and user_attributes.tenure_years >= 2 }"
+ - if: "{ user_attributes.is_full_time_employee and user_attributes.is_senior }"
- if: "{ user_attributes.is_admin or user_attributes.is_owner }"
- - if: "{ not (security_context.groups and 'contractors' in security_context.groups) }"
+ - if: "{ not (security_context.groups and security_context.groups.includes('contractors')) }"
member_level:
includes: "*"
```
@@ -249,7 +253,7 @@ cube(`orders`, {
{
group: `manager`,
conditions: [
- { if: userAttributes.is_full_time_employee && userAttributes.tenure_years >= 2 },
+ { if: userAttributes.is_full_time_employee && userAttributes.is_senior },
{ if: userAttributes.is_admin || userAttributes.is_owner },
{ if: !(securityContext.groups && securityContext.groups.includes(`contractors`)) }
],
@@ -509,14 +513,17 @@ You can also use `and` and `or` parameters to combine multiple filters into
#### `allow_all`
-Use the `allow_all` parameter to make the row-level intent of a policy explicit
-without listing any filters:
+Use `allow_all: true` to make the row-level intent of a policy explicit without
+listing any filters. It grants the policy access to all rows and is equivalent
+to omitting `row_level` from the policy — useful when you want the policy to
+clearly state that no row-level restriction applies, or as an admin override
+that combines with more restrictive policies via [_OR_ semantics][ref-dap-rls].
-- `allow_all: true` grants the policy access to all rows. It is equivalent to
-omitting `row_level` (or omitting `filters`) and is useful when you want the
-policy to clearly state that no row-level restriction applies.
-- `allow_all: false` denies the policy access to all rows. Other matching
-policies (if any) still apply on top — see [row-level access][ref-dap-rls].
+A `row_level` block must contain either `filters` or `allow_all` — the two are
+mutually exclusive. `allow_all` only accepts `true`; `allow_all: false` is not a
+valid value. To deny a group all rows, don't grant it a matching policy: access
+policies are deny-by-default, so any member not granted by a matching policy is
+inaccessible.
@@ -529,10 +536,6 @@ cubes:
- group: admin
row_level:
allow_all: true
-
- - group: guest
- row_level:
- allow_all: false
```
```javascript title="JavaScript"
@@ -545,12 +548,6 @@ cube(`orders`, {
row_level: {
allow_all: true
}
- },
- {
- group: `guest`,
- row_level: {
- allow_all: false
- }
}
]
})
@@ -561,13 +558,15 @@ cube(`orders`, {
#### Conditional `row_level`
You can make `row_level` conditional so that different filters apply depending
-on the [security context][ref-sec-ctx] or user attributes. In YAML, attach
+on the [security context][ref-sec-ctx] or user attributes. Attach
[`conditions`](#conditions) to a policy so its `row_level` is skipped when the
-conditions don't match. In JavaScript, you can additionally make `row_level` a
-function of `securityContext` and return different filters at evaluation time.
-When a policy's `row_level` is skipped, other matching policies still apply;
-if no policy matches, access is denied by default. See the [conditional
-row-level access recipe][ref-recipe-conditional-row-level] for worked examples.
+conditions don't match, and define separate policies for the different filters
+you want to apply. In JavaScript, you can additionally compute a filter's
+`member` or `values` from `securityContext` at evaluation time (for example,
+with a ternary), which lets a single policy vary its filter per request. When a
+policy's `row_level` is skipped, other matching policies still apply; if no
+policy matches, access is denied by default. See the [conditional row-level
+access recipe][ref-recipe-conditional-row-level] for worked examples.
Note that access policies also respect [row-level security][ref-rls] restrictions
configured via the `query_rewrite` configuration option. See [row-level access][ref-dap-rls] to