You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/access-control/index.md
+28-37Lines changed: 28 additions & 37 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -71,20 +71,22 @@ First, let's create our hardcoded user mappings in `cube.py`. In practice, thes
71
71
Make sure to update your user email in the first entry of the `USER_SECURITY_MAPPINGS` dictionary below with your workshop email address. This will ensure you have full access to the data when logged in to D3 in the final workshop module.
@@ -236,6 +238,10 @@ In this example, we'll mask phone numbers for sales reps and regional directors,
236
238
4. Extend the security context to lookup the user's PII access
237
239
5. Add the `context_to_app_id` function to cache our model both with PII access and without PII access
238
240
241
+
:::note
242
+
If you save the model changes in between steps, you may see compile errors. Just make all 5 changes and then save, or ignore the compile errors until you finish all 5 steps.
243
+
:::
244
+
239
245
### Step 1: Update the Phone Dimension
240
246
241
247
Update the existing phone dimension in your `customers` cube to include PII masking:
@@ -260,7 +266,7 @@ Update the existing phone dimension in your `customers` cube to include PII mask
260
266
261
267
We also need to include the phone field in our sales view. Update your `sales` view definition to move the phone dimension from `excludes` to `includes`:
262
268
263
-
```yaml title="/model/views/sales.yml" {11}
269
+
```yaml title="/model/views/sales.yml" {11,13}
264
270
...
265
271
266
272
# Customer information via orders
@@ -273,6 +279,7 @@ We also need to include the phone field in our sales view. Update your `sales` v
@@ -381,26 +388,8 @@ In this section, we'll create two new views:
381
388
382
389
First, we need to ensure user roles are available in the security context. Update your `extend_context` function in `cube.py` to include the user's role. We'll also make our function more robust to handle both the React app and D3 formats of the security context:
383
390
384
-
```python title="/cube.py" {9-19,26}
391
+
```python title="/cube.py" {8}
385
392
...
386
-
387
-
@config('extend_context')
388
-
def extend_context(req: dict) -> dict:
389
-
# Check if securityContext exists, skip extending context if not
390
-
if 'securityContext' not in req:
391
-
return req
392
-
393
-
# Get user from security context - handle both React app and D3 formats
394
-
security_context = req.get('securityContext', {})
395
-
396
-
# If D3 format (has cubeCloud key), extract username from cubeCloud.username
2. **Test each user type and observe available views**:
533
522
523
+

524
+
The padlock icon means this view (or cube or field) is not visible to the current user based on their security context through the APIs.
525
+
534
526
**Admin User**:
535
527
```json
536
528
{ "user_id": "admin@tpch.com" }
@@ -556,8 +548,7 @@ views:
556
548
- Sarah sees only her customers with masked phone numbers
557
549
- Admin sees everything including real phone numbers
558
550
559
-

560
-
The padlock icon means this view (or cube or field) is not visible to the current user based on their security context through the APIs.
551
+
561
552
562
553
### Advanced: Combining View Visibility with Row-Level Security
563
554
@@ -646,7 +637,7 @@ Now that you've implemented comprehensive access control, let's save your work:
646
637
647
638
**Step 2: Commit Your Changes**
648
639
1. **Navigate to the Data Model page**
649
-
2. **Review all your changes** - You should see modified files: `cube.py`, `globals.py`, `sales.yml`, `director_dashboard.yml`, `sales_team.yml`
640
+
2. **Review all your changes** - You should see modified files: `customers.yml`, `cube.py`, `globals.py`, `sales.yml`, `director_dashboard.yml`, `sales_team.yml`
- Full performance with production-scale resources (NOTE: just for this workshop, our prod environment is still scaled down to use dev-scale resources)
Now that you have your Bearer token, let's query TPCH's monthly revenue using the REST API. We'll use the GET method with URL-encoded query parameters - this is simpler for testing in the terminal.
101
+
Let's query TPCH's monthly revenue using the REST API. We'll use the GET method with URL-encoded query parameters - this is simpler for testing in the terminal.
97
102
98
-
Head to the **Integrations** page and click the **API Credentials** button, then the **REST API** tab. This will show you your endpoint URL and how to construct a query using curl.
103
+
:::tip
104
+
On the **Integrations** page and click the **API Credentials** button, then the **REST API** tab. This will show you your endpoint URL and how to construct a query using `curl`.
Copy file name to clipboardExpand all lines: docs/d3-analytics/index.md
+15-4Lines changed: 15 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -42,16 +42,15 @@ Cube D3 is currently in private preview and may have some limitations or errors
42
42
:::
43
43
44
44
In Cube Cloud:
45
-
1.**Navigate to D3** (click the Cube logo in the top left, then select "D3 AI")
46
-
2.**Click Admin**in the left sidebar
45
+
1.**Navigate to D3** (click the Cube logo in the top left, then select "D3 AI") The interface will look like it's still loading, but move on to the next step anyway.
46
+
2.**Click Admin**at the bottom of the left sidebar
47
47
3. In **Spaces**, click **Add Space**
48
48
4.**Name your space** (e.g. "TPCH Analytics")
49
49
5. In **Agents**, click **Add Agent**
50
50
6.**Name your agent** (e.g. "TPCH Analyst")
51
-
7. Select **"WDC 2025 Workshop"** as the **Semantic Model**
51
+
7. Select **"WDC 2025"** as the **Semantic Model**
52
52
8. Assign it to the **TPCH Analytics** space you just created
53
53
9. Navigate **"Back to app"** to return to the D3 interface
54
-
10. Make sure your Space is selected in the top dropdown menu.
55
54
56
55
## Exercise: Interacting with D3
57
56
@@ -62,6 +61,18 @@ Ask D3 a simple question about your data:
62
61
What is our total revenue this year?
63
62
```
64
63
64
+
:::tip
65
+
Don't see any data? Make sure you updated your cube.py file with your username (email address) in the `USER_SECURITY_MAPPINGS` section. This allows D3 to recognize you as an admin and access the data.
66
+
```USER_SECURITY_MAPPINGS = {
67
+
# YOUR USER - UPDATE WITH YOUR WORKSHOP EMAIL
68
+
"wdc-2025-044@example.com": {
69
+
"role": "global_admin",
70
+
"filter_type": "none",
71
+
"show_pii": "true" # Admins can see PII data
72
+
},
73
+
```
74
+
:::
75
+
65
76
Notice on the right side, D3 shows you the **Semantic Views** you have access to. If you click on them, you can see the same fields we added to the views in our prior modules.
66
77
67
78
As the agent processes your request, it will generate a response and display the results in a table or chart format. You can also see the underlying **Semantic SQL** query that was generated. Click on the **Semantic SQL** tab to view it.
Copy file name to clipboardExpand all lines: docs/data-modeling/index.md
+30-37Lines changed: 30 additions & 37 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -53,7 +53,7 @@ You should see a time series of order counts. Check out the tabs for **SQL API*
53
53
54
54
Now click on the **Generated SQL** tab - this is the query that Cube generates which goes back to our PostgreSQL database.
55
55
56
-
Let's **add another field to the query**. From the `regions` cube, click the `name` field. Now check those API tabs again. The "Semantic SQL" (what we see on the **SQL API** tab) is simple - you're just asking for fields without worrying about the join logic which we've already defined and is now part of the data model.
56
+
Let's **add another field to the query**. From the `customer_regions` cube, click the `name` field. Now check those API tabs again. The "Semantic SQL" (what we see on the **SQL API** tab) is simple - you're just asking for fields without worrying about the join logic which we've already defined and is now part of the data model.
57
57
58
58
On the **Generated SQL** tab, the query is now much more complex as the joins traverse a few tables to go from `orders` -> `customers` -> `nations` -> `regions` but as a semantic layer end user, we are able to simply re-use the logic that was already setup ahead of time.
59
59
@@ -171,8 +171,11 @@ In development mode, you'll see a separate API endpoint for testing:
@@ -513,7 +516,9 @@ Create business-friendly categories by adding binning dimensions. Instead of de
513
516
Create a business-critical metric using subqueries and measure dependencies. Let's build **Average Customer Value (ACV)** in the customers cube:
514
517
515
518
**Step 1: Add a subquery dimension to customers.yml**
516
-
```yaml title="model/cubes/customers.yml" {7-12}
519
+
```yaml title="model/cubes/customers.yml" {9-14}
520
+
...
521
+
dimensions:
517
522
...
518
523
519
524
- name: comment
@@ -696,9 +701,11 @@ You simply define a view that includes all the measures and related dimensions y
696
701
697
702
## Creating a Sales View
698
703
699
-
To create a view, it's a best practice define it in a separate YAML file. **Important**: Generally you'll use the lowest granularity cube with the measures you want in the view - typically one tied to a fact table as your base. In our case, that's `line_items` since it contains the actual sales transactions:
704
+
To create a view, it's a best practice to define it in a separate YAML file in the `views` directory to help keep them organized. Since we don't have that yet, let's create it now. Hover over the `/model` directory in the Cube Cloud IDE and click the **...** menu, then the **Add Directory** button. Name the folder `views`.
700
705
701
-
Hover over the `/model/views` directory in the Cube Cloud IDE and click the **...*** menu, then the **New File** button. Name the file `sales.yml` and add the following content:
706
+

707
+
708
+
Now let's add a new file for our new view. Hover over the `/model/views` directory in the Cube Cloud IDE and click the **...** menu, then the **New File** button. Name the file `sales.yml` and add the following content:
702
709
703
710
```yaml title="model/views/sales.yml"
704
711
views:
@@ -781,6 +788,8 @@ views:
781
788
- region_key
782
789
```
783
790
791
+
**Important**: Generally you'll use the lowest granularity cube with the measures you want in the view - typically one tied to a fact table as your base. In our case, that's `line_items` since it contains the actual sales transactions.
792
+
784
793
## What This Enables
785
794
786
795
With this view, end users can:
@@ -831,26 +840,7 @@ With this view, end users can:
831
840
3. **Clean Schema**: Only relevant, business-friendly fields
832
841
4. **Accurate Metrics**: Revenue and quantity calculations are precise
833
842
834
-
## Complete Model Files
835
-
836
-
### 📁 Starter Files
837
-
**Location**: `static/cube-models/starter/`
838
-
839
-
Contains:
840
-
- Basic cubes with dimensions and count measures
841
-
- Most joins (missing one for exercise)
842
-
- Foundation for building upon
843
-
844
-
### 📁 Data Modeling Complete
845
-
**Location**: `static/cube-models/data-modeling/`
846
-
847
-
Contains:
848
-
- All revenue measures
849
-
- Subquery dimensions
850
-
- Binning dimensions
851
-
- Multi-level measure dependencies
852
-
- Complete join relationships
853
-
- **Sales View** - Denormalized cube perfect for dashboards and reporting
843
+
This data model is well on its way to power dashboards, reports, and applications with consistent, reliable business metrics.
854
844
855
845
## Deploying Your Sales View to Production
856
846
@@ -859,15 +849,20 @@ Now that you've built a comprehensive sales view with all the business metrics,
859
849
### Final Exercise: Commit your Changes
860
850
861
851
**Step 1: Review Your Changes**
862
-
1. **Ensure you're in Development Mode** - Look for the "Dev Mode" indicator
852
+
1. **Ensure you're still in Development Mode** - Look for the "Dev Mode" indicator
863
853
2. **Test your sales view** one final time in the Playground:
864
854
- Query `sales.total_sales_amount` by `sales.region`
865
855
- Query `sales.parts_brand` with `sales.total_quantity`
866
856
- Verify all field names and calculations are correct
0 commit comments