Skip to content

Commit 91a0108

Browse files
dblythydplewis
andauthored
New: allow options to be async on Cloud Validator (#7155)
* new: allow options to be async on Cloud Validator * Update CHANGELOG.md * Ensure pushStatus is properly running (#7213) * Ensure pushStatus is properly running * remove duplicate test * new: allow options to be async on Cloud Validator * Update CHANGELOG.md * Update CloudCode.Validator.spec.js Co-authored-by: Diamond Lewis <findlewis@gmail.com>
1 parent 0476832 commit 91a0108

File tree

3 files changed

+86
-4
lines changed

3 files changed

+86
-4
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
__BREAKING CHANGES:__
1616
- NEW: Added file upload restriction. File upload is now only allowed for authenticated users by default for improved security. To allow file upload also for Anonymous Users or Public, set the `fileUpload` parameter in the [Parse Server Options](https://parseplatform.org/parse-server/api/master/ParseServerOptions.html). [#7071](https://github.com/parse-community/parse-server/pull/7071). Thanks to [dblythy](https://github.com/dblythy), [Manuel Trezza](https://github.com/mtrezza).
1717
___
18+
- IMPROVE: Allow Cloud Validator `options` to be async [#7155](https://github.com/parse-community/parse-server/pull/7155). Thanks to [dblythy](https://github.com/dblythy)
1819
- NEW (EXPERIMENTAL): Added new page router with placeholder rendering and localization of custom and feature pages such as password reset and email verification. **Caution, this is an experimental feature that may not be appropriate for production.** [#6891](https://github.com/parse-community/parse-server/issues/6891). Thanks to [Manuel Trezza](https://github.com/mtrezza).
1920
- NEW: Added convenience method `Parse.Cloud.sendEmail(...)` to send email via email adapter in Cloud Code. [#7089](https://github.com/parse-community/parse-server/pull/7089). Thanks to [dblythy](https://github.com/dblythy)
2021
- NEW: LiveQuery support for $and, $nor, $containedBy, $geoWithin, $geoIntersects queries [#7113](https://github.com/parse-community/parse-server/pull/7113). Thanks to [dplewis](https://github.com/dplewis)
@@ -25,6 +26,7 @@ ___
2526
- IMPROVE: Added new account lockout policy option `accountLockout.unlockOnPasswordReset` to automatically unlock account on password reset. [#7146](https://github.com/parse-community/parse-server/pull/7146). Thanks to [Manuel Trezza](https://github.com/mtrezza).
2627
- IMPROVE: Parse Server is from now on continuously tested against all recent MongoDB versions that have not reached their end-of-life support date. Added MongoDB compatibility table to Parse Server docs. [7161](https://github.com/parse-community/parse-server/pull/7161). Thanks to [Manuel Trezza](https://github.com/mtrezza).
2728
- IMPROVE: Parse Server is from now on continuously tested against all recent Node.js versions that have not reached their end-of-life support date. [7161](https://github.com/parse-community/parse-server/pull/7177). Thanks to [Manuel Trezza](https://github.com/mtrezza).
29+
- IMPROVE: Allow Cloud Validator `options` to be async [#7155](https://github.com/parse-community/parse-server/pull/7155). Thanks to [dblythy](https://github.com/dblythy)
2830
- IMPROVE: Optimize queries on classes with pointer permissions. [#7061](https://github.com/parse-community/parse-server/pull/7061). Thanks to [Pedro Diaz](https://github.com/pdiaz)
2931
- IMPROVE: Parse Server will from now on be continuously tested against all relevant Postgres versions (minor versions). Added Postgres compatibility table to Parse Server docs. [#7176](https://github.com/parse-community/parse-server/pull/7176). Thanks to [Corey Baker](https://github.com/cbaker6).
3032
- FIX: Fix error when a not yet inserted job is updated [#7196](https://github.com/parse-community/parse-server/pull/7196). Thanks to [Antonio Davi Macedo Coelho de Castro](https://github.com/davimacedo).

spec/CloudCode.Validator.spec.js

+76
Original file line numberDiff line numberDiff line change
@@ -1428,4 +1428,80 @@ describe('cloud validator', () => {
14281428
done();
14291429
}
14301430
});
1431+
1432+
it('set params options function async', async () => {
1433+
Parse.Cloud.define(
1434+
'hello',
1435+
() => {
1436+
return 'Hello world!';
1437+
},
1438+
{
1439+
fields: {
1440+
data: {
1441+
type: String,
1442+
required: true,
1443+
options: async val => {
1444+
await new Promise(resolve => {
1445+
setTimeout(resolve, 500);
1446+
});
1447+
return val === 'f';
1448+
},
1449+
error: 'Validation failed.',
1450+
},
1451+
},
1452+
}
1453+
);
1454+
try {
1455+
await Parse.Cloud.run('hello', { data: 'd' });
1456+
fail('validation should have failed');
1457+
} catch (error) {
1458+
expect(error.code).toEqual(Parse.Error.VALIDATION_ERROR);
1459+
expect(error.message).toEqual('Validation failed.');
1460+
}
1461+
const result = await Parse.Cloud.run('hello', { data: 'f' });
1462+
expect(result).toBe('Hello world!');
1463+
});
1464+
1465+
it('basic beforeSave requireUserKey as custom async function', async () => {
1466+
Parse.Cloud.beforeSave(Parse.User, () => {}, {
1467+
fields: {
1468+
accType: {
1469+
default: 'normal',
1470+
constant: true,
1471+
},
1472+
},
1473+
});
1474+
Parse.Cloud.define(
1475+
'secureFunction',
1476+
() => {
1477+
return "Here's all the secure data!";
1478+
},
1479+
{
1480+
requireUserKeys: {
1481+
accType: {
1482+
options: async val => {
1483+
await new Promise(resolve => {
1484+
setTimeout(resolve, 500);
1485+
});
1486+
return ['admin', 'admin2'].includes(val);
1487+
},
1488+
error: 'Unauthorized.',
1489+
},
1490+
},
1491+
}
1492+
);
1493+
const user = new Parse.User();
1494+
user.set('username', 'testuser');
1495+
user.set('password', 'p@ssword');
1496+
user.set('accType', 'admin');
1497+
await user.signUp();
1498+
expect(user.get('accType')).toBe('normal');
1499+
try {
1500+
await Parse.Cloud.run('secureFunction');
1501+
fail('function should only be available to admin users');
1502+
} catch (error) {
1503+
expect(error.code).toEqual(Parse.Error.VALIDATION_ERROR);
1504+
expect(error.message).toEqual('Unauthorized.');
1505+
}
1506+
});
14311507
});

src/triggers.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -662,11 +662,11 @@ async function builtInTriggerValidator(options, request, auth) {
662662
}
663663
};
664664

665-
const validateOptions = (opt, key, val) => {
665+
const validateOptions = async (opt, key, val) => {
666666
let opts = opt.options;
667667
if (typeof opts === 'function') {
668668
try {
669-
const result = opts(val);
669+
const result = await opts(val);
670670
if (!result && result != null) {
671671
throw opt.error || `Validation failed. Invalid value for ${key}.`;
672672
}
@@ -699,6 +699,7 @@ async function builtInTriggerValidator(options, request, auth) {
699699
requiredParam(key);
700700
}
701701
} else {
702+
const optionPromises = [];
702703
for (const key in options.fields) {
703704
const opt = options.fields[key];
704705
let val = params[key];
@@ -731,10 +732,11 @@ async function builtInTriggerValidator(options, request, auth) {
731732
}
732733
}
733734
if (opt.options) {
734-
validateOptions(opt, key, val);
735+
optionPromises.push(validateOptions(opt, key, val));
735736
}
736737
}
737738
}
739+
await Promise.all(optionPromises);
738740
}
739741
let userRoles = options.requireAnyUserRoles;
740742
let requireAllRoles = options.requireAllUserRoles;
@@ -780,12 +782,14 @@ async function builtInTriggerValidator(options, request, auth) {
780782
}
781783
}
782784
} else if (typeof userKeys === 'object') {
785+
const optionPromises = [];
783786
for (const key in options.requireUserKeys) {
784787
const opt = options.requireUserKeys[key];
785788
if (opt.options) {
786-
validateOptions(opt, key, reqUser.get(key));
789+
optionPromises.push(validateOptions(opt, key, reqUser.get(key)));
787790
}
788791
}
792+
await Promise.all(optionPromises);
789793
}
790794
}
791795

0 commit comments

Comments
 (0)