From cdfa197559c1580e88deefa587be12733746c5cf Mon Sep 17 00:00:00 2001 From: Lucas Coratger <73360179+coratgerl@users.noreply.github.com> Date: Tue, 30 Sep 2025 14:25:26 +0200 Subject: [PATCH 01/10] feat: improve README config table --- README.md | 134 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 109 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 69324ac98..07ae2971a 100644 --- a/README.md +++ b/README.md @@ -142,31 +142,115 @@ Parse Dashboard is continuously tested with the most recent releases of Node.js ### Options -| Parameter | Type | Optional | Default | Example | Description | -|----------------------------------------|---------------------|----------|---------|--------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `apps` | Array<Object> | no | - | `[{ ... }, { ... }]` | The apps that are configured for the dashboard. | -| `apps.appId` | String | yes | - | `"myAppId"` | The Application ID for your Parse Server instance. | -| `apps.masterKey` | String \| Function | yes | - | `"exampleMasterKey"`, `() => "exampleMasterKey"` | The master key for full access to Parse Server. It can be provided directly as a String or as a Function returning a String. | -| `apps.masterKeyTtl` | Number | no | - | `3600` | Time-to-live (TTL) for the master key in seconds. This defines how long the master key is cached before the `masterKey` function is re-triggered. | -| `apps.serverURL` | String | yes | - | `"http://localhost:1337/parse"` | The URL where your Parse Server is running. | -| `apps.appName` | String | no | - | `"MyApp"` | The display name of the app in the dashboard. | -| `infoPanel` | Array<Object> | yes | - | `[{ ... }, { ... }]` | The [info panel](#info-panel) configuration. | -| `infoPanel[*].title` | String | no | - | `User Details` | The panel title. | -| `infoPanel[*].classes` | Array<String> | no | - | `["_User"]` | The classes for which the info panel should be displayed. | -| `infoPanel[*].cloudCodeFunction` | String | no | - | `getUserDetails` | The Cloud Code Function which received the selected object in the data browser and returns the response to be displayed in the info panel. | -| `infoPanel[*].prefetchObjects` | Number | yes | `0` | `2` | Number of next rows to prefetch when browsing sequential rows. For example, `2` means the next 2 rows will be fetched in advance. | -| `infoPanel[*].prefetchStale` | Number | yes | `0` | `10` | Duration in seconds after which prefetched data is discarded as stale. | -| `apps.scripts` | Array<Object> | yes | `[]` | `[{ ... }, { ... }]` | The scripts that can be executed for that app. | -| `apps.scripts.title` | String | no | - | `'Delete User'` | The title that will be displayed in the data browser context menu and the script run confirmation dialog. | -| `apps.scripts.classes` | Array<String> | no | - | `['_User']` | The classes of Parse Objects for which the scripts can be executed. | -| `apps.scripts.cloudCodeFunction` | String | no | - | `'deleteUser'` | The name of the Parse Cloud Function to execute. | -| `apps.scripts.executionBatchSize` | Integer | yes | `1` | `10` | The batch size with which a script should be executed on all selected objects. For example, with 50 objects selected, a batch size of 10 means the script will run on 10 objects in parallel, running a total of 5 batches in serial. | -| `apps.scripts.showConfirmationDialog` | Bool | yes | `false` | `true` | Is `true` if a confirmation dialog should be displayed before the script is executed, `false` if the script should be executed immediately. | -| `apps.scripts.confirmationDialogStyle` | String | yes | `info` | `critical` | The style of the confirmation dialog. Valid values: `info` (blue style), `critical` (red style). | -| `apps.cloudConfigHistoryLimit` | Integer | yes | `100` | `100` | The number of historic values that should be saved in the Cloud Config change history. Valid values: `0`...`Number.MAX_SAFE_INTEGER`. -| `apps.config` | Object | yes | - | `{ ... }` | App settings option used to store dashboard configuration on the server. -| `apps.config.className` | String | yes | _ | `DashboardConfig` | The table name used to save and migrate the dashboard configuration. | - +This section provides a comprehensive reference for all Parse Dashboard configuration options that can be used in the configuration file, via CLI arguments, or as environment variables. + +#### Configuration File Options + +##### App Configuration (`apps` array) + +| Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | +|-----------|------|----------|---------|-----|--------------|---------|-------------| +| `appId` | String | no | - | `--appId` | `PARSE_DASHBOARD_APP_ID` | `"myAppId"` | The Application ID for your Parse Server instance. | +| `masterKey` | String \| Function | no | - | `--masterKey` | `PARSE_DASHBOARD_MASTER_KEY` | `"key"` | Master key for full access. Can be a String or Function returning a String. | +| `serverURL` | String | no | - | `--serverURL` | `PARSE_DASHBOARD_SERVER_URL` | `"http://localhost:1337/parse"` | The URL where your Parse Server is running. | +| `appName` | String | yes | `appId` | `--appName` | `PARSE_DASHBOARD_APP_NAME` | `"MyApp"` | Display name of the app. | +| `masterKeyTtl` | Number | yes | - | `--masterKeyTtl` | - | `3600` | TTL for master key cache in seconds (when `masterKey` is a Function). | +| `readOnlyMasterKey` | String | yes | - | - | - | `"myReadOnlyKey"` | Read-only master key that prevents mutations. | +| `graphQLServerURL` | String | yes | - | `--graphQLServerURL` | `PARSE_DASHBOARD_GRAPHQL_SERVER_URL` | `"http://localhost:1337/graphql"` | URL of GraphQL Server. | +| `appNameForURL` | String | yes | `appName` | - | - | `"my-app"` | URL-friendly name used in dashboard URLs. | +| `production` | Boolean | yes | `false` | - | - | `true` | Mark as production environment. | +| `iconName` | String | yes | - | - | - | `"icon.png"` | Filename of app icon (requires global `iconsFolder`). | +| `primaryBackgroundColor` | String | yes | - | - | - | `"#FFA500"` | Primary background color (CSS value). | +| `secondaryBackgroundColor` | String | yes | - | - | - | `"#FF4500"` | Secondary background color (CSS value). | +| `supportedPushLocales` | Array<String> | yes | - | - | - | `["en","fr"]` | Supported locales for push notifications. | +| `columnPreference` | Object | yes | - | - | - | `{"_User":[...]}` | Column visibility/sorting/filtering preferences. | +| `classPreference` | Object | yes | - | - | - | `{"_Role":{...}}` | Persistent filters for all users. | +| `enableSecurityChecks` | Boolean | yes | `false` | - | - | `true` | Enable security checks under App Settings > Security. | +| `cloudConfigHistoryLimit` | Integer | yes | `100` | - | - | `200` | Number of historic Cloud Config values (0 to Number.MAX_SAFE_INTEGER). | +| `config` | Object | yes | - | - | - | `{...}` | Settings for storing dashboard config on server. | +| `config.className` | String | yes | - | - | - | `"DashboardConfig"` | Table name for dashboard configuration. | +| `scripts` | Array<Object> | yes | `[]` | - | - | `[{...}]` | Scripts for this app. See [scripts table below](#scripts-configuration). | +| `infoPanel` | Array<Object> | yes | - | - | - | `[{...}]` | Info panel config. See [info panel table below](#info-panel-configuration). | + +##### Scripts Configuration (`apps[].scripts[]`) + +| Parameter | Type | Optional | Default | Example | Description | +|-----------|------|----------|---------|---------|-------------| +| `title` | String | no | - | `"Delete User"` | Title in context menu and confirmation dialog. | +| `classes` | Array<String> \| Array<Object> | no | - | `["_User"]` | Classes for which script can run. | +| `cloudCodeFunction` | String | no | - | `"deleteUser"` | Parse Cloud Function name to execute. | +| `executionBatchSize` | Integer | yes | `1` | `10` | Batch size for multiple objects (runs in serial). | +| `showConfirmationDialog` | Boolean | yes | `false` | `true` | Show confirmation dialog before execution. | +| `confirmationDialogStyle` | String | yes | `info` | `critical` | Dialog style: `info` (blue) or `critical` (red). | + +##### Info Panel Configuration (`apps[].infoPanel[]`) + +| Parameter | Type | Optional | Default | Example | Description | +|-----------|------|----------|---------|---------|-------------| +| `title` | String | no | - | `"User Details"` | Panel title. | +| `classes` | Array<String> | no | - | `["_User"]` | Classes for which panel is displayed. | +| `cloudCodeFunction` | String | no | - | `"getUserDetails"` | Cloud Function receiving selected object. | +| `prefetchObjects` | Number | yes | `0` | `2` | Number of next rows to prefetch. | +| `prefetchStale` | Number | yes | `0` | `10` | Seconds after which prefetched data is stale. | + +##### Global Configuration + +| Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | +|-----------|------|----------|---------|-----|--------------|---------|-------------| +| `apps` | Array<Object> | no | - | - | `PARSE_DASHBOARD_CONFIG` | `[{...}]` | Array of apps to manage. | +| `users` | Array<Object> | yes | - | - | - | `[{...}]` | User accounts for authentication. See [users table below](#user-configuration). | +| `useEncryptedPasswords` | Boolean | yes | `false` | - | - | `true` | Use bcrypt hashes instead of plain text passwords. | +| `trustProxy` | Boolean \| Number | yes | `false` | `--trustProxy` | `PARSE_DASHBOARD_TRUST_PROXY` | `1` | Trust X-Forwarded-* headers when behind proxy. | +| `iconsFolder` | String | yes | - | - | - | `"icons"` | Folder for app icons (relative or absolute path). | +| `agent` | Object | yes | - | - | `PARSE_DASHBOARD_AGENT` (JSON) | `{...}` | AI agent config. See [agent table below](#ai-agent-configuration). | +| `enableResourceCache` | Boolean | yes | `false` | - | - | `true` | Enable browser caching of dashboard resources. | + +##### User Configuration (`users[]`) + +| Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | +|-----------|------|----------|---------|-----|--------------|---------|-------------| +| `user` | String | no | - | `--userId` | `PARSE_DASHBOARD_USER_ID` | `"admin"` | Username for authentication. | +| `pass` | String | no | - | `--userPassword` | `PARSE_DASHBOARD_USER_PASSWORD` | `"pass"` | Password (plain or bcrypt hash). | +| `mfa` | String | yes | - | - | - | `"JBSWY3DPEHPK3PXP"` | MFA secret for TOTP. | +| `mfaAlgorithm` | String | yes | `"SHA1"` | - | - | `"SHA256"` | TOTP algorithm for MFA. | +| `mfaDigits` | Number | yes | `6` | - | - | `8` | Number of digits in MFA code. | +| `mfaPeriod` | Number | yes | `30` | - | - | `60` | MFA code validity period in seconds. | +| `readOnly` | Boolean | yes | `false` | - | - | `true` | Read-only access to all their apps. | +| `apps` | Array<Object> | yes | - | - | - | `[{...}]` | Apps user can access (all if omitted). | +| `apps[].appId` | String | no | - | - | - | `"myAppId"` | App ID user can access. | +| `apps[].readOnly` | Boolean | yes | `false` | - | - | `true` | Read-only access to this specific app. | + +##### AI Agent Configuration (`agent`) + +| Parameter | Type | Optional | Example | Description | +|-----------|------|----------|---------|-------------| +| `models` | Array<Object> | no | `[{...}]` | Array of AI model configurations. | +| `models[].name` | String | no | `"ChatGPT 4.1"` | Display name for AI model. | +| `models[].provider` | String | no | `"openai"` | AI provider (currently only `"openai"`). | +| `models[].model` | String | no | `"gpt-4.1"` | Model name from provider. | +| `models[].apiKey` | String | no | `"sk-..."` | API key for authentication. | + +#### CLI & Server Options + +| Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | +|-----------|------|----------|---------|-----|--------------|---------|-------------| +| `host` | String | yes | `"0.0.0.0"` | `--host` | `HOST` | `"127.0.0.1"` | Host address to bind server. | +| `port` | Number | yes | `4040` | `--port` | `PORT` | `8080` | Port for dashboard server. | +| `mountPath` | String | yes | `"/"` | `--mountPath` | `MOUNT_PATH` | `"/dashboard"` | Mount path for application. | +| `allowInsecureHTTP` | Boolean | yes | `false` | `--allowInsecureHTTP` | `PARSE_DASHBOARD_ALLOW_INSECURE_HTTP` | `true` | Allow HTTP (use behind HTTPS proxy). | +| `sslKey` | String | yes | - | `--sslKey` | `PARSE_DASHBOARD_SSL_KEY` | `"/path/key"` | Path to SSL private key for HTTPS. | +| `sslCert` | String | yes | - | `--sslCert` | `PARSE_DASHBOARD_SSL_CERT` | `"/path/cert"` | Path to SSL certificate for HTTPS. | +| `cookieSessionSecret` | String | yes | Random | `--cookieSessionSecret` | `PARSE_DASHBOARD_COOKIE_SESSION_SECRET` | `"secret"` | Secret for session cookies (for multi-server). | +| `cookieSessionMaxAge` | Number | yes | Session-only | `--cookieSessionMaxAge` | `PARSE_DASHBOARD_COOKIE_SESSION_MAX_AGE` | `3600` | Session cookie expiration (seconds). | +| `dev` | Boolean | yes | `false` | `--dev` | - | - | Development mode (**DO NOT use in production**). | +| `config` | String | yes | - | `--config` | - | `"config.json"` | Path to JSON configuration file. | + +#### Helper CLI Commands + +| Command | Description | +|---------|-------------| +| `--createUser` | Interactive tool to generate secure user passwords and MFA secrets. | +| `--createMFA` | Interactive tool to generate MFA secrets for existing users. | ### File You can also start the dashboard from the command line with a config file. To do this, create a new file called `parse-dashboard-config.json` inside your local Parse Dashboard directory hierarchy. The file should match the following format: From e5dfcb3adda7ff5349a97dff28f39258fed03adc Mon Sep 17 00:00:00 2001 From: Lucas Coratger <73360179+coratgerl@users.noreply.github.com> Date: Tue, 30 Sep 2025 14:32:05 +0200 Subject: [PATCH 02/10] feat: more configuration --- README.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 07ae2971a..603e3895d 100644 --- a/README.md +++ b/README.md @@ -156,15 +156,22 @@ This section provides a comprehensive reference for all Parse Dashboard configur | `appName` | String | yes | `appId` | `--appName` | `PARSE_DASHBOARD_APP_NAME` | `"MyApp"` | Display name of the app. | | `masterKeyTtl` | Number | yes | - | `--masterKeyTtl` | - | `3600` | TTL for master key cache in seconds (when `masterKey` is a Function). | | `readOnlyMasterKey` | String | yes | - | - | - | `"myReadOnlyKey"` | Read-only master key that prevents mutations. | -| `graphQLServerURL` | String | yes | - | `--graphQLServerURL` | `PARSE_DASHBOARD_GRAPHQL_SERVER_URL` | `"http://localhost:1337/graphql"` | URL of GraphQL Server. | +| `clientKey` | String | yes | - | - | - | `"myClientKey"` | Client key for Parse SDK (legacy, mostly unused). | +| `javascriptKey` | String | yes | - | - | - | `"myJsKey"` | JavaScript key for Parse SDK (legacy, mostly unused). | +| `restKey` | String | yes | - | - | - | `"myRestKey"` | REST API key for server-side REST applications. | +| `windowsKey` | String | yes | - | - | - | `"myWindowsKey"` | Windows SDK key (legacy, mostly unused). | +| `webhookKey` | String | yes | - | - | - | `"myWebhookKey"` | Webhook key for Cloud Code Webhooks. | +| `apiKey` | String | yes | - | - | - | `"myFileKey"` | File key (also called apiKey) for file migrations. | +| `graphQLServerURL` | String | yes | - | `--graphQLServerURL` | `PARSE_DASHBOARD_GRAPHQL_SERVER_URL` | `"http://localhost:1337/graphql"` | The URL where your Parse GraphQL Server is running. | | `appNameForURL` | String | yes | `appName` | - | - | `"my-app"` | URL-friendly name used in dashboard URLs. | | `production` | Boolean | yes | `false` | - | - | `true` | Mark as production environment. | | `iconName` | String | yes | - | - | - | `"icon.png"` | Filename of app icon (requires global `iconsFolder`). | | `primaryBackgroundColor` | String | yes | - | - | - | `"#FFA500"` | Primary background color (CSS value). | | `secondaryBackgroundColor` | String | yes | - | - | - | `"#FF4500"` | Secondary background color (CSS value). | | `supportedPushLocales` | Array<String> | yes | - | - | - | `["en","fr"]` | Supported locales for push notifications. | -| `columnPreference` | Object | yes | - | - | - | `{"_User":[...]}` | Column visibility/sorting/filtering preferences. | -| `classPreference` | Object | yes | - | - | - | `{"_Role":{...}}` | Persistent filters for all users. | +| `preventSchemaEdits` | Boolean | yes | `false` | - | - | `true` | Prevent schema modifications through the dashboard. | +| `columnPreference` | Object | yes | - | - | - | `{"_User":[...]}` | Column visibility/sorting/filtering preferences. See [column preferences details](#prevent-columns-sorting). | +| `classPreference` | Object | yes | - | - | - | `{"_Role":{...}}` | Persistent filters for all users. See [persistent filters details](#persistent-filters). | | `enableSecurityChecks` | Boolean | yes | `false` | - | - | `true` | Enable security checks under App Settings > Security. | | `cloudConfigHistoryLimit` | Integer | yes | `100` | - | - | `200` | Number of historic Cloud Config values (0 to Number.MAX_SAFE_INTEGER). | | `config` | Object | yes | - | - | - | `{...}` | Settings for storing dashboard config on server. | @@ -172,6 +179,17 @@ This section provides a comprehensive reference for all Parse Dashboard configur | `scripts` | Array<Object> | yes | `[]` | - | - | `[{...}]` | Scripts for this app. See [scripts table below](#scripts-configuration). | | `infoPanel` | Array<Object> | yes | - | - | - | `[{...}]` | Info panel config. See [info panel table below](#info-panel-configuration). | +##### Column Preference Configuration (`apps[].columnPreference.[]`) + +Each class in `columnPreference` can have an array of column configurations: + +| Parameter | Type | Optional | Default | Example | Description | +|-----------|------|----------|---------|---------|-------------| +| `name` | String | no | - | `"createdAt"` | Column/field name. | +| `visible` | Boolean | yes | `true` | `false` | Whether the column is visible in the data browser. | +| `preventSort` | Boolean | yes | `false` | `true` | Prevent this column from being sortable. | +| `filterSortToTop` | Boolean | yes | `false` | `true` | Sort this column to the top in filter popup. | + ##### Scripts Configuration (`apps[].scripts[]`) | Parameter | Type | Optional | Default | Example | Description | From 142494341697ff2d74d73a3e4ec38d428a9f81aa Mon Sep 17 00:00:00 2001 From: Lucas Coratger <73360179+coratgerl@users.noreply.github.com> Date: Tue, 30 Sep 2025 14:36:02 +0200 Subject: [PATCH 03/10] fix: remove ai agent from config --- README.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/README.md b/README.md index 603e3895d..d6491ebf5 100644 --- a/README.md +++ b/README.md @@ -238,16 +238,6 @@ Each class in `columnPreference` can have an array of column configurations: | `apps[].appId` | String | no | - | - | - | `"myAppId"` | App ID user can access. | | `apps[].readOnly` | Boolean | yes | `false` | - | - | `true` | Read-only access to this specific app. | -##### AI Agent Configuration (`agent`) - -| Parameter | Type | Optional | Example | Description | -|-----------|------|----------|---------|-------------| -| `models` | Array<Object> | no | `[{...}]` | Array of AI model configurations. | -| `models[].name` | String | no | `"ChatGPT 4.1"` | Display name for AI model. | -| `models[].provider` | String | no | `"openai"` | AI provider (currently only `"openai"`). | -| `models[].model` | String | no | `"gpt-4.1"` | Model name from provider. | -| `models[].apiKey` | String | no | `"sk-..."` | API key for authentication. | - #### CLI & Server Options | Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | From 9ee3ac22042bf4ffe9a105c60e32208217318fd7 Mon Sep 17 00:00:00 2001 From: coratgerl <73360179+coratgerl@users.noreply.github.com> Date: Tue, 30 Sep 2025 18:21:23 +0200 Subject: [PATCH 04/10] fix: coderabit feedback --- README.md | 478 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 252 insertions(+), 226 deletions(-) diff --git a/README.md b/README.md index d6491ebf5..a77fad684 100644 --- a/README.md +++ b/README.md @@ -123,20 +123,22 @@ After starting the dashboard, you can visit http://localhost:4040 in your browse ## Compatibility ### Parse Server + Parse Dashboard is compatible with the following Parse Server versions. | Parse Dashboard Version | Parse Server Version | Compatible | -|-------------------------|----------------------|------------| -| >=1.0 | >= 2.1.4 | ✅ Yes | +| ----------------------- | -------------------- | ---------- | +| >=1.0 | >= 2.1.4 | ✅ Yes | ### Node.js + Parse Dashboard is continuously tested with the most recent releases of Node.js to ensure compatibility. We follow the [Node.js Long Term Support plan](https://github.com/nodejs/Release) and only test against versions that are officially supported and have not reached their end-of-life date. | Version | Latest Version | End-of-Life | Compatible | -|------------|----------------|-------------|------------| -| Node.js 18 | 18.20.4 | May 2025 | ✅ Yes | -| Node.js 20 | 20.18.0 | April 2026 | ✅ Yes | -| Node.js 22 | 22.9.0 | April 2027 | ✅ Yes | +| ---------- | -------------- | ----------- | ---------- | +| Node.js 18 | 18.20.4 | May 2025 | ✅ Yes | +| Node.js 20 | 20.18.0 | April 2026 | ✅ Yes | +| Node.js 22 | 22.9.0 | April 2027 | ✅ Yes | ## Configuring Parse Dashboard @@ -148,120 +150,121 @@ This section provides a comprehensive reference for all Parse Dashboard configur ##### App Configuration (`apps` array) -| Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | -|-----------|------|----------|---------|-----|--------------|---------|-------------| -| `appId` | String | no | - | `--appId` | `PARSE_DASHBOARD_APP_ID` | `"myAppId"` | The Application ID for your Parse Server instance. | -| `masterKey` | String \| Function | no | - | `--masterKey` | `PARSE_DASHBOARD_MASTER_KEY` | `"key"` | Master key for full access. Can be a String or Function returning a String. | -| `serverURL` | String | no | - | `--serverURL` | `PARSE_DASHBOARD_SERVER_URL` | `"http://localhost:1337/parse"` | The URL where your Parse Server is running. | -| `appName` | String | yes | `appId` | `--appName` | `PARSE_DASHBOARD_APP_NAME` | `"MyApp"` | Display name of the app. | -| `masterKeyTtl` | Number | yes | - | `--masterKeyTtl` | - | `3600` | TTL for master key cache in seconds (when `masterKey` is a Function). | -| `readOnlyMasterKey` | String | yes | - | - | - | `"myReadOnlyKey"` | Read-only master key that prevents mutations. | -| `clientKey` | String | yes | - | - | - | `"myClientKey"` | Client key for Parse SDK (legacy, mostly unused). | -| `javascriptKey` | String | yes | - | - | - | `"myJsKey"` | JavaScript key for Parse SDK (legacy, mostly unused). | -| `restKey` | String | yes | - | - | - | `"myRestKey"` | REST API key for server-side REST applications. | -| `windowsKey` | String | yes | - | - | - | `"myWindowsKey"` | Windows SDK key (legacy, mostly unused). | -| `webhookKey` | String | yes | - | - | - | `"myWebhookKey"` | Webhook key for Cloud Code Webhooks. | -| `apiKey` | String | yes | - | - | - | `"myFileKey"` | File key (also called apiKey) for file migrations. | -| `graphQLServerURL` | String | yes | - | `--graphQLServerURL` | `PARSE_DASHBOARD_GRAPHQL_SERVER_URL` | `"http://localhost:1337/graphql"` | The URL where your Parse GraphQL Server is running. | -| `appNameForURL` | String | yes | `appName` | - | - | `"my-app"` | URL-friendly name used in dashboard URLs. | -| `production` | Boolean | yes | `false` | - | - | `true` | Mark as production environment. | -| `iconName` | String | yes | - | - | - | `"icon.png"` | Filename of app icon (requires global `iconsFolder`). | -| `primaryBackgroundColor` | String | yes | - | - | - | `"#FFA500"` | Primary background color (CSS value). | -| `secondaryBackgroundColor` | String | yes | - | - | - | `"#FF4500"` | Secondary background color (CSS value). | -| `supportedPushLocales` | Array<String> | yes | - | - | - | `["en","fr"]` | Supported locales for push notifications. | -| `preventSchemaEdits` | Boolean | yes | `false` | - | - | `true` | Prevent schema modifications through the dashboard. | -| `columnPreference` | Object | yes | - | - | - | `{"_User":[...]}` | Column visibility/sorting/filtering preferences. See [column preferences details](#prevent-columns-sorting). | -| `classPreference` | Object | yes | - | - | - | `{"_Role":{...}}` | Persistent filters for all users. See [persistent filters details](#persistent-filters). | -| `enableSecurityChecks` | Boolean | yes | `false` | - | - | `true` | Enable security checks under App Settings > Security. | -| `cloudConfigHistoryLimit` | Integer | yes | `100` | - | - | `200` | Number of historic Cloud Config values (0 to Number.MAX_SAFE_INTEGER). | -| `config` | Object | yes | - | - | - | `{...}` | Settings for storing dashboard config on server. | -| `config.className` | String | yes | - | - | - | `"DashboardConfig"` | Table name for dashboard configuration. | -| `scripts` | Array<Object> | yes | `[]` | - | - | `[{...}]` | Scripts for this app. See [scripts table below](#scripts-configuration). | -| `infoPanel` | Array<Object> | yes | - | - | - | `[{...}]` | Info panel config. See [info panel table below](#info-panel-configuration). | +| Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | +| -------------------------- | ------------------- | -------- | --------- | -------------------- | ------------------------------------ | --------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| `appId` | String | no | - | `--appId` | `PARSE_DASHBOARD_APP_ID` | `"myAppId"` | The Application ID for your Parse Server instance. | +| `masterKey` | String \| Function | no | - | `--masterKey` | `PARSE_DASHBOARD_MASTER_KEY` | `"key"` | Master key for full access. Can be a String or Function returning a String. | +| `serverURL` | String | no | - | `--serverURL` | `PARSE_DASHBOARD_SERVER_URL` | `"http://localhost:1337/parse"` | The URL where your Parse Server is running. | +| `appName` | String | yes | `appId` | `--appName` | `PARSE_DASHBOARD_APP_NAME` | `"MyApp"` | Display name of the app. | +| `masterKeyTtl` | Number | yes | - | `--masterKeyTtl` | - | `3600` | TTL for master key cache in seconds (when `masterKey` is a Function). | +| `readOnlyMasterKey` | String | yes | - | - | - | `"myReadOnlyKey"` | Read-only master key that prevents mutations. | +| `clientKey` | String | yes | - | - | - | `"myClientKey"` | Client key for Parse SDK (legacy, mostly unused). | +| `javascriptKey` | String | yes | - | - | - | `"myJsKey"` | JavaScript key for Parse SDK (legacy, mostly unused). | +| `restKey` | String | yes | - | - | - | `"myRestKey"` | REST API key for server-side REST applications. | +| `windowsKey` | String | yes | - | - | - | `"myWindowsKey"` | Windows SDK key (legacy, mostly unused). | +| `webhookKey` | String | yes | - | - | - | `"myWebhookKey"` | Webhook key for Cloud Code Webhooks. | +| `apiKey` | String | yes | - | - | - | `"myFileKey"` | File key (also called apiKey) for file migrations. | +| `graphQLServerURL` | String | yes | - | `--graphQLServerURL` | `PARSE_DASHBOARD_GRAPHQL_SERVER_URL` | `"http://localhost:1337/graphql"` | The URL where your Parse GraphQL Server is running. | +| `appNameForURL` | String | yes | `appName` | - | - | `"my-app"` | URL-friendly name used in dashboard URLs. | +| `production` | Boolean | yes | `false` | - | - | `true` | Mark as production environment. | +| `iconName` | String | yes | - | - | - | `"icon.png"` | Filename of app icon (requires global `iconsFolder`). | +| `primaryBackgroundColor` | String | yes | - | - | - | `"#FFA500"` | Primary background color (CSS value). | +| `secondaryBackgroundColor` | String | yes | - | - | - | `"#FF4500"` | Secondary background color (CSS value). | +| `supportedPushLocales` | Array<String> | yes | - | - | - | `["en","fr"]` | Supported locales for push notifications. | +| `preventSchemaEdits` | Boolean | yes | `false` | - | - | `true` | Prevent schema modifications through the dashboard. | +| `columnPreference` | Object | yes | - | - | - | `{"_User":[...]}` | Column visibility/sorting/filtering preferences. See [column preferences details](#prevent-columns-sorting). | +| `classPreference` | Object | yes | - | - | - | `{"_Role":{...}}` | Persistent filters for all users. See [persistent filters details](#persistent-filters). | +| `enableSecurityChecks` | Boolean | yes | `false` | - | - | `true` | Enable security checks under App Settings > Security. | +| `cloudConfigHistoryLimit` | Integer | yes | `100` | - | - | `200` | Number of historic Cloud Config values (0 to Number.MAX_SAFE_INTEGER). | +| `config` | Object | yes | - | - | - | `{...}` | Settings for storing dashboard config on server. | +| `config.className` | String | yes | - | - | - | `"DashboardConfig"` | Table name for dashboard configuration. | +| `scripts` | Array<Object> | yes | `[]` | - | - | `[{...}]` | Scripts for this app. See [scripts table below](#scripts). | +| `infoPanel` | Array<Object> | yes | - | - | - | `[{...}]` | Info panel config. See [info panel table below](#info-panel). | ##### Column Preference Configuration (`apps[].columnPreference.[]`) Each class in `columnPreference` can have an array of column configurations: -| Parameter | Type | Optional | Default | Example | Description | -|-----------|------|----------|---------|---------|-------------| -| `name` | String | no | - | `"createdAt"` | Column/field name. | -| `visible` | Boolean | yes | `true` | `false` | Whether the column is visible in the data browser. | -| `preventSort` | Boolean | yes | `false` | `true` | Prevent this column from being sortable. | -| `filterSortToTop` | Boolean | yes | `false` | `true` | Sort this column to the top in filter popup. | +| Parameter | Type | Optional | Default | Example | Description | +| ----------------- | ------- | -------- | ------- | ------------- | -------------------------------------------------- | +| `name` | String | no | - | `"createdAt"` | Column/field name. | +| `visible` | Boolean | yes | `true` | `false` | Whether the column is visible in the data browser. | +| `preventSort` | Boolean | yes | `false` | `true` | Prevent this column from being sortable. | +| `filterSortToTop` | Boolean | yes | `false` | `true` | Sort this column to the top in filter popup. | ##### Scripts Configuration (`apps[].scripts[]`) -| Parameter | Type | Optional | Default | Example | Description | -|-----------|------|----------|---------|---------|-------------| -| `title` | String | no | - | `"Delete User"` | Title in context menu and confirmation dialog. | -| `classes` | Array<String> \| Array<Object> | no | - | `["_User"]` | Classes for which script can run. | -| `cloudCodeFunction` | String | no | - | `"deleteUser"` | Parse Cloud Function name to execute. | -| `executionBatchSize` | Integer | yes | `1` | `10` | Batch size for multiple objects (runs in serial). | -| `showConfirmationDialog` | Boolean | yes | `false` | `true` | Show confirmation dialog before execution. | -| `confirmationDialogStyle` | String | yes | `info` | `critical` | Dialog style: `info` (blue) or `critical` (red). | +| Parameter | Type | Optional | Default | Example | Description | +| ------------------------- | ------------------------------------------ | -------- | ------- | --------------- | ------------------------------------------------- | +| `title` | String | no | - | `"Delete User"` | Title in context menu and confirmation dialog. | +| `classes` | Array<String> \| Array<Object> | no | - | `["_User"]` | Classes for which script can run. | +| `cloudCodeFunction` | String | no | - | `"deleteUser"` | Parse Cloud Function name to execute. | +| `executionBatchSize` | Integer | yes | `1` | `10` | Batch size for multiple objects (runs in serial). | +| `showConfirmationDialog` | Boolean | yes | `false` | `true` | Show confirmation dialog before execution. | +| `confirmationDialogStyle` | String | yes | `info` | `critical` | Dialog style: `info` (blue) or `critical` (red). | ##### Info Panel Configuration (`apps[].infoPanel[]`) -| Parameter | Type | Optional | Default | Example | Description | -|-----------|------|----------|---------|---------|-------------| -| `title` | String | no | - | `"User Details"` | Panel title. | -| `classes` | Array<String> | no | - | `["_User"]` | Classes for which panel is displayed. | -| `cloudCodeFunction` | String | no | - | `"getUserDetails"` | Cloud Function receiving selected object. | -| `prefetchObjects` | Number | yes | `0` | `2` | Number of next rows to prefetch. | -| `prefetchStale` | Number | yes | `0` | `10` | Seconds after which prefetched data is stale. | +| Parameter | Type | Optional | Default | Example | Description | +| ------------------- | ------------------- | -------- | ------- | ------------------ | --------------------------------------------- | +| `title` | String | no | - | `"User Details"` | Panel title. | +| `classes` | Array<String> | no | - | `["_User"]` | Classes for which panel is displayed. | +| `cloudCodeFunction` | String | no | - | `"getUserDetails"` | Cloud Function receiving selected object. | +| `prefetchObjects` | Number | yes | `0` | `2` | Number of next rows to prefetch. | +| `prefetchStale` | Number | yes | `0` | `10` | Seconds after which prefetched data is stale. | ##### Global Configuration -| Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | -|-----------|------|----------|---------|-----|--------------|---------|-------------| -| `apps` | Array<Object> | no | - | - | `PARSE_DASHBOARD_CONFIG` | `[{...}]` | Array of apps to manage. | -| `users` | Array<Object> | yes | - | - | - | `[{...}]` | User accounts for authentication. See [users table below](#user-configuration). | -| `useEncryptedPasswords` | Boolean | yes | `false` | - | - | `true` | Use bcrypt hashes instead of plain text passwords. | -| `trustProxy` | Boolean \| Number | yes | `false` | `--trustProxy` | `PARSE_DASHBOARD_TRUST_PROXY` | `1` | Trust X-Forwarded-* headers when behind proxy. | -| `iconsFolder` | String | yes | - | - | - | `"icons"` | Folder for app icons (relative or absolute path). | -| `agent` | Object | yes | - | - | `PARSE_DASHBOARD_AGENT` (JSON) | `{...}` | AI agent config. See [agent table below](#ai-agent-configuration). | -| `enableResourceCache` | Boolean | yes | `false` | - | - | `true` | Enable browser caching of dashboard resources. | +| Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | +| ----------------------- | ------------------- | -------- | ------- | -------------- | ------------------------------ | --------- | ------------------------------------------------------------------------------------- | +| `apps` | Array<Object> | no | - | - | `PARSE_DASHBOARD_CONFIG` | `[{...}]` | Array of apps to manage. | +| `users` | Array<Object> | yes | - | - | - | `[{...}]` | User accounts for authentication. See [users table below](#user-configuration-users). | +| `useEncryptedPasswords` | Boolean | yes | `false` | - | - | `true` | Use bcrypt hashes instead of plain text passwords. | +| `trustProxy` | Boolean \| Number | yes | `false` | `--trustProxy` | `PARSE_DASHBOARD_TRUST_PROXY` | `1` | Trust X-Forwarded-\* headers when behind proxy. | +| `iconsFolder` | String | yes | - | - | - | `"icons"` | Folder for app icons (relative or absolute path). | +| `agent` | Object | yes | - | - | `PARSE_DASHBOARD_AGENT` (JSON) | `{...}` | AI agent config. See [agent table below](#configuration). | +| `enableResourceCache` | Boolean | yes | `false` | - | - | `true` | Enable browser caching of dashboard resources. | ##### User Configuration (`users[]`) -| Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | -|-----------|------|----------|---------|-----|--------------|---------|-------------| -| `user` | String | no | - | `--userId` | `PARSE_DASHBOARD_USER_ID` | `"admin"` | Username for authentication. | -| `pass` | String | no | - | `--userPassword` | `PARSE_DASHBOARD_USER_PASSWORD` | `"pass"` | Password (plain or bcrypt hash). | -| `mfa` | String | yes | - | - | - | `"JBSWY3DPEHPK3PXP"` | MFA secret for TOTP. | -| `mfaAlgorithm` | String | yes | `"SHA1"` | - | - | `"SHA256"` | TOTP algorithm for MFA. | -| `mfaDigits` | Number | yes | `6` | - | - | `8` | Number of digits in MFA code. | -| `mfaPeriod` | Number | yes | `30` | - | - | `60` | MFA code validity period in seconds. | -| `readOnly` | Boolean | yes | `false` | - | - | `true` | Read-only access to all their apps. | -| `apps` | Array<Object> | yes | - | - | - | `[{...}]` | Apps user can access (all if omitted). | -| `apps[].appId` | String | no | - | - | - | `"myAppId"` | App ID user can access. | -| `apps[].readOnly` | Boolean | yes | `false` | - | - | `true` | Read-only access to this specific app. | +| Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | +| ----------------- | ------------------- | -------- | -------- | ---------------- | ------------------------------- | -------------------- | -------------------------------------- | +| `user` | String | no | - | `--userId` | `PARSE_DASHBOARD_USER_ID` | `"admin"` | Username for authentication. | +| `pass` | String | no | - | `--userPassword` | `PARSE_DASHBOARD_USER_PASSWORD` | `"pass"` | Password (plain or bcrypt hash). | +| `mfa` | String | yes | - | - | - | `"JBSWY3DPEHPK3PXP"` | MFA secret for TOTP. | +| `mfaAlgorithm` | String | yes | `"SHA1"` | - | - | `"SHA256"` | TOTP algorithm for MFA. | +| `mfaDigits` | Number | yes | `6` | - | - | `8` | Number of digits in MFA code. | +| `mfaPeriod` | Number | yes | `30` | - | - | `60` | MFA code validity period in seconds. | +| `readOnly` | Boolean | yes | `false` | - | - | `true` | Read-only access to all their apps. | +| `apps` | Array<Object> | yes | - | - | - | `[{...}]` | Apps user can access (all if omitted). | +| `apps[].appId` | String | no | - | - | - | `"myAppId"` | App ID user can access. | +| `apps[].readOnly` | Boolean | yes | `false` | - | - | `true` | Read-only access to this specific app. | #### CLI & Server Options -| Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | -|-----------|------|----------|---------|-----|--------------|---------|-------------| -| `host` | String | yes | `"0.0.0.0"` | `--host` | `HOST` | `"127.0.0.1"` | Host address to bind server. | -| `port` | Number | yes | `4040` | `--port` | `PORT` | `8080` | Port for dashboard server. | -| `mountPath` | String | yes | `"/"` | `--mountPath` | `MOUNT_PATH` | `"/dashboard"` | Mount path for application. | -| `allowInsecureHTTP` | Boolean | yes | `false` | `--allowInsecureHTTP` | `PARSE_DASHBOARD_ALLOW_INSECURE_HTTP` | `true` | Allow HTTP (use behind HTTPS proxy). | -| `sslKey` | String | yes | - | `--sslKey` | `PARSE_DASHBOARD_SSL_KEY` | `"/path/key"` | Path to SSL private key for HTTPS. | -| `sslCert` | String | yes | - | `--sslCert` | `PARSE_DASHBOARD_SSL_CERT` | `"/path/cert"` | Path to SSL certificate for HTTPS. | -| `cookieSessionSecret` | String | yes | Random | `--cookieSessionSecret` | `PARSE_DASHBOARD_COOKIE_SESSION_SECRET` | `"secret"` | Secret for session cookies (for multi-server). | -| `cookieSessionMaxAge` | Number | yes | Session-only | `--cookieSessionMaxAge` | `PARSE_DASHBOARD_COOKIE_SESSION_MAX_AGE` | `3600` | Session cookie expiration (seconds). | -| `dev` | Boolean | yes | `false` | `--dev` | - | - | Development mode (**DO NOT use in production**). | -| `config` | String | yes | - | `--config` | - | `"config.json"` | Path to JSON configuration file. | +| Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | +| --------------------- | ------- | -------- | ------------ | ----------------------- | ---------------------------------------- | --------------- | ------------------------------------------------ | +| `host` | String | yes | `"0.0.0.0"` | `--host` | `HOST` | `"127.0.0.1"` | Host address to bind server. | +| `port` | Number | yes | `4040` | `--port` | `PORT` | `8080` | Port for dashboard server. | +| `mountPath` | String | yes | `"/"` | `--mountPath` | `MOUNT_PATH` | `"/dashboard"` | Mount path for application. | +| `allowInsecureHTTP` | Boolean | yes | `false` | `--allowInsecureHTTP` | `PARSE_DASHBOARD_ALLOW_INSECURE_HTTP` | `true` | Allow HTTP (use behind HTTPS proxy). | +| `sslKey` | String | yes | - | `--sslKey` | `PARSE_DASHBOARD_SSL_KEY` | `"/path/key"` | Path to SSL private key for HTTPS. | +| `sslCert` | String | yes | - | `--sslCert` | `PARSE_DASHBOARD_SSL_CERT` | `"/path/cert"` | Path to SSL certificate for HTTPS. | +| `cookieSessionSecret` | String | yes | Random | `--cookieSessionSecret` | `PARSE_DASHBOARD_COOKIE_SESSION_SECRET` | `"secret"` | Secret for session cookies (for multi-server). | +| `cookieSessionMaxAge` | Number | yes | Session-only | `--cookieSessionMaxAge` | `PARSE_DASHBOARD_COOKIE_SESSION_MAX_AGE` | `3600` | Session cookie expiration (seconds). | +| `dev` | Boolean | yes | `false` | `--dev` | - | - | Development mode (**DO NOT use in production**). | +| `config` | String | yes | - | `--config` | - | `"config.json"` | Path to JSON configuration file. | #### Helper CLI Commands -| Command | Description | -|---------|-------------| +| Command | Description | +| -------------- | ------------------------------------------------------------------- | | `--createUser` | Interactive tool to generate secure user passwords and MFA secrets. | -| `--createMFA` | Interactive tool to generate MFA secrets for existing users. | +| `--createMFA` | Interactive tool to generate MFA secrets for existing users. | + ### File -You can also start the dashboard from the command line with a config file. To do this, create a new file called `parse-dashboard-config.json` inside your local Parse Dashboard directory hierarchy. The file should match the following format: +You can also start the dashboard from the command line with a config file. To do this, create a new file called `parse-dashboard-config.json` inside your local Parse Dashboard directory hierarchy. The file should match the following format: ```json { @@ -386,7 +389,7 @@ After starting the dashboard, you can visit http://0.0.0.0:4040/apps/MyTestApp/a ## App Icon Configuration -Parse Dashboard supports adding an optional icon for each app, so you can identify them easier in the list. To do so, you *must* use the configuration file, define an `iconsFolder` in it, and define the `iconName` parameter for each app (including the extension). The path of the `iconsFolder` is relative to the configuration file. If you have installed ParseDashboard globally you need to use the full path as value for the `iconsFolder`. To visualize what it means, in the following example `icons` is a directory located under the same directory as the configuration file: +Parse Dashboard supports adding an optional icon for each app, so you can identify them easier in the list. To do so, you _must_ use the configuration file, define an `iconsFolder` in it, and define the `iconName` parameter for each app (including the extension). The path of the `iconsFolder` is relative to the configuration file. If you have installed ParseDashboard globally you need to use the full path as value for the `iconsFolder`. To visualize what it means, in the following example `icons` is a directory located under the same directory as the configuration file: ```json { @@ -396,7 +399,7 @@ Parse Dashboard supports adding an optional icon for each app, so you can identi "appId": "myAppId", "masterKey": "myMasterKey", "appName": "My Parse Server App", - "iconName": "MyAppIcon.png", + "iconName": "MyAppIcon.png" } ], "iconsFolder": "icons" @@ -405,7 +408,7 @@ Parse Dashboard supports adding an optional icon for each app, so you can identi ## App Background Color Configuration -Parse Dashboard supports adding an optional background color for each app, so you can identify them easier in the list. To do so, you *must* use the configuration file, define an `primaryBackgroundColor` and `secondaryBackgroundColor` in it, parameter for each app. It is `CSS style`. To visualize what it means, in the following example `backgroundColor` is a configuration file: +Parse Dashboard supports adding an optional background color for each app, so you can identify them easier in the list. To do so, you _must_ use the configuration file, define an `primaryBackgroundColor` and `secondaryBackgroundColor` in it, parameter for each app. It is `CSS style`. To visualize what it means, in the following example `backgroundColor` is a configuration file: ```json { @@ -436,7 +439,7 @@ You can set `appNameForURL` in the config file for each app to control the url o To change the app to production, simply set `production` to `true` in your config file. The default value is false if not specified. - ### Prevent columns sorting +### Prevent columns sorting You can prevent some columns to be sortable by adding `preventSort` to columnPreference options in each app configuration @@ -510,7 +513,7 @@ For example: }] ``` -You can conveniently create a filter definition without having to write it by hand by first saving a filter in the data browser, then exporting the filter definition under *App Settings > Export Class Preferences*. +You can conveniently create a filter definition without having to write it by hand by first saving a filter in the data browser, then exporting the filter definition under _App Settings > Export Class Preferences_. ### Scripts @@ -559,26 +562,37 @@ You can also specify custom fields with the `scrips` option: Next, define the Cloud Function in Parse Server that will be called. The object that has been selected in the data browser will be made available as a request parameter: ```js -Parse.Cloud.define('deleteAccount', async (req) => { - req.params.object.set('deleted', true); - await req.params.object.save(null, {useMasterKey: true}); -}, { - requireMaster: true -}); +Parse.Cloud.define( + 'deleteAccount', + async req => { + req.params.object.set('deleted', true); + await req.params.object.save(null, { useMasterKey: true }); + }, + { + requireMaster: true, + } +); ``` The field which the script was invoked on can be accessed by `selectedField`: ```js -Parse.Cloud.define('deleteAccount', async (req) => { - if (req.params.selectedField !== 'objectId') { - throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Deleting accounts is only available on the objectId field.'); +Parse.Cloud.define( + 'deleteAccount', + async req => { + if (req.params.selectedField !== 'objectId') { + throw new Parse.Error( + Parse.Error.SCRIPT_FAILED, + 'Deleting accounts is only available on the objectId field.' + ); + } + req.params.object.set('deleted', true); + await req.params.object.save(null, { useMasterKey: true }); + }, + { + requireMaster: true, } - req.params.object.set('deleted', true); - await req.params.object.save(null, {useMasterKey: true}); -}, { - requireMaster: true -}); +); ``` ⚠️ Depending on your Parse Server version you may need to set the Parse Server option `encodeParseObjectInCloudFunction` to `true` so that the selected object in the data browser is made available in the Cloud Function as an instance of `Parse.Object`. If the option is not set, is set to `false`, or you are using an older version of Parse Server, the object is made available as a plain JavaScript object and needs to be converted from a JSON object to a `Parse.Object` instance with `req.params.object = Parse.Object.fromJSON(req.params.object);`, before you can call any `Parse.Object` properties and methods on it. @@ -589,13 +603,17 @@ For older versions of Parse Server: Parse Server >=4.4.0 <6.2.0 ```js -Parse.Cloud.define('deleteAccount', async (req) => { - req.params.object = Parse.Object.fromJSON(req.params.object); - req.params.object.set('deleted', true); - await req.params.object.save(null, {useMasterKey: true}); -}, { - requireMaster: true -}); +Parse.Cloud.define( + 'deleteAccount', + async req => { + req.params.object = Parse.Object.fromJSON(req.params.object); + req.params.object.set('deleted', true); + await req.params.object.save(null, { useMasterKey: true }); + }, + { + requireMaster: true, + } +); ``` @@ -604,13 +622,13 @@ Parse.Cloud.define('deleteAccount', async (req) => { Parse Server >=2.1.4 <4.4.0 ```js -Parse.Cloud.define('deleteAccount', async (req) => { +Parse.Cloud.define('deleteAccount', async req => { if (!req.master || !req.params.object) { throw 'Unauthorized'; } req.params.object = Parse.Object.fromJSON(req.params.object); req.params.object.set('deleted', true); - await req.params.object.save(null, {useMasterKey: true}); + await req.params.object.save(null, { useMasterKey: true }); }); ``` @@ -621,10 +639,9 @@ Parse.Cloud.define('deleteAccount', async (req) => { Parse Dashboard can cache its resources such as bundles in the browser, so that opening the dashboard in another tab does not reload the dashboard resources from the server but from the local browser cache. Caching only starts after login in the dashboard. | Parameter | Type | Optional | Default | Example | Description | -|-----------------------|---------|----------|---------|---------|----------------------------------------------------------------------------------------------------------------| +| --------------------- | ------- | -------- | ------- | ------- | -------------------------------------------------------------------------------------------------------------- | | `enableResourceCache` | Boolean | yes | `false` | `true` | Enables caching of dashboard resources in the browser for faster dashboard loading in additional browser tabs. | - Example configuration: ```javascript @@ -635,9 +652,9 @@ const dashboard = new ParseDashboard({ serverURL: 'http://localhost:1337/parse', appId: 'myAppId', masterKey: 'myMasterKey', - appName: 'MyApp' - } - ] + appName: 'MyApp', + }, + ], }); ``` @@ -645,7 +662,7 @@ const dashboard = new ParseDashboard({ > This feature can make it more difficult to push dashboard updates to users. Enabling the resource cache will start a browser service worker that caches dashboard resources locally only once. As long as the service worker is running, it will prevent loading any dashboard updates from the server, even if the user reloads the browser tab. The service worker is automatically stopped, once the last dashboard browser tab is closed. On the opening of the first dashboard browser tab, a new service worker is started and the dashboard resources are loaded from the server. > [!Note] -> For developers: during dashboard development, the resource cache should be disabled to ensure reloading the dashboard tab in the browser loads the new dashboard bundle with any changes you made in the source code. You can inspect the service worker in the developer tools of most browsers. For example in Google Chrome, go to *Developer Tools > Application tab > Service workers* to see whether the dashboard service worker is currently running and to debug it. +> For developers: during dashboard development, the resource cache should be disabled to ensure reloading the dashboard tab in the browser loads the new dashboard bundle with any changes you made in the source code. You can inspect the service worker in the developer tools of most browsers. For example in Google Chrome, go to _Developer Tools > Application tab > Service workers_ to see whether the dashboard service worker is currently running and to debug it. # Running as Express Middleware @@ -656,14 +673,14 @@ var express = require('express'); var ParseDashboard = require('parse-dashboard'); var dashboard = new ParseDashboard({ - "apps": [ + apps: [ { - "serverURL": "http://localhost:1337/parse", - "appId": "myAppId", - "masterKey": "myMasterKey", - "appName": "MyApp" - } - ] + serverURL: 'http://localhost:1337/parse', + appId: 'myAppId', + masterKey: 'myMasterKey', + appName: 'MyApp', + }, + ], }); var app = express(); @@ -683,14 +700,17 @@ var ParseServer = require('parse-server').ParseServer; var ParseDashboard = require('parse-dashboard'); var api = new ParseServer({ - // Parse Server settings + // Parse Server settings }); var options = { allowInsecureHTTP: false }; -var dashboard = new ParseDashboard({ - // Parse Dashboard settings -}, options); +var dashboard = new ParseDashboard( + { + // Parse Dashboard settings + }, + options +); var app = express(); @@ -711,22 +731,23 @@ httpServer.listen(4040); Make sure the server URLs for your apps can be accessed by your browser. If you are deploying the dashboard, then `localhost` urls will not work. ## Security Considerations + In order to securely deploy the dashboard without leaking your apps master key, you will need to use HTTPS and Basic Authentication. -The deployed dashboard detects if you are using a secure connection. If you are deploying the dashboard behind a load balancer or front-facing proxy, then the app won't be able to detect that the connection is secure. In this case, you can start the dashboard with the `--trustProxy=1` option (or set the PARSE_DASHBOARD_TRUST_PROXY config var to 1) to rely on the X-Forwarded-* headers for the client's connection security. This is useful for hosting on services like Heroku, where you can trust the provided proxy headers to correctly determine whether you're using HTTP or HTTPS. You can also turn on this setting when using the dashboard as [express](https://github.com/expressjs/express) middleware: +The deployed dashboard detects if you are using a secure connection. If you are deploying the dashboard behind a load balancer or front-facing proxy, then the app won't be able to detect that the connection is secure. In this case, you can start the dashboard with the `--trustProxy=1` option (or set the PARSE_DASHBOARD_TRUST_PROXY config var to 1) to rely on the X-Forwarded-\* headers for the client's connection security. This is useful for hosting on services like Heroku, where you can trust the provided proxy headers to correctly determine whether you're using HTTP or HTTPS. You can also turn on this setting when using the dashboard as [express](https://github.com/expressjs/express) middleware: ```javascript var trustProxy = true; var dashboard = new ParseDashboard({ - "apps": [ + apps: [ { - "serverURL": "http://localhost:1337/parse", - "appId": "myAppId", - "masterKey": "myMasterKey", - "appName": "MyApp" - } + serverURL: 'http://localhost:1337/parse', + appId: 'myAppId', + masterKey: 'myMasterKey', + appName: 'MyApp', + }, ], - "trustProxy": 1 + trustProxy: 1, }); ``` @@ -749,6 +770,7 @@ const dashboard = new ParseDashboard({ ``` ### Configuring Basic Authentication + You can configure your dashboard for Basic Authentication by adding usernames and passwords your `parse-dashboard-config.json` configuration file: ```json @@ -779,49 +801,52 @@ With MFA enabled, a user must provide a one-time password that is typically boun The user requires an authenticator app to generate the one-time password. These apps are provided by many 3rd parties and mostly for free. -If you create a new user by running `parse-dashboard --createUser`, you will be asked whether you want to enable MFA for the new user. To enable MFA for an existing user, run `parse-dashboard --createMFA` to generate a `mfa` secret that you then add to the existing user configuration, for example: +If you create a new user by running `parse-dashboard --createUser`, you will be asked whether you want to enable MFA for the new user. To enable MFA for an existing user, run `parse-dashboard --createMFA` to generate a `mfa` secret that you then add to the existing user configuration, for example: ```json { - "apps": [{"...": "..."}], + "apps": [{ "...": "..." }], "users": [ { - "user":"user1", - "pass":"pass", + "user": "user1", + "pass": "pass", "mfa": "lmvmOIZGMTQklhOIhveqkumss" } ] } ``` - Parse Dashboard follows the industry standard and supports the common OTP algorithm `SHA-1` by default, to be compatible with most authenticator apps. If you have specific security requirements regarding TOTP characteristics (algorithm, digit length, time period) you can customize them by using the guided configuration mentioned above. +Parse Dashboard follows the industry standard and supports the common OTP algorithm `SHA-1` by default, to be compatible with most authenticator apps. If you have specific security requirements regarding TOTP characteristics (algorithm, digit length, time period) you can customize them by using the guided configuration mentioned above. ### Separating App Access Based on User Identity + If you have configured your dashboard to manage multiple applications, you can restrict the management of apps based on user identity. To do so, update your `parse-dashboard-config.json` configuration file to match the following format: ```json { - "apps": [{"...": "..."}], + "apps": [{ "...": "..." }], "users": [ - { - "user":"user1", - "pass":"pass1", - "apps": [{"appId": "myAppId1"}, {"appId": "myAppId2"}] - }, - { - "user":"user2", - "pass":"pass2", - "apps": [{"appId": "myAppId1"}] - } ] + { + "user": "user1", + "pass": "pass1", + "apps": [{ "appId": "myAppId1" }, { "appId": "myAppId2" }] + }, + { + "user": "user2", + "pass": "pass2", + "apps": [{ "appId": "myAppId1" }] + } + ] } ``` + The effect of such a configuration is as follows: When `user1` logs in, he/she will be able to manage `myAppId1` and `myAppId2` from the dashboard. -When *`user2`* logs in, he/she will only be able to manage *`myAppId1`* from the dashboard. +When _`user2`_ logs in, he/she will only be able to manage _`myAppId1`_ from the dashboard. ## Use Read-Only masterKey @@ -834,8 +859,8 @@ Start your `parse-server` with ```json { -"masterKey": "YOUR_MASTER_KEY_HERE", -"readOnlyMasterKey": "YOUR_READ_ONLY_MASTER_KEY", + "masterKey": "YOUR_MASTER_KEY_HERE", + "readOnlyMasterKey": "YOUR_READ_ONLY_MASTER_KEY" } ``` @@ -844,15 +869,15 @@ Then in your dashboard configuration: ```javascript var trustProxy = true; var dashboard = new ParseDashboard({ - "apps": [ + apps: [ { - "serverURL": "http://localhost:1337/parse", - "appId": "myAppId", - "masterKey": "YOUR_READ_ONLY_MASTER_KEY", - "appName": "MyApp" - } + serverURL: 'http://localhost:1337/parse', + appId: 'myAppId', + masterKey: 'YOUR_READ_ONLY_MASTER_KEY', + appName: 'MyApp', + }, ], - "trustProxy": 1 + trustProxy: 1, }); ``` @@ -883,15 +908,15 @@ You can mark a user as a read-only user: ], "users": [ { - "user":"user1", - "pass":"pass1", + "user": "user1", + "pass": "pass1", "readOnly": true, - "apps": [{"appId": "myAppId1"}, {"appId": "myAppId2"}] + "apps": [{ "appId": "myAppId1" }, { "appId": "myAppId2" }] }, { - "user":"user2", - "pass":"pass2", - "apps": [{"appId": "myAppId1"}] + "user": "user2", + "pass": "pass2", + "apps": [{ "appId": "myAppId1" }] } ] } @@ -915,13 +940,13 @@ You can give read only access to a user on a per-app basis: "port": 4040, "production": true }, - {"...": "..."} + { "...": "..." } ], "users": [ { - "user":"user", - "pass":"pass", - "apps": [{"appId": "myAppId", "readOnly": true}, {"appId": "myAppId2"}] + "user": "user", + "pass": "pass", + "apps": [{ "appId": "myAppId", "readOnly": true }, { "appId": "myAppId2" }] } ] } @@ -954,7 +979,7 @@ You can provide a list of locales or languages you want to support for your dash The official docker image is published on [docker hub](https://hub.docker.com/r/parseplatform/parse-dashboard) -Run the image with your ``config.json`` mounted as a volume +Run the image with your `config.json` mounted as a volume ``` docker run -d -p 8080:4040 -v host/path/to/config.json:/src/Parse-Dashboard/parse-dashboard-config.json parseplatform/parse-dashboard --dev @@ -966,7 +991,7 @@ You can also pass the appId, masterKey and serverURL as arguments: docker run -d -p 4040:4040 parseplatform/parse-dashboard --dev --appId $APP_ID --masterKey $MASTER_KEY --serverURL $SERVER_URL ``` -By default, the container will start the app at port 4040 inside the container. However, you can run custom command as well (see ``Deploying in production`` for custom setup). +By default, the container will start the app at port 4040 inside the container. However, you can run custom command as well (see `Deploying in production` for custom setup). In this example, we want to run the application in production mode at port 80 of the host machine. @@ -974,16 +999,17 @@ In this example, we want to run the application in production mode at port 80 of docker run -d -p 80:8080 -v host/path/to/config.json:/src/Parse-Dashboard/parse-dashboard-config.json parse-dashboard --port 8080 --dev ``` -If you are not familiar with Docker, ``--port 8080`` will be passed in as argument to the entrypoint to form the full command ``npm start -- --port 8080``. The application will start at port 8080 inside the container and port ``8080`` will be mounted to port ``80`` on your host machine. +If you are not familiar with Docker, `--port 8080` will be passed in as argument to the entrypoint to form the full command `npm start -- --port 8080`. The application will start at port 8080 inside the container and port `8080` will be mounted to port `80` on your host machine. # Features -*(The following is not a complete list of features but a work in progress to build a comprehensive feature list.)* + +_(The following is not a complete list of features but a work in progress to build a comprehensive feature list.)_ ## Data Browser ### Filters -▶️ *Core > Browser > Filter* +▶️ _Core > Browser > Filter_ The filter dialog allows to add relational filter conditions based on other classes that have a pointer to the current class. @@ -1001,9 +1027,9 @@ To apply such a filter, simply go to the `_User` class and add the two required ### Info Panel -▶️ *Core > Browser > Show Panel / Hide Panel* +▶️ _Core > Browser > Show Panel / Hide Panel_ -The data browser offers an info panel that can display information related to the currently selected object in the data browser table. The info panel is made visible by clicking on the menu button *Show Panel* in the top right corner when browsing a class for which the info panel is configured in the dashboard options. +The data browser offers an info panel that can display information related to the currently selected object in the data browser table. The info panel is made visible by clicking on the menu button _Show Panel_ in the top right corner when browsing a class for which the info panel is configured in the dashboard options. The following example dashboard configuration shows an info panel for the `_User` class with the title `User Details`, by calling the Cloud Code Function `getUserDetails` and displaying the returned response. @@ -1032,7 +1058,7 @@ The Cloud Code Function receives the selected object in the payload and returns The info panel can contain multiple segments to display different groups of information. | Parameter | Value | Optional | Description | -|--------------------------|--------|----------|----------------------------------------------------------------------------------------------------------------------------------------| +| ------------------------ | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `segments` | Array | No | An ordered array of segments, where each segment represents a distinct group of items to display. | | `segments[i].title` | String | No | The title of the segment that will be displayed. | | `segments[i].items` | Array | No | An ordered array of items within the segment. Each item can be of different types, such as text, key-value pairs, tables, images, etc. | @@ -1068,7 +1094,7 @@ The items array can include various types of content such as text, key-value pai A simple text field. | Parameter | Value | Optional | Description | -|-----------|--------|----------|---------------------------| +| --------- | ------ | -------- | ------------------------- | | `type` | String | No | Must be `"text"`. | | `text` | String | No | The text to display. | | `style` | Object | Yes | The CSS style definition. | @@ -1079,7 +1105,7 @@ Example: { "type": "text", "text": "This user has a high churn risk!", - "style": { "backgroundColor": "red" }, + "style": { "backgroundColor": "red" } } ``` @@ -1088,7 +1114,7 @@ Example: A text item that consists of a key and a value. The value can optionally be linked to a URL. | Parameter | Value | Default | Optional | Description | -|-----------------|---------|-------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| --------------- | ------- | ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `type` | String | - | No | Must be `"keyValue"`. | | `key` | String | - | No | The key text to display. | | `value` | String | - | No | The value text to display. | @@ -1104,7 +1130,7 @@ Examples: "type": "keyValue", "key": "Lifetime purchase value", "value": "$10k", - "style": { "backgroundColor": "green" }, + "style": { "backgroundColor": "green" } } ``` @@ -1150,8 +1176,8 @@ const item = { key: 'Purchase', value: objectId, url, - isRelativeUrl: true -} + isRelativeUrl: true, +}; ``` ##### Table Item @@ -1159,7 +1185,7 @@ const item = { A table with columns and rows to display data in a structured format. | Parameter | Value | Optional | Description | -|-------------------|--------|----------|----------------------------------------------------------------------------------| +| ----------------- | ------ | -------- | -------------------------------------------------------------------------------- | | `type` | String | No | Must be `"table"`. | | `columns` | Array | No | The column definitions, including names and types. | | `columns[*].name` | String | No | The name of the column to display. | @@ -1201,7 +1227,7 @@ Example: An image to be displayed in the panel. | Parameter | Value | Optional | Description | -|-----------|--------|----------|----------------------------------| +| --------- | ------ | -------- | -------------------------------- | | `type` | String | No | Must be `"image"`. | | `url` | String | No | The URL of the image to display. | | `style` | Object | Yes | The CSS style definition. | @@ -1221,7 +1247,7 @@ Example: A video to be displayed in the panel. | Parameter | Value | Optional | Description | -|-----------|--------|----------|----------------------------------| +| --------- | ------ | -------- | -------------------------------- | | `type` | String | No | Must be `"video"`. | | `url` | String | No | The URL of the video to display. | | `style` | Object | Yes | The CSS style definition. | @@ -1241,7 +1267,7 @@ Example: An audio file to be played in the panel. | Parameter | Value | Optional | Description | -|-----------|--------|----------|-------------------------------| +| --------- | ------ | -------- | ----------------------------- | | `type` | String | No | Must be `"audio"`. | | `url` | String | No | The URL of the audio to play. | | `style` | Object | Yes | The CSS style definition. | @@ -1261,7 +1287,7 @@ Example: A button that triggers an action when clicked. | Parameter | Value | Optional | Description | -|------------------|--------|----------|---------------------------------------------------------| +| ---------------- | ------ | -------- | ------------------------------------------------------- | | `type` | String | No | Must be `"button"`. | | `text` | String | No | The text to display on the button. | | `action` | Object | No | The action to be performed when the button is clicked. | @@ -1296,7 +1322,7 @@ Example: A sub-panel whose data is loaded on-demand by expanding the item. | Parameter | Value | Optional | Description | -|---------------------|--------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------| +| ------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | `type` | String | No | Must be `"infoPanel"`. | | `title` | String | No | The title to display in the expandable headline. | | `cloudCodeFunction` | String | No | The Cloud Code Function to call which receives the selected object in the data browser and returns the response to be displayed in the sub-panel. | @@ -1309,7 +1335,7 @@ Example: "type": "panel", "title": "Purchase History", "cloudCodeFunction": "getUserPurchaseHistory", - "style": { "backgroundColor": "lightGray" }, + "style": { "backgroundColor": "lightGray" } } ``` @@ -1318,7 +1344,7 @@ Example: To reduce the time for info panel data to appear, data can be prefetched. | Parameter | Type | Optional | Default | Example | Description | -|--------------------------------|--------|----------|---------|---------|-----------------------------------------------------------------------------------------------------------------------------------| +| ------------------------------ | ------ | -------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `infoPanel[*].prefetchObjects` | Number | yes | `0` | `2` | Number of next rows to prefetch when browsing sequential rows. For example, `2` means the next 2 rows will be fetched in advance. | | `infoPanel[*].prefetchStale` | Number | yes | `0` | `10` | Duration in seconds after which prefetched data is discarded as stale. | @@ -1326,13 +1352,13 @@ Prefetching is particularly useful when navigating through lists of objects. To ### Freeze Columns -▶️ *Core > Browser > Freeze column* +▶️ _Core > Browser > Freeze column_ Right-click on a table column header to freeze columns from the left up to the clicked column in the data browser. When scrolling horizontally, the frozen columns remain visible while the other columns scroll underneath. ### Browse as User -▶️ *Core > Browser > Browse* +▶️ _Core > Browser > Browse_ This feature allows you to use the data browser as another user, respecting that user's data permissions. For example, you will only see records and fields the user has permission to see. @@ -1340,7 +1366,7 @@ This feature allows you to use the data browser as another user, respecting that ### Change Pointer Key -▶️ *Core > Browser > Edit > Change pointer key* +▶️ _Core > Browser > Edit > Change pointer key_ This feature allows you to change how a pointer is represented in the browser. By default, a pointer is represented by the `objectId` of the linked object. You can change this to any other column of the object class. For example, if class `Installation` has a field that contains a pointer to class `User`, the pointer will show the `objectId` of the user by default. You can change this to display the field `email` of the user, so that a pointer displays the user's email address instead. @@ -1354,7 +1380,7 @@ This feature allows you to change how a pointer is represented in the browser. B ### CSV Export -▶️ *Core > Browser > Export* +▶️ _Core > Browser > Export_ This feature will take either selected rows or all rows of an individual class and saves them to a CSV file, which is then downloaded. CSV headers are added to the top of the file matching the column names. @@ -1383,20 +1409,20 @@ To configure the AI agent for your dashboard, you need to add the `agent` config "provider": "openai", "model": "gpt-4.1", "apiKey": "YOUR_OPENAI_API_KEY" - }, + } ] } } ``` -| Parameter | Type | Required | Description | -|----------------------------|--------|----------|-------------------------------------------------------------------------------------------------------------------------------------| -| `agent` | Object | Yes | The AI agent configuration object. When using the environment variable, provide the complete agent configuration as a JSON string. | -| `agent.models` | Array | Yes | Array of AI model configurations available to the agent. | -| `agent.models[*].name` | String | Yes | The display name for the model (e.g., `ChatGPT 4.1`). | -| `agent.models[*].provider` | String | Yes | The AI provider identifier (e.g., "openai"). | -| `agent.models[*].model` | String | Yes | The specific model name from the provider (e.g., `gpt-4.1`). | -| `agent.models[*].apiKey` | String | Yes | The API key for authenticating with the AI provider. | +| Parameter | Type | Required | Description | +| -------------------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| `agent` | Object | Yes | The AI agent configuration object. When using the environment variable, provide the complete agent configuration as a JSON string. | +| `agent.models` | Array | Yes | Array of AI model configurations available to the agent. | +| `agent.models[*].name` | String | Yes | The display name for the model (e.g., `ChatGPT 4.1`). | +| `agent.models[*].provider` | String | Yes | The AI provider identifier (e.g., "openai"). | +| `agent.models[*].model` | String | Yes | The specific model name from the provider (e.g., `gpt-4.1`). | +| `agent.models[*].apiKey` | String | Yes | The API key for authenticating with the AI provider. | The agent will use the configured models to process natural language commands and perform database operations using the master key from your app configuration. @@ -1413,7 +1439,7 @@ To get an OpenAI API key for use with the AI agent: 2. **Access the API section**: Once logged in, navigate to the API section of your OpenAI dashboard. -3. **Create a new project**: +3. **Create a new project**: - Go to the "Projects" section - Click "Create project" - Name your project "Parse-Dashboard" (or any descriptive name) @@ -1424,7 +1450,7 @@ To get an OpenAI API key for use with the AI agent: - Select the AI models you want to use (e.g., `gpt-4`, `gpt-3.5-turbo`) - These model names will be used as the `agent.models[*].model` parameter in your dashboard configuration -5. **Generate an API key**: +5. **Generate an API key**: - Go to the "API Keys" page in your project settings - Click "Create new secret key" - Give your key a descriptive name (e.g., "Parse Dashboard Agent") @@ -1439,7 +1465,7 @@ To get an OpenAI API key for use with the AI agent: ## Views -▶️ *Core > Views* +▶️ _Core > Views_ Views are saved queries that display data in a table format. Saved views appear in the sidebar, where you can select, edit, or delete them. Optionally you can enable the object counter to show in the sidebar how many items match the view. @@ -1451,11 +1477,11 @@ Views are saved queries that display data in a table format. Saved views appear Views can pull their data from the following data sources. #### Aggregation Pipeline - + Display aggregated data from your classes using a MongoDB aggregation pipeline. Create a view by selecting a class and defining an aggregation pipeline. #### Cloud Function - + Display data returned by a Parse Cloud Function. Create a view specifying a Cloud Function that returns an array of objects. Cloud Functions enable custom business logic, computed fields, and complex data transformations. Cloud Function views can prompt users for text input and/or file upload when opened. Enable "Require text input" or "Require file upload" checkboxes when creating the view. The user provided data will then be available in the Cloud Function as parameters. @@ -1463,7 +1489,7 @@ Cloud Function views can prompt users for text input and/or file upload when ope Cloud Function example: ```js -Parse.Cloud.define("myViewFunction", request => { +Parse.Cloud.define('myViewFunction', request => { const text = request.params.text; const fileData = request.params.fileData; return processDataWithTextAndFile(text, fileData); @@ -1531,7 +1557,7 @@ Example: In the example above, the query string will be escaped and added to the url, resulting in the complete URL: ```js -"browser/_Installation?filters=%5B%7B%22field%22%3A%22objectId%22%2C%22constraint%22%3A%22eq%22%2C%22compareTo%22%3A%22xWMyZ4YEGZ%22%2C%22class%22%3A%22_Installation%22%7D%5D" +'browser/_Installation?filters=%5B%7B%22field%22%3A%22objectId%22%2C%22constraint%22%3A%22eq%22%2C%22compareTo%22%3A%22xWMyZ4YEGZ%22%2C%22class%22%3A%22_Installation%22%7D%5D'; ``` > [!Tip] @@ -1563,7 +1589,7 @@ Example: We really want Parse to be yours, to see it grow and thrive in the open source community. Please see the [Contributing to Parse Dashboard guide](CONTRIBUTING.md). ------ +--- As of April 5, 2017, Parse, LLC has transferred this code to the parse-community organization, and will no longer be contributing to or distributing this code. From eb5497e0d316269d46dfec96a52ffdceb5a36122 Mon Sep 17 00:00:00 2001 From: Lucas Coratger <73360179+coratgerl@users.noreply.github.com> Date: Thu, 2 Oct 2025 16:36:39 +0200 Subject: [PATCH 05/10] fix: feedback --- README.md | 285 +++++++++++++++++++++++++----------------------------- 1 file changed, 130 insertions(+), 155 deletions(-) diff --git a/README.md b/README.md index a77fad684..777dc8e70 100644 --- a/README.md +++ b/README.md @@ -123,22 +123,20 @@ After starting the dashboard, you can visit http://localhost:4040 in your browse ## Compatibility ### Parse Server - Parse Dashboard is compatible with the following Parse Server versions. | Parse Dashboard Version | Parse Server Version | Compatible | -| ----------------------- | -------------------- | ---------- | -| >=1.0 | >= 2.1.4 | ✅ Yes | +|-------------------------|----------------------|------------| +| >=1.0 | >= 2.1.4 | ✅ Yes | ### Node.js - Parse Dashboard is continuously tested with the most recent releases of Node.js to ensure compatibility. We follow the [Node.js Long Term Support plan](https://github.com/nodejs/Release) and only test against versions that are officially supported and have not reached their end-of-life date. | Version | Latest Version | End-of-Life | Compatible | -| ---------- | -------------- | ----------- | ---------- | -| Node.js 18 | 18.20.4 | May 2025 | ✅ Yes | -| Node.js 20 | 20.18.0 | April 2026 | ✅ Yes | -| Node.js 22 | 22.9.0 | April 2027 | ✅ Yes | +|------------|----------------|-------------|------------| +| Node.js 18 | 18.20.4 | May 2025 | ✅ Yes | +| Node.js 20 | 20.18.0 | April 2026 | ✅ Yes | +| Node.js 22 | 22.9.0 | April 2027 | ✅ Yes | ## Configuring Parse Dashboard @@ -389,7 +387,7 @@ After starting the dashboard, you can visit http://0.0.0.0:4040/apps/MyTestApp/a ## App Icon Configuration -Parse Dashboard supports adding an optional icon for each app, so you can identify them easier in the list. To do so, you _must_ use the configuration file, define an `iconsFolder` in it, and define the `iconName` parameter for each app (including the extension). The path of the `iconsFolder` is relative to the configuration file. If you have installed ParseDashboard globally you need to use the full path as value for the `iconsFolder`. To visualize what it means, in the following example `icons` is a directory located under the same directory as the configuration file: +Parse Dashboard supports adding an optional icon for each app, so you can identify them easier in the list. To do so, you *must* use the configuration file, define an `iconsFolder` in it, and define the `iconName` parameter for each app (including the extension). The path of the `iconsFolder` is relative to the configuration file. If you have installed ParseDashboard globally you need to use the full path as value for the `iconsFolder`. To visualize what it means, in the following example `icons` is a directory located under the same directory as the configuration file: ```json { @@ -399,7 +397,7 @@ Parse Dashboard supports adding an optional icon for each app, so you can identi "appId": "myAppId", "masterKey": "myMasterKey", "appName": "My Parse Server App", - "iconName": "MyAppIcon.png" + "iconName": "MyAppIcon.png", } ], "iconsFolder": "icons" @@ -408,7 +406,7 @@ Parse Dashboard supports adding an optional icon for each app, so you can identi ## App Background Color Configuration -Parse Dashboard supports adding an optional background color for each app, so you can identify them easier in the list. To do so, you _must_ use the configuration file, define an `primaryBackgroundColor` and `secondaryBackgroundColor` in it, parameter for each app. It is `CSS style`. To visualize what it means, in the following example `backgroundColor` is a configuration file: +Parse Dashboard supports adding an optional background color for each app, so you can identify them easier in the list. To do so, you *must* use the configuration file, define an `primaryBackgroundColor` and `secondaryBackgroundColor` in it, parameter for each app. It is `CSS style`. To visualize what it means, in the following example `backgroundColor` is a configuration file: ```json { @@ -439,7 +437,7 @@ You can set `appNameForURL` in the config file for each app to control the url o To change the app to production, simply set `production` to `true` in your config file. The default value is false if not specified. -### Prevent columns sorting + ### Prevent columns sorting You can prevent some columns to be sortable by adding `preventSort` to columnPreference options in each app configuration @@ -562,37 +560,26 @@ You can also specify custom fields with the `scrips` option: Next, define the Cloud Function in Parse Server that will be called. The object that has been selected in the data browser will be made available as a request parameter: ```js -Parse.Cloud.define( - 'deleteAccount', - async req => { - req.params.object.set('deleted', true); - await req.params.object.save(null, { useMasterKey: true }); - }, - { - requireMaster: true, - } -); +Parse.Cloud.define('deleteAccount', async (req) => { + req.params.object.set('deleted', true); + await req.params.object.save(null, {useMasterKey: true}); +}, { + requireMaster: true +}); ``` The field which the script was invoked on can be accessed by `selectedField`: ```js -Parse.Cloud.define( - 'deleteAccount', - async req => { - if (req.params.selectedField !== 'objectId') { - throw new Parse.Error( - Parse.Error.SCRIPT_FAILED, - 'Deleting accounts is only available on the objectId field.' - ); - } - req.params.object.set('deleted', true); - await req.params.object.save(null, { useMasterKey: true }); - }, - { - requireMaster: true, +Parse.Cloud.define('deleteAccount', async (req) => { + if (req.params.selectedField !== 'objectId') { + throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Deleting accounts is only available on the objectId field.'); } -); + req.params.object.set('deleted', true); + await req.params.object.save(null, {useMasterKey: true}); +}, { + requireMaster: true +}); ``` ⚠️ Depending on your Parse Server version you may need to set the Parse Server option `encodeParseObjectInCloudFunction` to `true` so that the selected object in the data browser is made available in the Cloud Function as an instance of `Parse.Object`. If the option is not set, is set to `false`, or you are using an older version of Parse Server, the object is made available as a plain JavaScript object and needs to be converted from a JSON object to a `Parse.Object` instance with `req.params.object = Parse.Object.fromJSON(req.params.object);`, before you can call any `Parse.Object` properties and methods on it. @@ -603,17 +590,13 @@ For older versions of Parse Server: Parse Server >=4.4.0 <6.2.0 ```js -Parse.Cloud.define( - 'deleteAccount', - async req => { - req.params.object = Parse.Object.fromJSON(req.params.object); - req.params.object.set('deleted', true); - await req.params.object.save(null, { useMasterKey: true }); - }, - { - requireMaster: true, - } -); +Parse.Cloud.define('deleteAccount', async (req) => { + req.params.object = Parse.Object.fromJSON(req.params.object); + req.params.object.set('deleted', true); + await req.params.object.save(null, {useMasterKey: true}); +}, { + requireMaster: true +}); ``` @@ -622,13 +605,13 @@ Parse.Cloud.define( Parse Server >=2.1.4 <4.4.0 ```js -Parse.Cloud.define('deleteAccount', async req => { +Parse.Cloud.define('deleteAccount', async (req) => { if (!req.master || !req.params.object) { throw 'Unauthorized'; } req.params.object = Parse.Object.fromJSON(req.params.object); req.params.object.set('deleted', true); - await req.params.object.save(null, { useMasterKey: true }); + await req.params.object.save(null, {useMasterKey: true}); }); ``` @@ -639,9 +622,10 @@ Parse.Cloud.define('deleteAccount', async req => { Parse Dashboard can cache its resources such as bundles in the browser, so that opening the dashboard in another tab does not reload the dashboard resources from the server but from the local browser cache. Caching only starts after login in the dashboard. | Parameter | Type | Optional | Default | Example | Description | -| --------------------- | ------- | -------- | ------- | ------- | -------------------------------------------------------------------------------------------------------------- | +|-----------------------|---------|----------|---------|---------|----------------------------------------------------------------------------------------------------------------| | `enableResourceCache` | Boolean | yes | `false` | `true` | Enables caching of dashboard resources in the browser for faster dashboard loading in additional browser tabs. | + Example configuration: ```javascript @@ -652,9 +636,9 @@ const dashboard = new ParseDashboard({ serverURL: 'http://localhost:1337/parse', appId: 'myAppId', masterKey: 'myMasterKey', - appName: 'MyApp', - }, - ], + appName: 'MyApp' + } + ] }); ``` @@ -673,14 +657,14 @@ var express = require('express'); var ParseDashboard = require('parse-dashboard'); var dashboard = new ParseDashboard({ - apps: [ + "apps": [ { - serverURL: 'http://localhost:1337/parse', - appId: 'myAppId', - masterKey: 'myMasterKey', - appName: 'MyApp', - }, - ], + "serverURL": "http://localhost:1337/parse", + "appId": "myAppId", + "masterKey": "myMasterKey", + "appName": "MyApp" + } + ] }); var app = express(); @@ -700,17 +684,14 @@ var ParseServer = require('parse-server').ParseServer; var ParseDashboard = require('parse-dashboard'); var api = new ParseServer({ - // Parse Server settings + // Parse Server settings }); var options = { allowInsecureHTTP: false }; -var dashboard = new ParseDashboard( - { - // Parse Dashboard settings - }, - options -); +var dashboard = new ParseDashboard({ + // Parse Dashboard settings +}, options); var app = express(); @@ -731,23 +712,22 @@ httpServer.listen(4040); Make sure the server URLs for your apps can be accessed by your browser. If you are deploying the dashboard, then `localhost` urls will not work. ## Security Considerations - In order to securely deploy the dashboard without leaking your apps master key, you will need to use HTTPS and Basic Authentication. -The deployed dashboard detects if you are using a secure connection. If you are deploying the dashboard behind a load balancer or front-facing proxy, then the app won't be able to detect that the connection is secure. In this case, you can start the dashboard with the `--trustProxy=1` option (or set the PARSE_DASHBOARD_TRUST_PROXY config var to 1) to rely on the X-Forwarded-\* headers for the client's connection security. This is useful for hosting on services like Heroku, where you can trust the provided proxy headers to correctly determine whether you're using HTTP or HTTPS. You can also turn on this setting when using the dashboard as [express](https://github.com/expressjs/express) middleware: +The deployed dashboard detects if you are using a secure connection. If you are deploying the dashboard behind a load balancer or front-facing proxy, then the app won't be able to detect that the connection is secure. In this case, you can start the dashboard with the `--trustProxy=1` option (or set the PARSE_DASHBOARD_TRUST_PROXY config var to 1) to rely on the X-Forwarded-* headers for the client's connection security. This is useful for hosting on services like Heroku, where you can trust the provided proxy headers to correctly determine whether you're using HTTP or HTTPS. You can also turn on this setting when using the dashboard as [express](https://github.com/expressjs/express) middleware: ```javascript var trustProxy = true; var dashboard = new ParseDashboard({ - apps: [ + "apps": [ { - serverURL: 'http://localhost:1337/parse', - appId: 'myAppId', - masterKey: 'myMasterKey', - appName: 'MyApp', - }, + "serverURL": "http://localhost:1337/parse", + "appId": "myAppId", + "masterKey": "myMasterKey", + "appName": "MyApp" + } ], - trustProxy: 1, + "trustProxy": 1 }); ``` @@ -770,7 +750,6 @@ const dashboard = new ParseDashboard({ ``` ### Configuring Basic Authentication - You can configure your dashboard for Basic Authentication by adding usernames and passwords your `parse-dashboard-config.json` configuration file: ```json @@ -801,52 +780,49 @@ With MFA enabled, a user must provide a one-time password that is typically boun The user requires an authenticator app to generate the one-time password. These apps are provided by many 3rd parties and mostly for free. -If you create a new user by running `parse-dashboard --createUser`, you will be asked whether you want to enable MFA for the new user. To enable MFA for an existing user, run `parse-dashboard --createMFA` to generate a `mfa` secret that you then add to the existing user configuration, for example: +If you create a new user by running `parse-dashboard --createUser`, you will be asked whether you want to enable MFA for the new user. To enable MFA for an existing user, run `parse-dashboard --createMFA` to generate a `mfa` secret that you then add to the existing user configuration, for example: ```json { - "apps": [{ "...": "..." }], + "apps": [{"...": "..."}], "users": [ { - "user": "user1", - "pass": "pass", + "user":"user1", + "pass":"pass", "mfa": "lmvmOIZGMTQklhOIhveqkumss" } ] } ``` -Parse Dashboard follows the industry standard and supports the common OTP algorithm `SHA-1` by default, to be compatible with most authenticator apps. If you have specific security requirements regarding TOTP characteristics (algorithm, digit length, time period) you can customize them by using the guided configuration mentioned above. + Parse Dashboard follows the industry standard and supports the common OTP algorithm `SHA-1` by default, to be compatible with most authenticator apps. If you have specific security requirements regarding TOTP characteristics (algorithm, digit length, time period) you can customize them by using the guided configuration mentioned above. ### Separating App Access Based on User Identity - If you have configured your dashboard to manage multiple applications, you can restrict the management of apps based on user identity. To do so, update your `parse-dashboard-config.json` configuration file to match the following format: ```json { - "apps": [{ "...": "..." }], + "apps": [{"...": "..."}], "users": [ - { - "user": "user1", - "pass": "pass1", - "apps": [{ "appId": "myAppId1" }, { "appId": "myAppId2" }] - }, - { - "user": "user2", - "pass": "pass2", - "apps": [{ "appId": "myAppId1" }] - } - ] + { + "user":"user1", + "pass":"pass1", + "apps": [{"appId": "myAppId1"}, {"appId": "myAppId2"}] + }, + { + "user":"user2", + "pass":"pass2", + "apps": [{"appId": "myAppId1"}] + } ] } ``` - The effect of such a configuration is as follows: When `user1` logs in, he/she will be able to manage `myAppId1` and `myAppId2` from the dashboard. -When _`user2`_ logs in, he/she will only be able to manage _`myAppId1`_ from the dashboard. +When *`user2`* logs in, he/she will only be able to manage *`myAppId1`* from the dashboard. ## Use Read-Only masterKey @@ -859,8 +835,8 @@ Start your `parse-server` with ```json { - "masterKey": "YOUR_MASTER_KEY_HERE", - "readOnlyMasterKey": "YOUR_READ_ONLY_MASTER_KEY" +"masterKey": "YOUR_MASTER_KEY_HERE", +"readOnlyMasterKey": "YOUR_READ_ONLY_MASTER_KEY", } ``` @@ -869,15 +845,15 @@ Then in your dashboard configuration: ```javascript var trustProxy = true; var dashboard = new ParseDashboard({ - apps: [ + "apps": [ { - serverURL: 'http://localhost:1337/parse', - appId: 'myAppId', - masterKey: 'YOUR_READ_ONLY_MASTER_KEY', - appName: 'MyApp', - }, + "serverURL": "http://localhost:1337/parse", + "appId": "myAppId", + "masterKey": "YOUR_READ_ONLY_MASTER_KEY", + "appName": "MyApp" + } ], - trustProxy: 1, + "trustProxy": 1 }); ``` @@ -908,15 +884,15 @@ You can mark a user as a read-only user: ], "users": [ { - "user": "user1", - "pass": "pass1", + "user":"user1", + "pass":"pass1", "readOnly": true, - "apps": [{ "appId": "myAppId1" }, { "appId": "myAppId2" }] + "apps": [{"appId": "myAppId1"}, {"appId": "myAppId2"}] }, { - "user": "user2", - "pass": "pass2", - "apps": [{ "appId": "myAppId1" }] + "user":"user2", + "pass":"pass2", + "apps": [{"appId": "myAppId1"}] } ] } @@ -940,13 +916,13 @@ You can give read only access to a user on a per-app basis: "port": 4040, "production": true }, - { "...": "..." } + {"...": "..."} ], "users": [ { - "user": "user", - "pass": "pass", - "apps": [{ "appId": "myAppId", "readOnly": true }, { "appId": "myAppId2" }] + "user":"user", + "pass":"pass", + "apps": [{"appId": "myAppId", "readOnly": true}, {"appId": "myAppId2"}] } ] } @@ -979,7 +955,7 @@ You can provide a list of locales or languages you want to support for your dash The official docker image is published on [docker hub](https://hub.docker.com/r/parseplatform/parse-dashboard) -Run the image with your `config.json` mounted as a volume +Run the image with your ``config.json`` mounted as a volume ``` docker run -d -p 8080:4040 -v host/path/to/config.json:/src/Parse-Dashboard/parse-dashboard-config.json parseplatform/parse-dashboard --dev @@ -991,7 +967,7 @@ You can also pass the appId, masterKey and serverURL as arguments: docker run -d -p 4040:4040 parseplatform/parse-dashboard --dev --appId $APP_ID --masterKey $MASTER_KEY --serverURL $SERVER_URL ``` -By default, the container will start the app at port 4040 inside the container. However, you can run custom command as well (see `Deploying in production` for custom setup). +By default, the container will start the app at port 4040 inside the container. However, you can run custom command as well (see ``Deploying in production`` for custom setup). In this example, we want to run the application in production mode at port 80 of the host machine. @@ -999,17 +975,16 @@ In this example, we want to run the application in production mode at port 80 of docker run -d -p 80:8080 -v host/path/to/config.json:/src/Parse-Dashboard/parse-dashboard-config.json parse-dashboard --port 8080 --dev ``` -If you are not familiar with Docker, `--port 8080` will be passed in as argument to the entrypoint to form the full command `npm start -- --port 8080`. The application will start at port 8080 inside the container and port `8080` will be mounted to port `80` on your host machine. +If you are not familiar with Docker, ``--port 8080`` will be passed in as argument to the entrypoint to form the full command ``npm start -- --port 8080``. The application will start at port 8080 inside the container and port ``8080`` will be mounted to port ``80`` on your host machine. # Features - -_(The following is not a complete list of features but a work in progress to build a comprehensive feature list.)_ +*(The following is not a complete list of features but a work in progress to build a comprehensive feature list.)* ## Data Browser ### Filters -▶️ _Core > Browser > Filter_ +▶️ *Core > Browser > Filter* The filter dialog allows to add relational filter conditions based on other classes that have a pointer to the current class. @@ -1027,9 +1002,9 @@ To apply such a filter, simply go to the `_User` class and add the two required ### Info Panel -▶️ _Core > Browser > Show Panel / Hide Panel_ +▶️ *Core > Browser > Show Panel / Hide Panel* -The data browser offers an info panel that can display information related to the currently selected object in the data browser table. The info panel is made visible by clicking on the menu button _Show Panel_ in the top right corner when browsing a class for which the info panel is configured in the dashboard options. +The data browser offers an info panel that can display information related to the currently selected object in the data browser table. The info panel is made visible by clicking on the menu button *Show Panel* in the top right corner when browsing a class for which the info panel is configured in the dashboard options. The following example dashboard configuration shows an info panel for the `_User` class with the title `User Details`, by calling the Cloud Code Function `getUserDetails` and displaying the returned response. @@ -1058,7 +1033,7 @@ The Cloud Code Function receives the selected object in the payload and returns The info panel can contain multiple segments to display different groups of information. | Parameter | Value | Optional | Description | -| ------------------------ | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------- | +|--------------------------|--------|----------|----------------------------------------------------------------------------------------------------------------------------------------| | `segments` | Array | No | An ordered array of segments, where each segment represents a distinct group of items to display. | | `segments[i].title` | String | No | The title of the segment that will be displayed. | | `segments[i].items` | Array | No | An ordered array of items within the segment. Each item can be of different types, such as text, key-value pairs, tables, images, etc. | @@ -1105,7 +1080,7 @@ Example: { "type": "text", "text": "This user has a high churn risk!", - "style": { "backgroundColor": "red" } + "style": { "backgroundColor": "red" }, } ``` @@ -1114,7 +1089,7 @@ Example: A text item that consists of a key and a value. The value can optionally be linked to a URL. | Parameter | Value | Default | Optional | Description | -| --------------- | ------- | ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +|-----------------|---------|-------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `type` | String | - | No | Must be `"keyValue"`. | | `key` | String | - | No | The key text to display. | | `value` | String | - | No | The value text to display. | @@ -1130,7 +1105,7 @@ Examples: "type": "keyValue", "key": "Lifetime purchase value", "value": "$10k", - "style": { "backgroundColor": "green" } + "style": { "backgroundColor": "green" }, } ``` @@ -1176,8 +1151,8 @@ const item = { key: 'Purchase', value: objectId, url, - isRelativeUrl: true, -}; + isRelativeUrl: true +} ``` ##### Table Item @@ -1185,7 +1160,7 @@ const item = { A table with columns and rows to display data in a structured format. | Parameter | Value | Optional | Description | -| ----------------- | ------ | -------- | -------------------------------------------------------------------------------- | +|-------------------|--------|----------|----------------------------------------------------------------------------------| | `type` | String | No | Must be `"table"`. | | `columns` | Array | No | The column definitions, including names and types. | | `columns[*].name` | String | No | The name of the column to display. | @@ -1287,7 +1262,7 @@ Example: A button that triggers an action when clicked. | Parameter | Value | Optional | Description | -| ---------------- | ------ | -------- | ------------------------------------------------------- | +|------------------|--------|----------|---------------------------------------------------------| | `type` | String | No | Must be `"button"`. | | `text` | String | No | The text to display on the button. | | `action` | Object | No | The action to be performed when the button is clicked. | @@ -1322,7 +1297,7 @@ Example: A sub-panel whose data is loaded on-demand by expanding the item. | Parameter | Value | Optional | Description | -| ------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +|---------------------|--------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------| | `type` | String | No | Must be `"infoPanel"`. | | `title` | String | No | The title to display in the expandable headline. | | `cloudCodeFunction` | String | No | The Cloud Code Function to call which receives the selected object in the data browser and returns the response to be displayed in the sub-panel. | @@ -1335,7 +1310,7 @@ Example: "type": "panel", "title": "Purchase History", "cloudCodeFunction": "getUserPurchaseHistory", - "style": { "backgroundColor": "lightGray" } + "style": { "backgroundColor": "lightGray" }, } ``` @@ -1344,7 +1319,7 @@ Example: To reduce the time for info panel data to appear, data can be prefetched. | Parameter | Type | Optional | Default | Example | Description | -| ------------------------------ | ------ | -------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | +|--------------------------------|--------|----------|---------|---------|-----------------------------------------------------------------------------------------------------------------------------------| | `infoPanel[*].prefetchObjects` | Number | yes | `0` | `2` | Number of next rows to prefetch when browsing sequential rows. For example, `2` means the next 2 rows will be fetched in advance. | | `infoPanel[*].prefetchStale` | Number | yes | `0` | `10` | Duration in seconds after which prefetched data is discarded as stale. | @@ -1352,13 +1327,13 @@ Prefetching is particularly useful when navigating through lists of objects. To ### Freeze Columns -▶️ _Core > Browser > Freeze column_ +▶️ *Core > Browser > Freeze column* Right-click on a table column header to freeze columns from the left up to the clicked column in the data browser. When scrolling horizontally, the frozen columns remain visible while the other columns scroll underneath. ### Browse as User -▶️ _Core > Browser > Browse_ +▶️ *Core > Browser > Browse* This feature allows you to use the data browser as another user, respecting that user's data permissions. For example, you will only see records and fields the user has permission to see. @@ -1366,7 +1341,7 @@ This feature allows you to use the data browser as another user, respecting that ### Change Pointer Key -▶️ _Core > Browser > Edit > Change pointer key_ +▶️ *Core > Browser > Edit > Change pointer key* This feature allows you to change how a pointer is represented in the browser. By default, a pointer is represented by the `objectId` of the linked object. You can change this to any other column of the object class. For example, if class `Installation` has a field that contains a pointer to class `User`, the pointer will show the `objectId` of the user by default. You can change this to display the field `email` of the user, so that a pointer displays the user's email address instead. @@ -1380,7 +1355,7 @@ This feature allows you to change how a pointer is represented in the browser. B ### CSV Export -▶️ _Core > Browser > Export_ +▶️ *Core > Browser > Export* This feature will take either selected rows or all rows of an individual class and saves them to a CSV file, which is then downloaded. CSV headers are added to the top of the file matching the column names. @@ -1409,20 +1384,20 @@ To configure the AI agent for your dashboard, you need to add the `agent` config "provider": "openai", "model": "gpt-4.1", "apiKey": "YOUR_OPENAI_API_KEY" - } + }, ] } } ``` -| Parameter | Type | Required | Description | -| -------------------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------- | -| `agent` | Object | Yes | The AI agent configuration object. When using the environment variable, provide the complete agent configuration as a JSON string. | -| `agent.models` | Array | Yes | Array of AI model configurations available to the agent. | -| `agent.models[*].name` | String | Yes | The display name for the model (e.g., `ChatGPT 4.1`). | -| `agent.models[*].provider` | String | Yes | The AI provider identifier (e.g., "openai"). | -| `agent.models[*].model` | String | Yes | The specific model name from the provider (e.g., `gpt-4.1`). | -| `agent.models[*].apiKey` | String | Yes | The API key for authenticating with the AI provider. | +| Parameter | Type | Required | Description | +|----------------------------|--------|----------|-------------------------------------------------------------------------------------------------------------------------------------| +| `agent` | Object | Yes | The AI agent configuration object. When using the environment variable, provide the complete agent configuration as a JSON string. | +| `agent.models` | Array | Yes | Array of AI model configurations available to the agent. | +| `agent.models[*].name` | String | Yes | The display name for the model (e.g., `ChatGPT 4.1`). | +| `agent.models[*].provider` | String | Yes | The AI provider identifier (e.g., "openai"). | +| `agent.models[*].model` | String | Yes | The specific model name from the provider (e.g., `gpt-4.1`). | +| `agent.models[*].apiKey` | String | Yes | The API key for authenticating with the AI provider. | The agent will use the configured models to process natural language commands and perform database operations using the master key from your app configuration. @@ -1465,7 +1440,7 @@ To get an OpenAI API key for use with the AI agent: ## Views -▶️ _Core > Views_ +▶️ *Core > Views* Views are saved queries that display data in a table format. Saved views appear in the sidebar, where you can select, edit, or delete them. Optionally you can enable the object counter to show in the sidebar how many items match the view. @@ -1477,11 +1452,11 @@ Views are saved queries that display data in a table format. Saved views appear Views can pull their data from the following data sources. #### Aggregation Pipeline - + Display aggregated data from your classes using a MongoDB aggregation pipeline. Create a view by selecting a class and defining an aggregation pipeline. #### Cloud Function - + Display data returned by a Parse Cloud Function. Create a view specifying a Cloud Function that returns an array of objects. Cloud Functions enable custom business logic, computed fields, and complex data transformations. Cloud Function views can prompt users for text input and/or file upload when opened. Enable "Require text input" or "Require file upload" checkboxes when creating the view. The user provided data will then be available in the Cloud Function as parameters. @@ -1489,7 +1464,7 @@ Cloud Function views can prompt users for text input and/or file upload when ope Cloud Function example: ```js -Parse.Cloud.define('myViewFunction', request => { +Parse.Cloud.define("myViewFunction", request => { const text = request.params.text; const fileData = request.params.fileData; return processDataWithTextAndFile(text, fileData); @@ -1557,7 +1532,7 @@ Example: In the example above, the query string will be escaped and added to the url, resulting in the complete URL: ```js -'browser/_Installation?filters=%5B%7B%22field%22%3A%22objectId%22%2C%22constraint%22%3A%22eq%22%2C%22compareTo%22%3A%22xWMyZ4YEGZ%22%2C%22class%22%3A%22_Installation%22%7D%5D'; +"browser/_Installation?filters=%5B%7B%22field%22%3A%22objectId%22%2C%22constraint%22%3A%22eq%22%2C%22compareTo%22%3A%22xWMyZ4YEGZ%22%2C%22class%22%3A%22_Installation%22%7D%5D" ``` > [!Tip] @@ -1589,7 +1564,7 @@ Example: We really want Parse to be yours, to see it grow and thrive in the open source community. Please see the [Contributing to Parse Dashboard guide](CONTRIBUTING.md). ---- +----- As of April 5, 2017, Parse, LLC has transferred this code to the parse-community organization, and will no longer be contributing to or distributing this code. From d9a26016d23344eef3c0e5e78196f19dab1ef2f2 Mon Sep 17 00:00:00 2001 From: Lucas Coratger <73360179+coratgerl@users.noreply.github.com> Date: Thu, 2 Oct 2025 16:38:50 +0200 Subject: [PATCH 06/10] fix: more --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 777dc8e70..56fd781e0 100644 --- a/README.md +++ b/README.md @@ -511,7 +511,7 @@ For example: }] ``` -You can conveniently create a filter definition without having to write it by hand by first saving a filter in the data browser, then exporting the filter definition under _App Settings > Export Class Preferences_. +You can conveniently create a filter definition without having to write it by hand by first saving a filter in the data browser, then exporting the filter definition under *App Settings > Export Class Preferences*. ### Scripts @@ -646,7 +646,7 @@ const dashboard = new ParseDashboard({ > This feature can make it more difficult to push dashboard updates to users. Enabling the resource cache will start a browser service worker that caches dashboard resources locally only once. As long as the service worker is running, it will prevent loading any dashboard updates from the server, even if the user reloads the browser tab. The service worker is automatically stopped, once the last dashboard browser tab is closed. On the opening of the first dashboard browser tab, a new service worker is started and the dashboard resources are loaded from the server. > [!Note] -> For developers: during dashboard development, the resource cache should be disabled to ensure reloading the dashboard tab in the browser loads the new dashboard bundle with any changes you made in the source code. You can inspect the service worker in the developer tools of most browsers. For example in Google Chrome, go to _Developer Tools > Application tab > Service workers_ to see whether the dashboard service worker is currently running and to debug it. +> For developers: during dashboard development, the resource cache should be disabled to ensure reloading the dashboard tab in the browser loads the new dashboard bundle with any changes you made in the source code. You can inspect the service worker in the developer tools of most browsers. For example in Google Chrome, go to *Developer Tools > Application tab > Service workers* to see whether the dashboard service worker is currently running and to debug it. # Running as Express Middleware From bc89dc0c479f9cc29cef8caba9880f24d17ec240 Mon Sep 17 00:00:00 2001 From: coratgerl <73360179+coratgerl@users.noreply.github.com> Date: Sat, 4 Oct 2025 13:11:27 +0200 Subject: [PATCH 07/10] fix: feedbacks --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 56fd781e0..9a68c4458 100644 --- a/README.md +++ b/README.md @@ -1069,7 +1069,7 @@ The items array can include various types of content such as text, key-value pai A simple text field. | Parameter | Value | Optional | Description | -| --------- | ------ | -------- | ------------------------- | +|-----------|--------|----------|---------------------------| | `type` | String | No | Must be `"text"`. | | `text` | String | No | The text to display. | | `style` | Object | Yes | The CSS style definition. | @@ -1202,7 +1202,7 @@ Example: An image to be displayed in the panel. | Parameter | Value | Optional | Description | -| --------- | ------ | -------- | -------------------------------- | +|-----------|--------|----------|----------------------------------| | `type` | String | No | Must be `"image"`. | | `url` | String | No | The URL of the image to display. | | `style` | Object | Yes | The CSS style definition. | @@ -1222,7 +1222,7 @@ Example: A video to be displayed in the panel. | Parameter | Value | Optional | Description | -| --------- | ------ | -------- | -------------------------------- | +|-----------|--------|----------|----------------------------------| | `type` | String | No | Must be `"video"`. | | `url` | String | No | The URL of the video to display. | | `style` | Object | Yes | The CSS style definition. | @@ -1242,7 +1242,7 @@ Example: An audio file to be played in the panel. | Parameter | Value | Optional | Description | -| --------- | ------ | -------- | ----------------------------- | +|-----------|--------|----------|-------------------------------| | `type` | String | No | Must be `"audio"`. | | `url` | String | No | The URL of the audio to play. | | `style` | Object | Yes | The CSS style definition. | @@ -1414,7 +1414,7 @@ To get an OpenAI API key for use with the AI agent: 2. **Access the API section**: Once logged in, navigate to the API section of your OpenAI dashboard. -3. **Create a new project**: +3. **Create a new project**: - Go to the "Projects" section - Click "Create project" - Name your project "Parse-Dashboard" (or any descriptive name) @@ -1425,7 +1425,7 @@ To get an OpenAI API key for use with the AI agent: - Select the AI models you want to use (e.g., `gpt-4`, `gpt-3.5-turbo`) - These model names will be used as the `agent.models[*].model` parameter in your dashboard configuration -5. **Generate an API key**: +5. **Generate an API key**: - Go to the "API Keys" page in your project settings - Click "Create new secret key" - Give your key a descriptive name (e.g., "Parse Dashboard Agent") From b31b89d101eeb34535e07a3c258ae8f104984a29 Mon Sep 17 00:00:00 2001 From: coratgerl <73360179+coratgerl@users.noreply.github.com> Date: Sat, 4 Oct 2025 13:12:20 +0200 Subject: [PATCH 08/10] fix: more --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9a68c4458..90ac6aa61 100644 --- a/README.md +++ b/README.md @@ -256,7 +256,7 @@ Each class in `columnPreference` can have an array of column configurations: #### Helper CLI Commands | Command | Description | -| -------------- | ------------------------------------------------------------------- | +| ---------------|---------------------------------------------------------------------| | `--createUser` | Interactive tool to generate secure user passwords and MFA secrets. | | `--createMFA` | Interactive tool to generate MFA secrets for existing users. | From ff6c8bf1d9482de9234fa6a3d302fd6d0e386204 Mon Sep 17 00:00:00 2001 From: coratgerl <73360179+coratgerl@users.noreply.github.com> Date: Sat, 4 Oct 2025 13:15:56 +0200 Subject: [PATCH 09/10] fix: more --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 90ac6aa61..f3fcce581 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,7 @@ This section provides a comprehensive reference for all Parse Dashboard configur Each class in `columnPreference` can have an array of column configurations: | Parameter | Type | Optional | Default | Example | Description | -| ----------------- | ------- | -------- | ------- | ------------- | -------------------------------------------------- | +| ------------------|---------|----------|---------|---------------|----------------------------------------------------| | `name` | String | no | - | `"createdAt"` | Column/field name. | | `visible` | Boolean | yes | `true` | `false` | Whether the column is visible in the data browser. | | `preventSort` | Boolean | yes | `false` | `true` | Prevent this column from being sortable. | @@ -193,7 +193,7 @@ Each class in `columnPreference` can have an array of column configurations: ##### Scripts Configuration (`apps[].scripts[]`) | Parameter | Type | Optional | Default | Example | Description | -| ------------------------- | ------------------------------------------ | -------- | ------- | --------------- | ------------------------------------------------- | +| --------------------------|--------------------------------------------|----------|---------|-----------------|---------------------------------------------------| | `title` | String | no | - | `"Delete User"` | Title in context menu and confirmation dialog. | | `classes` | Array<String> \| Array<Object> | no | - | `["_User"]` | Classes for which script can run. | | `cloudCodeFunction` | String | no | - | `"deleteUser"` | Parse Cloud Function name to execute. | @@ -204,7 +204,7 @@ Each class in `columnPreference` can have an array of column configurations: ##### Info Panel Configuration (`apps[].infoPanel[]`) | Parameter | Type | Optional | Default | Example | Description | -| ------------------- | ------------------- | -------- | ------- | ------------------ | --------------------------------------------- | +| --------------------|---------------------|----------|---------|--------------------|-----------------------------------------------| | `title` | String | no | - | `"User Details"` | Panel title. | | `classes` | Array<String> | no | - | `["_User"]` | Classes for which panel is displayed. | | `cloudCodeFunction` | String | no | - | `"getUserDetails"` | Cloud Function receiving selected object. | @@ -214,7 +214,7 @@ Each class in `columnPreference` can have an array of column configurations: ##### Global Configuration | Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | -| ----------------------- | ------------------- | -------- | ------- | -------------- | ------------------------------ | --------- | ------------------------------------------------------------------------------------- | +| ------------------------|---------------------|----------|---------|----------------|--------------------------------|-----------| --------------------------------------------------------------------------------------| | `apps` | Array<Object> | no | - | - | `PARSE_DASHBOARD_CONFIG` | `[{...}]` | Array of apps to manage. | | `users` | Array<Object> | yes | - | - | - | `[{...}]` | User accounts for authentication. See [users table below](#user-configuration-users). | | `useEncryptedPasswords` | Boolean | yes | `false` | - | - | `true` | Use bcrypt hashes instead of plain text passwords. | @@ -226,7 +226,7 @@ Each class in `columnPreference` can have an array of column configurations: ##### User Configuration (`users[]`) | Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | -| ----------------- | ------------------- | -------- | -------- | ---------------- | ------------------------------- | -------------------- | -------------------------------------- | +| ------------------|---------------------|----------|----------|------------------|---------------------------------|----------------------|----------------------------------------| | `user` | String | no | - | `--userId` | `PARSE_DASHBOARD_USER_ID` | `"admin"` | Username for authentication. | | `pass` | String | no | - | `--userPassword` | `PARSE_DASHBOARD_USER_PASSWORD` | `"pass"` | Password (plain or bcrypt hash). | | `mfa` | String | yes | - | - | - | `"JBSWY3DPEHPK3PXP"` | MFA secret for TOTP. | @@ -241,7 +241,7 @@ Each class in `columnPreference` can have an array of column configurations: #### CLI & Server Options | Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | -| --------------------- | ------- | -------- | ------------ | ----------------------- | ---------------------------------------- | --------------- | ------------------------------------------------ | +| ----------------------|---------|----------|--------------|-------------------------|------------------------------------------|-----------------| -------------------------------------------------| | `host` | String | yes | `"0.0.0.0"` | `--host` | `HOST` | `"127.0.0.1"` | Host address to bind server. | | `port` | Number | yes | `4040` | `--port` | `PORT` | `8080` | Port for dashboard server. | | `mountPath` | String | yes | `"/"` | `--mountPath` | `MOUNT_PATH` | `"/dashboard"` | Mount path for application. | From 7876028b88a7589a524ab5451542d140eec48aa7 Mon Sep 17 00:00:00 2001 From: coratgerl <73360179+coratgerl@users.noreply.github.com> Date: Sat, 4 Oct 2025 20:01:53 +0200 Subject: [PATCH 10/10] fix: feedbacks --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f3fcce581..44f019705 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,18 @@ Parse Dashboard is continuously tested with the most recent releases of Node.js This section provides a comprehensive reference for all Parse Dashboard configuration options that can be used in the configuration file, via CLI arguments, or as environment variables. +#### Root Configuration Keys + +| Key | Type | Required | Description | Links to Details | +|-----|------|----------|-------------|------------------| +| `apps` | Array<Object> | Yes | Array of Parse Server apps to manage | [App Configuration](#app-configuration-apps-array) | +| `users` | Array<Object> | No | User accounts for dashboard authentication | [User Configuration](#user-configuration-users) | +| `useEncryptedPasswords` | Boolean | No | Use bcrypt hashes instead of plain text passwords | [Global Configuration](#global-configuration) | +| `trustProxy` | Boolean \| Number | No | Trust X-Forwarded-* headers when behind proxy | [Global Configuration](#global-configuration) | +| `iconsFolder` | String | No | Folder for app icons (relative or absolute path) | [Global Configuration](#global-configuration) | +| `agent` | Object | No | AI agent configuration | [AI Agent Configuration](#ai-agent) | +| `enableResourceCache` | Boolean | No | Enable browser caching of dashboard resources | [Global Configuration](#global-configuration) | + #### Configuration File Options ##### App Configuration (`apps` array) @@ -151,7 +163,7 @@ This section provides a comprehensive reference for all Parse Dashboard configur | Parameter | Type | Optional | Default | CLI | Env Variable | Example | Description | | -------------------------- | ------------------- | -------- | --------- | -------------------- | ------------------------------------ | --------------------------------- | ------------------------------------------------------------------------------------------------------------ | | `appId` | String | no | - | `--appId` | `PARSE_DASHBOARD_APP_ID` | `"myAppId"` | The Application ID for your Parse Server instance. | -| `masterKey` | String \| Function | no | - | `--masterKey` | `PARSE_DASHBOARD_MASTER_KEY` | `"key"` | Master key for full access. Can be a String or Function returning a String. | +| `masterKey` | String \| Function | no | - | `--masterKey` | `PARSE_DASHBOARD_MASTER_KEY` | `"key"` or `() => "key"` | Master key for full access. Can be a String or Function returning a String. | | `serverURL` | String | no | - | `--serverURL` | `PARSE_DASHBOARD_SERVER_URL` | `"http://localhost:1337/parse"` | The URL where your Parse Server is running. | | `appName` | String | yes | `appId` | `--appName` | `PARSE_DASHBOARD_APP_NAME` | `"MyApp"` | Display name of the app. | | `masterKeyTtl` | Number | yes | - | `--masterKeyTtl` | - | `3600` | TTL for master key cache in seconds (when `masterKey` is a Function). |