From 42aacdf62bc359782c755ffecb595e76dfc993c2 Mon Sep 17 00:00:00 2001 From: Francis Lessard Date: Thu, 11 Feb 2016 22:16:07 -0500 Subject: [PATCH 1/8] FIX : User Roles not added to create, update or delete calls --- src/RestWrite.js | 28 ++++++++++++++++++---------- src/rest.js | 7 +++++++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/RestWrite.js b/src/RestWrite.js index f4bb7353..3832d59f 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -28,6 +28,7 @@ function RestWrite(config, auth, className, query, data, originalData) { this.auth = auth; this.className = className; this.storage = {}; + this.runOptions = {}; if (!query && data.objectId) { throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'objectId ' + @@ -67,6 +68,8 @@ function RestWrite(config, auth, className, query, data, originalData) { // status and location are optional. RestWrite.prototype.execute = function() { return Promise.resolve().then(() => { + return this.getUserAndRoleACL(); + }).then(() => { return this.validateSchema(); }).then(() => { return this.handleInstallation(); @@ -89,6 +92,19 @@ RestWrite.prototype.execute = function() { }); }; +// Uses the Auth object to get the list of roles, adds the user id +RestWrite.prototype.getUserAndRoleACL = function() { + if (this.auth.isMaster || !this.auth.user) { + return Promise.resolve(); + } + return this.auth.getUserRoles().then((roles) => { + roles.push('*'); + roles.push(this.auth.user.id); + this.runOptions.acl = roles; + return Promise.resolve(); + }); +}; + // Validates this operation against the schema. RestWrite.prototype.validateSchema = function() { return this.config.database.validateObject(this.className, this.data); @@ -645,24 +661,16 @@ RestWrite.prototype.runDatabaseOperation = function() { throw new Parse.Error(Parse.Error.INVALID_ACL, 'Invalid ACL.'); } - var options = {}; - if (!this.auth.isMaster) { - options.acl = ['*']; - if (this.auth.user) { - options.acl.push(this.auth.user.id); - } - } - if (this.query) { // Run an update return this.config.database.update( - this.className, this.query, this.data, options).then((resp) => { + this.className, this.query, this.data, this.runOptions).then((resp) => { this.response = resp; this.response.updatedAt = this.updatedAt; }); } else { // Run a create - return this.config.database.create(this.className, this.data, options) + return this.config.database.create(this.className, this.data, this.runOptions) .then(() => { var resp = { objectId: this.data.objectId, diff --git a/src/rest.js b/src/rest.js index 552fa6be..094e8ab6 100644 --- a/src/rest.js +++ b/src/rest.js @@ -56,12 +56,19 @@ function del(config, auth, className, objectId) { }); } return Promise.resolve({}); + }).then(() => { + if (!auth.isMaster) { + return auth.getUserRoles(); + }else{ + return Promise.resolve(); + } }).then(() => { var options = {}; if (!auth.isMaster) { options.acl = ['*']; if (auth.user) { options.acl.push(auth.user.id); + options.acl = options.acl.concat(auth.userRoles); } } From 220a13392d9ed587402ba04b0308f0524a2f87a4 Mon Sep 17 00:00:00 2001 From: Francis Lessard Date: Fri, 12 Feb 2016 16:32:45 -0500 Subject: [PATCH 2/8] no message --- src/RestWrite.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/RestWrite.js b/src/RestWrite.js index 497ac5b1..8dab5344 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -27,7 +27,9 @@ function RestWrite(config, auth, className, query, data, originalData) { this.auth = auth; this.className = className; this.storage = {}; - this.runOptions = {}; + this.runOptions = { + acl:['*'] + }; if (!query && data.objectId) { throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'objectId ' + @@ -97,9 +99,8 @@ RestWrite.prototype.getUserAndRoleACL = function() { return Promise.resolve(); } return this.auth.getUserRoles().then((roles) => { - roles.push('*'); roles.push(this.auth.user.id); - this.runOptions.acl = roles; + this.runOptions.acl = this.runOptions.acl.concat(roles); return Promise.resolve(); }); }; From 83c0f92553fc3eda195488dc7f962c21d15d0b95 Mon Sep 17 00:00:00 2001 From: Francis Lessard Date: Sat, 13 Feb 2016 08:18:43 -0500 Subject: [PATCH 3/8] no message --- spec/ParseRole.spec.js | 2 +- src/Auth.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/ParseRole.spec.js b/spec/ParseRole.spec.js index 44476f1b..919e0b55 100644 --- a/spec/ParseRole.spec.js +++ b/spec/ParseRole.spec.js @@ -49,7 +49,7 @@ describe('Parse Role testing', () => { }).then((x) => { x.set('foo', 'baz'); // This should fail: - return x.save(); + return x.save({},{sessionToken: ""}); }).then((x) => { fail('Should not have been able to save.'); }, (e) => { diff --git a/src/Auth.js b/src/Auth.js index ad905654..27bbf885 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -80,7 +80,7 @@ Auth.prototype.getUserRoles = function() { return Promise.resolve(this.userRoles); } if (this.rolePromise) { - return rolePromise; + return this.rolePromise; } this.rolePromise = this._loadRoles(); return this.rolePromise; From 5b40a589c0d06aa223dd622444da4ea093d5b3a7 Mon Sep 17 00:00:00 2001 From: Francis Lessard Date: Tue, 16 Feb 2016 10:45:43 -0500 Subject: [PATCH 4/8] Remove public ACL set by default. --- src/RestWrite.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/RestWrite.js b/src/RestWrite.js index 8dab5344..e43aea94 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -28,7 +28,7 @@ function RestWrite(config, auth, className, query, data, originalData) { this.className = className; this.storage = {}; this.runOptions = { - acl:['*'] + acl:[] }; if (!query && data.objectId) { @@ -95,14 +95,21 @@ RestWrite.prototype.execute = function() { // Uses the Auth object to get the list of roles, adds the user id RestWrite.prototype.getUserAndRoleACL = function() { - if (this.auth.isMaster || !this.auth.user) { + if (this.auth.isMaster) { return Promise.resolve(); } - return this.auth.getUserRoles().then((roles) => { - roles.push(this.auth.user.id); - this.runOptions.acl = this.runOptions.acl.concat(roles); + + this.runOptions.acl.push("*"); + + if( this.auth.user ){ + return this.auth.getUserRoles().then((roles) => { + roles.push(this.auth.user.id); + this.runOptions.acl = this.runOptions.acl.concat(roles); + return Promise.resolve(); + }); + }else{ return Promise.resolve(); - }); + } }; // Validates this operation against the schema. From 06b8157eeae3956e282cea325198d5f2c9c8fdc4 Mon Sep 17 00:00:00 2001 From: Marco129 Date: Wed, 17 Feb 2016 02:52:32 +0800 Subject: [PATCH 5/8] Throw error when query with wrongly encoded parameter --- spec/RestQuery.spec.js | 48 ++++++++++++++++++++++++++++++++++++ src/Routers/ClassesRouter.js | 11 +++++++++ 2 files changed, 59 insertions(+) diff --git a/spec/RestQuery.spec.js b/spec/RestQuery.spec.js index b93a07d5..279f45f6 100644 --- a/spec/RestQuery.spec.js +++ b/spec/RestQuery.spec.js @@ -4,6 +4,9 @@ var cache = require('../src/cache'); var Config = require('../src/Config'); var rest = require('../src/rest'); +var querystring = require('querystring'); +var request = require('request'); + var config = new Config('test'); var nobody = auth.nobody(config); @@ -92,4 +95,49 @@ describe('rest query', () => { }).catch((error) => { console.log(error); }); }); + it('query with wrongly encoded parameter', (done) => { + rest.create(config, nobody, 'TestParameterEncode', {foo: 'bar'} + ).then(() => { + return rest.create(config, nobody, + 'TestParameterEncode', {foo: 'baz'}); + }).then(() => { + var headers = { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest' + }; + request.get({ + headers: headers, + url: 'http://localhost:8378/1/classes/TestParameterEncode?' + + querystring.stringify({ + where: '{"foo":{"$ne": "baz"}}', + limit: 1 + }).replace('=', '%3D'), + }, (error, response, body) => { + expect(error).toBe(null); + var b = JSON.parse(body); + expect(b.code).toEqual(Parse.Error.INVALID_QUERY); + expect(b.error).toEqual('Improper encode of parameter'); + done(); + }); + }).then(() => { + var headers = { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest' + }; + request.get({ + headers: headers, + url: 'http://localhost:8378/1/classes/TestParameterEncode?' + + querystring.stringify({ + limit: 1 + }).replace('=', '%3D'), + }, (error, response, body) => { + expect(error).toBe(null); + var b = JSON.parse(body); + expect(b.code).toEqual(Parse.Error.INVALID_QUERY); + expect(b.error).toEqual('Improper encode of parameter'); + done(); + }); + }); + }); + }); diff --git a/src/Routers/ClassesRouter.js b/src/Routers/ClassesRouter.js index c9fe9c48..f13185a2 100644 --- a/src/Routers/ClassesRouter.js +++ b/src/Routers/ClassesRouter.js @@ -2,11 +2,22 @@ import PromiseRouter from '../PromiseRouter'; import rest from '../rest'; +import url from 'url'; + export class ClassesRouter { // Returns a promise that resolves to a {response} object. handleFind(req) { let body = Object.assign(req.body, req.query); let options = {}; + let allowConstraints = ['skip', 'limit', 'order', 'count', 'keys', + 'include', 'redirectClassNameForKey', 'where']; + + for (var key in body) { + if (allowConstraints.indexOf(key) === -1) { + throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Improper encode of parameter'); + } + } + if (body.skip) { options.skip = Number(body.skip); } From 4ecf0ac10c4e7689c103dbfa916e28d1c768ae7f Mon Sep 17 00:00:00 2001 From: Simon Bengtsson Date: Wed, 17 Feb 2016 20:30:43 +0100 Subject: [PATCH 6/8] Don't use https://api.parse.com/1 as default serverURL --- src/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index a5355f6c..07629a36 100644 --- a/src/index.js +++ b/src/index.js @@ -115,9 +115,7 @@ function ParseServer(args) { // Initialize the node client SDK automatically Parse.initialize(args.appId, args.javascriptKey || '', args.masterKey); - if(args.serverURL) { - Parse.serverURL = args.serverURL; - } + Parse.serverURL = args.serverURL || ''; // This app serves the Parse API directly. // It's the equivalent of https://api.parse.com/1 in the hosted Parse API. From 5de33ac226025e1d8c7b9a59566d42ca3cbb2177 Mon Sep 17 00:00:00 2001 From: Francis Lessard Date: Thu, 18 Feb 2016 13:29:26 -0500 Subject: [PATCH 7/8] Fix : save whit masterKey cause object not found. --- src/RestWrite.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/RestWrite.js b/src/RestWrite.js index 88296b4e..777973d7 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -27,9 +27,7 @@ function RestWrite(config, auth, className, query, data, originalData) { this.auth = auth; this.className = className; this.storage = {}; - this.runOptions = { - acl:[] - }; + this.runOptions = {}; if (!query && data.objectId) { throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'objectId ' + @@ -99,7 +97,7 @@ RestWrite.prototype.getUserAndRoleACL = function() { return Promise.resolve(); } - this.runOptions.acl.push("*"); + this.runOptions.acl = ['*']; if( this.auth.user ){ return this.auth.getUserRoles().then((roles) => { From 7db69ac8f2c400698c2a25e027ab01eeade44e57 Mon Sep 17 00:00:00 2001 From: Fosco Marotto Date: Fri, 19 Feb 2016 12:10:00 -0800 Subject: [PATCH 8/8] Updating to 2.1.2 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7e83371..c27fb140 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ ## Parse Server Changelog +### 2.1.2 (2/19/2016) + +* Change: The S3 file adapter constructor requires a bucket name +* Fix: Parse Query should throw if improperly encoded +* Fix: Issue where roles were not used in some requests +* Fix: serverURL will no longer default to api.parse.com/1 + ### 2.1.1 (2/18/2016) * Experimental: Schemas API support for DELETE operations