Description
New Issue Checklist
- I am not disclosing a vulnerability.
- I am not just asking a question.
- I have searched through existing issues.
- I can reproduce the issue with the latest version of Parse Server.
Issue Description
I'm doing a data collection and publication application. It has two roles, data uploader, and reader. When readers retrieve data, the server need to remove data that is not reviewed by the administrator and only show data which had been reviewed. But for data uploader, he/she can see data uploaded by him/herself although the data has not been reviewed by the administrator. So we defined beforeFind
trigger in a class named Topic(data class), it has a nested "equalTo relational fields" in Parse.Query.and (Parse.Query.or is ok). But the server sdk will treat nested "equalTo relational fields" as "equalTo pointer fields", other than relation.
Steps to reproduce
- define a class 'A', class 'B'
- add some test data
- set a relational field 'rel' in A, which is the relation between 'A' and 'B'
- set an arbitrary field(String, Boolean, etc) named 'C'
- define a beforeFind trigger in 'A'
...
const q1 = request.query; // class A
q1.equalTo('rel',<Parse.Object for 'B'>);
const q2 = new Parse.Query('A');
q2.equalTo('C',true);
const finalReturnQuery = Parse.Query.and(q1,q2);
return finalReturnQuery;
Actual Outcome
zero results found.
explain:
{
"results":{
"queryPlanner": {
"parsedQuery":{
"$and":[
{
"rel" : {
{ "$eq" : "B$<id>"}
...
}}]}}}}
the 'rel' not be parsed to containedIn but be treated as a pointer.
Expected Outcome
multiple results found.
expected explain:
{
"results":{
"queryPlanner": {
"parsedQuery":{
"$and":[
{
"rel" : {
"_id" : { "$in" : [<A objectId 1>,<A objectId 2>]}
...
}}]}}}}
Environment
^4.10.3
Server
- Parse Server version: 4.10.3
- Operating system: macOS Catalina 10.15.7
- Local or remote host (AWS, Azure, Google Cloud, Heroku, Digital Ocean, etc): local
Database
- System (MongoDB or Postgres): MongoDB
- Database version: 4.4.6
- Local or remote host (MongoDB Atlas, mLab, AWS, Azure, Google Cloud, etc): local
Client
- SDK (iOS, Android, JavaScript, PHP, Unity, etc): Flutter
- SDK version: ^3.0.0
test using Postman and restful-api for parse server too.
Logs
Topic is the target class, and 'cls' is a relational field to the class named 'Class'.
verbose: REQUEST for [GET] /parse/classes/Topic: {}
verbose: RESPONSE from [GET] /parse/classes/Topic: {
"response": {
"results": {
"queryPlanner": {
"plannerVersion": 1,
"namespace": "parse.Topic",
"indexFilterSet": false,
"parsedQuery": {
"$and": [
{
"cls": {
"$eq": "Class$5E1lG8FaQo"
}
},
{
"_rperm": {
"$in": [
null,
"*",
"role:schoolAdmin",
"role:teacher",
"role:topAdmin",
"sLBwuv5J6B"
]
}
}
]
},
"winningPlan": {
"stage": "LIMIT",
"limitAmount": 100,
"inputStage": {
"stage": "COLLSCAN",
"filter": {
"$and": [
{
"cls": {
"$eq": "Class$5E1lG8FaQo"
}
},
{
"_rperm": {
"$in": [
null,
"*",
"role:schoolAdmin",
"role:teacher",
"role:topAdmin",
"sLBwuv5J6B"
]
}
}
]
},
"direction": "forward"
}
},
"rejectedPlans": []
},
"executionStats": {
"executionSuccess": true,
"nReturned": 0,
"executionTimeMillis": 0,
"totalKeysExamined": 0,
"totalDocsExamined": 22,
"executionStages": {
"stage": "LIMIT",
"nReturned": 0,
"executionTimeMillisEstimate": 0,
"works": 24,
"advanced": 0,
"needTime": 23,
"needYield": 0,
"saveState": 0,
"restoreState": 0,
"isEOF": 1,
"limitAmount": 100,
"inputStage": {
"stage": "COLLSCAN",
"filter": {
"$and": [
{
"cls": {
"$eq": "Class$5E1lG8FaQo"
}
},
{
"_rperm": {
"$in": [
null,
"*",
"role:schoolAdmin",
"role:teacher",
"role:topAdmin",
"sLBwuv5J6B"
]
}
}
]
},
"nReturned": 0,
"executionTimeMillisEstimate": 0,
"works": 24,
"advanced": 0,
"needTime": 23,
"needYield": 0,
"saveState": 0,
"restoreState": 0,
"isEOF": 1,
"direction": "forward",
"docsExamined": 22
}
},
"allPlansExecution": []
},
"serverInfo": {
"host": "kingtousdeMBP.lan",
"port": 27017,
"version": "4.4.6",
"gitVersion": "72e66213c2c3eab37d9358d5e78ad7f5c1d0d0d7"
},
"ok": 1
}
}
} {"result":{"response":{"results":{"queryPlanner":{"plannerVersion":1,"namespace":"parse.Topic","indexFilterSet":false,"parsedQuery":{"$and":[{"cls":{"$eq":"Class$5E1lG8FaQo"}},{"_rperm":{"$in":[null,"*","role:schoolAdmin","role:teacher","role:topAdmin","sLBwuv5J6B"]}}]},"winningPlan":{"stage":"LIMIT","limitAmount":100,"inputStage":{"stage":"COLLSCAN","filter":{"$and":[{"cls":{"$eq":"Class$5E1lG8FaQo"}},{"_rperm":{"$in":[null,"*","role:schoolAdmin","role:teacher","role:topAdmin","sLBwuv5J6B"]}}]},"direction":"forward"}},"rejectedPlans":[]},"executionStats":{"executionSuccess":true,"nReturned":0,"executionTimeMillis":0,"totalKeysExamined":0,"totalDocsExamined":22,"executionStages":{"stage":"LIMIT","nReturned":0,"executionTimeMillisEstimate":0,"works":24,"advanced":0,"needTime":23,"needYield":0,"saveState":0,"restoreState":0,"isEOF":1,"limitAmount":100,"inputStage":{"stage":"COLLSCAN","filter":{"$and":[{"cls":{"$eq":"Class$5E1lG8FaQo"}},{"_rperm":{"$in":[null,"*","role:schoolAdmin","role:teacher","role:topAdmin","sLBwuv5J6B"]}}]},"nReturned":0,"executionTimeMillisEstimate":0,"works":24,"advanced":0,"needTime":23,"needYield":0,"saveState":0,"restoreState":0,"isEOF":1,"direction":"forward","docsExamined":22}},"allPlansExecution":[]},"serverInfo":{"host":"kingtousdeMBP.lan","port":27017,"version":"4.4.6","gitVersion":"72e66213c2c3eab37d9358d5e78ad7f5c1d0d0d7"},"ok":1}}}}