parse-dashboard 5.2.0 → 5.3.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,18 +27,18 @@ module.exports = (options) => {
27
27
  process.exit(-1);
28
28
  }
29
29
 
30
- let explicitConfigFileProvided = !!options.config;
30
+ const explicitConfigFileProvided = !!options.config;
31
31
  let configFile = null;
32
32
  let configFromCLI = null;
33
- let configServerURL = options.serverURL || process.env.PARSE_DASHBOARD_SERVER_URL;
34
- let configGraphQLServerURL = options.graphQLServerURL || process.env.PARSE_DASHBOARD_GRAPHQL_SERVER_URL;
35
- let configMasterKey = options.masterKey || process.env.PARSE_DASHBOARD_MASTER_KEY;
36
- let configAppId = options.appId || process.env.PARSE_DASHBOARD_APP_ID;
37
- let configAppName = options.appName || process.env.PARSE_DASHBOARD_APP_NAME;
38
- let configUserId = options.userId || process.env.PARSE_DASHBOARD_USER_ID;
39
- let configUserPassword = options.userPassword || process.env.PARSE_DASHBOARD_USER_PASSWORD;
40
- let configSSLKey = options.sslKey || process.env.PARSE_DASHBOARD_SSL_KEY;
41
- let configSSLCert = options.sslCert || process.env.PARSE_DASHBOARD_SSL_CERT;
33
+ const configServerURL = options.serverURL || process.env.PARSE_DASHBOARD_SERVER_URL;
34
+ const configGraphQLServerURL = options.graphQLServerURL || process.env.PARSE_DASHBOARD_GRAPHQL_SERVER_URL;
35
+ const configMasterKey = options.masterKey || process.env.PARSE_DASHBOARD_MASTER_KEY;
36
+ const configAppId = options.appId || process.env.PARSE_DASHBOARD_APP_ID;
37
+ const configAppName = options.appName || process.env.PARSE_DASHBOARD_APP_NAME;
38
+ const configUserId = options.userId || process.env.PARSE_DASHBOARD_USER_ID;
39
+ const configUserPassword = options.userPassword || process.env.PARSE_DASHBOARD_USER_PASSWORD;
40
+ const configSSLKey = options.sslKey || process.env.PARSE_DASHBOARD_SSL_KEY;
41
+ const configSSLCert = options.sslCert || process.env.PARSE_DASHBOARD_SSL_CERT;
42
42
 
43
43
  function handleSIGs(server) {
44
44
  const signals = {
@@ -143,10 +143,10 @@ module.exports = (options) => {
143
143
 
144
144
  const app = express();
145
145
 
146
- if (allowInsecureHTTP || trustProxy || dev) app.enable('trust proxy');
146
+ if (allowInsecureHTTP || trustProxy || dev) {app.enable('trust proxy');}
147
147
 
148
148
  config.data.trustProxy = trustProxy;
149
- let dashboardOptions = { allowInsecureHTTP, cookieSessionSecret, dev, cookieSessionMaxAge };
149
+ const dashboardOptions = { allowInsecureHTTP, cookieSessionSecret, dev, cookieSessionMaxAge };
150
150
  app.use(mountPath, parseDashboard(config.data, dashboardOptions));
151
151
  let server;
152
152
  if(!configSSLKey || !configSSLCert){
@@ -156,8 +156,8 @@ module.exports = (options) => {
156
156
  });
157
157
  } else {
158
158
  // Start the server using SSL.
159
- var privateKey = fs.readFileSync(configSSLKey);
160
- var certificate = fs.readFileSync(configSSLCert);
159
+ const privateKey = fs.readFileSync(configSSLKey);
160
+ const certificate = fs.readFileSync(configSSLCert);
161
161
 
162
162
  server = require('https').createServer({
163
163
  key: privateKey,
package/README.md CHANGED
@@ -31,6 +31,7 @@ Parse Dashboard is a standalone dashboard for managing your [Parse Server](https
31
31
  - [Parse Server](#parse-server)
32
32
  - [Node.js](#nodejs)
33
33
  - [Configuring Parse Dashboard](#configuring-parse-dashboard)
34
+ - [Options](#options)
34
35
  - [File](#file)
35
36
  - [Environment variables](#environment-variables)
36
37
  - [Multiple apps](#multiple-apps)
@@ -42,6 +43,8 @@ Parse Dashboard is a standalone dashboard for managing your [Parse Server](https
42
43
  - [Other Configuration Options](#other-configuration-options)
43
44
  - [Prevent columns sorting](#prevent-columns-sorting)
44
45
  - [Custom order in the filter popup](#custom-order-in-the-filter-popup)
46
+ - [Persistent Filters](#persistent-filters)
47
+ - [Scripts](#scripts)
45
48
  - [Running as Express Middleware](#running-as-express-middleware)
46
49
  - [Deploying Parse Dashboard](#deploying-parse-dashboard)
47
50
  - [Preparing for Deployment](#preparing-for-deployment)
@@ -102,14 +105,26 @@ Parse Dashboard is compatible with the following Parse Server versions.
102
105
  ### Node.js
103
106
  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.
104
107
 
105
- | Version | Latest Version | End-of-Life | Compatible |
106
- |------------|----------------|-------------|--------------|
107
- | Node.js 14 | 14.20.1 | April 2023 | ✅ Yes |
108
- | Node.js 16 | 16.17.0 | April 2024 | ✅ Yes |
109
- | Node.js 18 | 18.9.0 | May 2025 | ✅ Yes |
108
+ | Version | Latest Version | End-of-Life | Compatible |
109
+ |------------|----------------|-------------|------------|
110
+ | Node.js 14 | 14.20.1 | April 2023 | ✅ Yes |
111
+ | Node.js 16 | 16.17.0 | April 2024 | ✅ Yes |
112
+ | Node.js 18 | 18.9.0 | May 2025 | ✅ Yes |
110
113
 
111
114
  ## Configuring Parse Dashboard
112
115
 
116
+ ### Options
117
+
118
+ | Parameter | Type | Optional | Default | Example | Description |
119
+ |----------------------------------------|---------------------|----------|---------|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
120
+ | `apps` | Array<Object> | no | - | `[{ ... }, { ... }]` | The apps that are configured for the dashboard. |
121
+ | `apps.scripts` | Array<Object> | yes | `[]` | `[{ ... }, { ... }]` | The scripts that can be executed for that app. |
122
+ | `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. |
123
+ | `apps.scripts.classes` | Array<String> | no | - | `['_User']` | The classes of Parse Objects for which the scripts can be executed. |
124
+ | `apps.scripts.cloudCodeFunction` | String | no | - | `'deleteUser'` | The name of the Parse Cloud Function to execute. |
125
+ | `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. |
126
+ | `apps.scripts.confirmationDialogStyle` | String | yes | `info` | `critical` | The style of the confirmation dialog. Valid values: `info` (blue style), `critical` (red style). |
127
+
113
128
  ### File
114
129
 
115
130
  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:
@@ -362,6 +377,86 @@ For example:
362
377
 
363
378
  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*.
364
379
 
380
+ ### Scripts
381
+
382
+ You can specify scripts to execute Cloud Functions with the `scripts` option:
383
+
384
+ ```json
385
+ "apps": [
386
+ {
387
+ "scripts": [
388
+ {
389
+ "title": "Delete Account",
390
+ "classes": ["_User"],
391
+ "cloudCodeFunction": "deleteAccount",
392
+ "showConfirmationDialog": true,
393
+ "confirmationDialogStyle": "critical"
394
+ }
395
+ ]
396
+ }
397
+ ]
398
+ ```
399
+
400
+ 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:
401
+
402
+ ```js
403
+ Parse.Cloud.define('deleteAccount', async (req) => {
404
+ req.params.object.set('deleted', true);
405
+ await req.params.object.save(null, {useMasterKey: true});
406
+ }, {
407
+ requireMaster: true
408
+ });
409
+ ```
410
+
411
+ The field which the script was invoked on can be accessed by `selectedField`:
412
+
413
+ ```js
414
+ Parse.Cloud.define('deleteAccount', async (req) => {
415
+ if (req.params.selectedField !== 'objectId') {
416
+ throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Deleting accounts is only available on the objectId field.');
417
+ }
418
+ req.params.object.set('deleted', true);
419
+ await req.params.object.save(null, {useMasterKey: true});
420
+ }, {
421
+ requireMaster: true
422
+ });
423
+ ```
424
+
425
+ ⚠️ 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.
426
+
427
+ For older versions of Parse Server:
428
+
429
+ <details>
430
+ <summary>Parse Server &gt;=4.4.0 &lt;6.2.0</summary>
431
+
432
+ ```js
433
+ Parse.Cloud.define('deleteAccount', async (req) => {
434
+ req.params.object = Parse.Object.fromJSON(req.params.object);
435
+ req.params.object.set('deleted', true);
436
+ await req.params.object.save(null, {useMasterKey: true});
437
+ }, {
438
+ requireMaster: true
439
+ });
440
+ ```
441
+
442
+ </details>
443
+
444
+ <details>
445
+ <summary>Parse Server &gt;=2.1.4 &lt;4.4.0</summary>
446
+
447
+ ```js
448
+ Parse.Cloud.define('deleteAccount', async (req) => {
449
+ if (!req.master || !req.params.object) {
450
+ throw 'Unauthorized';
451
+ }
452
+ req.params.object = Parse.Object.fromJSON(req.params.object);
453
+ req.params.object.set('deleted', true);
454
+ await req.params.object.save(null, {useMasterKey: true});
455
+ });
456
+ ```
457
+
458
+ </details>
459
+
365
460
  # Running as Express Middleware
366
461
 
367
462
  Instead of starting Parse Dashboard with the CLI, you can also run it as an [express](https://github.com/expressjs/express) middleware.
@@ -445,6 +540,24 @@ var dashboard = new ParseDashboard({
445
540
  });
446
541
  ```
447
542
 
543
+ ## Security Checks
544
+
545
+ You can view the security status of your Parse Server by enabling the dashboard option `enableSecurityChecks`, and visiting App Settings > Security.
546
+
547
+ ```javascript
548
+ const dashboard = new ParseDashboard({
549
+ "apps": [
550
+ {
551
+ "serverURL": "http://localhost:1337/parse",
552
+ "appId": "myAppId",
553
+ "masterKey": "myMasterKey",
554
+ "appName": "MyApp"
555
+ "enableSecurityChecks": true
556
+ }
557
+ ],
558
+ });
559
+ ```
560
+
448
561
 
449
562
 
450
563
  ### Configuring Basic Authentication
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "parse-dashboard",
3
- "version": "5.2.0",
3
+ "version": "5.3.0-alpha.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/ParsePlatform/parse-dashboard"
@@ -47,7 +47,7 @@
47
47
  "csurf": "1.11.0",
48
48
  "express": "4.18.1",
49
49
  "graphiql": "2.0.8",
50
- "graphql": "16.6.0",
50
+ "graphql": "16.8.1",
51
51
  "immutable": "4.1.0",
52
52
  "immutable-devtools": "0.1.5",
53
53
  "inquirer": "8.2.4",
@@ -70,7 +70,7 @@
70
70
  "react-popper-tooltip": "4.4.2",
71
71
  "react-router-dom": "6.4.1",
72
72
  "regenerator-runtime": "0.13.11",
73
- "semver": "7.3.7",
73
+ "semver": "7.5.2",
74
74
  "typescript": "4.8.3"
75
75
  },
76
76
  "devDependencies": {
@@ -96,11 +96,13 @@
96
96
  "eslint-plugin-jest": "27.0.4",
97
97
  "eslint-plugin-react": "7.31.8",
98
98
  "http-server": "14.0.0",
99
+ "husky": "8.0.3",
99
100
  "jest": "29.1.2",
100
101
  "jest-environment-jsdom": "29.1.2",
101
102
  "madge": "5.0.1",
102
103
  "marked": "4.0.10",
103
104
  "null-loader": "4.0.1",
105
+ "prettier": "2.8.8",
104
106
  "puppeteer": "18.0.5",
105
107
  "react-test-renderer": "16.13.1",
106
108
  "request": "2.88.2",
@@ -122,7 +124,9 @@
122
124
  "pig": "http-server ./PIG -p 4041 -s & webpack --config webpack/PIG.config.js --progress --watch",
123
125
  "build": "webpack --node-env=production --config webpack/production.config.js && webpack --config webpack/PIG.config.js",
124
126
  "test": "jest",
125
- "lint": "eslint . --ignore-path .gitignore --cache",
127
+ "lint": "eslint --ignore-path .gitignore --cache ./",
128
+ "lint:fix": "DEBUG=eslint:cli-engine eslint --ignore-path .gitignore --fix --cache ./",
129
+ "prettier": "prettier --write '{src,webpack}/**/*.js'",
126
130
  "generate": "node scripts/generate.js",
127
131
  "prepare": "webpack --config webpack/publish.config.js --progress",
128
132
  "start": "node ./Parse-Dashboard/index.js",
@@ -152,5 +156,17 @@
152
156
  "react-addons-test-utils",
153
157
  "fbjs"
154
158
  ]
159
+ },
160
+ "husky": {
161
+ "hooks": {
162
+ "pre-commit": "lint-staged"
163
+ }
164
+ },
165
+ "lint-staged": {
166
+ "{src,webpack}/{**/*,*}.js": [
167
+ "prettier --write",
168
+ "eslint --fix --cache",
169
+ "git add"
170
+ ]
155
171
  }
156
172
  }