From cea2734c8e112af0f67665afc03ac362e2bf94c3 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 22 Oct 2020 11:05:42 +1100 Subject: [PATCH 1/2] Initial Commit --- spec/CloudCode.spec.js | 31 +++++++++++++++++++++++++++++ src/RestQuery.js | 44 ++++++++++++++++++++++++------------------ src/triggers.js | 7 ++++++- 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index c42922ca26..246bcad0c6 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -2018,6 +2018,37 @@ describe('beforeFind hooks', () => { }); describe('afterFind hooks', () => { + it('should add afterFind trigger', done => { + Parse.Cloud.afterFind('MyObject', req => { + const q = req.query; + expect(q instanceof Parse.Query).toBe(true); + const jsonQuery = q.toJSON(); + expect(jsonQuery.where.key).toEqual('value'); + expect(jsonQuery.where.some).toEqual({ $gt: 10 }); + expect(jsonQuery.include).toEqual('otherKey,otherValue'); + expect(jsonQuery.excludeKeys).toBe('exclude'); + expect(jsonQuery.limit).toEqual(100); + expect(jsonQuery.skip).toBe(undefined); + expect(jsonQuery.order).toBe('key'); + expect(jsonQuery.keys).toBe('select'); + expect(jsonQuery.readPreference).toBe('PRIMARY'); + expect(jsonQuery.includeReadPreference).toBe('SECONDARY'); + expect(jsonQuery.subqueryReadPreference).toBe('SECONDARY_PREFERRED'); + }); + + const query = new Parse.Query('MyObject'); + query.equalTo('key', 'value'); + query.greaterThan('some', 10); + query.include('otherKey'); + query.include('otherValue'); + query.ascending('key'); + query.select('select'); + query.exclude('exclude'); + query.readPreference('PRIMARY', 'SECONDARY', 'SECONDARY_PREFERRED'); + query.find().then(() => { + done(); + }); + }); it('should add afterFind trigger using get', done => { Parse.Cloud.afterFind('MyObject', req => { for (let i = 0; i < req.objects.length; i++) { diff --git a/src/RestQuery.js b/src/RestQuery.js index 79862d4aed..1f6f4b520c 100644 --- a/src/RestQuery.js +++ b/src/RestQuery.js @@ -188,7 +188,7 @@ function RestQuery( // Returns a promise for the response - an object with optional keys // 'results' and 'count'. // TODO: consolidate the replaceX functions -RestQuery.prototype.execute = function(executeOptions) { +RestQuery.prototype.execute = function (executeOptions) { return Promise.resolve() .then(() => { return this.buildRestWhere(); @@ -216,7 +216,7 @@ RestQuery.prototype.execute = function(executeOptions) { }); }; -RestQuery.prototype.each = function(callback) { +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; @@ -248,7 +248,7 @@ RestQuery.prototype.each = function(callback) { ); }; -RestQuery.prototype.buildRestWhere = function() { +RestQuery.prototype.buildRestWhere = function () { return Promise.resolve() .then(() => { return this.getUserAndRoleACL(); @@ -277,7 +277,7 @@ RestQuery.prototype.buildRestWhere = function() { }; // Uses the Auth object to get the list of roles, adds the user id -RestQuery.prototype.getUserAndRoleACL = function() { +RestQuery.prototype.getUserAndRoleACL = function () { if (this.auth.isMaster) { return Promise.resolve(); } @@ -298,7 +298,7 @@ RestQuery.prototype.getUserAndRoleACL = function() { // Changes the className if redirectClassNameForKey is set. // Returns a promise. -RestQuery.prototype.redirectClassNameForKey = function() { +RestQuery.prototype.redirectClassNameForKey = function () { if (!this.redirectKey) { return Promise.resolve(); } @@ -313,7 +313,7 @@ RestQuery.prototype.redirectClassNameForKey = function() { }; // Validates this operation against the allowClientClassCreation config. -RestQuery.prototype.validateClientClassCreation = function() { +RestQuery.prototype.validateClientClassCreation = function () { if ( this.config.allowClientClassCreation === false && !this.auth.isMaster && @@ -358,7 +358,7 @@ function transformInQuery(inQueryObject, className, results) { // $inQuery clause. // The $inQuery clause turns into an $in with values that are just // pointers to the objects returned in the subquery. -RestQuery.prototype.replaceInQuery = function() { +RestQuery.prototype.replaceInQuery = function () { var inQueryObject = findObjectWithKey(this.restWhere, '$inQuery'); if (!inQueryObject) { return; @@ -419,7 +419,7 @@ function transformNotInQuery(notInQueryObject, className, results) { // $notInQuery clause. // The $notInQuery clause turns into a $nin with values that are just // pointers to the objects returned in the subquery. -RestQuery.prototype.replaceNotInQuery = function() { +RestQuery.prototype.replaceNotInQuery = function () { var notInQueryObject = findObjectWithKey(this.restWhere, '$notInQuery'); if (!notInQueryObject) { return; @@ -485,7 +485,7 @@ const transformSelect = (selectObject, key, objects) => { // The $select clause turns into an $in with values selected out of // the subquery. // Returns a possible-promise. -RestQuery.prototype.replaceSelect = function() { +RestQuery.prototype.replaceSelect = function () { var selectObject = findObjectWithKey(this.restWhere, '$select'); if (!selectObject) { return; @@ -550,7 +550,7 @@ const transformDontSelect = (dontSelectObject, key, objects) => { // The $dontSelect clause turns into an $nin with values selected out of // the subquery. // Returns a possible-promise. -RestQuery.prototype.replaceDontSelect = function() { +RestQuery.prototype.replaceDontSelect = function () { var dontSelectObject = findObjectWithKey(this.restWhere, '$dontSelect'); if (!dontSelectObject) { return; @@ -599,7 +599,7 @@ RestQuery.prototype.replaceDontSelect = function() { }); }; -const cleanResultAuthData = function(result) { +const cleanResultAuthData = function (result) { delete result.password; if (result.authData) { Object.keys(result.authData).forEach(provider => { @@ -638,7 +638,7 @@ const replaceEqualityConstraint = constraint => { return constraint; }; -RestQuery.prototype.replaceEquality = function() { +RestQuery.prototype.replaceEquality = function () { if (typeof this.restWhere !== 'object') { return; } @@ -649,7 +649,7 @@ RestQuery.prototype.replaceEquality = function() { // Returns a promise for whether it was successful. // Populates this.response with an object that only has 'results'. -RestQuery.prototype.runFind = function(options = {}) { +RestQuery.prototype.runFind = function (options = {}) { if (this.findOptions.limit === 0) { this.response = { results: [] }; return Promise.resolve(); @@ -685,7 +685,7 @@ RestQuery.prototype.runFind = function(options = {}) { // Returns a promise for whether it was successful. // Populates this.response.count with the count -RestQuery.prototype.runCount = function() { +RestQuery.prototype.runCount = function () { if (!this.doCount) { return; } @@ -700,7 +700,7 @@ RestQuery.prototype.runCount = function() { }; // Augments this.response with all pointers on an object -RestQuery.prototype.handleIncludeAll = function() { +RestQuery.prototype.handleIncludeAll = function () { if (!this.includeAll) { return; } @@ -729,7 +729,7 @@ RestQuery.prototype.handleIncludeAll = function() { }; // Updates property `this.keys` to contain all keys but the ones unselected. -RestQuery.prototype.handleExcludeKeys = function() { +RestQuery.prototype.handleExcludeKeys = function () { if (!this.excludeKeys) { return; } @@ -747,7 +747,7 @@ RestQuery.prototype.handleExcludeKeys = function() { }; // Augments this.response with data at the paths provided in this.include. -RestQuery.prototype.handleInclude = function() { +RestQuery.prototype.handleInclude = function () { if (this.include.length == 0) { return; } @@ -774,7 +774,7 @@ RestQuery.prototype.handleInclude = function() { }; //Returns a promise of a processed set of results -RestQuery.prototype.runAfterFindTrigger = function() { +RestQuery.prototype.runAfterFindTrigger = function () { if (!this.response) { return; } @@ -794,6 +794,11 @@ RestQuery.prototype.runAfterFindTrigger = function() { if (this.findOptions.pipeline || this.findOptions.distinct) { return Promise.resolve(); } + + const json = Object.assign({}, this.restOptions); + json.where = this.restWhere; + const parseQuery = new Parse.Query(this.className); + parseQuery.withJSON(json); // Run afterFind trigger and set the new results return triggers .maybeRunAfterFindTrigger( @@ -801,7 +806,8 @@ RestQuery.prototype.runAfterFindTrigger = function() { this.auth, this.className, this.response.results, - this.config + this.config, + parseQuery ) .then(results => { // Ensure we properly set the className back diff --git a/src/triggers.js b/src/triggers.js index 48464c2ff4..fed0265720 100644 --- a/src/triggers.js +++ b/src/triggers.js @@ -416,7 +416,8 @@ export function maybeRunAfterFindTrigger( auth, className, objects, - config + config, + query ) { return new Promise((resolve, reject) => { const trigger = getTrigger(className, triggerType, config.applicationId); @@ -424,6 +425,10 @@ export function maybeRunAfterFindTrigger( return resolve(); } const request = getRequestObject(triggerType, auth, null, null, config); + // pass query to afterFind + if (query) { + request.query = query; + } const { success, error } = getResponseObject( request, object => { From 7c87d127bf3c10bec29d02f8fe3e07980f3b5507 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 22 Oct 2020 13:22:51 +1100 Subject: [PATCH 2/2] Update triggers.js --- src/triggers.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/triggers.js b/src/triggers.js index fed0265720..6a8370b98a 100644 --- a/src/triggers.js +++ b/src/triggers.js @@ -425,7 +425,6 @@ export function maybeRunAfterFindTrigger( return resolve(); } const request = getRequestObject(triggerType, auth, null, null, config); - // pass query to afterFind if (query) { request.query = query; }