@openinc/parse-server-opendash 2.4.7 → 2.4.9
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/README.md +10 -0
- package/dist/config.js +60 -36
- package/dist/hooks/BDE_Page.js +3 -3
- package/dist/hooks/BDE_Result.js +1 -1
- package/dist/hooks/Dashboard.js +1 -1
- package/dist/hooks/_User.js +1 -1
- package/dist/index.d.ts +137 -6
- package/dist/index.js +204 -8
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -16,6 +16,16 @@ const { init } = require("@openinc/parse-server-opendash");
|
|
|
16
16
|
init();
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
For a full list of exports see the file at [EXPORTS.md](./EXPORTS.md)
|
|
20
|
+
|
|
21
|
+
## Configuration
|
|
22
|
+
|
|
23
|
+
The configuration of this cloud code is done using environment variables.
|
|
24
|
+
|
|
25
|
+
By default no classes will be created. To create classes from the schema definition, you need to enable the feature flags according your needs.
|
|
26
|
+
|
|
27
|
+
For a full list of options see the file at [CONFIG.md](./CONFIG.md)
|
|
28
|
+
|
|
19
29
|
## Development
|
|
20
30
|
|
|
21
31
|
See the file at [DEVELOPMENT.md](./DEVELOPMENT.md)
|
package/dist/config.js
CHANGED
|
@@ -9,7 +9,7 @@ const options = {
|
|
|
9
9
|
required: true,
|
|
10
10
|
secret: false,
|
|
11
11
|
public: true,
|
|
12
|
-
description: "
|
|
12
|
+
description: "This is not the Parse Server URL, but the URL of the web app.",
|
|
13
13
|
},
|
|
14
14
|
ENFORCE_APP_URL: {
|
|
15
15
|
env: "OPENINC_PARSE_ENFORCE_APP_URL",
|
|
@@ -17,7 +17,8 @@ const options = {
|
|
|
17
17
|
required: false,
|
|
18
18
|
secret: false,
|
|
19
19
|
public: true,
|
|
20
|
-
|
|
20
|
+
default: "false",
|
|
21
|
+
description: "If this setting is enabled, the app will redirect to the APP_URL if the request is not coming from this URL.",
|
|
21
22
|
},
|
|
22
23
|
APP_TITLE: {
|
|
23
24
|
env: "OPENINC_PARSE_APP_TITLE",
|
|
@@ -26,7 +27,7 @@ const options = {
|
|
|
26
27
|
secret: false,
|
|
27
28
|
public: true,
|
|
28
29
|
default: "open.DASH",
|
|
29
|
-
description: "
|
|
30
|
+
description: "Title of the application.",
|
|
30
31
|
},
|
|
31
32
|
APP_COPYRIGHT_TEXT: {
|
|
32
33
|
env: "OPENINC_PARSE_APP_COPYRIGHT_TEXT",
|
|
@@ -35,7 +36,7 @@ const options = {
|
|
|
35
36
|
secret: false,
|
|
36
37
|
public: true,
|
|
37
38
|
default: "Powered by open.INC",
|
|
38
|
-
description: "
|
|
39
|
+
description: "Text which is displayed in the footer of the application.",
|
|
39
40
|
},
|
|
40
41
|
APP_COPYRIGHT_LINK: {
|
|
41
42
|
env: "OPENINC_PARSE_APP_COPYRIGHT_LINK",
|
|
@@ -44,7 +45,7 @@ const options = {
|
|
|
44
45
|
secret: false,
|
|
45
46
|
public: true,
|
|
46
47
|
default: "https://openinc.de/",
|
|
47
|
-
description: "
|
|
48
|
+
description: "Link which is used for the copyright in the footer of the application.",
|
|
48
49
|
},
|
|
49
50
|
APP_IMPRINT_URL: {
|
|
50
51
|
env: "OPENINC_PARSE_APP_IMPRINT_URL",
|
|
@@ -52,7 +53,7 @@ const options = {
|
|
|
52
53
|
required: false,
|
|
53
54
|
secret: false,
|
|
54
55
|
public: true,
|
|
55
|
-
description: "
|
|
56
|
+
description: "Link to the imprint of the application.",
|
|
56
57
|
},
|
|
57
58
|
APP_DATA_PROTECTION_URL: {
|
|
58
59
|
env: "OPENINC_PARSE_APP_DATA_PROTECTION_URL",
|
|
@@ -60,7 +61,7 @@ const options = {
|
|
|
60
61
|
required: false,
|
|
61
62
|
secret: false,
|
|
62
63
|
public: true,
|
|
63
|
-
description: "
|
|
64
|
+
description: "Link to the data protection policy of the application.",
|
|
64
65
|
},
|
|
65
66
|
APP_TOS_URL: {
|
|
66
67
|
env: "OPENINC_PARSE_APP_TOS_URL",
|
|
@@ -68,7 +69,7 @@ const options = {
|
|
|
68
69
|
required: false,
|
|
69
70
|
secret: false,
|
|
70
71
|
public: true,
|
|
71
|
-
description: "
|
|
72
|
+
description: "Link to the terms of service of the application.",
|
|
72
73
|
},
|
|
73
74
|
APP_NOTIFICATIONS_PER_EMAIL: {
|
|
74
75
|
env: "OPENINC_PARSE_APP_NOTIFICATIONS_PER_EMAIL",
|
|
@@ -76,7 +77,8 @@ const options = {
|
|
|
76
77
|
required: false,
|
|
77
78
|
secret: false,
|
|
78
79
|
public: true,
|
|
79
|
-
|
|
80
|
+
default: "false",
|
|
81
|
+
description: "Whether to send notifications via e-mail or not.",
|
|
80
82
|
dependencies: ["SMTP_ENABLED"],
|
|
81
83
|
},
|
|
82
84
|
AUTH_SIGNUP_ENABLED: {
|
|
@@ -85,7 +87,8 @@ const options = {
|
|
|
85
87
|
required: false,
|
|
86
88
|
secret: false,
|
|
87
89
|
public: true,
|
|
88
|
-
|
|
90
|
+
default: "false",
|
|
91
|
+
description: "If set to false, users will not be able to sign up - users must be created by an admin.",
|
|
89
92
|
},
|
|
90
93
|
AUTH_SIGNUP_REQUIRE_TENANT: {
|
|
91
94
|
env: "OPENINC_PARSE_AUTH_SIGNUP_REQUIRE_TENANT",
|
|
@@ -93,7 +96,8 @@ const options = {
|
|
|
93
96
|
required: false,
|
|
94
97
|
secret: false,
|
|
95
98
|
public: true,
|
|
96
|
-
|
|
99
|
+
default: "false",
|
|
100
|
+
description: "If set to true, users must have a tenant when signing up.",
|
|
97
101
|
},
|
|
98
102
|
AUTH_VERIFY_EMAIL: {
|
|
99
103
|
env: "OPENINC_PARSE_AUTH_VERIFY_EMAIL",
|
|
@@ -101,7 +105,8 @@ const options = {
|
|
|
101
105
|
required: false,
|
|
102
106
|
secret: false,
|
|
103
107
|
public: true,
|
|
104
|
-
|
|
108
|
+
default: "false",
|
|
109
|
+
description: "If set to true, users must verify their e-mail address before they can log in.",
|
|
105
110
|
dependencies: ["SMTP_ENABLED"],
|
|
106
111
|
},
|
|
107
112
|
AUTH_VERIFY_TENANT: {
|
|
@@ -110,7 +115,8 @@ const options = {
|
|
|
110
115
|
required: false,
|
|
111
116
|
secret: false,
|
|
112
117
|
public: true,
|
|
113
|
-
|
|
118
|
+
default: "false",
|
|
119
|
+
description: "If set to true, users must be verified by a tenant admin before they can log in.",
|
|
114
120
|
},
|
|
115
121
|
AUTH_ALLOW_USERNAME: {
|
|
116
122
|
env: "OPENINC_PARSE_AUTH_ALLOW_USERNAME",
|
|
@@ -118,7 +124,8 @@ const options = {
|
|
|
118
124
|
required: false,
|
|
119
125
|
secret: false,
|
|
120
126
|
public: true,
|
|
121
|
-
|
|
127
|
+
default: "false",
|
|
128
|
+
description: "If set to true, users can sign up and login using a username. If set to false, the email will be used as the username.",
|
|
122
129
|
},
|
|
123
130
|
AUTH_ALLOW_PASSWORDLESS_LOGIN: {
|
|
124
131
|
env: "OPENINC_PARSE_AUTH_ALLOW_PASSWORDLESS_LOGIN",
|
|
@@ -126,7 +133,8 @@ const options = {
|
|
|
126
133
|
required: false,
|
|
127
134
|
secret: false,
|
|
128
135
|
public: true,
|
|
129
|
-
|
|
136
|
+
default: "false",
|
|
137
|
+
description: "If set to true, users will be able to login without a password, for example using a magic link sent to their email address.",
|
|
130
138
|
},
|
|
131
139
|
AUTH_ALLOW_PASSWORDLESS_SIGNUP: {
|
|
132
140
|
env: "OPENINC_PARSE_AUTH_ALLOW_PASSWORDLESS_SIGNUP",
|
|
@@ -134,7 +142,8 @@ const options = {
|
|
|
134
142
|
required: false,
|
|
135
143
|
secret: false,
|
|
136
144
|
public: true,
|
|
137
|
-
|
|
145
|
+
default: "false",
|
|
146
|
+
description: "If set to true, users will be able to sign up without a password, for example using a magic link sent to their email address.",
|
|
138
147
|
},
|
|
139
148
|
AUTH_PASSWORD_MIN_LENGTH: {
|
|
140
149
|
env: "OPENINC_PARSE_AUTH_PASSWORD_MIN_LENGTH",
|
|
@@ -143,7 +152,7 @@ const options = {
|
|
|
143
152
|
secret: false,
|
|
144
153
|
public: true,
|
|
145
154
|
default: "8",
|
|
146
|
-
description: "
|
|
155
|
+
description: "Minimum length of the password.",
|
|
147
156
|
},
|
|
148
157
|
AUTOLOAD_DIR: {
|
|
149
158
|
env: "OPENINC_PARSE_CLOUDCODE_AUTOLOAD_DIR",
|
|
@@ -159,6 +168,7 @@ const options = {
|
|
|
159
168
|
required: false,
|
|
160
169
|
secret: false,
|
|
161
170
|
public: true,
|
|
171
|
+
default: "false",
|
|
162
172
|
description: "Enable Parse Classes and Cloud Code for core features.",
|
|
163
173
|
},
|
|
164
174
|
FEATURE_MONITORING: {
|
|
@@ -167,6 +177,7 @@ const options = {
|
|
|
167
177
|
required: false,
|
|
168
178
|
secret: false,
|
|
169
179
|
public: true,
|
|
180
|
+
default: "false",
|
|
170
181
|
description: "Enable Parse Classes and Cloud Code for the Monitoring plugin.",
|
|
171
182
|
},
|
|
172
183
|
FEATURE_BDE: {
|
|
@@ -175,6 +186,7 @@ const options = {
|
|
|
175
186
|
required: false,
|
|
176
187
|
secret: false,
|
|
177
188
|
public: true,
|
|
189
|
+
default: "false",
|
|
178
190
|
description: "Enable Parse Classes and Cloud Code for the BDE plugin.",
|
|
179
191
|
},
|
|
180
192
|
FEATURE_GTFS: {
|
|
@@ -183,6 +195,7 @@ const options = {
|
|
|
183
195
|
required: false,
|
|
184
196
|
secret: false,
|
|
185
197
|
public: true,
|
|
198
|
+
default: "false",
|
|
186
199
|
description: "Enable Parse Classes and Cloud Code for the GTFS plugin.",
|
|
187
200
|
},
|
|
188
201
|
FEATURE_KNOWLEDGE: {
|
|
@@ -191,6 +204,7 @@ const options = {
|
|
|
191
204
|
required: false,
|
|
192
205
|
secret: false,
|
|
193
206
|
public: true,
|
|
207
|
+
default: "false",
|
|
194
208
|
description: "Enable Parse Classes and Cloud Code for the open.KNOWLEDGE plugin.",
|
|
195
209
|
},
|
|
196
210
|
FEATURE_MAINTENANCE: {
|
|
@@ -199,6 +213,7 @@ const options = {
|
|
|
199
213
|
required: false,
|
|
200
214
|
secret: false,
|
|
201
215
|
public: true,
|
|
216
|
+
default: "false",
|
|
202
217
|
description: "Enable Parse Classes and Cloud Code for the open.SERVICE plugin.",
|
|
203
218
|
},
|
|
204
219
|
FEATURE_MIAAS: {
|
|
@@ -207,6 +222,7 @@ const options = {
|
|
|
207
222
|
required: false,
|
|
208
223
|
secret: false,
|
|
209
224
|
public: true,
|
|
225
|
+
default: "false",
|
|
210
226
|
description: "Enable Parse Classes and Cloud Code for the MIAAS plugin.",
|
|
211
227
|
},
|
|
212
228
|
FORCE_SCHEMA: {
|
|
@@ -215,6 +231,7 @@ const options = {
|
|
|
215
231
|
required: false,
|
|
216
232
|
secret: false,
|
|
217
233
|
public: false,
|
|
234
|
+
default: "false",
|
|
218
235
|
description: "This will force the schema to be updated on startup including removing fields and classes, which is a destructive operation and can result in data loss.",
|
|
219
236
|
},
|
|
220
237
|
EMAIL_TEMPLATE_DIR: {
|
|
@@ -223,7 +240,7 @@ const options = {
|
|
|
223
240
|
required: false,
|
|
224
241
|
secret: false,
|
|
225
242
|
public: false,
|
|
226
|
-
description: "
|
|
243
|
+
description: "The directory where the email templates are stored. The default is 'views/emails'.",
|
|
227
244
|
default: "views/emails",
|
|
228
245
|
},
|
|
229
246
|
SMTP_ENABLED: {
|
|
@@ -232,7 +249,8 @@ const options = {
|
|
|
232
249
|
required: false,
|
|
233
250
|
secret: false,
|
|
234
251
|
public: true,
|
|
235
|
-
|
|
252
|
+
default: "false",
|
|
253
|
+
description: "Enable SMTP for sending e-mails.",
|
|
236
254
|
dependencies: [
|
|
237
255
|
"SMTP_HOST",
|
|
238
256
|
"SMTP_PORT",
|
|
@@ -288,6 +306,7 @@ const options = {
|
|
|
288
306
|
required: false,
|
|
289
307
|
secret: false,
|
|
290
308
|
public: false,
|
|
309
|
+
default: "false",
|
|
291
310
|
description: "E-Mail from/sender E-Mail",
|
|
292
311
|
},
|
|
293
312
|
SMTP_IGNORE_TLS: {
|
|
@@ -296,6 +315,7 @@ const options = {
|
|
|
296
315
|
required: false,
|
|
297
316
|
secret: false,
|
|
298
317
|
public: false,
|
|
318
|
+
default: "false",
|
|
299
319
|
description: "E-Mail from/sender E-Mail",
|
|
300
320
|
},
|
|
301
321
|
WEB_PUSH_ENABLED: {
|
|
@@ -304,7 +324,8 @@ const options = {
|
|
|
304
324
|
required: false,
|
|
305
325
|
secret: false,
|
|
306
326
|
public: true,
|
|
307
|
-
|
|
327
|
+
default: "false",
|
|
328
|
+
description: "Enable Web Push Notifications.",
|
|
308
329
|
dependencies: [
|
|
309
330
|
"WEB_PUSH_HOST",
|
|
310
331
|
"WEB_PUSH_ICON",
|
|
@@ -319,7 +340,7 @@ const options = {
|
|
|
319
340
|
required: false,
|
|
320
341
|
secret: false,
|
|
321
342
|
public: false,
|
|
322
|
-
description: "
|
|
343
|
+
description: "First/subject paramter of setVapidDetails() from https://www.npmjs.com/package/web-push",
|
|
323
344
|
},
|
|
324
345
|
WEB_PUSH_ICON: {
|
|
325
346
|
env: "OPENINC_PARSE_WEB_PUSH_ICON",
|
|
@@ -327,7 +348,7 @@ const options = {
|
|
|
327
348
|
required: false,
|
|
328
349
|
secret: false,
|
|
329
350
|
public: false,
|
|
330
|
-
description: "
|
|
351
|
+
description: "Icon URL for the push notifications.",
|
|
331
352
|
},
|
|
332
353
|
WEB_PUSH_VAPID_PUBLIC_KEY: {
|
|
333
354
|
env: "OPENINC_PARSE_WEB_PUSH_VAPID_PUBLIC_KEY",
|
|
@@ -335,7 +356,7 @@ const options = {
|
|
|
335
356
|
required: false,
|
|
336
357
|
secret: true,
|
|
337
358
|
public: false,
|
|
338
|
-
description: "
|
|
359
|
+
description: "Second paramter of setVapidDetails() from https://www.npmjs.com/package/web-push",
|
|
339
360
|
},
|
|
340
361
|
WEB_PUSH_VAPID_PRIVATE_KEY: {
|
|
341
362
|
env: "OPENINC_PARSE_WEB_PUSH_VAPID_PRIVATE_KEY",
|
|
@@ -343,7 +364,7 @@ const options = {
|
|
|
343
364
|
required: false,
|
|
344
365
|
secret: true,
|
|
345
366
|
public: false,
|
|
346
|
-
description: "
|
|
367
|
+
description: "Third paramter of setVapidDetails() from https://www.npmjs.com/package/web-push",
|
|
347
368
|
},
|
|
348
369
|
WEB_PUSH_FCM_KEY: {
|
|
349
370
|
env: "OPENINC_PARSE_WEB_PUSH_FCM_KEY",
|
|
@@ -351,7 +372,7 @@ const options = {
|
|
|
351
372
|
required: false,
|
|
352
373
|
secret: true,
|
|
353
374
|
public: false,
|
|
354
|
-
description: "
|
|
375
|
+
description: "First paramter of setGCMAPIKey() from https://www.npmjs.com/package/web-push",
|
|
355
376
|
},
|
|
356
377
|
GEO_VECTOR_STYLE: {
|
|
357
378
|
env: "OPENINC_PARSE_GEO_VECTOR_STYLE",
|
|
@@ -359,7 +380,7 @@ const options = {
|
|
|
359
380
|
required: false,
|
|
360
381
|
secret: false,
|
|
361
382
|
public: true,
|
|
362
|
-
description: "
|
|
383
|
+
description: "URL to the vector style file for mapgl.",
|
|
363
384
|
},
|
|
364
385
|
GEO_GOOGLE_ENABLED: {
|
|
365
386
|
env: "OPENINC_PARSE_GEO_GOOGLE_ENABLED",
|
|
@@ -367,7 +388,8 @@ const options = {
|
|
|
367
388
|
required: false,
|
|
368
389
|
secret: false,
|
|
369
390
|
public: true,
|
|
370
|
-
|
|
391
|
+
default: "false",
|
|
392
|
+
description: "Enable Google Maps for geocoding and routing.",
|
|
371
393
|
dependencies: ["GEO_GOOGLE_API_KEY"],
|
|
372
394
|
},
|
|
373
395
|
GEO_GOOGLE_API_KEY: {
|
|
@@ -376,7 +398,7 @@ const options = {
|
|
|
376
398
|
required: false,
|
|
377
399
|
secret: true,
|
|
378
400
|
public: false,
|
|
379
|
-
description: "
|
|
401
|
+
description: "Google Maps API Key. Needs places, autocomplate, geocoding and routing permissions.",
|
|
380
402
|
},
|
|
381
403
|
GEO_GRAPHHOPPER_ENABLED: {
|
|
382
404
|
env: "OPENINC_PARSE_GEO_GRAPHHOPPER_ENABLED",
|
|
@@ -384,7 +406,8 @@ const options = {
|
|
|
384
406
|
required: false,
|
|
385
407
|
secret: false,
|
|
386
408
|
public: true,
|
|
387
|
-
|
|
409
|
+
default: "false",
|
|
410
|
+
description: "Enable Graphhopper for geocding and routing.",
|
|
388
411
|
dependencies: ["GEO_GRAPHHOPPER_HOST", "GEO_GRAPHHOPPER_API_KEY"],
|
|
389
412
|
},
|
|
390
413
|
GEO_GRAPHHOPPER_HOST: {
|
|
@@ -393,7 +416,7 @@ const options = {
|
|
|
393
416
|
required: false,
|
|
394
417
|
secret: false,
|
|
395
418
|
public: false,
|
|
396
|
-
description: "
|
|
419
|
+
description: "Host of the Graphhopper API. The hosted service URL is https://graphhopper.com/api/1/",
|
|
397
420
|
},
|
|
398
421
|
GEO_GRAPHHOPPER_API_KEY: {
|
|
399
422
|
env: "OPENINC_PARSE_GEO_GRAPHHOPPER_API_KEY",
|
|
@@ -401,7 +424,7 @@ const options = {
|
|
|
401
424
|
required: false,
|
|
402
425
|
secret: true,
|
|
403
426
|
public: false,
|
|
404
|
-
description: "
|
|
427
|
+
description: "Graphhopper API Key.",
|
|
405
428
|
},
|
|
406
429
|
OPENWARE: {
|
|
407
430
|
env: "PARSE_SERVER_OPENWARE",
|
|
@@ -409,6 +432,7 @@ const options = {
|
|
|
409
432
|
required: false,
|
|
410
433
|
secret: false,
|
|
411
434
|
public: true,
|
|
435
|
+
default: "false",
|
|
412
436
|
description: "Enable open.WARE Cloud Code features.",
|
|
413
437
|
},
|
|
414
438
|
OPENWARE_BASEURL: {
|
|
@@ -417,7 +441,7 @@ const options = {
|
|
|
417
441
|
required: false,
|
|
418
442
|
secret: false,
|
|
419
443
|
public: false,
|
|
420
|
-
description: "
|
|
444
|
+
description: "Base URL of the open.WARE API.",
|
|
421
445
|
},
|
|
422
446
|
OPENWARE_JWT_SECRET: {
|
|
423
447
|
env: "PARSE_SERVER_OPENWARE_JWT_SECRET",
|
|
@@ -425,7 +449,7 @@ const options = {
|
|
|
425
449
|
required: false,
|
|
426
450
|
secret: false,
|
|
427
451
|
public: false,
|
|
428
|
-
description: "
|
|
452
|
+
description: "Secret for the JWT tokens for open.WARE.",
|
|
429
453
|
},
|
|
430
454
|
OPENWARE_JWT_ISS: {
|
|
431
455
|
env: "PARSE_SERVER_OPENWARE_JWT_ISS",
|
|
@@ -433,7 +457,7 @@ const options = {
|
|
|
433
457
|
required: false,
|
|
434
458
|
secret: false,
|
|
435
459
|
public: false,
|
|
436
|
-
description: "
|
|
460
|
+
description: "Issuer of the JWT tokens for open.WARE.",
|
|
437
461
|
},
|
|
438
462
|
OPENWARE_JWT_ADMIN_EMAIL: {
|
|
439
463
|
env: "PARSE_SERVER_OPENWARE_JWT_ADMIN_EMAIL",
|
|
@@ -441,7 +465,7 @@ const options = {
|
|
|
441
465
|
required: false,
|
|
442
466
|
secret: false,
|
|
443
467
|
public: false,
|
|
444
|
-
description: "
|
|
468
|
+
description: "E-Mail of the admin user for open.WARE.",
|
|
445
469
|
},
|
|
446
470
|
OPENWARE_JWT_TOKEN: {
|
|
447
471
|
env: "PARSE_SERVER_OPENWARE_JWT_TOKEN",
|
|
@@ -449,7 +473,7 @@ const options = {
|
|
|
449
473
|
required: false,
|
|
450
474
|
secret: false,
|
|
451
475
|
public: false,
|
|
452
|
-
description: "
|
|
476
|
+
description: "Use the given JWT token instead of creating a new one.",
|
|
453
477
|
},
|
|
454
478
|
};
|
|
455
479
|
exports.config = new Config_1.Config(options);
|
package/dist/hooks/BDE_Page.js
CHANGED
|
@@ -7,7 +7,7 @@ async function init() {
|
|
|
7
7
|
(0, __1.beforeSaveHook)(types_1.BDE_Page, async (request) => {
|
|
8
8
|
const { object, original, user } = request;
|
|
9
9
|
request.context.dirtyKeys = object.dirtyKeys();
|
|
10
|
-
const query = new Parse.Query(
|
|
10
|
+
const query = new Parse.Query(types_1.BDE_Form).equalTo("entries", [object.id]);
|
|
11
11
|
const affectedForms = await query.find({ useMasterKey: true });
|
|
12
12
|
const aclCandidates = {};
|
|
13
13
|
affectedForms.forEach((form) => {
|
|
@@ -28,7 +28,7 @@ async function init() {
|
|
|
28
28
|
});
|
|
29
29
|
(0, __1.afterSaveHook)(types_1.BDE_Page, async (request) => {
|
|
30
30
|
const { object, original, user } = request;
|
|
31
|
-
const query = new Parse.Query(
|
|
31
|
+
const query = new Parse.Query(types_1.BDE_Form).equalTo("entries", [object.id]);
|
|
32
32
|
const affectedForms = await query.find({ useMasterKey: true });
|
|
33
33
|
const dirtyKeys = request.context.dirtyKeys;
|
|
34
34
|
if (dirtyKeys.length > 0 && dirtyKeys[0] !== "acl")
|
|
@@ -36,7 +36,7 @@ async function init() {
|
|
|
36
36
|
});
|
|
37
37
|
(0, __1.afterDeleteHook)(types_1.BDE_Page, async (request) => {
|
|
38
38
|
const { object, original, user } = request;
|
|
39
|
-
const query = new Parse.Query(
|
|
39
|
+
const query = new Parse.Query(types_1.BDE_Form).equalTo("entries", [object.id]);
|
|
40
40
|
const affectedForms = await query.find({ useMasterKey: true });
|
|
41
41
|
await Parse.Object.saveAll(affectedForms, { useMasterKey: true });
|
|
42
42
|
});
|
package/dist/hooks/BDE_Result.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.init = void 0;
|
|
4
4
|
const __1 = require("..");
|
|
5
|
-
const types_1 = require("../types");
|
|
6
5
|
const ow_1 = require("../ow");
|
|
6
|
+
const types_1 = require("../types");
|
|
7
7
|
async function init() {
|
|
8
8
|
(0, __1.beforeSaveHook)(types_1.BDE_Result, async (request) => {
|
|
9
9
|
const { object, original, user } = request;
|
package/dist/hooks/Dashboard.js
CHANGED
|
@@ -16,7 +16,7 @@ async function init() {
|
|
|
16
16
|
if (acl && Array.isArray(widgetIds) && widgetIds.length > 0) {
|
|
17
17
|
for (const widgetId of widgetIds) {
|
|
18
18
|
try {
|
|
19
|
-
const widget = new
|
|
19
|
+
const widget = new types_1.Widget({
|
|
20
20
|
objectId: widgetId,
|
|
21
21
|
});
|
|
22
22
|
await widget.fetch({ useMasterKey: true });
|
package/dist/hooks/_User.js
CHANGED
|
@@ -21,7 +21,7 @@ async function init() {
|
|
|
21
21
|
!!user.get("emailVerified") &&
|
|
22
22
|
!user.get("tenantVerified")) {
|
|
23
23
|
const email = user.get("email");
|
|
24
|
-
const domains = await new Parse.Query(
|
|
24
|
+
const domains = await new Parse.Query(types_1.TenantTrustedDomain)
|
|
25
25
|
.equalTo("tenant", tenant)
|
|
26
26
|
.find({ useMasterKey: true });
|
|
27
27
|
for (const domain of domains) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,30 +1,104 @@
|
|
|
1
1
|
import type { Cloud as ParseCloud } from "parse";
|
|
2
|
-
|
|
2
|
+
import { Permission } from "./types";
|
|
3
3
|
export { sendSimpleEmail, sendTemplateEmail } from "./hooks/Core_Email";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Initializes the Cloud Code for open.DASH.
|
|
6
|
+
* This function performs various initialization tasks such as
|
|
7
|
+
* initializing configuration, setting up email transport, initializing web push,
|
|
8
|
+
* initializing class schema, setting up default roles, initializing parse lifecycle hooks,
|
|
9
|
+
* loading default data, initializing cloud functions, and setting up cloud code autoloading.
|
|
10
|
+
*
|
|
11
|
+
* @returns {Promise<void>} A promise that resolves when the initialization is complete.
|
|
12
|
+
*/
|
|
8
13
|
export declare function init(): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Checks if a user has a specific permission in OD3_Permission.
|
|
16
|
+
* @param sessionToken - The session token of the user.
|
|
17
|
+
* @param key - The key of the permission to check.
|
|
18
|
+
* @returns A promise that resolves to a boolean indicating whether the user has the permission.
|
|
19
|
+
*/
|
|
9
20
|
export declare function hasPermission(sessionToken: string, key: string): Promise<boolean>;
|
|
21
|
+
/**
|
|
22
|
+
* Checks if the user has the required permission to perform an operation using hasPermission().
|
|
23
|
+
* If the user does not have the required permission, an error is thrown.
|
|
24
|
+
*
|
|
25
|
+
* @param request - The request object containing the user's session token and masterkey status.
|
|
26
|
+
* @param key - The permission key required for the operation.
|
|
27
|
+
* @param message - The error message to be thrown if the user does not have the required permission.
|
|
28
|
+
* @returns A Promise that resolves if the user has the required permission, or throws an error if not.
|
|
29
|
+
*/
|
|
10
30
|
export declare function requirePermission(request: {
|
|
11
31
|
master?: boolean;
|
|
12
32
|
sessionToken: string | undefined;
|
|
13
33
|
}, key: string | null, message: string): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Retrieves the value of a configuration key from OD3_Config.
|
|
36
|
+
* @param key - The key of the configuration to retrieve.
|
|
37
|
+
* @returns A promise that resolves to the value of the configuration key, or undefined if not found.
|
|
38
|
+
*/
|
|
14
39
|
export declare function getConfig(key: string): Promise<string | undefined>;
|
|
40
|
+
/**
|
|
41
|
+
* Retrieves the value of a configuration key from OD3_Config as a boolean
|
|
42
|
+
* Converts the string value to a boolean value using the following rules:
|
|
43
|
+
* - "true" or "1" -> true
|
|
44
|
+
* - "false" or "0" -> false
|
|
45
|
+
* - undefined/null -> false
|
|
46
|
+
* - Any other value -> true
|
|
47
|
+
*
|
|
48
|
+
* @param key - The key of the configuration value.
|
|
49
|
+
* @returns A boolean value indicating the configuration value.
|
|
50
|
+
*/
|
|
15
51
|
export declare function getConfigBoolean(key: string): Promise<boolean>;
|
|
52
|
+
/**
|
|
53
|
+
* Ensures the existence of a role with the specified name.
|
|
54
|
+
* If the role does not exist, it creates a new role with the given name and options.
|
|
55
|
+
* If the role already exists, it updates the role with the provided options.
|
|
56
|
+
*
|
|
57
|
+
* @param name - The name of the role.
|
|
58
|
+
* @param options - Optional parameters for the role.
|
|
59
|
+
* @param options.label - The label for the role.
|
|
60
|
+
* @param options.acl - The Parse.ACL for the role.
|
|
61
|
+
* @param options.childRoles - An array of child role names to be associated with the role.
|
|
62
|
+
* @returns A Promise that resolves when the role is successfully created or updated.
|
|
63
|
+
*/
|
|
16
64
|
export declare function ensureRole(name: string, options?: {
|
|
17
65
|
label?: string;
|
|
18
66
|
acl?: Parse.ACL;
|
|
19
67
|
childRoles?: string[];
|
|
20
68
|
}): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Ensures that a user has a specific role.
|
|
71
|
+
* @param user The user to assign the role to.
|
|
72
|
+
* @param roleName The name of the role.
|
|
73
|
+
* @param add Specifies whether to add or remove the user from the role. Default is false (remove).
|
|
74
|
+
*/
|
|
21
75
|
export declare function ensureUserRole(user: Parse.User, roleName: string, add?: boolean): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Checks if a field is immutable and throws an error if an attempt is made to edit it in a beforeSave hook.
|
|
78
|
+
*
|
|
79
|
+
* This will not throw an error if the request is made with the master key.
|
|
80
|
+
*
|
|
81
|
+
* @param request - The request object containing the original and object Parse objects, master flag, and session token.
|
|
82
|
+
* @param fieldName - The name of the field to check for immutability.
|
|
83
|
+
* @param permissionName - The name of the permission required to edit the field. Defaults to "parse:edit-immutable-fields".
|
|
84
|
+
* @returns Promise<void>
|
|
85
|
+
*/
|
|
22
86
|
export declare function immutableField(request: {
|
|
23
87
|
original?: Parse.Object;
|
|
24
88
|
object: Parse.Object;
|
|
25
89
|
master?: boolean;
|
|
26
90
|
sessionToken: string | undefined;
|
|
27
91
|
}, fieldName: string, permissionName?: string | null): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Handles the default beforeSave() logic for a Parse.Object.
|
|
94
|
+
*
|
|
95
|
+
* This function will check if a user or tenant field is present in the schema and set the value to the current user and/or the tenant of the current user if not provided.
|
|
96
|
+
* This will also mark the user and tenant fields as immutable, preventing them from being edited in the future.
|
|
97
|
+
*
|
|
98
|
+
* @param request - The Parse.Cloud.BeforeSaveRequest object.
|
|
99
|
+
* @returns - Returns void.
|
|
100
|
+
* @throws - Throws an error if the user is not provided.
|
|
101
|
+
*/
|
|
28
102
|
export declare function defaultHandler(request: {
|
|
29
103
|
original?: Parse.Object;
|
|
30
104
|
object: Parse.Object;
|
|
@@ -32,6 +106,17 @@ export declare function defaultHandler(request: {
|
|
|
32
106
|
master?: boolean;
|
|
33
107
|
sessionToken: string | undefined;
|
|
34
108
|
}): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* Handles the default Parse.ACL beforeSave() logic for a Parse.Object.
|
|
111
|
+
*
|
|
112
|
+
* This function will set the default ACL for the object based on the user and tenant fields. By default, the object will be readable and writable by the tenant role and readable by tenant users.
|
|
113
|
+
*
|
|
114
|
+
* @param request - The Parse.Cloud.BeforeSaveRequest object.
|
|
115
|
+
* @param options - Optional configuration options.
|
|
116
|
+
* @param options.allowCustomACL - Whether to allow custom ACL (default: false).
|
|
117
|
+
* @param options.allowTenantUserWrite - Whether to allow tenant users to write (default: false).
|
|
118
|
+
* @param options.denyTenantUserRead - Whether to deny tenant users from reading (default: false).
|
|
119
|
+
*/
|
|
35
120
|
export declare function defaultAclHandler(request: Parse.Cloud.BeforeSaveRequest, options?: {
|
|
36
121
|
allowCustomACL?: boolean;
|
|
37
122
|
allowTenantUserWrite?: boolean;
|
|
@@ -40,26 +125,72 @@ export declare function defaultAclHandler(request: Parse.Cloud.BeforeSaveRequest
|
|
|
40
125
|
type beforeSaveHookType<T extends Parse.Object<Parse.Attributes>> = (request: ParseCloud.BeforeSaveRequest<T> & {
|
|
41
126
|
sessionToken: string | undefined;
|
|
42
127
|
}) => Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* Registers a beforeSave hook for a Parse class. In comparison to Parse.Cloud.beforeSave(), this function allows multiple beforeSave hooks to be registered for the same class.
|
|
130
|
+
*
|
|
131
|
+
* @template T - The type of the Parse.Object.
|
|
132
|
+
* @param {string | { new (): T }} target - The name of the Parse class or the class itself.
|
|
133
|
+
* @param {beforeSaveHookType<T>} callback - The callback function to be executed before saving the object.
|
|
134
|
+
* @returns {void}
|
|
135
|
+
*/
|
|
43
136
|
export declare function beforeSaveHook<T extends Parse.Object<Parse.Attributes>>(target: string | {
|
|
44
137
|
new (): T;
|
|
45
138
|
}, callback: beforeSaveHookType<T>): void;
|
|
46
139
|
type afterSaveHookType<T extends Parse.Object<Parse.Attributes>> = (request: ParseCloud.AfterSaveRequest<T> & {
|
|
47
140
|
sessionToken: string | undefined;
|
|
48
141
|
}) => Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* Registers a afterSave hook for a Parse class. In comparison to Parse.Cloud.afterSave(), this function allows multiple beforeSave hooks to be registered for the same class.
|
|
144
|
+
*
|
|
145
|
+
* @template T - The type of the Parse.Object.
|
|
146
|
+
* @param {string | { new (): T }} target - The name of the Parse class or the class itself.
|
|
147
|
+
* @param {afterSaveHookType<T>} callback - The callback function to be executed after saving the object.
|
|
148
|
+
* @returns {void}
|
|
149
|
+
*/
|
|
49
150
|
export declare function afterSaveHook<T extends Parse.Object<Parse.Attributes>>(target: string | {
|
|
50
151
|
new (): T;
|
|
51
152
|
}, callback: afterSaveHookType<T>): void;
|
|
52
153
|
type beforeDeleteHookType<T extends Parse.Object<Parse.Attributes>> = (request: ParseCloud.BeforeDeleteRequest<T> & {
|
|
53
154
|
sessionToken: string | undefined;
|
|
54
155
|
}) => Promise<void>;
|
|
156
|
+
/**
|
|
157
|
+
* Registers a beforeDelete hook for a Parse class. In comparison to Parse.Cloud.beforeDelete(), this function allows multiple beforeSave hooks to be registered for the same class.
|
|
158
|
+
*
|
|
159
|
+
* @template T - The type of the Parse.Object.
|
|
160
|
+
* @param {string | { new (): T }} target - The name of the Parse class or the class itself.
|
|
161
|
+
* @param {beforeDeleteHookType<T>} callback - The callback function to be executed before deleting an object.
|
|
162
|
+
*/
|
|
55
163
|
export declare function beforeDeleteHook<T extends Parse.Object<Parse.Attributes>>(target: string | {
|
|
56
164
|
new (): T;
|
|
57
165
|
}, callback: beforeDeleteHookType<T>): void;
|
|
58
166
|
type afterDeleteHookType<T extends Parse.Object<Parse.Attributes>> = (request: ParseCloud.AfterDeleteRequest<T> & {
|
|
59
167
|
sessionToken: string | undefined;
|
|
60
168
|
}) => Promise<void>;
|
|
169
|
+
/**
|
|
170
|
+
* Registers a afterDelete hook for a Parse class. In comparison to Parse.Cloud.afterDelete(), this function allows multiple beforeSave hooks to be registered for the same class.
|
|
171
|
+
*
|
|
172
|
+
* @template T - The type of the Parse.Object.
|
|
173
|
+
* @param {string | { new (): T }} target - The name of the Parse class or the class itself.
|
|
174
|
+
* @param {afterDeleteHookType<T>} callback - The callback function to be executed after a delete operation.
|
|
175
|
+
* @returns {void}
|
|
176
|
+
*/
|
|
61
177
|
export declare function afterDeleteHook<T extends Parse.Object<Parse.Attributes>>(target: string | {
|
|
62
178
|
new (): T;
|
|
63
179
|
}, callback: afterDeleteHookType<T>): void;
|
|
180
|
+
/**
|
|
181
|
+
* Autoloads cloud code files from the specified path. Each file MUST export an init() function that takes the file name (without it's extension) as an argument.
|
|
182
|
+
*
|
|
183
|
+
* @param path - The path to the directory containing the cloud code files.
|
|
184
|
+
* @param regex - Optional regular expression to filter the file names. Defaults to /^[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*$/.
|
|
185
|
+
* @returns A promise that resolves when all the cloud code files have been loaded and initialized.
|
|
186
|
+
*/
|
|
64
187
|
export declare function autoloadCloudCode(path: string, regex?: RegExp): Promise<void>;
|
|
65
|
-
|
|
188
|
+
/**
|
|
189
|
+
* Ensures that a OD3_Permission with the specified key exists in the database.
|
|
190
|
+
* If the permission already exists, it updates the ACL if provided.
|
|
191
|
+
* If the permission does not exist, it creates a new permission with the specified key and ACL.
|
|
192
|
+
* @param key - The key of the permission.
|
|
193
|
+
* @param acl - The Parse.ACL to be set for the permission.
|
|
194
|
+
* @returns The updated or newly created permission.
|
|
195
|
+
*/
|
|
196
|
+
export declare function ensurePermission(key: string, acl?: Parse.ACL): Promise<Permission>;
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.ensurePermission = exports.autoloadCloudCode = exports.afterDeleteHook = exports.beforeDeleteHook = exports.afterSaveHook = exports.beforeSaveHook = exports.defaultAclHandler = exports.defaultHandler = exports.immutableField = exports.ensureUserRole = exports.ensureRole = exports.getConfigBoolean = exports.getConfig = exports.requirePermission = exports.hasPermission = exports.init = exports.sendTemplateEmail = exports.sendSimpleEmail = void 0;
|
|
7
7
|
const parse_server_schema_1 = require("@openinc/parse-server-schema");
|
|
8
8
|
const fast_equals_1 = require("fast-equals");
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
@@ -15,13 +15,21 @@ const _init_1 = require("./functions/_init");
|
|
|
15
15
|
const Core_Email_1 = require("./hooks/Core_Email");
|
|
16
16
|
const _init_2 = require("./hooks/_init");
|
|
17
17
|
const types_1 = require("./types");
|
|
18
|
-
|
|
19
|
-
Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return Config_1.Config; } });
|
|
18
|
+
// export { Config } from "./helper/Config";
|
|
20
19
|
var Core_Email_2 = require("./hooks/Core_Email");
|
|
21
20
|
Object.defineProperty(exports, "sendSimpleEmail", { enumerable: true, get: function () { return Core_Email_2.sendSimpleEmail; } });
|
|
22
21
|
Object.defineProperty(exports, "sendTemplateEmail", { enumerable: true, get: function () { return Core_Email_2.sendTemplateEmail; } });
|
|
23
|
-
|
|
22
|
+
const PREFIX = "OD3_";
|
|
24
23
|
let schema = {};
|
|
24
|
+
/**
|
|
25
|
+
* Initializes the Cloud Code for open.DASH.
|
|
26
|
+
* This function performs various initialization tasks such as
|
|
27
|
+
* initializing configuration, setting up email transport, initializing web push,
|
|
28
|
+
* initializing class schema, setting up default roles, initializing parse lifecycle hooks,
|
|
29
|
+
* loading default data, initializing cloud functions, and setting up cloud code autoloading.
|
|
30
|
+
*
|
|
31
|
+
* @returns {Promise<void>} A promise that resolves when the initialization is complete.
|
|
32
|
+
*/
|
|
25
33
|
async function init() {
|
|
26
34
|
try {
|
|
27
35
|
const pkg = require("../package.json");
|
|
@@ -33,8 +41,8 @@ async function init() {
|
|
|
33
41
|
await initWebPush();
|
|
34
42
|
await initSchema();
|
|
35
43
|
await initDefaultRoles();
|
|
36
|
-
await initDefaultData();
|
|
37
44
|
await (0, _init_2.init)();
|
|
45
|
+
await initDefaultData();
|
|
38
46
|
await (0, _init_1.init)();
|
|
39
47
|
await initAutoload();
|
|
40
48
|
}
|
|
@@ -55,7 +63,7 @@ async function initSchema() {
|
|
|
55
63
|
const schemaConfig = await (0, parse_server_schema_1.loadConfig)();
|
|
56
64
|
try {
|
|
57
65
|
await (0, parse_server_schema_1.up)(schemaConfig, (0, path_1.resolve)(__dirname, "../schema"), {
|
|
58
|
-
prefix:
|
|
66
|
+
prefix: PREFIX,
|
|
59
67
|
deleteClasses: config_1.config.getBoolean("FORCE_SCHEMA"),
|
|
60
68
|
deleteFields: config_1.config.getBoolean("FORCE_SCHEMA"),
|
|
61
69
|
filter: (className) => isClassEnabled(className),
|
|
@@ -85,12 +93,49 @@ async function initDefaultRoles() {
|
|
|
85
93
|
}
|
|
86
94
|
async function initDefaultData() {
|
|
87
95
|
try {
|
|
88
|
-
|
|
96
|
+
const permissions = [await ensurePermission("parse-admin")];
|
|
97
|
+
const tenantCount = await new Parse.Query(types_1.Tenant).count({
|
|
98
|
+
useMasterKey: true,
|
|
99
|
+
});
|
|
100
|
+
if (tenantCount > 0) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const tenant = new types_1.Tenant({
|
|
104
|
+
label: "Default Tenant",
|
|
105
|
+
});
|
|
106
|
+
await tenant.save(null, { useMasterKey: true });
|
|
107
|
+
const password = await createRandomPassword();
|
|
108
|
+
const user = new Parse.User({
|
|
109
|
+
name: "Default User",
|
|
110
|
+
username: "openinc",
|
|
111
|
+
password: password,
|
|
112
|
+
email: "noreply@openinc.de",
|
|
113
|
+
emailVerified: true,
|
|
114
|
+
tenant,
|
|
115
|
+
tenantVerified: true,
|
|
116
|
+
tenantAdmin: true,
|
|
117
|
+
});
|
|
118
|
+
await user.save(null, { useMasterKey: true });
|
|
119
|
+
for (const permission of permissions) {
|
|
120
|
+
permission.getACL()?.setReadAccess(user, true);
|
|
121
|
+
await permission.save(null, { useMasterKey: true });
|
|
122
|
+
}
|
|
123
|
+
console.log("Default User and Tenant created.");
|
|
124
|
+
console.log("Username: " + user.get("username"));
|
|
125
|
+
console.log("Password: " + password);
|
|
126
|
+
console.log("User: " + user.id);
|
|
127
|
+
console.log("Tenant: " + tenant.id);
|
|
89
128
|
}
|
|
90
129
|
catch (error) {
|
|
91
130
|
console.error(error);
|
|
92
131
|
}
|
|
93
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Checks if a user has a specific permission in OD3_Permission.
|
|
135
|
+
* @param sessionToken - The session token of the user.
|
|
136
|
+
* @param key - The key of the permission to check.
|
|
137
|
+
* @returns A promise that resolves to a boolean indicating whether the user has the permission.
|
|
138
|
+
*/
|
|
94
139
|
async function hasPermission(sessionToken, key) {
|
|
95
140
|
const result = await new Parse.Query(types_1.Permission)
|
|
96
141
|
.equalTo("key", key)
|
|
@@ -98,6 +143,15 @@ async function hasPermission(sessionToken, key) {
|
|
|
98
143
|
return !!result;
|
|
99
144
|
}
|
|
100
145
|
exports.hasPermission = hasPermission;
|
|
146
|
+
/**
|
|
147
|
+
* Checks if the user has the required permission to perform an operation using hasPermission().
|
|
148
|
+
* If the user does not have the required permission, an error is thrown.
|
|
149
|
+
*
|
|
150
|
+
* @param request - The request object containing the user's session token and masterkey status.
|
|
151
|
+
* @param key - The permission key required for the operation.
|
|
152
|
+
* @param message - The error message to be thrown if the user does not have the required permission.
|
|
153
|
+
* @returns A Promise that resolves if the user has the required permission, or throws an error if not.
|
|
154
|
+
*/
|
|
101
155
|
async function requirePermission(request, key, message) {
|
|
102
156
|
if (request.master) {
|
|
103
157
|
return;
|
|
@@ -114,6 +168,11 @@ async function requirePermission(request, key, message) {
|
|
|
114
168
|
}
|
|
115
169
|
}
|
|
116
170
|
exports.requirePermission = requirePermission;
|
|
171
|
+
/**
|
|
172
|
+
* Retrieves the value of a configuration key from OD3_Config.
|
|
173
|
+
* @param key - The key of the configuration to retrieve.
|
|
174
|
+
* @returns A promise that resolves to the value of the configuration key, or undefined if not found.
|
|
175
|
+
*/
|
|
117
176
|
async function getConfig(key) {
|
|
118
177
|
const result = await new Parse.Query(types_1.Config).equalTo("key", key).first({
|
|
119
178
|
useMasterKey: true,
|
|
@@ -123,6 +182,17 @@ async function getConfig(key) {
|
|
|
123
182
|
return value || "";
|
|
124
183
|
}
|
|
125
184
|
exports.getConfig = getConfig;
|
|
185
|
+
/**
|
|
186
|
+
* Retrieves the value of a configuration key from OD3_Config as a boolean
|
|
187
|
+
* Converts the string value to a boolean value using the following rules:
|
|
188
|
+
* - "true" or "1" -> true
|
|
189
|
+
* - "false" or "0" -> false
|
|
190
|
+
* - undefined/null -> false
|
|
191
|
+
* - Any other value -> true
|
|
192
|
+
*
|
|
193
|
+
* @param key - The key of the configuration value.
|
|
194
|
+
* @returns A boolean value indicating the configuration value.
|
|
195
|
+
*/
|
|
126
196
|
async function getConfigBoolean(key) {
|
|
127
197
|
const value = await getConfig(key);
|
|
128
198
|
if (!value || value.toLowerCase() === "false" || value === "0") {
|
|
@@ -131,6 +201,18 @@ async function getConfigBoolean(key) {
|
|
|
131
201
|
return true;
|
|
132
202
|
}
|
|
133
203
|
exports.getConfigBoolean = getConfigBoolean;
|
|
204
|
+
/**
|
|
205
|
+
* Ensures the existence of a role with the specified name.
|
|
206
|
+
* If the role does not exist, it creates a new role with the given name and options.
|
|
207
|
+
* If the role already exists, it updates the role with the provided options.
|
|
208
|
+
*
|
|
209
|
+
* @param name - The name of the role.
|
|
210
|
+
* @param options - Optional parameters for the role.
|
|
211
|
+
* @param options.label - The label for the role.
|
|
212
|
+
* @param options.acl - The Parse.ACL for the role.
|
|
213
|
+
* @param options.childRoles - An array of child role names to be associated with the role.
|
|
214
|
+
* @returns A Promise that resolves when the role is successfully created or updated.
|
|
215
|
+
*/
|
|
134
216
|
async function ensureRole(name, options) {
|
|
135
217
|
const label = options?.label || undefined;
|
|
136
218
|
const acl = options?.acl || new Parse.ACL();
|
|
@@ -179,6 +261,12 @@ async function ensureRole(name, options) {
|
|
|
179
261
|
}
|
|
180
262
|
}
|
|
181
263
|
exports.ensureRole = ensureRole;
|
|
264
|
+
/**
|
|
265
|
+
* Ensures that a user has a specific role.
|
|
266
|
+
* @param user The user to assign the role to.
|
|
267
|
+
* @param roleName The name of the role.
|
|
268
|
+
* @param add Specifies whether to add or remove the user from the role. Default is false (remove).
|
|
269
|
+
*/
|
|
182
270
|
async function ensureUserRole(user, roleName, add = false) {
|
|
183
271
|
const role = await new Parse.Query(Parse.Role)
|
|
184
272
|
.equalTo("name", roleName)
|
|
@@ -196,6 +284,16 @@ async function ensureUserRole(user, roleName, add = false) {
|
|
|
196
284
|
}
|
|
197
285
|
}
|
|
198
286
|
exports.ensureUserRole = ensureUserRole;
|
|
287
|
+
/**
|
|
288
|
+
* Checks if a field is immutable and throws an error if an attempt is made to edit it in a beforeSave hook.
|
|
289
|
+
*
|
|
290
|
+
* This will not throw an error if the request is made with the master key.
|
|
291
|
+
*
|
|
292
|
+
* @param request - The request object containing the original and object Parse objects, master flag, and session token.
|
|
293
|
+
* @param fieldName - The name of the field to check for immutability.
|
|
294
|
+
* @param permissionName - The name of the permission required to edit the field. Defaults to "parse:edit-immutable-fields".
|
|
295
|
+
* @returns Promise<void>
|
|
296
|
+
*/
|
|
199
297
|
async function immutableField(request, fieldName, permissionName = "parse:edit-immutable-fields") {
|
|
200
298
|
if (!request.original || request.master) {
|
|
201
299
|
return;
|
|
@@ -208,6 +306,16 @@ async function immutableField(request, fieldName, permissionName = "parse:edit-i
|
|
|
208
306
|
await requirePermission(request, permissionName, `You are not allowed to edit the '${fieldName}' field.`);
|
|
209
307
|
}
|
|
210
308
|
exports.immutableField = immutableField;
|
|
309
|
+
/**
|
|
310
|
+
* Handles the default beforeSave() logic for a Parse.Object.
|
|
311
|
+
*
|
|
312
|
+
* This function will check if a user or tenant field is present in the schema and set the value to the current user and/or the tenant of the current user if not provided.
|
|
313
|
+
* This will also mark the user and tenant fields as immutable, preventing them from being edited in the future.
|
|
314
|
+
*
|
|
315
|
+
* @param request - The Parse.Cloud.BeforeSaveRequest object.
|
|
316
|
+
* @returns - Returns void.
|
|
317
|
+
* @throws - Throws an error if the user is not provided.
|
|
318
|
+
*/
|
|
211
319
|
async function defaultHandler(request) {
|
|
212
320
|
const className = request.object.className;
|
|
213
321
|
if (request.master) {
|
|
@@ -243,6 +351,17 @@ async function defaultHandler(request) {
|
|
|
243
351
|
}
|
|
244
352
|
}
|
|
245
353
|
exports.defaultHandler = defaultHandler;
|
|
354
|
+
/**
|
|
355
|
+
* Handles the default Parse.ACL beforeSave() logic for a Parse.Object.
|
|
356
|
+
*
|
|
357
|
+
* This function will set the default ACL for the object based on the user and tenant fields. By default, the object will be readable and writable by the tenant role and readable by tenant users.
|
|
358
|
+
*
|
|
359
|
+
* @param request - The Parse.Cloud.BeforeSaveRequest object.
|
|
360
|
+
* @param options - Optional configuration options.
|
|
361
|
+
* @param options.allowCustomACL - Whether to allow custom ACL (default: false).
|
|
362
|
+
* @param options.allowTenantUserWrite - Whether to allow tenant users to write (default: false).
|
|
363
|
+
* @param options.denyTenantUserRead - Whether to deny tenant users from reading (default: false).
|
|
364
|
+
*/
|
|
246
365
|
async function defaultAclHandler(request, options) {
|
|
247
366
|
const className = request.object.className;
|
|
248
367
|
const currentSchema = schema[className];
|
|
@@ -281,6 +400,14 @@ async function defaultAclHandler(request, options) {
|
|
|
281
400
|
}
|
|
282
401
|
exports.defaultAclHandler = defaultAclHandler;
|
|
283
402
|
const beforeSaveHooks = {};
|
|
403
|
+
/**
|
|
404
|
+
* Registers a beforeSave hook for a Parse class. In comparison to Parse.Cloud.beforeSave(), this function allows multiple beforeSave hooks to be registered for the same class.
|
|
405
|
+
*
|
|
406
|
+
* @template T - The type of the Parse.Object.
|
|
407
|
+
* @param {string | { new (): T }} target - The name of the Parse class or the class itself.
|
|
408
|
+
* @param {beforeSaveHookType<T>} callback - The callback function to be executed before saving the object.
|
|
409
|
+
* @returns {void}
|
|
410
|
+
*/
|
|
284
411
|
function beforeSaveHook(target, callback) {
|
|
285
412
|
// @ts-ignore
|
|
286
413
|
const className = typeof target === "string" ? target : target.className;
|
|
@@ -298,6 +425,14 @@ function beforeSaveHook(target, callback) {
|
|
|
298
425
|
}
|
|
299
426
|
exports.beforeSaveHook = beforeSaveHook;
|
|
300
427
|
const afterSaveHooks = {};
|
|
428
|
+
/**
|
|
429
|
+
* Registers a afterSave hook for a Parse class. In comparison to Parse.Cloud.afterSave(), this function allows multiple beforeSave hooks to be registered for the same class.
|
|
430
|
+
*
|
|
431
|
+
* @template T - The type of the Parse.Object.
|
|
432
|
+
* @param {string | { new (): T }} target - The name of the Parse class or the class itself.
|
|
433
|
+
* @param {afterSaveHookType<T>} callback - The callback function to be executed after saving the object.
|
|
434
|
+
* @returns {void}
|
|
435
|
+
*/
|
|
301
436
|
function afterSaveHook(target, callback) {
|
|
302
437
|
// @ts-ignore
|
|
303
438
|
const className = typeof target === "string" ? target : target.className;
|
|
@@ -315,6 +450,13 @@ function afterSaveHook(target, callback) {
|
|
|
315
450
|
}
|
|
316
451
|
exports.afterSaveHook = afterSaveHook;
|
|
317
452
|
const beforeDeleteHooks = {};
|
|
453
|
+
/**
|
|
454
|
+
* Registers a beforeDelete hook for a Parse class. In comparison to Parse.Cloud.beforeDelete(), this function allows multiple beforeSave hooks to be registered for the same class.
|
|
455
|
+
*
|
|
456
|
+
* @template T - The type of the Parse.Object.
|
|
457
|
+
* @param {string | { new (): T }} target - The name of the Parse class or the class itself.
|
|
458
|
+
* @param {beforeDeleteHookType<T>} callback - The callback function to be executed before deleting an object.
|
|
459
|
+
*/
|
|
318
460
|
function beforeDeleteHook(target, callback) {
|
|
319
461
|
// @ts-ignore
|
|
320
462
|
const className = typeof target === "string" ? target : target.className;
|
|
@@ -332,6 +474,14 @@ function beforeDeleteHook(target, callback) {
|
|
|
332
474
|
}
|
|
333
475
|
exports.beforeDeleteHook = beforeDeleteHook;
|
|
334
476
|
const afterDeleteHooks = {};
|
|
477
|
+
/**
|
|
478
|
+
* Registers a afterDelete hook for a Parse class. In comparison to Parse.Cloud.afterDelete(), this function allows multiple beforeSave hooks to be registered for the same class.
|
|
479
|
+
*
|
|
480
|
+
* @template T - The type of the Parse.Object.
|
|
481
|
+
* @param {string | { new (): T }} target - The name of the Parse class or the class itself.
|
|
482
|
+
* @param {afterDeleteHookType<T>} callback - The callback function to be executed after a delete operation.
|
|
483
|
+
* @returns {void}
|
|
484
|
+
*/
|
|
335
485
|
function afterDeleteHook(target, callback) {
|
|
336
486
|
// @ts-ignore
|
|
337
487
|
const className = typeof target === "string" ? target : target.className;
|
|
@@ -348,6 +498,13 @@ function afterDeleteHook(target, callback) {
|
|
|
348
498
|
afterDeleteHooks[className].push(callback);
|
|
349
499
|
}
|
|
350
500
|
exports.afterDeleteHook = afterDeleteHook;
|
|
501
|
+
/**
|
|
502
|
+
* Autoloads cloud code files from the specified path. Each file MUST export an init() function that takes the file name (without it's extension) as an argument.
|
|
503
|
+
*
|
|
504
|
+
* @param path - The path to the directory containing the cloud code files.
|
|
505
|
+
* @param regex - Optional regular expression to filter the file names. Defaults to /^[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*$/.
|
|
506
|
+
* @returns A promise that resolves when all the cloud code files have been loaded and initialized.
|
|
507
|
+
*/
|
|
351
508
|
async function autoloadCloudCode(path, regex = /^[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*$/) {
|
|
352
509
|
const fns = fs_1.default
|
|
353
510
|
.readdirSync(path)
|
|
@@ -366,7 +523,6 @@ async function initAutoload() {
|
|
|
366
523
|
await autoloadCloudCode((0, path_1.resolve)(process.cwd(), path));
|
|
367
524
|
}
|
|
368
525
|
}
|
|
369
|
-
exports.initAutoload = initAutoload;
|
|
370
526
|
function getFeatureForClassName(className) {
|
|
371
527
|
const map = featuremap_json_1.default;
|
|
372
528
|
return map[className] || "unknown";
|
|
@@ -397,3 +553,43 @@ function isClassEnabled(className) {
|
|
|
397
553
|
const enabled = isFeatureEnabled(feature);
|
|
398
554
|
return enabled;
|
|
399
555
|
}
|
|
556
|
+
/**
|
|
557
|
+
* Ensures that a OD3_Permission with the specified key exists in the database.
|
|
558
|
+
* If the permission already exists, it updates the ACL if provided.
|
|
559
|
+
* If the permission does not exist, it creates a new permission with the specified key and ACL.
|
|
560
|
+
* @param key - The key of the permission.
|
|
561
|
+
* @param acl - The Parse.ACL to be set for the permission.
|
|
562
|
+
* @returns The updated or newly created permission.
|
|
563
|
+
*/
|
|
564
|
+
async function ensurePermission(key, acl) {
|
|
565
|
+
const permission = await new Parse.Query(types_1.Permission)
|
|
566
|
+
.equalTo("key", key)
|
|
567
|
+
.first({ useMasterKey: true });
|
|
568
|
+
if (permission) {
|
|
569
|
+
if (acl) {
|
|
570
|
+
permission.setACL(acl);
|
|
571
|
+
return await permission.save(null, { useMasterKey: true });
|
|
572
|
+
}
|
|
573
|
+
return permission;
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
const newPermission = new types_1.Permission({ key });
|
|
577
|
+
if (acl) {
|
|
578
|
+
newPermission.setACL(acl);
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
newPermission.setACL(new Parse.ACL());
|
|
582
|
+
}
|
|
583
|
+
return await newPermission.save(null, { useMasterKey: true });
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
exports.ensurePermission = ensurePermission;
|
|
587
|
+
async function createRandomPassword() {
|
|
588
|
+
const length = 32;
|
|
589
|
+
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
590
|
+
let password = "";
|
|
591
|
+
for (let i = 0; i < length; i++) {
|
|
592
|
+
password += charset.charAt(Math.floor(Math.random() * charset.length));
|
|
593
|
+
}
|
|
594
|
+
return password;
|
|
595
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openinc/parse-server-opendash",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.9",
|
|
4
4
|
"description": "Parse Server Cloud Code for open.DASH",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"parse",
|
|
@@ -30,12 +30,15 @@
|
|
|
30
30
|
"@types/nunjucks": "^3.2.2",
|
|
31
31
|
"@types/parse": "^3.0.0",
|
|
32
32
|
"@types/web-push": "^3.0.0",
|
|
33
|
+
"typedoc": "^0.25.8",
|
|
34
|
+
"typedoc-plugin-markdown": "^3.17.1",
|
|
33
35
|
"typescript": "^5.0.0"
|
|
34
36
|
},
|
|
35
37
|
"scripts": {
|
|
36
38
|
"start": "tsc -w",
|
|
37
39
|
"build": "tsc",
|
|
38
40
|
"schema-down": "parse-server-schema down --prefix OD3_ ./schema",
|
|
39
|
-
"schema-ts": "parse-server-schema typescript --prefix OD3_ --global-sdk ./src/types"
|
|
41
|
+
"schema-ts": "parse-server-schema typescript --prefix OD3_ --global-sdk ./src/types",
|
|
42
|
+
"typedoc": "typedoc --plugin typedoc-plugin-markdown --hideBreadcrumbs --out docs src/index.ts"
|
|
40
43
|
}
|
|
41
44
|
}
|