Skip to content

Commit 3723b9b

Browse files
committed
Merge pull request #924 from ParsePlatform/nlutsenko.hooks.acl
Make sure that ACLs propagate to before/after save hooks.
2 parents 7143a12 + 0f07c52 commit 3723b9b

File tree

2 files changed

+99
-7
lines changed

2 files changed

+99
-7
lines changed

spec/ParseAPI.spec.js

+92-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
var DatabaseAdapter = require('../src/DatabaseAdapter');
66
var request = require('request');
7+
const Parse = require("parse/node");
78

89
describe('miscellaneous', function() {
910
it('create a GameScore object', function(done) {
@@ -372,8 +373,8 @@ describe('miscellaneous', function() {
372373
done();
373374
});
374375
});
375-
376-
it('test cloud function shoud echo keys', function(done) {
376+
377+
it('test cloud function should echo keys', function(done) {
377378
Parse.Cloud.run('echoKeys').then((result) => {
378379
expect(result.applicationId).toEqual(Parse.applicationId);
379380
expect(result.masterKey).toEqual(Parse.masterKey);
@@ -399,7 +400,7 @@ describe('miscellaneous', function() {
399400
expect(results.length).toEqual(1);
400401
expect(results[0]['foo']).toEqual('bar');
401402
done();
402-
}).fail( err => {
403+
}).fail(err => {
403404
fail(err);
404405
done();
405406
})
@@ -415,9 +416,9 @@ describe('miscellaneous', function() {
415416
// Make sure the required mock for all tests is unset.
416417
Parse.Cloud._removeHook("Triggers", "beforeSave", "GameScore");
417418
done();
418-
});
419-
420-
it('object is set on create and update', done => {
419+
});
420+
421+
it('object is set on create and update', done => {
421422
let triggerTime = 0;
422423
// Register a mock beforeSave hook
423424
Parse.Cloud.beforeSave('GameScore', (req, res) => {
@@ -683,7 +684,7 @@ describe('miscellaneous', function() {
683684
// Make sure the checking has been triggered
684685
expect(triggerTime).toBe(2);
685686
// Clear mock afterSave
686-
Parse.Cloud._removeHook("Triggers", "afterSave", "GameScore");
687+
Parse.Cloud._removeHook("Triggers", "afterSave", "GameScore");
687688
done();
688689
}, function(error) {
689690
console.error(error);
@@ -732,6 +733,90 @@ describe('miscellaneous', function() {
732733
});
733734
});
734735

736+
it('beforeSave receives ACL', done => {
737+
let triggerTime = 0;
738+
// Register a mock beforeSave hook
739+
Parse.Cloud.beforeSave('GameScore', function(req, res) {
740+
let object = req.object;
741+
if (triggerTime == 0) {
742+
let acl = object.getACL();
743+
expect(acl.getPublicReadAccess()).toBeTruthy();
744+
expect(acl.getPublicWriteAccess()).toBeTruthy();
745+
} else if (triggerTime == 1) {
746+
let acl = object.getACL();
747+
expect(acl.getPublicReadAccess()).toBeFalsy();
748+
expect(acl.getPublicWriteAccess()).toBeTruthy();
749+
} else {
750+
res.error();
751+
}
752+
triggerTime++;
753+
res.success();
754+
});
755+
756+
let obj = new Parse.Object('GameScore');
757+
let acl = new Parse.ACL();
758+
acl.setPublicReadAccess(true);
759+
acl.setPublicWriteAccess(true);
760+
obj.setACL(acl);
761+
obj.save().then(() => {
762+
acl.setPublicReadAccess(false);
763+
obj.setACL(acl);
764+
return obj.save();
765+
}).then(() => {
766+
// Make sure the checking has been triggered
767+
expect(triggerTime).toBe(2);
768+
// Clear mock afterSave
769+
Parse.Cloud._removeHook("Triggers", "beforeSave", "GameScore");
770+
done();
771+
}, error => {
772+
console.error(error);
773+
fail(error);
774+
done();
775+
});
776+
});
777+
778+
it('afterSave receives ACL', done => {
779+
let triggerTime = 0;
780+
// Register a mock beforeSave hook
781+
Parse.Cloud.afterSave('GameScore', function(req, res) {
782+
let object = req.object;
783+
if (triggerTime == 0) {
784+
let acl = object.getACL();
785+
expect(acl.getPublicReadAccess()).toBeTruthy();
786+
expect(acl.getPublicWriteAccess()).toBeTruthy();
787+
} else if (triggerTime == 1) {
788+
let acl = object.getACL();
789+
expect(acl.getPublicReadAccess()).toBeFalsy();
790+
expect(acl.getPublicWriteAccess()).toBeTruthy();
791+
} else {
792+
res.error();
793+
}
794+
triggerTime++;
795+
res.success();
796+
});
797+
798+
let obj = new Parse.Object('GameScore');
799+
let acl = new Parse.ACL();
800+
acl.setPublicReadAccess(true);
801+
acl.setPublicWriteAccess(true);
802+
obj.setACL(acl);
803+
obj.save().then(() => {
804+
acl.setPublicReadAccess(false);
805+
obj.setACL(acl);
806+
return obj.save();
807+
}).then(() => {
808+
// Make sure the checking has been triggered
809+
expect(triggerTime).toBe(2);
810+
// Clear mock afterSave
811+
Parse.Cloud._removeHook("Triggers", "afterSave", "GameScore");
812+
done();
813+
}, error => {
814+
console.error(error);
815+
fail(error);
816+
done();
817+
});
818+
});
819+
735820
it('test cloud function error handling', (done) => {
736821
// Register a function which will fail
737822
Parse.Cloud.define('willFail', (req, res) => {

src/Controllers/DatabaseController.js

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ var Parse = require('parse/node').Parse;
66

77
var Schema = require('./../Schema');
88
var transform = require('./../transform');
9+
const deepcopy = require('deepcopy');
910

1011
// options can contain:
1112
// collectionPrefix: the string to put in front of every collection name.
@@ -130,6 +131,9 @@ DatabaseController.prototype.untransformObject = function(
130131
// one of the provided strings must provide the caller with
131132
// write permissions.
132133
DatabaseController.prototype.update = function(className, query, update, options) {
134+
// Make a copy of the object, so we don't mutate the incoming data.
135+
update = deepcopy(update);
136+
133137
var acceptor = function(schema) {
134138
return schema.hasKeys(className, Object.keys(query));
135139
};
@@ -300,6 +304,9 @@ DatabaseController.prototype.destroy = function(className, query, options = {})
300304
// Inserts an object into the database.
301305
// Returns a promise that resolves successfully iff the object saved.
302306
DatabaseController.prototype.create = function(className, object, options) {
307+
// Make a copy of the object, so we don't mutate the incoming data.
308+
object = deepcopy(object);
309+
303310
var schema;
304311
var isMaster = !('acl' in options);
305312
var aclGroup = options.acl || [];

0 commit comments

Comments
 (0)