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.
- package/Parse-Dashboard/Authentication.js +21 -21
- package/Parse-Dashboard/CLI/mfa.js +2 -2
- package/Parse-Dashboard/app.js +20 -20
- package/Parse-Dashboard/public/bundles/817.bundle.js +1 -1
- package/Parse-Dashboard/public/bundles/dashboard.bundle.js +1 -1
- package/Parse-Dashboard/server.js +14 -14
- package/README.md +118 -5
- package/package.json +20 -4
|
@@ -27,18 +27,18 @@ module.exports = (options) => {
|
|
|
27
27
|
process.exit(-1);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
const explicitConfigFileProvided = !!options.config;
|
|
31
31
|
let configFile = null;
|
|
32
32
|
let configFromCLI = null;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
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
|
-
|
|
160
|
-
|
|
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 >=4.4.0 <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 >=2.1.4 <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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
}
|