From c6b63137f66fd92729e1dea3887dc4121fe431ba Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 19 Oct 2018 01:15:09 +0200 Subject: [PATCH 01/15] Fix Limitation Role #5131 Allow to manage Live Query with User that have more than 100 Parse.Roles --- src/Auth.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Auth.js b/src/Auth.js index 64c69cfd9c..7ef04f5975 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -203,10 +203,13 @@ Auth.prototype.getRolesForUser = function() { return query.execute().then(({ results }) => results); } + //Stack all Parse.Role + var _tmpUserRoles = []; + return new Parse.Query(Parse.Role) .equalTo('users', this.user) - .find({ useMasterKey: true }) - .then(results => results.map(obj => obj.toJSON())); + .each(result => _tmpUserRoles.push(result),{useMasterKey:true}) + .then(() => _tmpUserRoles.map(obj => obj.toJSON())); }; // Iterates through the role tree and compiles a user's roles From 90db03a52880d91a14ebdddfe8effe9db0ea8d1f Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 19 Oct 2018 01:23:04 +0200 Subject: [PATCH 02/15] Clean Up --- src/Auth.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Auth.js b/src/Auth.js index 7ef04f5975..a04333a552 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -204,12 +204,12 @@ Auth.prototype.getRolesForUser = function() { } //Stack all Parse.Role - var _tmpUserRoles = []; + const results = []; return new Parse.Query(Parse.Role) .equalTo('users', this.user) - .each(result => _tmpUserRoles.push(result),{useMasterKey:true}) - .then(() => _tmpUserRoles.map(obj => obj.toJSON())); + .each(result => results.push(result),{useMasterKey:true}) + .then(() => results.map(obj => obj.toJSON())); }; // Iterates through the role tree and compiles a user's roles From 06600ab45f5d1925a854f27486acf369ebb1f792 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 19 Oct 2018 22:50:07 +0200 Subject: [PATCH 03/15] Add Custom Config Support and Test --- spec/Auth.spec.js | 20 ++++++++++++++++++++ src/Auth.js | 45 +++++++++++++++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/spec/Auth.spec.js b/spec/Auth.spec.js index 6dc34e36f1..933a1b9437 100644 --- a/spec/Auth.spec.js +++ b/spec/Auth.spec.js @@ -149,4 +149,24 @@ describe('Auth', () => { expect(userAuth.user instanceof Parse.User).toBe(true); expect(userAuth.user.id).toBe(user.id); }); + + it('should load all roles', async () => { + const user = new Parse.User(); + await user.signUp({ + username: 'hello', + password: 'password', + }); + const roles = []; + for(var i=0; i < 200;i++){ + const acl = new Parse.ACL(); + const role = new Parse.Role("roleloadtest"+i, acl); + role.getUsers().add([user]); + roles.push(role.save()) + } + const savedRoles = await Promise.all(roles) + //Additionnal length check + expect(savedRoles).to.have.lengthOf(200) + const cloudRoles = auth.getUserRoles() + expect(cloudRoles).to.have.lengthOf(200) + }); }); diff --git a/src/Auth.js b/src/Auth.js index a04333a552..aaccbd61c8 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -2,6 +2,9 @@ const cryptoUtils = require('./cryptoUtils'); const RestQuery = require('./RestQuery'); const Parse = require('parse/node'); +//Needed for getRolesForUser() +const { continueWhile } = require('parse/lib/node/promiseUtils'); + // An Auth object tells you who is requesting something and whether // the master key was used. // userObject is a Parse.User and can be null if there's no user. @@ -186,21 +189,35 @@ Auth.prototype.getUserRoles = function() { Auth.prototype.getRolesForUser = function() { if (this.config) { - const restWhere = { - users: { - __type: 'Pointer', - className: '_User', - objectId: this.user.id, - }, + const masterConfig = master(this.config); + const queryOptions = { + limit: 100, + order: 'objectId' }; - const query = new RestQuery( - this.config, - master(this.config), - '_Role', - restWhere, - {} - ); - return query.execute().then(({ results }) => results); + let finished = false; + + //Stack all Parse.Role + let results = []; + + //Get All Parse.Role from the User + await continueWhile(() => { + return !finished; + }, async () => { + const query = new RestQuery( + this.config, + masterConfig, + '_Role', + restWhere, + queryOptions + ); + const currentResults = await query.execute().then(({ results }) => results); + finished = currentResults.length < queryOptions.limit; + if (!finished) { + restWhere.objectId = { '$gt': currentResults[currentResults.length - 1].id} + } + results = results.concat(currentResults); + }); + return results; } //Stack all Parse.Role From 1e95a8f0235388caa3ff6e8ae3a6cfc47f94b811 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 19 Oct 2018 22:55:07 +0200 Subject: [PATCH 04/15] Fix Auth Test --- spec/Auth.spec.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/spec/Auth.spec.js b/spec/Auth.spec.js index 933a1b9437..df95fa7aa5 100644 --- a/spec/Auth.spec.js +++ b/spec/Auth.spec.js @@ -152,10 +152,7 @@ describe('Auth', () => { it('should load all roles', async () => { const user = new Parse.User(); - await user.signUp({ - username: 'hello', - password: 'password', - }); + user.id = currentUserId const roles = []; for(var i=0; i < 200;i++){ const acl = new Parse.ACL(); From 6a8a0a2113d9793e25c01c7a344c990237bed2d3 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 19 Oct 2018 23:15:08 +0200 Subject: [PATCH 05/15] Switch to Async Function --- src/Auth.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Auth.js b/src/Auth.js index aaccbd61c8..9bdb95c195 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -187,7 +187,7 @@ Auth.prototype.getUserRoles = function() { return this.rolePromise; }; -Auth.prototype.getRolesForUser = function() { +Auth.prototype.getRolesForUser = async function() { if (this.config) { const masterConfig = master(this.config); const queryOptions = { @@ -199,7 +199,7 @@ Auth.prototype.getRolesForUser = function() { //Stack all Parse.Role let results = []; - //Get All Parse.Role from the User + //Get All Parse.Role for User await continueWhile(() => { return !finished; }, async () => { @@ -217,16 +217,16 @@ Auth.prototype.getRolesForUser = function() { } results = results.concat(currentResults); }); - return results; + return results.map(obj => obj.toJSON()); } //Stack all Parse.Role const results = []; - return new Parse.Query(Parse.Role) + await new Parse.Query(Parse.Role) .equalTo('users', this.user) .each(result => results.push(result),{useMasterKey:true}) - .then(() => results.map(obj => obj.toJSON())); + return results.map(obj => obj.toJSON()); }; // Iterates through the role tree and compiles a user's roles From a81da71c7fdde9eaf36197a22a0a83d2024c3e79 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 19 Oct 2018 23:26:26 +0200 Subject: [PATCH 06/15] Fix restWhere --- src/Auth.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Auth.js b/src/Auth.js index 9bdb95c195..3f8791516f 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -190,6 +190,13 @@ Auth.prototype.getUserRoles = function() { Auth.prototype.getRolesForUser = async function() { if (this.config) { const masterConfig = master(this.config); + const restWhere = { + users: { + __type: 'Pointer', + className: '_User', + objectId: this.user.id, + }, + }; const queryOptions = { limit: 100, order: 'objectId' From 55be8a2e2a5a6f69312e93dc97d5907370fa08d3 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 19 Oct 2018 23:52:26 +0200 Subject: [PATCH 07/15] Fix Test --- spec/Auth.spec.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/spec/Auth.spec.js b/spec/Auth.spec.js index df95fa7aa5..fc39ef23ac 100644 --- a/spec/Auth.spec.js +++ b/spec/Auth.spec.js @@ -90,6 +90,23 @@ describe('Auth', () => { }); }); }); + + it('should load all roles', async () => { + const user = new Parse.User(); + user.id = currentUserId; + const roles = []; + for(let i = 0; i < 200;i++){ + const acl = new Parse.ACL(); + const role = new Parse.Role("roleloadtest" + i, acl); + role.getUsers().add([user]); + roles.push(role.save()) + } + const savedRoles = await Promise.all(roles); + //Additionnal length check + expect(savedRoles).to.have.lengthOf(200); + const cloudRoles = auth.getUserRoles(); + expect(cloudRoles).to.have.lengthOf(200); + }); }); it('should load auth without a config', async () => { @@ -149,21 +166,4 @@ describe('Auth', () => { expect(userAuth.user instanceof Parse.User).toBe(true); expect(userAuth.user.id).toBe(user.id); }); - - it('should load all roles', async () => { - const user = new Parse.User(); - user.id = currentUserId - const roles = []; - for(var i=0; i < 200;i++){ - const acl = new Parse.ACL(); - const role = new Parse.Role("roleloadtest"+i, acl); - role.getUsers().add([user]); - roles.push(role.save()) - } - const savedRoles = await Promise.all(roles) - //Additionnal length check - expect(savedRoles).to.have.lengthOf(200) - const cloudRoles = auth.getUserRoles() - expect(cloudRoles).to.have.lengthOf(200) - }); }); From 651d6fab91ba43721f945700d04fe378904e649a Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Sat, 20 Oct 2018 01:37:45 +0200 Subject: [PATCH 08/15] Clean Final Commit --- spec/Auth.spec.js | 69 +++++++++++++++++++++++++++++++++++------------ src/Auth.js | 10 +++---- 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/spec/Auth.spec.js b/spec/Auth.spec.js index fc39ef23ac..4b422ca376 100644 --- a/spec/Auth.spec.js +++ b/spec/Auth.spec.js @@ -90,23 +90,6 @@ describe('Auth', () => { }); }); }); - - it('should load all roles', async () => { - const user = new Parse.User(); - user.id = currentUserId; - const roles = []; - for(let i = 0; i < 200;i++){ - const acl = new Parse.ACL(); - const role = new Parse.Role("roleloadtest" + i, acl); - role.getUsers().add([user]); - roles.push(role.save()) - } - const savedRoles = await Promise.all(roles); - //Additionnal length check - expect(savedRoles).to.have.lengthOf(200); - const cloudRoles = auth.getUserRoles(); - expect(cloudRoles).to.have.lengthOf(200); - }); }); it('should load auth without a config', async () => { @@ -166,4 +149,56 @@ describe('Auth', () => { expect(userAuth.user instanceof Parse.User).toBe(true); expect(userAuth.user.id).toBe(user.id); }); + + describe('getRolesForUser', () => { + + let rolesNumber = 300; + + it('should load all roles without config', async () => { + const user = new Parse.User(); + await user.signUp({ + username: 'hello', + password: 'password', + }); + expect(user.getSessionToken()).not.toBeUndefined(); + const userAuth = await getAuthForSessionToken({ + sessionToken: user.getSessionToken(), + }); + const roles = []; + for(let i = 0; i < rolesNumber;i++){ + const acl = new Parse.ACL(); + const role = new Parse.Role("roleloadtest" + i, acl); + role.getUsers().add([user]); + roles.push(role.save()) + } + const savedRoles = await Promise.all(roles); + expect(savedRoles.length).toBe(rolesNumber); + const cloudRoles = await userAuth.getRolesForUser(); + expect(cloudRoles.length).toBe(rolesNumber); + }); + + it('should load all roles with config', async () => { + const user = new Parse.User(); + await user.signUp({ + username: 'hello', + password: 'password', + }); + expect(user.getSessionToken()).not.toBeUndefined(); + const userAuth = await getAuthForSessionToken({ + sessionToken: user.getSessionToken(), + config: Config.get('test'), + }); + const roles = []; + for(let i = 0; i < rolesNumber;i++){ + const acl = new Parse.ACL(); + const role = new Parse.Role("roleloadtest" + i, acl); + role.getUsers().add([user]); + roles.push(role.save()) + } + const savedRoles = await Promise.all(roles); + expect(savedRoles.length).toBe(rolesNumber); + const cloudRoles = await userAuth.getRolesForUser(); + expect(cloudRoles.length).toBe(rolesNumber); + }); + }); }); diff --git a/src/Auth.js b/src/Auth.js index 3f8791516f..2ac8910e09 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -1,8 +1,6 @@ const cryptoUtils = require('./cryptoUtils'); const RestQuery = require('./RestQuery'); const Parse = require('parse/node'); - -//Needed for getRolesForUser() const { continueWhile } = require('parse/lib/node/promiseUtils'); // An Auth object tells you who is requesting something and whether @@ -220,11 +218,11 @@ Auth.prototype.getRolesForUser = async function() { const currentResults = await query.execute().then(({ results }) => results); finished = currentResults.length < queryOptions.limit; if (!finished) { - restWhere.objectId = { '$gt': currentResults[currentResults.length - 1].id} + restWhere.objectId = { '$gt': currentResults[currentResults.length - 1].objectId} } results = results.concat(currentResults); }); - return results.map(obj => obj.toJSON()); + return results; } //Stack all Parse.Role @@ -232,8 +230,8 @@ Auth.prototype.getRolesForUser = async function() { await new Parse.Query(Parse.Role) .equalTo('users', this.user) - .each(result => results.push(result),{useMasterKey:true}) - return results.map(obj => obj.toJSON()); + .each(result => results.push(result.toJSON()),{useMasterKey:true}) + return results; }; // Iterates through the role tree and compiles a user's roles From 2d73f23d3c52bea219574e71460a3bcad58d5e77 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Sat, 20 Oct 2018 02:19:02 +0200 Subject: [PATCH 09/15] Lint Fix --- spec/Auth.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/Auth.spec.js b/spec/Auth.spec.js index 4b422ca376..0b44ca95b0 100644 --- a/spec/Auth.spec.js +++ b/spec/Auth.spec.js @@ -152,7 +152,7 @@ describe('Auth', () => { describe('getRolesForUser', () => { - let rolesNumber = 300; + const rolesNumber = 300; it('should load all roles without config', async () => { const user = new Parse.User(); From 2ca9bc5bee6c3d723553154c9e35a6a8dcffbeff Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Sat, 20 Oct 2018 16:04:51 +0200 Subject: [PATCH 10/15] Need to Fix Test Callback --- spec/ParseLiveQueryServer.spec.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/spec/ParseLiveQueryServer.spec.js b/spec/ParseLiveQueryServer.spec.js index 6def159240..aa7a3ec846 100644 --- a/spec/ParseLiveQueryServer.spec.js +++ b/spec/ParseLiveQueryServer.spec.js @@ -1295,9 +1295,9 @@ describe('ParseLiveQueryServer', function() { shouldReturn = false; return this; }, - find() { + each(callback) { if (!shouldReturn) { - return Promise.resolve([]); + return Promise.resolve(); } //Return a role with the name "liveQueryRead" as that is what was set on the ACL const liveQueryRole = new Parse.Role( @@ -1305,7 +1305,8 @@ describe('ParseLiveQueryServer', function() { new Parse.ACL() ); liveQueryRole.id = 'abcdef1234'; - return Promise.resolve([liveQueryRole]); + callback(liveQueryRole) + return Promise.resolve(); }, }; }); From 3186bf9f315eae20c1621c8c46227f41b3ccadda Mon Sep 17 00:00:00 2001 From: Florent Vilmart <364568+flovilmart@users.noreply.github.com> Date: Sat, 20 Oct 2018 11:17:13 -0400 Subject: [PATCH 11/15] Fixes broken test --- spec/ParseLiveQueryServer.spec.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/spec/ParseLiveQueryServer.spec.js b/spec/ParseLiveQueryServer.spec.js index aa7a3ec846..d5da44bcfd 100644 --- a/spec/ParseLiveQueryServer.spec.js +++ b/spec/ParseLiveQueryServer.spec.js @@ -1296,9 +1296,6 @@ describe('ParseLiveQueryServer', function() { return this; }, each(callback) { - if (!shouldReturn) { - return Promise.resolve(); - } //Return a role with the name "liveQueryRead" as that is what was set on the ACL const liveQueryRole = new Parse.Role( 'liveQueryRead', @@ -1317,13 +1314,6 @@ describe('ParseLiveQueryServer', function() { expect(isMatched).toBe(true); done(); }); - - parseLiveQueryServer - ._matchesACL(acl, client, requestId) - .then(function(isMatched) { - expect(isMatched).toBe(true); - done(); - }); }); describe('class level permissions', () => { From 9af8d6c7bb2420363c5c2b0d732f4bdb14e6057b Mon Sep 17 00:00:00 2001 From: Florent Vilmart <364568+flovilmart@users.noreply.github.com> Date: Sat, 20 Oct 2018 11:17:59 -0400 Subject: [PATCH 12/15] Restore find() method in spy --- spec/ParseLiveQueryServer.spec.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/spec/ParseLiveQueryServer.spec.js b/spec/ParseLiveQueryServer.spec.js index d5da44bcfd..934cf46722 100644 --- a/spec/ParseLiveQueryServer.spec.js +++ b/spec/ParseLiveQueryServer.spec.js @@ -1295,6 +1295,18 @@ describe('ParseLiveQueryServer', function() { shouldReturn = false; return this; }, + find() { + if (!shouldReturn) { + return Promise.resolve([]); + } + //Return a role with the name "liveQueryRead" as that is what was set on the ACL + const liveQueryRole = new Parse.Role( + 'liveQueryRead', + new Parse.ACL() + ); + liveQueryRole.id = 'abcdef1234'; + return Promise.resolve([liveQueryRole]); + }, each(callback) { //Return a role with the name "liveQueryRead" as that is what was set on the ACL const liveQueryRole = new Parse.Role( From fd63e89139747eaeb5b05fa3cdbeb010239eacc6 Mon Sep 17 00:00:00 2001 From: Florent Vilmart <364568+flovilmart@users.noreply.github.com> Date: Sat, 20 Oct 2018 14:10:53 -0400 Subject: [PATCH 13/15] adds restquery-each --- spec/RestQuery.spec.js | 29 +++++++++++++ src/Auth.js | 93 ++++++++++++++++++------------------------ src/RestQuery.js | 32 ++++++++++++++- 3 files changed, 99 insertions(+), 55 deletions(-) diff --git a/spec/RestQuery.spec.js b/spec/RestQuery.spec.js index 18f9f72657..e17af81b8d 100644 --- a/spec/RestQuery.spec.js +++ b/spec/RestQuery.spec.js @@ -3,6 +3,7 @@ const auth = require('../lib/Auth'); const Config = require('../lib/Config'); const rest = require('../lib/rest'); +const RestQuery = require('../lib/RestQuery'); const request = require('../lib/request'); const querystring = require('querystring'); @@ -335,3 +336,31 @@ describe('rest query', () => { ); }); }); + +describe('RestQuery.each', () => { + it('should run each', async () => { + const objects = []; + while (objects.length != 10) { + objects.push(new Parse.Object('Object', { value: objects.length })); + } + const config = Config.get('test'); + await Parse.Object.saveAll(objects); + const query = new RestQuery( + config, + auth.master(config), + 'Object', + { value: { $gt: 2 } }, + { limit: 2 } + ); + const spy = spyOn(query, 'execute').and.callThrough(); + const classSpy = spyOn(RestQuery.prototype, 'execute').and.callThrough(); + const results = []; + await query.each(result => { + expect(result.value).toBeGreaterThan(2); + results.push(result); + }); + expect(spy.calls.count()).toBe(0); + expect(classSpy.calls.count()).toBe(4); + expect(results.length).toBe(7); + }); +}); diff --git a/src/Auth.js b/src/Auth.js index 2ac8910e09..e502d81e6a 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -1,7 +1,6 @@ const cryptoUtils = require('./cryptoUtils'); const RestQuery = require('./RestQuery'); const Parse = require('parse/node'); -const { continueWhile } = require('parse/lib/node/promiseUtils'); // An Auth object tells you who is requesting something and whether // the master key was used. @@ -186,8 +185,9 @@ Auth.prototype.getUserRoles = function() { }; Auth.prototype.getRolesForUser = async function() { + //Stack all Parse.Role + const results = []; if (this.config) { - const masterConfig = master(this.config); const restWhere = { users: { __type: 'Pointer', @@ -195,42 +195,18 @@ Auth.prototype.getRolesForUser = async function() { objectId: this.user.id, }, }; - const queryOptions = { - limit: 100, - order: 'objectId' - }; - let finished = false; - - //Stack all Parse.Role - let results = []; - - //Get All Parse.Role for User - await continueWhile(() => { - return !finished; - }, async () => { - const query = new RestQuery( - this.config, - masterConfig, - '_Role', - restWhere, - queryOptions - ); - const currentResults = await query.execute().then(({ results }) => results); - finished = currentResults.length < queryOptions.limit; - if (!finished) { - restWhere.objectId = { '$gt': currentResults[currentResults.length - 1].objectId} - } - results = results.concat(currentResults); - }); - return results; + await new RestQuery( + this.config, + master(this.config), + '_Role', + restWhere, + {} + ).each(result => results.push(result)); + } else { + await new Parse.Query(Parse.Role) + .equalTo('users', this.user) + .each(result => results.push(result.toJSON()), { useMasterKey: true }); } - - //Stack all Parse.Role - const results = []; - - await new Parse.Query(Parse.Role) - .equalTo('users', this.user) - .each(result => results.push(result.toJSON()),{useMasterKey:true}) return results; }; @@ -287,19 +263,11 @@ Auth.prototype.cacheRoles = function() { return true; }; -Auth.prototype.getRolesByIds = function(ins) { - const roles = ins.map(id => { - return { - __type: 'Pointer', - className: '_Role', - objectId: id, - }; - }); - const restWhere = { roles: { $in: roles } }; - +Auth.prototype.getRolesByIds = async function(ins) { + const results = []; // Build an OR query across all parentRoles if (!this.config) { - return new Parse.Query(Parse.Role) + await new Parse.Query(Parse.Role) .containedIn( 'roles', ins.map(id => { @@ -308,13 +276,30 @@ Auth.prototype.getRolesByIds = function(ins) { return role; }) ) - .find({ useMasterKey: true }) - .then(results => results.map(obj => obj.toJSON())); + .each( + result => { + results.push(result.toJSON()); + }, + { useMasterKey: true } + ); + } else { + const roles = ins.map(id => { + return { + __type: 'Pointer', + className: '_Role', + objectId: id, + }; + }); + const restWhere = { roles: { $in: roles } }; + await new RestQuery( + this.config, + master(this.config), + '_Role', + restWhere, + {} + ).each(result => results.push(result)); } - - return new RestQuery(this.config, master(this.config), '_Role', restWhere, {}) - .execute() - .then(({ results }) => results); + return results; }; // Given a list of roleIds, find all the parent roles, returns a promise with all names diff --git a/src/RestQuery.js b/src/RestQuery.js index e39d52804f..aa53c0ebf0 100644 --- a/src/RestQuery.js +++ b/src/RestQuery.js @@ -4,7 +4,7 @@ var SchemaController = require('./Controllers/SchemaController'); var Parse = require('parse/node').Parse; const triggers = require('./triggers'); - +const { continueWhile } = require('parse/lib/node/promiseUtils'); const AlwaysSelectedKeys = ['objectId', 'createdAt', 'updatedAt', 'ACL']; // restOptions can include: // skip @@ -199,6 +199,36 @@ RestQuery.prototype.execute = function(executeOptions) { }); }; +RestQuery.prototype.each = function(callback) { + const { config, auth, className, restWhere, restOptions, clientSDK } = this; + // if the limit is set, use it + restOptions.limit = restOptions.limit || 100; + restOptions.order = 'objectId'; + let finished = false; + + return continueWhile( + () => { + return !finished; + }, + async () => { + const query = new RestQuery( + config, + auth, + className, + restWhere, + restOptions, + clientSDK + ); + const { results } = await query.execute(); + results.forEach(callback); + finished = results.length < restOptions.limit; + if (!finished) { + restWhere.objectId = { $gt: results[results.length - 1].objectId }; + } + } + ); +}; + RestQuery.prototype.buildRestWhere = function() { return Promise.resolve() .then(() => { From 51c6f5bc6c6509529f6fd4a28f39285726d6ac84 Mon Sep 17 00:00:00 2001 From: Florent Vilmart <364568+flovilmart@users.noreply.github.com> Date: Sat, 20 Oct 2018 15:43:24 -0400 Subject: [PATCH 14/15] small nit --- src/Auth.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Auth.js b/src/Auth.js index e502d81e6a..ebb5debfd2 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -276,12 +276,7 @@ Auth.prototype.getRolesByIds = async function(ins) { return role; }) ) - .each( - result => { - results.push(result.toJSON()); - }, - { useMasterKey: true } - ); + .each(result => results.push(result.toJSON()), { useMasterKey: true }); } else { const roles = ins.map(id => { return { From d37e3cf875f2cc2cab4fa16cf32113f7bcede0de Mon Sep 17 00:00:00 2001 From: Florent Vilmart <364568+flovilmart@users.noreply.github.com> Date: Sat, 20 Oct 2018 16:17:55 -0400 Subject: [PATCH 15/15] adds changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b5fc868a1..67b1e053a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ ### master [Full Changelog](https://github.com/parse-community/parse-server/compare/3.1.0...master) +#### Improvements: +* Fixes issue that would prevent users with large number of roles to resolve all of them [@Moumouls]() (#5131, #5132) + + ### 3.1.0 [Full Changelog](https://github.com/parse-community/parse-server/compare/3.0.0...3.1.0)