diff --git a/docs-mintlify/embedding/iframe/creator-mode.mdx b/docs-mintlify/embedding/iframe/creator-mode.mdx index 793d2d952911d..63b1851cfe0b5 100644 --- a/docs-mintlify/embedding/iframe/creator-mode.mdx +++ b/docs-mintlify/embedding/iframe/creator-mode.mdx @@ -7,48 +7,29 @@ description: Embed the full Cube application so users can build and modify their Creator Mode is available on the [Enterprise plan](https://cube.dev/pricing). -Creator Mode lets you embed the entire Cube application into your product so users can create and modify their own dashboards directly within the embedded experience. +Creator Mode embeds the full Cube application instead of an individual dashboard or chat. Users can create and modify workbooks, dashboards, and reports inside the iframe. + +To enable it, pass `creatorMode: true` to the [Generate Session API][ref-generate-session]. Creator Mode requires [Signed embedding](/embedding/iframe/auth/signed). Private embedding is not supported. -## How it works - -In Creator Mode, you embed the full Cube application instead of individual dashboards or chat interfaces. This provides users with the complete Cube experience, including the ability to: - -- Create new dashboards -- Modify existing dashboards -- Access all workbook and dashboard functionality -- Build custom analytics experiences - -To enable Creator Mode, pass `creatorMode: true` to the [Generate Session API][ref-generate-session] when generating an embed session. Optionally, pass `embedTenantName` to scope content to a specific embed tenant — by default, creator mode uses the current tenant's name. +## Embed tenant scoping -## Embed tenant name +In Creator Mode, content (workbooks, dashboards) and the groups/user attributes referenced by the session are scoped to an **embed tenant**. Pass `embedTenantName` to isolate content per customer; omit it to use the current tenant. -`embedTenantName` is an optional parameter on the Generate Session API used to scope all content (dashboards, workbooks, etc.) that users create within the embedded application to a specific embed tenant. This ensures proper data isolation in multi-tenant scenarios. +`embedTenantName` must be lowercase, 5–36 chars, start with a letter, end with a letter or digit, and contain only `a-z`, `0-9`, or `-`. -When `embedTenantName` is omitted in creator mode, the session defaults to the current tenant, so most setups don't need to set it. +## Provisioning groups and user attributes -The value must be lowercase, start with a letter, end with a letter or number, and only contain letters, numbers, or hyphens (length 5–36). +In Creator Mode, `groups` and `userAttributes` resolve against the embed tenant's scoped catalog (separate from the tenant-wide one used by read-only embedding). To define those entries from your backend in the same call, pass `groupDefinitions` and `userAttributeDefinitions` — they are idempotent and validated before memberships and values are applied. -## Using Creator Mode +See [Generate Session → Creator mode bootstrap][ref-bootstrap] for the input shape, value types, and the immutable-`type` rule on attribute definitions. -To use Creator Mode and embed the app: - -1. **Set the embed type to "App"** in the form -2. **Fill in Deployment ID** and either **External ID** or **Internal ID** (email). Optionally provide an **Embed Tenant Name** to scope content to a specific embed tenant -3. **Click "Generate Session & Embed"** — the request automatically includes `creatorMode: true` for app embeddings -4. The app is embedded at `/embed/d/{deploymentId}/app?session={sessionId}` and displayed in the iframe - -Creator mode is enabled automatically when the embed type is "app"; no additional configuration is needed. - -### Example +## Example ```javascript -const API_KEY = "YOUR_API_KEY"; -const DEPLOYMENT_ID = 32; - const session = await fetch( "https://your-account.cubecloud.dev/api/v1/embed/generate-session", { @@ -58,22 +39,18 @@ const session = await fetch( Authorization: `Api-Key ${API_KEY}`, }, body: JSON.stringify({ - deploymentId: DEPLOYMENT_ID, + deploymentId: 32, externalId: "user@example.com", - creatorMode: true, - // Optional — defaults to the current tenant when omitted: embedTenantName: "acme-corp", + creatorMode: true, }), }, ); -const data = await session.json(); -const sessionId = data.sessionId; +const { sessionId } = await session.json(); ``` -### Embedding the app - -Use the session ID to embed the full Cube application: +Embed the app with the returned session ID: ```html ``` -Replace `{deploymentId}` with your deployment ID and `{sessionId}` with the session ID returned from the Generate Session API. - -## Example application - -For a complete working example of embedding, including Creator Mode, check out the [cube-embedding-demo](https://github.com/cubedevinc/cube-embedding-demo) repository. This demo application provides: - -- A full working example of iframe embedding -- Implementation of signed iframe embedding with session generation -- Support for creator mode with an optional embed tenant name -- A React-based UI for testing embedding functionality -- Backend server that securely handles API key authentication - -You can clone the repository, configure it with your Cube credentials, and run it locally to test embedding functionality or use it as a reference implementation for your own application. +For a complete working example, see the [cube-embedding-demo](https://github.com/cubedevinc/cube-embedding-demo) repository. [ref-generate-session]: /reference/embed-apis/generate-session +[ref-bootstrap]: /reference/embed-apis/generate-session#creator-mode-bootstrapping-groups-and-user-attributes diff --git a/docs-mintlify/reference/embed-apis/generate-session.mdx b/docs-mintlify/reference/embed-apis/generate-session.mdx index d33e3ecd0b8fb..c14a05fedb2d8 100644 --- a/docs-mintlify/reference/embed-apis/generate-session.mdx +++ b/docs-mintlify/reference/embed-apis/generate-session.mdx @@ -32,15 +32,21 @@ POST https://{accountName}.cubecloud.dev/api/v1/embed/generate-session | Field | Type | Required | Description | |-------|------|----------|-------------| -| `externalId` | string | No | Unique identifier for the external user. Either `externalId` or `internalId` should be provided. | -| `internalId` | string | No | Email address of an internal Cube Cloud user. Either `externalId` or `internalId` should be provided. | -| `userAttributes` | array | No | Array of `{name, value}` pairs for row-level security. Not allowed with `internalId`. | -| `groups` | string[] | No | Array of group names for user. Not allowed with `internalId`. | +| `deploymentId` | number | Yes | ID of the deployment the session should grant access to. | +| `externalId` | string | Conditional | Stable identifier for the external user. Provide either `externalId` or `internalId` (not both). Must be lowercase and trimmed. | +| `internalId` | string | Conditional | Username of an existing internal Cube Cloud user. Provide either `externalId` or `internalId` (not both). The user must already exist. | +| `email` | string | No | Email to attach to the provisioned external user. Used only with `externalId`. | +| `embedTenantName` | string | No | Embed tenant to scope content to. Lowercase, 5–36 chars, must start with a letter and end with a letter or digit, only `a-z`, `0-9`, `-`. Defaults to the current tenant. | +| `creatorMode` | boolean | No | When `true`, mints a [creator-mode][ref-creator-mode] session and resolves groups/attributes against the embed tenant's scoped tables. Requires the `useCreatorMode` tenant flag. | +| `userAttributes` | array | No | Attribute values for row-level security. See [User attributes](#user-attributes). Not allowed with `internalId`. | +| `groups` | string[] | No | Group memberships for the user. See [Groups](#groups). Not allowed with `internalId`. | +| `userAttributeDefinitions` | array | No | Idempotently upsert attribute definitions before applying values. Requires `creatorMode: true`. See [Creator mode bootstrap](#creator-mode-bootstrapping-groups-and-user-attributes). | +| `groupDefinitions` | array | No | Idempotently upsert group definitions before assigning memberships. Requires `creatorMode: true`. See [Creator mode bootstrap](#creator-mode-bootstrapping-groups-and-user-attributes). | | `securityContext` | object | No | Custom security context object passed to Cube queries. Not allowed with `internalId`. | -When using `internalId`, the user must already exist in Cube Cloud. You cannot specify `roles`, `groups`, `userAttributes`, or `securityContext` with `internalId` — the internal user's existing permissions are used instead. +When using `internalId`, the user must already exist in Cube Cloud. You cannot specify `groups`, `userAttributes`, `groupDefinitions`, `userAttributeDefinitions`, or `securityContext` with `internalId` — the internal user's existing permissions are used instead. @@ -50,6 +56,167 @@ Accounts are limited to 10,000 external users. To increase this limit, please co +## User attributes + +`userAttributes` is an array of `{ name, value }` pairs that drive row-level security in queries. + +```json +{ + "userAttributes": [ + { "name": "department", "value": "Sales" }, + { "name": "tier", "value": 2 }, + { "name": "regions", "value": ["us-east", "eu-west"] }, + { "name": "thresholds", "value": [10, 25, 50] } + ] +} +``` + +| Property | Type | Notes | +|----------|------|-------| +| `name` | string | Must reference an existing attribute definition (see lookup rules below). | +| `value` | `string` \| `number` \| `string[]` \| `number[]` \| `null` | The value type must match the definition's `type`. `null` clears the value. | + +**Attribute definition lookup**: + +- **Read-only mode** (`creatorMode` omitted or `false`): names are resolved against the tenant-wide attribute catalog (managed in **Settings → User Attributes** or via the admin GraphQL API). Any name not present there fails with `User attributes not found`. +- **Creator mode** (`creatorMode: true`): names are resolved against the embed tenant's scoped catalog (`embed_user_attributes`). Use `userAttributeDefinitions` in the same request to upsert definitions on the fly — see [Creator mode bootstrap](#creator-mode-bootstrapping-groups-and-user-attributes). + +**Rules**: + +- Duplicate `name` entries are rejected with `400 Bad Request`. +- Values are persisted per user. Subsequent calls with the same `externalId` overwrite previous values for the supplied names. + +## Groups + +`groups` is an array of group **names** (not IDs) that the user should belong to. Group definitions must already exist (or be created in the same request via `groupDefinitions` in creator mode). + +```json +{ "groups": ["analysts", "marketing"] } +``` + +**Behavior**: + +| Value | Effect | +|-------|--------| +| Field omitted (`undefined`) | Existing memberships are preserved. | +| `[]` (empty array) | All memberships are cleared. | +| Populated array | Memberships are replaced with exactly the supplied names. | + +**Group definition lookup**: + +- **Read-only mode**: names are resolved against tenant-wide groups (managed in **Settings → Groups** or via the admin GraphQL API). The membership row references the global group. +- **Creator mode**: names are resolved against the embed tenant's scoped groups (`embed_user_groups`). Use `groupDefinitions` in the same request to upsert them. + +If any name in `groups` cannot be resolved, the request fails with `Groups with names not found`. + +## Creator mode: bootstrapping groups and user attributes + +In API-first integrations you often want to mint an embed session and define the groups/attributes it references in a single call, without first making a round trip to the admin UI. The `groupDefinitions` and `userAttributeDefinitions` fields do that — they idempotently upsert definitions in the embed tenant's scoped tables and are validated **before** `groups` and `userAttributes` are applied. + +Both fields: + +- Require `creatorMode: true`. +- Require an `embedTenantName` (definitions are only meaningful inside an embed tenant). +- Require the `useCreatorMode` tenant flag — contact support to enable. +- Land in the embed-tenant scope only — they never modify tenant-wide groups or attributes. +- Are idempotent: running the same request twice produces the same end state. + +### `groupDefinitions` + +```json +{ + "groupDefinitions": [ + { "name": "analysts", "description": "Read-only viewers" }, + { "name": "marketing" } + ] +} +``` + +| Property | Type | Required | Notes | +|----------|------|----------|-------| +| `name` | string | Yes | Group name. Existing groups with this name are reused. | +| `description` | string | No | Updated when supplied and different from the stored value. Never cleared. | + +Duplicate `name` entries within the same request are rejected. + +### `userAttributeDefinitions` + +```json +{ + "userAttributeDefinitions": [ + { + "name": "department", + "type": "string", + "displayName": "Department", + "defaultValue": "Unassigned", + "description": "Org unit" + } + ] +} +``` + +| Property | Type | Required | Notes | +|----------|------|----------|-------| +| `name` | string | Yes | Attribute name. Existing attributes with this name are reused. | +| `type` | enum | Yes | One of `string`, `number`, `string_array`, `number_array`. **Immutable** — see below. | +| `displayName` | string | No | Updated when supplied and different from the stored value. | +| `defaultValue` | string | No | Updated when supplied and different from the stored value. | +| `description` | string | No | Updated when supplied and different from the stored value. | + +**`type` is immutable.** If a definition with the supplied `name` already exists with a different `type`, the request fails with `cannot change type` and nothing is upserted. This protects every value already stored against that attribute from silently becoming invalid. To change the type, delete the attribute via the [embed-tenant admin API](#embed-tenant-admin-api) and recreate it. + +Duplicate `name` entries within the same request are rejected. + +### Bootstrap example + +Define a group and an attribute, assign the user to both, and mint a session — all in one call: + +```javascript +const session = await fetch( + `https://${ACCOUNT_NAME}.cubecloud.dev/api/v1/embed/generate-session`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Api-Key ${API_KEY}`, + }, + body: JSON.stringify({ + deploymentId: DEPLOYMENT_ID, + externalId: 'user-123', + embedTenantName: 'acme-corp', + creatorMode: true, + + // Upserted before validation runs + groupDefinitions: [ + { name: 'analysts', description: 'Read-only viewers' }, + ], + userAttributeDefinitions: [ + { name: 'department', type: 'string', displayName: 'Department' }, + ], + + // Reference the names we just defined + groups: ['analysts'], + userAttributes: [{ name: 'department', value: 'Sales' }], + }), + }, +); +``` + +A second call with the same body produces the same end state: the group and attribute already exist, descriptions/display names are reconciled if they changed, and the user's memberships and values are re-applied. + +## Embed-tenant admin API + +To list or delete the groups and attributes that have been bootstrapped into an embed tenant, use the admin endpoints scoped to that tenant: + +```text +GET /api/v1/embed-tenants/{embedTenantName}/groups +DELETE /api/v1/embed-tenants/{embedTenantName}/groups/{id} +GET /api/v1/embed-tenants/{embedTenantName}/user-attributes +DELETE /api/v1/embed-tenants/{embedTenantName}/user-attributes/{id} +``` + +These endpoints use the same `Api-Key` authentication as Generate Session and require admin access. List endpoints return cursor-paginated results (`?first=`, `?after=`). + ### Response The API returns a session object: @@ -84,10 +251,12 @@ response = requests.post( 'Authorization': f'Api-Key {API_KEY}' }, json={ + 'deploymentId': 32, 'externalId': 'user@example.com', 'userAttributes': [ {'name': 'department', 'value': 'Sales'} - ] + ], + 'groups': ['analysts'] } ) @@ -108,10 +277,12 @@ const response = await fetch( 'Authorization': `Api-Key ${API_KEY}` }, body: JSON.stringify({ + deploymentId: 32, externalId: 'user@example.com', userAttributes: [ { name: 'department', value: 'Sales' } - ] + ], + groups: ['analysts'] }) } ); @@ -124,10 +295,12 @@ curl -X POST "https://your-account.cubecloud.dev/api/v1/embed/generate-session" -H "Content-Type: application/json" \ -H "Authorization: Api-Key YOUR_API_KEY" \ -d '{ + "deploymentId": 32, "externalId": "user@example.com", "userAttributes": [ {"name": "department", "value": "Sales"} - ] + ], + "groups": ["analysts"] }' ``` @@ -136,4 +309,5 @@ curl -X POST "https://your-account.cubecloud.dev/api/v1/embed/generate-session" Use session ID in [signed embedding][ref-signed-embedding]. [ref-api-keys]: /admin/account-billing/api-keys -[ref-signed-embedding]: /embedding/iframe/auth/signed \ No newline at end of file +[ref-signed-embedding]: /embedding/iframe/auth/signed +[ref-creator-mode]: /embedding/iframe/creator-mode diff --git a/docs/content/product/apis-integrations/embed-apis/generate-session.mdx b/docs/content/product/apis-integrations/embed-apis/generate-session.mdx index 49f5460268f48..60843f85ab12e 100644 --- a/docs/content/product/apis-integrations/embed-apis/generate-session.mdx +++ b/docs/content/product/apis-integrations/embed-apis/generate-session.mdx @@ -29,15 +29,21 @@ POST https://{accountName}.cubecloud.dev/api/v1/embed/generate-session | Field | Type | Required | Description | |-------|------|----------|-------------| -| `externalId` | string | No | Unique identifier for the external user. Either `externalId` or `internalId` should be provided. | -| `internalId` | string | No | Email address of an internal Cube Cloud user. Either `externalId` or `internalId` should be provided. | -| `userAttributes` | array | No | Array of `{name, value}` pairs for row-level security. Not allowed with `internalId`. | -| `groups` | string[] | No | Array of group names for user. Not allowed with `internalId`. | +| `deploymentId` | number | Yes | ID of the deployment the session should grant access to. | +| `externalId` | string | Conditional | Stable identifier for the external user. Provide either `externalId` or `internalId` (not both). Must be lowercase and trimmed. | +| `internalId` | string | Conditional | Username of an existing internal Cube Cloud user. Provide either `externalId` or `internalId` (not both). The user must already exist. | +| `email` | string | No | Email to attach to the provisioned external user. Used only with `externalId`. | +| `embedTenantName` | string | No | Embed tenant to scope content to. Lowercase, 5–36 chars, must start with a letter and end with a letter or digit, only `a-z`, `0-9`, `-`. Defaults to the current tenant. | +| `creatorMode` | boolean | No | When `true`, mints a [creator-mode][ref-creator-mode] session and resolves groups/attributes against the embed tenant's scoped tables. Requires the `useCreatorMode` tenant flag. | +| `userAttributes` | array | No | Attribute values for row-level security. See [User attributes](#user-attributes). Not allowed with `internalId`. | +| `groups` | string[] | No | Group memberships for the user. See [Groups](#groups). Not allowed with `internalId`. | +| `userAttributeDefinitions` | array | No | Idempotently upsert attribute definitions before applying values. Requires `creatorMode: true`. See [Creator mode bootstrap](#creator-mode-bootstrapping-groups-and-user-attributes). | +| `groupDefinitions` | array | No | Idempotently upsert group definitions before assigning memberships. Requires `creatorMode: true`. See [Creator mode bootstrap](#creator-mode-bootstrapping-groups-and-user-attributes). | | `securityContext` | object | No | Custom security context object passed to Cube queries. Not allowed with `internalId`. | -When using `internalId`, the user must already exist in Cube Cloud. You cannot specify `roles`, `groups`, `userAttributes`, or `securityContext` with `internalId` — the internal user's existing permissions are used instead. +When using `internalId`, the user must already exist in Cube Cloud. You cannot specify `groups`, `userAttributes`, `groupDefinitions`, `userAttributeDefinitions`, or `securityContext` with `internalId` — the internal user's existing permissions are used instead. @@ -47,6 +53,167 @@ Accounts are limited to 10,000 external users. To increase this limit, please co +## User attributes + +`userAttributes` is an array of `{ name, value }` pairs that drive row-level security in queries. + +```json +{ + "userAttributes": [ + { "name": "department", "value": "Sales" }, + { "name": "tier", "value": 2 }, + { "name": "regions", "value": ["us-east", "eu-west"] }, + { "name": "thresholds", "value": [10, 25, 50] } + ] +} +``` + +| Property | Type | Notes | +|----------|------|-------| +| `name` | string | Must reference an existing attribute definition (see lookup rules below). | +| `value` | `string` \| `number` \| `string[]` \| `number[]` \| `null` | The value type must match the definition's `type`. `null` clears the value. | + +**Attribute definition lookup**: + +- **Read-only mode** (`creatorMode` omitted or `false`): names are resolved against the tenant-wide attribute catalog (managed in **Settings → User Attributes** or via the admin GraphQL API). Any name not present there fails with `User attributes not found`. +- **Creator mode** (`creatorMode: true`): names are resolved against the embed tenant's scoped catalog (`embed_user_attributes`). Use `userAttributeDefinitions` in the same request to upsert definitions on the fly — see [Creator mode bootstrap](#creator-mode-bootstrapping-groups-and-user-attributes). + +**Rules**: + +- Duplicate `name` entries are rejected with `400 Bad Request`. +- Values are persisted per user. Subsequent calls with the same `externalId` overwrite previous values for the supplied names. + +## Groups + +`groups` is an array of group **names** (not IDs) that the user should belong to. Group definitions must already exist (or be created in the same request via `groupDefinitions` in creator mode). + +```json +{ "groups": ["analysts", "marketing"] } +``` + +**Behavior**: + +| Value | Effect | +|-------|--------| +| Field omitted (`undefined`) | Existing memberships are preserved. | +| `[]` (empty array) | All memberships are cleared. | +| Populated array | Memberships are replaced with exactly the supplied names. | + +**Group definition lookup**: + +- **Read-only mode**: names are resolved against tenant-wide groups (managed in **Settings → Groups** or via the admin GraphQL API). The membership row references the global group. +- **Creator mode**: names are resolved against the embed tenant's scoped groups (`embed_user_groups`). Use `groupDefinitions` in the same request to upsert them. + +If any name in `groups` cannot be resolved, the request fails with `Groups with names not found`. + +## Creator mode: bootstrapping groups and user attributes + +In API-first integrations you often want to mint an embed session and define the groups/attributes it references in a single call, without first making a round trip to the admin UI. The `groupDefinitions` and `userAttributeDefinitions` fields do that — they idempotently upsert definitions in the embed tenant's scoped tables and are validated **before** `groups` and `userAttributes` are applied. + +Both fields: + +- Require `creatorMode: true`. +- Require an `embedTenantName` (definitions are only meaningful inside an embed tenant). +- Require the `useCreatorMode` tenant flag — contact support to enable. +- Land in the embed-tenant scope only — they never modify tenant-wide groups or attributes. +- Are idempotent: running the same request twice produces the same end state. + +### `groupDefinitions` + +```json +{ + "groupDefinitions": [ + { "name": "analysts", "description": "Read-only viewers" }, + { "name": "marketing" } + ] +} +``` + +| Property | Type | Required | Notes | +|----------|------|----------|-------| +| `name` | string | Yes | Group name. Existing groups with this name are reused. | +| `description` | string | No | Updated when supplied and different from the stored value. Never cleared. | + +Duplicate `name` entries within the same request are rejected. + +### `userAttributeDefinitions` + +```json +{ + "userAttributeDefinitions": [ + { + "name": "department", + "type": "string", + "displayName": "Department", + "defaultValue": "Unassigned", + "description": "Org unit" + } + ] +} +``` + +| Property | Type | Required | Notes | +|----------|------|----------|-------| +| `name` | string | Yes | Attribute name. Existing attributes with this name are reused. | +| `type` | enum | Yes | One of `string`, `number`, `string_array`, `number_array`. **Immutable** — see below. | +| `displayName` | string | No | Updated when supplied and different from the stored value. | +| `defaultValue` | string | No | Updated when supplied and different from the stored value. | +| `description` | string | No | Updated when supplied and different from the stored value. | + +**`type` is immutable.** If a definition with the supplied `name` already exists with a different `type`, the request fails with `cannot change type` and nothing is upserted. This protects every value already stored against that attribute from silently becoming invalid. To change the type, delete the attribute via the [embed-tenant admin API](#embed-tenant-admin-api) and recreate it. + +Duplicate `name` entries within the same request are rejected. + +### Bootstrap example + +Define a group and an attribute, assign the user to both, and mint a session — all in one call: + +```javascript +const session = await fetch( + `https://${ACCOUNT_NAME}.cubecloud.dev/api/v1/embed/generate-session`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Api-Key ${API_KEY}`, + }, + body: JSON.stringify({ + deploymentId: DEPLOYMENT_ID, + externalId: 'user-123', + embedTenantName: 'acme-corp', + creatorMode: true, + + // Upserted before validation runs + groupDefinitions: [ + { name: 'analysts', description: 'Read-only viewers' }, + ], + userAttributeDefinitions: [ + { name: 'department', type: 'string', displayName: 'Department' }, + ], + + // Reference the names we just defined + groups: ['analysts'], + userAttributes: [{ name: 'department', value: 'Sales' }], + }), + }, +); +``` + +A second call with the same body produces the same end state: the group and attribute already exist, descriptions/display names are reconciled if they changed, and the user's memberships and values are re-applied. + +## Embed-tenant admin API + +To list or delete the groups and attributes that have been bootstrapped into an embed tenant, use the admin endpoints scoped to that tenant: + +``` +GET /api/v1/embed-tenants/{embedTenantName}/groups +DELETE /api/v1/embed-tenants/{embedTenantName}/groups/{id} +GET /api/v1/embed-tenants/{embedTenantName}/user-attributes +DELETE /api/v1/embed-tenants/{embedTenantName}/user-attributes/{id} +``` + +These endpoints use the same `Api-Key` authentication as Generate Session and require admin access. List endpoints return cursor-paginated results (`?first=`, `?after=`). + ### Response The API returns a session object: @@ -81,10 +248,12 @@ const response = await fetch( 'Authorization': `Api-Key ${API_KEY}` }, body: JSON.stringify({ + deploymentId: 32, externalId: 'user@example.com', userAttributes: [ { name: 'department', value: 'Sales' } - ] + ], + groups: ['analysts'] }) } ); @@ -106,10 +275,12 @@ response = requests.post( 'Authorization': f'Api-Key {API_KEY}' }, json={ + 'deploymentId': 32, 'externalId': 'user@example.com', 'userAttributes': [ {'name': 'department', 'value': 'Sales'} - ] + ], + 'groups': ['analysts'] } ) @@ -121,10 +292,12 @@ curl -X POST "https://your-account.cubecloud.dev/api/v1/embed/generate-session" -H "Content-Type: application/json" \ -H "Authorization: Api-Key YOUR_API_KEY" \ -d '{ + "deploymentId": 32, "externalId": "user@example.com", "userAttributes": [ {"name": "department", "value": "Sales"} - ] + ], + "groups": ["analysts"] }' ``` @@ -134,4 +307,4 @@ Use session ID in [signed embedding][ref-signed-embedding]. [ref-api-keys]: /product/administration/api-keys [ref-signed-embedding]: /product/embedding/signed-embedding - +[ref-creator-mode]: /product/embedding/creator-mode diff --git a/docs/content/product/embedding/creator-mode.mdx b/docs/content/product/embedding/creator-mode.mdx index be7d9dd119386..ef78daea2032a 100644 --- a/docs/content/product/embedding/creator-mode.mdx +++ b/docs/content/product/embedding/creator-mode.mdx @@ -6,44 +6,25 @@ Available on the [Enterprise plan](https://cube.dev/pricing). -Creator mode enables you to embed the entire Cube application with workbooks-dashboard functionality. Users will be able to create and modify their dashboards directly within the embedded application. +Creator mode embeds the full Cube application instead of an individual dashboard or chat. Users can create and modify workbooks, dashboards, and reports inside the iframe. -## How it works +To enable it, pass `creatorMode: true` to the [Generate Session API][ref-generate-session]. -In creator mode, you embed the full Cube application instead of individual dashboards or chat interfaces. This provides users with the complete Cube experience, including the ability to: +## Embed tenant scoping -- Create new dashboards -- Modify existing dashboards -- Access all workbook and dashboard functionality -- Build custom analytics experiences +In creator mode, content (workbooks, dashboards) and the groups/user attributes referenced by the session are scoped to an **embed tenant**. Pass `embedTenantName` to isolate content per customer; omit it to use the current tenant. -To enable creator mode, pass `creatorMode: true` to the [Generate Session API][ref-generate-session] when generating an embed session. Optionally, pass `embedTenantName` to scope content to a specific embed tenant — by default, creator mode uses the current tenant's name. +`embedTenantName` must be lowercase, 5–36 chars, start with a letter, end with a letter or digit, and contain only `a-z`, `0-9`, or `-`. -## Embed tenant name +## Provisioning groups and user attributes -`embedTenantName` is an optional parameter on the Generate Session API used to scope all content (dashboards, workbooks, etc.) that users create within the embedded application to a specific embed tenant. This ensures proper data isolation in multi-tenant scenarios. +In creator mode, `groups` and `userAttributes` resolve against the embed tenant's scoped catalog (separate from the tenant-wide one used by read-only embedding). To define those entries from your backend in the same call, pass `groupDefinitions` and `userAttributeDefinitions` — they are idempotent and validated before memberships and values are applied. -When `embedTenantName` is omitted in creator mode, the session defaults to the current tenant, so most setups don't need to set it. +See [Generate Session → Creator mode bootstrap][ref-bootstrap] for the input shape, value types, and the immutable-`type` rule on attribute definitions. -The value must be lowercase, start with a letter, end with a letter or number, and only contain letters, numbers, or hyphens (length 5–36). - -## Using creator mode - -To use creator mode and embed an app: - -1. **Set the embed type to "App"** in the form -2. **Fill in Deployment ID** and either **External ID** or **Internal ID** (email). Optionally provide an **Embed Tenant Name** to scope content to a specific embed tenant -3. **Click "Generate Session & Embed"** — the request automatically includes `creatorMode: true` for app embeddings -4. The app is embedded at `/embed/d/{deploymentId}/app?session={sessionId}` and displayed in the iframe - -Creator mode is enabled automatically when the embed type is "app"; no additional configuration is needed. - -### Example +## Example ```javascript -const API_KEY = "YOUR_API_KEY"; -const DEPLOYMENT_ID = 32; - const session = await fetch( "https://your-account.cubecloud.dev/api/v1/embed/generate-session", { @@ -53,22 +34,18 @@ const session = await fetch( Authorization: `Api-Key ${API_KEY}`, }, body: JSON.stringify({ - deploymentId: DEPLOYMENT_ID, + deploymentId: 32, externalId: "user@example.com", + embedTenantName: "acme-corp", creatorMode: true, - // Optional — defaults to the current tenant when omitted: - // embedTenantName: "acme-corp", }), }, ); -const data = await session.json(); -const sessionId = data.sessionId; +const { sessionId } = await session.json(); ``` -### Embedding the app - -Use the session ID to embed the full Cube application: +Embed the app with the returned session ID: ```html ``` -Replace `{deploymentId}` with your deployment ID and `{sessionId}` with the session ID returned from the Generate Session API. - -## Example application - -For a complete working example of embedding, including creator mode, check out the [cube-embedding-demo](https://github.com/cubedevinc/cube-embedding-demo) repository. This demo application provides: - -- A full working example of iframe embedding -- Implementation of signed iframe embedding with session generation -- Support for creator mode with an optional embed tenant name -- A React-based UI for testing embedding functionality -- Backend server that securely handles API key authentication - -You can clone the repository, configure it with your Cube credentials, and run it locally to test embedding functionality or use it as a reference implementation for your own application. +For a complete working example, see the [cube-embedding-demo](https://github.com/cubedevinc/cube-embedding-demo) repository. [ref-generate-session]: /product/apis-integrations/embed-apis/generate-session +[ref-bootstrap]: /product/apis-integrations/embed-apis/generate-session#creator-mode-bootstrapping-groups-and-user-attributes