@openinc/parse-server-opendash 2.4.7 → 2.4.10

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 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
- description: "...",
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
- description: "...",
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
- description: "...",
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
- description: "...",
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
- description: "...",
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
- description: "...",
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
- description: "...",
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
- description: "...",
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
- description: "...",
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
- description: "...",
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
- description: "...",
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: "Enter a description here...",
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
- description: "...",
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: "Enter a description here...",
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
- description: "...",
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: "Enter a description here...",
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: "Enter a description here...",
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: "Enter a description here...",
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: "Enter a description here...",
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: "Enter a description here...",
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: "Enter a description here...",
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: "Enter a description here...",
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);
@@ -7,7 +7,8 @@ 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(__1.PREFIX + "BDE_Form").equalTo("entries", object.id);
10
+ const query = new Parse.Query(types_1.BDE_Form).equalTo("entries", object.id // Fix Parse SDK type error
11
+ );
11
12
  const affectedForms = await query.find({ useMasterKey: true });
12
13
  const aclCandidates = {};
13
14
  affectedForms.forEach((form) => {
@@ -28,7 +29,8 @@ async function init() {
28
29
  });
29
30
  (0, __1.afterSaveHook)(types_1.BDE_Page, async (request) => {
30
31
  const { object, original, user } = request;
31
- const query = new Parse.Query(__1.PREFIX + "BDE_Form").equalTo("entries", object.id);
32
+ const query = new Parse.Query(types_1.BDE_Form).equalTo("entries", object.id // Fix Parse SDK type error
33
+ );
32
34
  const affectedForms = await query.find({ useMasterKey: true });
33
35
  const dirtyKeys = request.context.dirtyKeys;
34
36
  if (dirtyKeys.length > 0 && dirtyKeys[0] !== "acl")
@@ -36,7 +38,8 @@ async function init() {
36
38
  });
37
39
  (0, __1.afterDeleteHook)(types_1.BDE_Page, async (request) => {
38
40
  const { object, original, user } = request;
39
- const query = new Parse.Query(__1.PREFIX + "BDE_Form").equalTo("entries", object.id);
41
+ const query = new Parse.Query(types_1.BDE_Form).equalTo("entries", object.id // Fix Parse SDK type error
42
+ );
40
43
  const affectedForms = await query.find({ useMasterKey: true });
41
44
  await Parse.Object.saveAll(affectedForms, { useMasterKey: true });
42
45
  });
@@ -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;
@@ -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 Parse.Object(`${__1.PREFIX}Widget`, {
19
+ const widget = new types_1.Widget({
20
20
  objectId: widgetId,
21
21
  });
22
22
  await widget.fetch({ useMasterKey: true });
@@ -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(`${__1.PREFIX}TenantTrustedDomain`)
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
- export { Config } from "./helper/Config";
2
+ import { Permission } from "./types";
3
3
  export { sendSimpleEmail, sendTemplateEmail } from "./hooks/Core_Email";
4
- export declare let PREFIX: string;
5
- export interface ConfigInterface {
6
- configPath?: string;
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
- export declare function initAutoload(): Promise<void>;
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.initAutoload = 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.PREFIX = exports.sendTemplateEmail = exports.sendSimpleEmail = exports.Config = void 0;
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
- var Config_1 = require("./helper/Config");
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
- exports.PREFIX = "OD3_";
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: exports.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
- // TODO
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.7",
3
+ "version": "2.4.10",
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
  }