diff --git a/spec/PushController.spec.js b/spec/PushController.spec.js index 6b8ee934fb..298595996e 100644 --- a/spec/PushController.spec.js +++ b/spec/PushController.spec.js @@ -395,7 +395,6 @@ describe('PushController', () => { }); it('properly creates _PushStatus', (done) => { - var installations = []; while(installations.length != 10) { const installation = new Parse.Object("_Installation"); @@ -436,7 +435,7 @@ describe('PushController', () => { reconfigureServer({ push: { adapter: pushAdapter } }).then(() => { - return Parse.Object.saveAll(installations) + return Parse.Object.saveAll(installations); }) .then(() => { return pushController.sendPush(payload, {}, config, auth); @@ -472,8 +471,8 @@ describe('PushController', () => { // Try to get it without masterKey const query = new Parse.Query('_PushStatus'); return query.find(); - }).then((results) => { - expect(results.length).toBe(0); + }).catch((error) => { + expect(error.code).toBe(119); done(); }); }); diff --git a/spec/rest.spec.js b/spec/rest.spec.js index 6326180732..e5ddc0303a 100644 --- a/spec/rest.spec.js +++ b/spec/rest.spec.js @@ -420,6 +420,35 @@ describe('rest create', () => { done(); }) }); + + it("can create object in volatileClasses if masterKey", (done) =>{ + rest.create(config, auth.master(config), '_PushStatus', {}) + .then((r) => { + expect(r.response.objectId.length).toBe(10); + }) + .then(() => { + rest.create(config, auth.master(config), '_JobStatus', {}) + .then((r) => { + expect(r.response.objectId.length).toBe(10); + done(); + }) + }) + + }); + + it("cannot create object in volatileClasses if not masterKey", (done) =>{ + Promise.resolve() + .then(() => { + rest.create(config, auth.nobody(config), '_PushStatus', {}) + }) + .then((r) => { + console.log(r); + }) + .catch((error) => { + expect(error.code).toEqual(119); + done(); + }) + }) }); describe('rest update', () => { diff --git a/src/Controllers/SchemaController.js b/src/Controllers/SchemaController.js index f29763be04..a29298b489 100644 --- a/src/Controllers/SchemaController.js +++ b/src/Controllers/SchemaController.js @@ -793,6 +793,7 @@ export default class SchemaController { // Validates an operation passes class-level-permissions set in the schema validatePermission(className, aclGroup, operation) { + if (this.testBaseCLP(className, aclGroup, operation)) { return Promise.resolve(); } diff --git a/src/rest.js b/src/rest.js index 2b4098fe06..d6341b14d3 100644 --- a/src/rest.js +++ b/src/rest.js @@ -142,6 +142,13 @@ function enforceRoleSecurity(method, className, auth) { throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error); } } + + //all volatileClasses are masterKey only + const volatileClasses = ['_JobStatus', '_PushStatus', '_Hooks', '_GlobalConfig']; + if(volatileClasses.includes(className) && !auth.isMaster){ + const error = `Clients aren't allowed to perform the ${method} operation on the ${className} collection.` + throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error); + } } module.exports = {