Adding support for AfterFind (#2968)
This commit is contained in:
@@ -1306,4 +1306,134 @@ describe('beforeFind hooks', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
|
describe('afterFind hooks', () => {
|
||||||
|
it('should add afterFind trigger using get',(done) => {
|
||||||
|
Parse.Cloud.afterFind('MyObject', (req, res) => {
|
||||||
|
for(let i = 0 ; i < req.objects.length ; i++){
|
||||||
|
req.objects[i].set("secretField","###");
|
||||||
|
}
|
||||||
|
res.success(req.objects);
|
||||||
|
});
|
||||||
|
let obj = new Parse.Object('MyObject');
|
||||||
|
obj.set('secretField', 'SSID');
|
||||||
|
obj.save().then(function() {
|
||||||
|
let query = new Parse.Query('MyObject');
|
||||||
|
query.get(obj.id).then(function(result) {
|
||||||
|
expect(result.get('secretField')).toEqual('###');
|
||||||
|
done();
|
||||||
|
}, function(error) {
|
||||||
|
fail(error);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}, function(error) {
|
||||||
|
fail(error);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add afterFind trigger using find',(done) => {
|
||||||
|
Parse.Cloud.afterFind('MyObject', (req, res) => {
|
||||||
|
for(let i = 0 ; i < req.objects.length ; i++){
|
||||||
|
req.objects[i].set("secretField","###");
|
||||||
|
}
|
||||||
|
res.success(req.objects);
|
||||||
|
});
|
||||||
|
let obj = new Parse.Object('MyObject');
|
||||||
|
obj.set('secretField', 'SSID');
|
||||||
|
obj.save().then(function() {
|
||||||
|
let query = new Parse.Query('MyObject');
|
||||||
|
query.equalTo('objectId',obj.id);
|
||||||
|
query.find().then(function(results) {
|
||||||
|
expect(results[0].get('secretField')).toEqual('###');
|
||||||
|
done();
|
||||||
|
}, function(error) {
|
||||||
|
fail(error);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}, function(error) {
|
||||||
|
fail(error);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should filter out results',(done) => {
|
||||||
|
Parse.Cloud.afterFind('MyObject', (req, res) => {
|
||||||
|
let filteredResults = [];
|
||||||
|
for(let i = 0 ; i < req.objects.length ; i++){
|
||||||
|
if(req.objects[i].get("secretField")==="SSID1") {
|
||||||
|
filteredResults.push(req.objects[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.success(filteredResults);
|
||||||
|
});
|
||||||
|
let obj0 = new Parse.Object('MyObject');
|
||||||
|
obj0.set('secretField', 'SSID1');
|
||||||
|
let obj1 = new Parse.Object('MyObject');
|
||||||
|
obj1.set('secretField', 'SSID2');
|
||||||
|
Parse.Object.saveAll([obj0, obj1]).then(function() {
|
||||||
|
let query = new Parse.Query('MyObject');
|
||||||
|
query.find().then(function(results) {
|
||||||
|
expect(results[0].get('secretField')).toEqual('SSID1');
|
||||||
|
expect(results.length).toEqual(1);
|
||||||
|
done();
|
||||||
|
}, function(error) {
|
||||||
|
fail(error);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}, function(error) {
|
||||||
|
fail(error);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle failures',(done) => {
|
||||||
|
Parse.Cloud.afterFind('MyObject', (req, res) => {
|
||||||
|
res.error(Parse.Error.SCRIPT_FAILED, "It should fail");
|
||||||
|
});
|
||||||
|
let obj = new Parse.Object('MyObject');
|
||||||
|
obj.set('secretField', 'SSID');
|
||||||
|
obj.save().then(function() {
|
||||||
|
let query = new Parse.Query('MyObject');
|
||||||
|
query.equalTo('objectId',obj.id);
|
||||||
|
query.find().then(function(results) {
|
||||||
|
fail("AfterFind should handle response failure correctly");
|
||||||
|
done();
|
||||||
|
}, function(error) {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}, function(error) {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should also work with promise',(done) => {
|
||||||
|
Parse.Cloud.afterFind('MyObject', (req, res) => {
|
||||||
|
let promise = new Parse.Promise();
|
||||||
|
setTimeout(function(){
|
||||||
|
for(let i = 0 ; i < req.objects.length ; i++){
|
||||||
|
req.objects[i].set("secretField","###");
|
||||||
|
}
|
||||||
|
promise.resolve(req.objects);
|
||||||
|
}, 1000);
|
||||||
|
return promise;
|
||||||
|
});
|
||||||
|
let obj = new Parse.Object('MyObject');
|
||||||
|
obj.set('secretField', 'SSID');
|
||||||
|
obj.save().then(function() {
|
||||||
|
let query = new Parse.Query('MyObject');
|
||||||
|
query.equalTo('objectId',obj.id);
|
||||||
|
query.find().then(function(results) {
|
||||||
|
expect(results[0].get('secretField')).toEqual('###');
|
||||||
|
done();
|
||||||
|
}, function(error) {
|
||||||
|
fail(error);
|
||||||
|
});
|
||||||
|
}, function(error) {
|
||||||
|
fail(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
var SchemaController = require('./Controllers/SchemaController');
|
var SchemaController = require('./Controllers/SchemaController');
|
||||||
var Parse = require('parse/node').Parse;
|
var Parse = require('parse/node').Parse;
|
||||||
|
const triggers = require('./triggers');
|
||||||
|
|
||||||
import { default as FilesController } from './Controllers/FilesController';
|
import { default as FilesController } from './Controllers/FilesController';
|
||||||
|
|
||||||
@@ -122,6 +123,8 @@ RestQuery.prototype.execute = function(executeOptions) {
|
|||||||
return this.runCount();
|
return this.runCount();
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return this.handleInclude();
|
return this.handleInclude();
|
||||||
|
}).then(() => {
|
||||||
|
return this.runAfterFindTrigger();
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return this.response;
|
return this.response;
|
||||||
});
|
});
|
||||||
@@ -468,6 +471,22 @@ RestQuery.prototype.handleInclude = function() {
|
|||||||
return pathResponse;
|
return pathResponse;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Returns a promise of a processed set of results
|
||||||
|
RestQuery.prototype.runAfterFindTrigger = function() {
|
||||||
|
if (!this.response) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Avoid doing any setup for triggers if there is no 'afterFind' trigger for this class.
|
||||||
|
const hasAfterFindHook = triggers.triggerExists(this.className, triggers.Types.afterFind, this.config.applicationId);
|
||||||
|
if (!hasAfterFindHook) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
// Run afterFind trigger and set the new results
|
||||||
|
return triggers.maybeRunAfterFindTrigger(triggers.Types.afterFind, this.auth, this.className,this.response.results, this.config).then((results) => {
|
||||||
|
this.response.results = results;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Adds included values to the response.
|
// Adds included values to the response.
|
||||||
// Path is a list of field names.
|
// Path is a list of field names.
|
||||||
// Returns a promise for an augmented response.
|
// Returns a promise for an augmented response.
|
||||||
|
|||||||
@@ -50,6 +50,11 @@ ParseCloud.beforeFind = function(parseClass, handler) {
|
|||||||
triggers.addTrigger(triggers.Types.beforeFind, className, handler, Parse.applicationId);
|
triggers.addTrigger(triggers.Types.beforeFind, className, handler, Parse.applicationId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ParseCloud.afterFind = function(parseClass, handler) {
|
||||||
|
const className = getClassName(parseClass);
|
||||||
|
triggers.addTrigger(triggers.Types.afterFind, className, handler, Parse.applicationId);
|
||||||
|
};
|
||||||
|
|
||||||
ParseCloud._removeAllHooks = () => {
|
ParseCloud._removeAllHooks = () => {
|
||||||
triggers._unregisterAll();
|
triggers._unregisterAll();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ export const Types = {
|
|||||||
afterSave: 'afterSave',
|
afterSave: 'afterSave',
|
||||||
beforeDelete: 'beforeDelete',
|
beforeDelete: 'beforeDelete',
|
||||||
afterDelete: 'afterDelete',
|
afterDelete: 'afterDelete',
|
||||||
beforeFind: 'beforeFind'
|
beforeFind: 'beforeFind',
|
||||||
|
afterFind: 'afterFind'
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseStore = function() {
|
const baseStore = function() {
|
||||||
@@ -185,6 +186,15 @@ export function getRequestQueryObject(triggerType, auth, query, config) {
|
|||||||
export function getResponseObject(request, resolve, reject) {
|
export function getResponseObject(request, resolve, reject) {
|
||||||
return {
|
return {
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
|
if (request.triggerName === Types.afterFind) {
|
||||||
|
if(!response){
|
||||||
|
response = request.objects;
|
||||||
|
}
|
||||||
|
response = response.map(object => {
|
||||||
|
return object.toJSON();
|
||||||
|
});
|
||||||
|
return resolve(response);
|
||||||
|
}
|
||||||
// Use the JSON response
|
// Use the JSON response
|
||||||
if (response && !request.object.equals(response)
|
if (response && !request.object.equals(response)
|
||||||
&& request.triggerName === Types.beforeSave) {
|
&& request.triggerName === Types.beforeSave) {
|
||||||
@@ -240,6 +250,42 @@ function logTriggerErrorBeforeHook(triggerType, className, input, auth, error) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function maybeRunAfterFindTrigger(triggerType, auth, className, objects, config) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const trigger = getTrigger(className, triggerType, config.applicationId);
|
||||||
|
if (!trigger) {
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
|
const request = getRequestObject(triggerType, auth, null, null, config);
|
||||||
|
const response = getResponseObject(request,
|
||||||
|
object => {
|
||||||
|
resolve(object);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
logTriggerSuccessBeforeHook(triggerType, className, 'AfterFind', JSON.stringify(objects), auth);
|
||||||
|
request.objects = objects.map(object => {
|
||||||
|
//setting the class name to transform into parse object
|
||||||
|
object.className=className;
|
||||||
|
return Parse.Object.fromJSON(object);
|
||||||
|
});
|
||||||
|
const triggerPromise = trigger(request, response);
|
||||||
|
if (triggerPromise && typeof triggerPromise.then === "function") {
|
||||||
|
return triggerPromise.then(promiseResults => {
|
||||||
|
if(promiseResults) {
|
||||||
|
resolve(promiseResults);
|
||||||
|
}else{
|
||||||
|
return reject(new Parse.Error(Parse.Error.SCRIPT_FAILED, "AfterFind expect results to be returned in the promise"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).then((results) => {
|
||||||
|
logTriggerAfterHook(triggerType, className, JSON.stringify(results), auth);
|
||||||
|
return results;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function maybeRunQueryTrigger(triggerType, className, restWhere, restOptions, config, auth) {
|
export function maybeRunQueryTrigger(triggerType, className, restWhere, restOptions, config, auth) {
|
||||||
let trigger = getTrigger(className, triggerType, config.applicationId);
|
let trigger = getTrigger(className, triggerType, config.applicationId);
|
||||||
if (!trigger) {
|
if (!trigger) {
|
||||||
|
|||||||
Reference in New Issue
Block a user