Description
Issue Description
When defining a beforeSave hook, any changes done to the request object will not apply if the hook function returns true. For example:
Parse.Cloud.beforeSave('People', (request) => {
request.object.set('name', 'John');
return true;
});
If the return is omitted, then the beforeSave hook works just fine.
If returning a Promise that returns true, the beforeSave does not apply any changes either. For example:
Parse.Cloud.beforeSave('People', (request) => {
request.object.set('name', 'John');
return new Promise.resolve(true);
});
I haven't tried with returning other things like strings, but I'm assuming it would also cause the same issue.
An argument could be made that beforeSaves should not return any values anyway and that this kind of bug is a developer error. However, some of the code samples on the migration guide to parse-server 3.0 have beforeSave examples were returns are used. This may lead developers to think returning in beforeSave hooks is safe.
Personally I believe this bug should be fixed so that the beforeSaves returning do not affect the ability to make changes to the request object. If that is deemed to be unnecessary, then a proper warning / changes to the migration guide could be helpful. This kind of bug is pretty difficult to find if your beforeSaves have considerable amounts of logic in them (such as data validation and formatting), and I find it strange that cloud jobs / functions can return just fine while hooks cannot.
Steps to reproduce
- Start a parse server 3.1.2.
- Create a beforeSave hook on a random class:
Foo
. - Have the beforeSave hook modify the request object in some way:
request.object.set('name', 'bar');
. - At the end of the hook:
return true
. - Create a new parse object of the class through CURL or the dashboard, giving it a different name than bar such as:
replace_me
.
Expected Results
Modifications should go through and the Parse object. The object's name field should be bar
if following the example above.
Actual Outcome
Modifications do not go through. The object's name stays as 'replace_me' if following the example above.
Environment Setup
-
Server
- parse-server version:
3.1.2
- Operating System:
Windows 10 Education
- Hardware:
i5-7500 3.40 GHz, 64 bit, 16 GB RAM
- Localhost or remote server?
Localhost server
- parse-server version:
-
Database
- MongoDB version:
v3.6.5
- Storage engine:
GridFSBucketAdapter
- Hardware:
i5-7500 3.40 GHz, 64 bit, 16 GB RAM
- Localhost or remote server?
Localhost server
- MongoDB version:
Logs/Trace
[10288] parse-server running on http://localhost:1337/parse
verbose: REQUEST for [POST] /parse/classes/Foo: {
"name": "replace_me"
} method=POST, url=/parse/classes/Foo, host=localhost:1337, connection=keep-alive, content-length=165, origin=http://localhost:4040, user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36, content-type=text/plain, accept=*/*, referer=http://localhost:4040/apps/BluApple/browser/Foo, accept-encoding=gzip, deflate, br, accept-language=en-US,en;q=0.9, name=replace_me
info: beforeSave triggered for Foo for user undefined:
Input: {"name":"bar"}
Result: true className=Foo, triggerType=beforeSave, user=undefined
verbose: RESPONSE from [POST] /parse/classes/Foo: {
"status": 201,
"response": {
"objectId": "Nqm02uklhY",
"createdAt": "2018-12-06T14:54:00.051Z"
},
"location": "http://localhost:1337/parse/classes/Foo/Nqm02uklhY"
} status=201, objectId=Nqm02uklhY, createdAt=2018-12-06T14:54:00.051Z, location=http://localhost:1337/parse/classes/Foo/Nqm02uklhY