-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix issue #5274 on RestQuery.each and relations #5276
Conversation
Codecov Report
@@ Coverage Diff @@
## master #5276 +/- ##
==========================================
- Coverage 93.93% 93.91% -0.03%
==========================================
Files 123 123
Lines 8975 8975
==========================================
- Hits 8431 8429 -2
- Misses 544 546 +2
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the query has the objectId constraint then finished should be ‘true’ and we should never override the objectId part of the RESTWhere?
For a simple equals yes, but for $in, it’s an array that can contains more items than the limit ! |
And it’s the case the when you have a bunch of roles for a user ! (More than the default limit of 100 in our case) |
After a quick glance and removing your fix
The first loop returns a result
The second loop returns a result
You could stop at the first loop since your limit is 1
There aren't a lot of tests for RestQuery.each so maybe more are needed were the number of results don't match the limit. |
Hum ok, I see what you mean. But in each, if we look at the current finished condition, and look at the fact that this function is used to retrieve the roles of a user in the purpose to check the read and/or write access on the result of a query, I’ve assumed that the limit here is only used to fragment the request in smaller pieces. |
Oh ! Ok, maybe you just mean I haven’t write enough tests ? |
I believe what @dplewis refers to is that you mention issues with users and roles, yet no test show the issue with such users and roles. |
After playing around a bit, either something is broken or will be broken. How did you discover this? Did you have to use RestQuery.each directly or can you reproduce with the JS SDK? |
It’s likely the bug can be found if the users appear in many many roles, perhaps there’s a bug there. |
I discovered the bug cause we have many roles by users (2000+ for the user with wich I have discovered the issue). The query through the Parse js SDK to our parse server timed out each time and I finally discovered that this issue existed. The user tried to retrieve a lot more roles from the database and of course, timed out |
The test I've written is the simplest way to reproduce the bug without creating a user and many many roles. But in fact, exactly the same thing happen for the two situation: a relation query is converted into $in query by RestQuery.execute and then overriden at the end of the first iteration (except if there is only one) of the RestQuery.each. With the limit of 1, for a relation A-B, only 2 A objects and 2 B objects are required to make one of 2 query fail each time. For A1 <-> B1 and A2 <-> B2.
And if A1.id < A2.id query 1 will fail and query 2 will pass. |
Here is a failing test (modified from Auth.spec.js) but passes with this fix.
The fix provided allows .each to only query on roles for this specific user instead of all roles |
Ok @dplewis, thanks I'm adding it. |
spec/RestQuery.spec.js
Outdated
|
||
const config = Config.get('test'); | ||
|
||
/* Two query needed since objectId are sorted and we can't know wich one |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typos and formatting in this comment needs to be fixed
All ok for you? @dplewis |
spec/Auth.spec.js
Outdated
} | ||
const savedRoles = await Promise.all(roles); | ||
expect(savedRoles.length).toBe(rolesNumber); | ||
const cloudRoles = await userAuth.getRolesForUser(); | ||
expect(cloudRoles.length).toBe(rolesNumber); | ||
}); | ||
|
||
fit('should load all roles for different users with config', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove fit
. That makes only this test run and ignore all other.
Run it locally also
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh shit, I've ran it locally but forget to remove the fit... Sorry
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its cool
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@flovilmart How does this look? |
Thanks for this! |
…-community#5276) * Add test on RestQuery.each with relation * Fix the failing test for RestQuery.each and relations * Add test for getRolesForUser * Fix format for comment * Remove extra fit
Closes: #5274
The RestQuery.prototype.each method was going through all results by adding a filter on
objectId
field of the concerned class when the results length exceed the limit. The problem was that if any constraint has been done onobjectId
field, it was overridden. That was the case for the all relation queries (like the_Role
s of a user for any user authenticated queries).To fix this, replace the assignation of an arbitrary object by the merge of the existing constraint with the new one.
The fix provided allows .each to only query on roles for this specific user instead of all roles