Skip to content

Commit 7d2473f

Browse files
Add recipe for cloud groups and user attributes with Core Data APIs (cube-js#10613)
Generated-By: mintlify-agent Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
1 parent 4081bee commit 7d2473f

2 files changed

Lines changed: 162 additions & 1 deletion

File tree

docs-mintlify/docs.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,8 @@
545545
"recipes/core-data-api/sorting",
546546
"recipes/core-data-api/pagination",
547547
"recipes/core-data-api/drilldowns",
548-
"recipes/core-data-api/real-time-data-fetch"
548+
"recipes/core-data-api/real-time-data-fetch",
549+
"recipes/core-data-api/cloud-groups-and-user-attributes"
549550
]
550551
},
551552
{
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
---
2+
title: Using cloud groups and user attributes with Core Data APIs
3+
description: Pass Cube Cloud groups and user attributes via JWT when querying Core Data APIs directly, so data access policies work seamlessly.
4+
---
5+
6+
## Use case
7+
8+
You have [groups][ref-groups] and [user attributes][ref-user-attributes]
9+
configured in Cube Cloud. Now you want to query
10+
[Core Data APIs][ref-core-data-apis] directly (e.g., the SQL API) while
11+
still having your [data access policies][ref-dap] enforced based on those
12+
groups and attributes.
13+
14+
By wrapping groups and user attributes inside the `cubeCloud` property of
15+
your JWT payload, the API request is treated the same as a request from an
16+
authenticated Cube Cloud user.
17+
18+
## Configuration
19+
20+
### JWT payload
21+
22+
Include a `cubeCloud` object in the JWT payload with `groups` and, optionally,
23+
`userAttributes`:
24+
25+
```json
26+
{
27+
"cubeCloud": {
28+
"groups": ["marketing"],
29+
"userAttributes": {
30+
"country": "United States"
31+
}
32+
}
33+
}
34+
```
35+
36+
- `groups` is an array of group names the user belongs to.
37+
- `userAttributes` is an object whose keys match the attribute names you
38+
defined in Cube Cloud.
39+
40+
### Data access policy
41+
42+
In your data model, reference `groups` and `userAttributes` as usual.
43+
Because the `cubeCloud` wrapper maps them automatically, the same policy
44+
works for both Cube Cloud UI users and direct API callers.
45+
46+
<CodeGroup>
47+
48+
```yaml title="YAML"
49+
cubes:
50+
- name: orders_transactions
51+
# ...
52+
53+
access_policy:
54+
- group: marketing
55+
row_level:
56+
filters:
57+
- member: users_country
58+
operator: equals
59+
values: ["{ userAttributes.country }"]
60+
```
61+
62+
```javascript title="JavaScript"
63+
cube(`orders_transactions`, {
64+
// ...
65+
66+
access_policy: [
67+
{
68+
group: `marketing`,
69+
row_level: {
70+
filters: [
71+
{
72+
member: `users_country`,
73+
operator: `equals`,
74+
values: [`{ userAttributes.country }`]
75+
}
76+
]
77+
}
78+
}
79+
]
80+
})
81+
```
82+
83+
</CodeGroup>
84+
85+
## Example
86+
87+
The following Node.js script signs a JWT with `cubeCloud` groups and user
88+
attributes, then queries the SQL API:
89+
90+
```javascript
91+
import jwt from "jsonwebtoken";
92+
93+
// ── Configuration ──────────────────────────────────────────────
94+
const CUBE_API_URL = "YOUR_SQL_API_URL";
95+
const CUBE_SECRET = "YOUR_CUBE_API_SECRET";
96+
97+
const JWT_PAYLOAD = {
98+
cubeCloud: {
99+
groups: ["marketing"],
100+
userAttributes: {
101+
country: "United States"
102+
}
103+
}
104+
};
105+
106+
const JWT_OPTIONS = {
107+
expiresIn: "1d"
108+
};
109+
110+
// ── SQL query ──────────────────────────────────────────────────
111+
const sql = `SELECT DISTINCT
112+
orders_transactions.users_country
113+
FROM
114+
orders_transactions
115+
LIMIT 5000`;
116+
117+
// ── Execute ────────────────────────────────────────────────────
118+
const token = jwt.sign(JWT_PAYLOAD, CUBE_SECRET, JWT_OPTIONS);
119+
120+
const res = await fetch(CUBE_API_URL, {
121+
method: "POST",
122+
headers: {
123+
Authorization: token,
124+
"Content-Type": "application/json"
125+
},
126+
body: JSON.stringify({ query: sql })
127+
});
128+
129+
if (!res.ok) {
130+
console.error(`HTTP ${res.status}: ${res.statusText}`);
131+
console.error(await res.text());
132+
process.exit(1);
133+
}
134+
135+
const text = await res.text();
136+
const lines = text.trim().split("\n").filter(Boolean);
137+
for (const line of lines) {
138+
console.log(JSON.stringify(JSON.parse(line), null, 2));
139+
}
140+
```
141+
142+
## Result
143+
144+
Because the JWT contains `cubeCloud.groups: ["marketing"]` and
145+
`cubeCloud.userAttributes.country: "United States"`, the query is filtered
146+
by the `marketing` group's access policy. Only rows matching the user
147+
attribute filter are returned:
148+
149+
```json
150+
{
151+
"data": [
152+
["United States"]
153+
]
154+
}
155+
```
156+
157+
[ref-groups]: /admin/users-and-permissions/user-groups
158+
[ref-user-attributes]: /admin/users-and-permissions/user-attributes
159+
[ref-core-data-apis]: /reference/core-data-apis
160+
[ref-dap]: /docs/data-modeling/data-access-policies

0 commit comments

Comments
 (0)