-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
/
Copy pathParse.Cloud.js
812 lines (779 loc) · 31.3 KB
/
Parse.Cloud.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
import { Parse } from 'parse/node';
import * as triggers from '../triggers';
import { addRateLimit } from '../middlewares';
const Config = require('../Config');
function isParseObjectConstructor(object) {
return typeof object === 'function' && Object.prototype.hasOwnProperty.call(object, 'className');
}
function validateValidator(validator) {
if (!validator || typeof validator === 'function') {
return;
}
const fieldOptions = {
type: ['Any'],
constant: [Boolean],
default: ['Any'],
options: [Array, 'function', 'Any'],
required: [Boolean],
error: [String],
};
const allowedKeys = {
requireUser: [Boolean],
requireAnyUserRoles: [Array, 'function'],
requireAllUserRoles: [Array, 'function'],
requireMaster: [Boolean],
validateMasterKey: [Boolean],
skipWithMasterKey: [Boolean],
requireUserKeys: [Array, Object],
fields: [Array, Object],
rateLimit: [Object],
};
const getType = fn => {
if (Array.isArray(fn)) {
return 'array';
}
if (fn === 'Any' || fn === 'function') {
return fn;
}
const type = typeof fn;
if (typeof fn === 'function') {
const match = fn && fn.toString().match(/^\s*function (\w+)/);
return (match ? match[1] : 'function').toLowerCase();
}
return type;
};
const checkKey = (key, data, validatorParam) => {
const parameter = data[key];
if (!parameter) {
throw `${key} is not a supported parameter for Cloud Function validations.`;
}
const types = parameter.map(type => getType(type));
const type = getType(validatorParam);
if (!types.includes(type) && !types.includes('Any')) {
throw `Invalid type for Cloud Function validation key ${key}. Expected ${types.join(
'|'
)}, actual ${type}`;
}
};
for (const key in validator) {
checkKey(key, allowedKeys, validator[key]);
if (key === 'fields' || key === 'requireUserKeys') {
const values = validator[key];
if (Array.isArray(values)) {
continue;
}
for (const value in values) {
const data = values[value];
for (const subKey in data) {
checkKey(subKey, fieldOptions, data[subKey]);
}
}
}
}
}
const getRoute = parseClass => {
const route =
{
_User: 'users',
_Session: 'sessions',
'@File': 'files',
'@Config' : 'config',
}[parseClass] || 'classes';
if (parseClass === '@File') {
return `/${route}/:id?(.*)`;
}
if (parseClass === '@Config') {
return `/${route}`;
}
return `/${route}/${parseClass}/:id?(.*)`;
};
/** @namespace
* @name Parse
* @description The Parse SDK.
* see [api docs](https://docs.parseplatform.org/js/api) and [guide](https://docs.parseplatform.org/js/guide)
*/
/** @namespace
* @name Parse.Cloud
* @memberof Parse
* @description The Parse Cloud Code SDK.
*/
var ParseCloud = {};
/**
* Defines a Cloud Function.
*
* **Available in Cloud Code only.**
*
* ```
* Parse.Cloud.define('functionName', (request) => {
* // code here
* }, (request) => {
* // validation code here
* });
*
* Parse.Cloud.define('functionName', (request) => {
* // code here
* }, { ...validationObject });
* ```
*
* @static
* @memberof Parse.Cloud
* @param {String} name The name of the Cloud Function
* @param {Function} data The Cloud Function to register. This function can be an async function and should take one parameter a {@link Parse.Cloud.FunctionRequest}.
* @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.FunctionRequest}, or a {@link Parse.Cloud.ValidatorObject}.
*/
ParseCloud.define = function (functionName, handler, validationHandler) {
validateValidator(validationHandler);
triggers.addFunction(functionName, handler, validationHandler, Parse.applicationId);
if (validationHandler && validationHandler.rateLimit) {
addRateLimit(
{ requestPath: `/functions/${functionName}`, ...validationHandler.rateLimit },
Parse.applicationId,
true
);
}
};
/**
* Defines a Background Job.
*
* **Available in Cloud Code only.**
*
* @method job
* @name Parse.Cloud.job
* @param {String} name The name of the Background Job
* @param {Function} func The Background Job to register. This function can be async should take a single parameters a {@link Parse.Cloud.JobRequest}
*
*/
ParseCloud.job = function (functionName, handler) {
triggers.addJob(functionName, handler, Parse.applicationId);
};
/**
*
* Registers a before save function.
*
* **Available in Cloud Code only.**
*
* If you want to use beforeSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1.
*
* ```
* Parse.Cloud.beforeSave('MyCustomClass', (request) => {
* // code here
* }, (request) => {
* // validation code here
* });
*
* Parse.Cloud.beforeSave(Parse.User, (request) => {
* // code here
* }, { ...validationObject })
* ```
*
* @method beforeSave
* @name Parse.Cloud.beforeSave
* @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the after save function for. This can instead be a String that is the className of the subclass.
* @param {Function} func The function to run before a save. This function can be async and should take one parameter a {@link Parse.Cloud.TriggerRequest};
* @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.TriggerRequest}, or a {@link Parse.Cloud.ValidatorObject}.
*/
ParseCloud.beforeSave = function (parseClass, handler, validationHandler) {
const className = triggers.getClassName(parseClass);
validateValidator(validationHandler);
triggers.addTrigger(
triggers.Types.beforeSave,
className,
handler,
Parse.applicationId,
validationHandler
);
if (validationHandler && validationHandler.rateLimit) {
addRateLimit(
{
requestPath: getRoute(className),
requestMethods: ['POST', 'PUT'],
...validationHandler.rateLimit,
},
Parse.applicationId,
true
);
}
};
/**
* Registers a before delete function.
*
* **Available in Cloud Code only.**
*
* If you want to use beforeDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1.
* ```
* Parse.Cloud.beforeDelete('MyCustomClass', (request) => {
* // code here
* }, (request) => {
* // validation code here
* });
*
* Parse.Cloud.beforeDelete(Parse.User, (request) => {
* // code here
* }, { ...validationObject })
*```
*
* @method beforeDelete
* @name Parse.Cloud.beforeDelete
* @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the before delete function for. This can instead be a String that is the className of the subclass.
* @param {Function} func The function to run before a delete. This function can be async and should take one parameter, a {@link Parse.Cloud.TriggerRequest}.
* @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.TriggerRequest}, or a {@link Parse.Cloud.ValidatorObject}.
*/
ParseCloud.beforeDelete = function (parseClass, handler, validationHandler) {
const className = triggers.getClassName(parseClass);
validateValidator(validationHandler);
triggers.addTrigger(
triggers.Types.beforeDelete,
className,
handler,
Parse.applicationId,
validationHandler
);
if (validationHandler && validationHandler.rateLimit) {
addRateLimit(
{
requestPath: getRoute(className),
requestMethods: 'DELETE',
...validationHandler.rateLimit,
},
Parse.applicationId,
true
);
}
};
/**
*
* Registers the before login function.
*
* **Available in Cloud Code only.**
*
* This function provides further control
* in validating a login attempt. Specifically,
* it is triggered after a user enters
* correct credentials (or other valid authData),
* but prior to a session being generated.
*
* ```
* Parse.Cloud.beforeLogin((request) => {
* // code here
* })
*
* ```
*
* @method beforeLogin
* @name Parse.Cloud.beforeLogin
* @param {Function} func The function to run before a login. This function can be async and should take one parameter a {@link Parse.Cloud.TriggerRequest};
*/
ParseCloud.beforeLogin = function (handler, validationHandler) {
let className = '_User';
if (typeof handler === 'string' || isParseObjectConstructor(handler)) {
// validation will occur downstream, this is to maintain internal
// code consistency with the other hook types.
className = triggers.getClassName(handler);
handler = arguments[1];
validationHandler = arguments.length >= 2 ? arguments[2] : null;
}
triggers.addTrigger(triggers.Types.beforeLogin, className, handler, Parse.applicationId);
if (validationHandler && validationHandler.rateLimit) {
addRateLimit(
{ requestPath: `/login`, requestMethods: 'POST', ...validationHandler.rateLimit },
Parse.applicationId,
true
);
}
};
/**
*
* Registers the after login function.
*
* **Available in Cloud Code only.**
*
* This function is triggered after a user logs in successfully,
* and after a _Session object has been created.
*
* ```
* Parse.Cloud.afterLogin((request) => {
* // code here
* });
* ```
*
* @method afterLogin
* @name Parse.Cloud.afterLogin
* @param {Function} func The function to run after a login. This function can be async and should take one parameter a {@link Parse.Cloud.TriggerRequest};
*/
ParseCloud.afterLogin = function (handler) {
let className = '_User';
if (typeof handler === 'string' || isParseObjectConstructor(handler)) {
// validation will occur downstream, this is to maintain internal
// code consistency with the other hook types.
className = triggers.getClassName(handler);
handler = arguments[1];
}
triggers.addTrigger(triggers.Types.afterLogin, className, handler, Parse.applicationId);
};
/**
*
* Registers the after logout function.
*
* **Available in Cloud Code only.**
*
* This function is triggered after a user logs out.
*
* ```
* Parse.Cloud.afterLogout((request) => {
* // code here
* });
* ```
*
* @method afterLogout
* @name Parse.Cloud.afterLogout
* @param {Function} func The function to run after a logout. This function can be async and should take one parameter a {@link Parse.Cloud.TriggerRequest};
*/
ParseCloud.afterLogout = function (handler) {
let className = '_Session';
if (typeof handler === 'string' || isParseObjectConstructor(handler)) {
// validation will occur downstream, this is to maintain internal
// code consistency with the other hook types.
className = triggers.getClassName(handler);
handler = arguments[1];
}
triggers.addTrigger(triggers.Types.afterLogout, className, handler, Parse.applicationId);
};
/**
* Registers an after save function.
*
* **Available in Cloud Code only.**
*
* If you want to use afterSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1.
*
* ```
* Parse.Cloud.afterSave('MyCustomClass', async function(request) {
* // code here
* }, (request) => {
* // validation code here
* });
*
* Parse.Cloud.afterSave(Parse.User, async function(request) {
* // code here
* }, { ...validationObject });
* ```
*
* @method afterSave
* @name Parse.Cloud.afterSave
* @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the after save function for. This can instead be a String that is the className of the subclass.
* @param {Function} func The function to run after a save. This function can be an async function and should take just one parameter, {@link Parse.Cloud.TriggerRequest}.
* @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.TriggerRequest}, or a {@link Parse.Cloud.ValidatorObject}.
*/
ParseCloud.afterSave = function (parseClass, handler, validationHandler) {
const className = triggers.getClassName(parseClass);
validateValidator(validationHandler);
triggers.addTrigger(
triggers.Types.afterSave,
className,
handler,
Parse.applicationId,
validationHandler
);
};
/**
* Registers an after delete function.
*
* **Available in Cloud Code only.**
*
* If you want to use afterDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1.
* ```
* Parse.Cloud.afterDelete('MyCustomClass', async (request) => {
* // code here
* }, (request) => {
* // validation code here
* });
*
* Parse.Cloud.afterDelete(Parse.User, async (request) => {
* // code here
* }, { ...validationObject });
*```
*
* @method afterDelete
* @name Parse.Cloud.afterDelete
* @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the after delete function for. This can instead be a String that is the className of the subclass.
* @param {Function} func The function to run after a delete. This function can be async and should take just one parameter, {@link Parse.Cloud.TriggerRequest}.
* @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.TriggerRequest}, or a {@link Parse.Cloud.ValidatorObject}.
*/
ParseCloud.afterDelete = function (parseClass, handler, validationHandler) {
const className = triggers.getClassName(parseClass);
validateValidator(validationHandler);
triggers.addTrigger(
triggers.Types.afterDelete,
className,
handler,
Parse.applicationId,
validationHandler
);
};
/**
* Registers a before find function.
*
* **Available in Cloud Code only.**
*
* If you want to use beforeFind for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1.
* ```
* Parse.Cloud.beforeFind('MyCustomClass', async (request) => {
* // code here
* }, (request) => {
* // validation code here
* });
*
* Parse.Cloud.beforeFind(Parse.User, async (request) => {
* // code here
* }, { ...validationObject });
*```
*
* @method beforeFind
* @name Parse.Cloud.beforeFind
* @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the before find function for. This can instead be a String that is the className of the subclass.
* @param {Function} func The function to run before a find. This function can be async and should take just one parameter, {@link Parse.Cloud.BeforeFindRequest}.
* @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.BeforeFindRequest}, or a {@link Parse.Cloud.ValidatorObject}.
*/
ParseCloud.beforeFind = function (parseClass, handler, validationHandler) {
const className = triggers.getClassName(parseClass);
validateValidator(validationHandler);
triggers.addTrigger(
triggers.Types.beforeFind,
className,
handler,
Parse.applicationId,
validationHandler
);
if (validationHandler && validationHandler.rateLimit) {
addRateLimit(
{
requestPath: getRoute(className),
requestMethods: 'GET',
...validationHandler.rateLimit,
},
Parse.applicationId,
true
);
}
};
/**
* Registers an after find function.
*
* **Available in Cloud Code only.**
*
* If you want to use afterFind for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1.
* ```
* Parse.Cloud.afterFind('MyCustomClass', async (request) => {
* // code here
* }, (request) => {
* // validation code here
* });
*
* Parse.Cloud.afterFind(Parse.User, async (request) => {
* // code here
* }, { ...validationObject });
*```
*
* @method afterFind
* @name Parse.Cloud.afterFind
* @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the after find function for. This can instead be a String that is the className of the subclass.
* @param {Function} func The function to run before a find. This function can be async and should take just one parameter, {@link Parse.Cloud.AfterFindRequest}.
* @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.AfterFindRequest}, or a {@link Parse.Cloud.ValidatorObject}.
*/
ParseCloud.afterFind = function (parseClass, handler, validationHandler) {
const className = triggers.getClassName(parseClass);
validateValidator(validationHandler);
triggers.addTrigger(
triggers.Types.afterFind,
className,
handler,
Parse.applicationId,
validationHandler
);
};
/**
* Registers a before live query server connect function.
*
* **Available in Cloud Code only.**
*
* ```
* Parse.Cloud.beforeConnect(async (request) => {
* // code here
* }, (request) => {
* // validation code here
* });
*
* Parse.Cloud.beforeConnect(async (request) => {
* // code here
* }, { ...validationObject });
*```
*
* @method beforeConnect
* @name Parse.Cloud.beforeConnect
* @param {Function} func The function to before connection is made. This function can be async and should take just one parameter, {@link Parse.Cloud.ConnectTriggerRequest}.
* @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.ConnectTriggerRequest}, or a {@link Parse.Cloud.ValidatorObject}.
*/
ParseCloud.beforeConnect = function (handler, validationHandler) {
validateValidator(validationHandler);
triggers.addConnectTrigger(
triggers.Types.beforeConnect,
handler,
Parse.applicationId,
validationHandler
);
};
/**
* Sends an email through the Parse Server mail adapter.
*
* **Available in Cloud Code only.**
* **Requires a mail adapter to be configured for Parse Server.**
*
* ```
* Parse.Cloud.sendEmail({
* from: 'Example <[email protected]>',
* to: '[email protected]',
* subject: 'Test email',
* text: 'This email is a test.'
* });
*```
*
* @method sendEmail
* @name Parse.Cloud.sendEmail
* @param {Object} data The object of the mail data to send.
*/
ParseCloud.sendEmail = function (data) {
const config = Config.get(Parse.applicationId);
const emailAdapter = config.userController.adapter;
if (!emailAdapter) {
config.loggerController.error(
'Failed to send email because no mail adapter is configured for Parse Server.'
);
return;
}
return emailAdapter.sendMail(data);
};
/**
* Registers a before live query subscription function.
*
* **Available in Cloud Code only.**
*
* If you want to use beforeSubscribe for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1.
* ```
* Parse.Cloud.beforeSubscribe('MyCustomClass', (request) => {
* // code here
* }, (request) => {
* // validation code here
* });
*
* Parse.Cloud.beforeSubscribe(Parse.User, (request) => {
* // code here
* }, { ...validationObject });
*```
*
* @method beforeSubscribe
* @name Parse.Cloud.beforeSubscribe
* @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the before subscription function for. This can instead be a String that is the className of the subclass.
* @param {Function} func The function to run before a subscription. This function can be async and should take one parameter, a {@link Parse.Cloud.TriggerRequest}.
* @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.TriggerRequest}, or a {@link Parse.Cloud.ValidatorObject}.
*/
ParseCloud.beforeSubscribe = function (parseClass, handler, validationHandler) {
validateValidator(validationHandler);
const className = triggers.getClassName(parseClass);
triggers.addTrigger(
triggers.Types.beforeSubscribe,
className,
handler,
Parse.applicationId,
validationHandler
);
};
/**
* Registers a before live query event function.
*
* **Available in Cloud Code only.**
*
* If you want to use beforeLiveQueryEvent for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1.
* ```
* Parse.Cloud.beforeLiveQueryEvent('MyCustomClass', (request) => {
* // code here
* }, (request) => {
* // validation code here
* });
*
* Parse.Cloud.beforeLiveQueryEvent(Parse.User, (request) => {
* // code here
* }, { ...validationObject });
*```
*
* @method beforeLiveQueryEvent
* @name Parse.Cloud.beforeLiveQueryEvent
* @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the before live query event function for. This can instead be a String that is the className of the subclass.
* @param {Function} func The function to run before a live query event (publish) is made. This function can be async and should take one parameter, a {@link Parse.Cloud.TriggerRequest}.
* @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.TriggerRequest}, or a {@link Parse.Cloud.ValidatorObject}.
*/
ParseCloud.beforeLiveQueryEvent = function (parseClass, handler, validationHandler) {
validateValidator(validationHandler);
const className = triggers.getClassName(parseClass);
triggers.addTrigger(
triggers.Types.beforeEvent,
className,
handler,
Parse.applicationId,
validationHandler
);
};
ParseCloud.onLiveQueryEvent = function (handler) {
triggers.addLiveQueryEventHandler(handler, Parse.applicationId);
};
/**
* Registers an after live query server event function.
*
* **Available in Cloud Code only.**
*
* ```
* Parse.Cloud.afterLiveQueryEvent('MyCustomClass', (request) => {
* // code here
* }, (request) => {
* // validation code here
* });
*
* Parse.Cloud.afterLiveQueryEvent('MyCustomClass', (request) => {
* // code here
* }, { ...validationObject });
*```
*
* @method afterLiveQueryEvent
* @name Parse.Cloud.afterLiveQueryEvent
* @param {(String|Parse.Object)} arg1 The Parse.Object subclass to register the after live query event function for. This can instead be a String that is the className of the subclass.
* @param {Function} func The function to run after a live query event. This function can be async and should take one parameter, a {@link Parse.Cloud.LiveQueryEventTrigger}.
* @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.LiveQueryEventTrigger}, or a {@link Parse.Cloud.ValidatorObject}.
*/
ParseCloud.afterLiveQueryEvent = function (parseClass, handler, validationHandler) {
const className = triggers.getClassName(parseClass);
validateValidator(validationHandler);
triggers.addTrigger(
triggers.Types.afterEvent,
className,
handler,
Parse.applicationId,
validationHandler
);
};
ParseCloud._removeAllHooks = () => {
triggers._unregisterAll();
const config = Config.get(Parse.applicationId);
config?.unregisterRateLimiters();
};
ParseCloud.useMasterKey = () => {
// eslint-disable-next-line
console.warn(
'Parse.Cloud.useMasterKey is deprecated (and has no effect anymore) on parse-server, please refer to the cloud code migration notes: http://docs.parseplatform.org/parse-server/guide/#master-key-must-be-passed-explicitly'
);
};
module.exports = ParseCloud;
/**
* @interface Parse.Cloud.TriggerRequest
* @property {String} installationId If set, the installationId triggering the request.
* @property {Boolean} master If true, means the master key was used.
* @property {Boolean} isChallenge If true, means the current request is originally triggered by an auth challenge.
* @property {Parse.User} user If set, the user that made the request.
* @property {Parse.Object} object The object triggering the hook.
* @property {String} ip The IP address of the client making the request. To ensure retrieving the correct IP address, set the Parse Server option `trustProxy: true` if Parse Server runs behind a proxy server, for example behind a load balancer.
* @property {Object} headers The original HTTP headers for the request.
* @property {String} triggerName The name of the trigger (`beforeSave`, `afterSave`, ...)
* @property {Object} log The current logger inside Parse Server.
* @property {Parse.Object} original If set, the object, as currently stored.
*/
/**
* @interface Parse.Cloud.FileTriggerRequest
* @property {String} installationId If set, the installationId triggering the request.
* @property {Boolean} master If true, means the master key was used.
* @property {Parse.User} user If set, the user that made the request.
* @property {Parse.File} file The file that triggered the hook.
* @property {Integer} fileSize The size of the file in bytes.
* @property {Integer} contentLength The value from Content-Length header
* @property {String} ip The IP address of the client making the request.
* @property {Object} headers The original HTTP headers for the request.
* @property {String} triggerName The name of the trigger (`beforeSave`, `afterSave`)
* @property {Object} log The current logger inside Parse Server.
*/
/**
* @interface Parse.Cloud.ConnectTriggerRequest
* @property {String} installationId If set, the installationId triggering the request.
* @property {Boolean} useMasterKey If true, means the master key was used.
* @property {Parse.User} user If set, the user that made the request.
* @property {Integer} clients The number of clients connected.
* @property {Integer} subscriptions The number of subscriptions connected.
* @property {String} sessionToken If set, the session of the user that made the request.
*/
/**
* @interface Parse.Cloud.LiveQueryEventTrigger
* @property {String} installationId If set, the installationId triggering the request.
* @property {Boolean} useMasterKey If true, means the master key was used.
* @property {Parse.User} user If set, the user that made the request.
* @property {String} sessionToken If set, the session of the user that made the request.
* @property {String} event The live query event that triggered the request.
* @property {Parse.Object} object The object triggering the hook.
* @property {Parse.Object} original If set, the object, as currently stored.
* @property {Integer} clients The number of clients connected.
* @property {Integer} subscriptions The number of subscriptions connected.
* @property {Boolean} sendEvent If the LiveQuery event should be sent to the client. Set to false to prevent LiveQuery from pushing to the client.
*/
/**
* @interface Parse.Cloud.BeforeFindRequest
* @property {String} installationId If set, the installationId triggering the request.
* @property {Boolean} master If true, means the master key was used.
* @property {Parse.User} user If set, the user that made the request.
* @property {Parse.Query} query The query triggering the hook.
* @property {String} ip The IP address of the client making the request.
* @property {Object} headers The original HTTP headers for the request.
* @property {String} triggerName The name of the trigger (`beforeSave`, `afterSave`, ...)
* @property {Object} log The current logger inside Parse Server.
* @property {Boolean} isGet wether the query a `get` or a `find`
*/
/**
* @interface Parse.Cloud.AfterFindRequest
* @property {String} installationId If set, the installationId triggering the request.
* @property {Boolean} master If true, means the master key was used.
* @property {Parse.User} user If set, the user that made the request.
* @property {Parse.Query} query The query triggering the hook.
* @property {Array<Parse.Object>} results The results the query yielded.
* @property {String} ip The IP address of the client making the request.
* @property {Object} headers The original HTTP headers for the request.
* @property {String} triggerName The name of the trigger (`beforeSave`, `afterSave`, ...)
* @property {Object} log The current logger inside Parse Server.
*/
/**
* @interface Parse.Cloud.FunctionRequest
* @property {String} installationId If set, the installationId triggering the request.
* @property {Boolean} master If true, means the master key was used.
* @property {Parse.User} user If set, the user that made the request.
* @property {Object} params The params passed to the cloud function.
*/
/**
* @interface Parse.Cloud.JobRequest
* @property {Object} params The params passed to the background job.
* @property {function} message If message is called with a string argument, will update the current message to be stored in the job status.
*/
/**
* @interface Parse.Cloud.ValidatorObject
* @property {Boolean} requireUser whether the cloud trigger requires a user.
* @property {Boolean} requireMaster whether the cloud trigger requires a master key.
* @property {Boolean} validateMasterKey whether the validator should run if masterKey is provided. Defaults to false.
* @property {Boolean} skipWithMasterKey whether the cloud code function should be ignored using a masterKey.
*
* @property {Array<String>|Object} requireUserKeys If set, keys required on request.user to make the request.
* @property {String} requireUserKeys.field If requireUserKeys is an object, name of field to validate on request user
* @property {Array|function|Any} requireUserKeys.field.options array of options that the field can be, function to validate field, or single value. Throw an error if value is invalid.
* @property {String} requireUserKeys.field.error custom error message if field is invalid.
*
* @property {Array<String>|function}requireAnyUserRoles If set, request.user has to be part of at least one roles name to make the request. If set to a function, function must return role names.
* @property {Array<String>|function}requireAllUserRoles If set, request.user has to be part all roles name to make the request. If set to a function, function must return role names.
*
* @property {Object|Array<String>} fields if an array of strings, validator will look for keys in request.params, and throw if not provided. If Object, fields to validate. If the trigger is a cloud function, `request.params` will be validated, otherwise `request.object`.
* @property {String} fields.field name of field to validate.
* @property {String} fields.field.type expected type of data for field.
* @property {Boolean} fields.field.constant whether the field can be modified on the object.
* @property {Any} fields.field.default default value if field is `null`, or initial value `constant` is `true`.
* @property {Array|function|Any} fields.field.options array of options that the field can be, function to validate field, or single value. Throw an error if value is invalid.
* @property {String} fields.field.error custom error message if field is invalid.
*/