From 4bda6e49e4e78573a4160542f28f6c260906c0f3 Mon Sep 17 00:00:00 2001 From: Taylor Stine Date: Mon, 1 Feb 2016 15:41:22 -0500 Subject: [PATCH 01/10] Added cloud funciton argument --- index.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 79a32198..ae526e19 100644 --- a/index.js +++ b/index.js @@ -51,7 +51,14 @@ function ParseServer(args) { } if (args.cloud) { addParseCloud(); - require(args.cloud); + if (typeof args.cloud === 'function') { + args.cloud(Parse) + } else if (typeof args.cloud === 'string') { + require(args.cloud); + } else { + throw "argument 'cloud' must either be a string or a function"; + } + } cache.apps[args.appId] = { From 15ab25940e9fa9ee6d47061047d76e1b133427fc Mon Sep 17 00:00:00 2001 From: Taylor Stine Date: Mon, 1 Feb 2016 14:15:30 -0500 Subject: [PATCH 02/10] Added encoding to user name and password --- ExportAdapter.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/ExportAdapter.js b/ExportAdapter.js index 89cb6c59..ffb493fe 100644 --- a/ExportAdapter.js +++ b/ExportAdapter.js @@ -34,8 +34,19 @@ ExportAdapter.prototype.connect = function() { return this.connectionPromise; } + var usernameStart = this.mongoURI.indexOf('://') + 3; + var lastAtIndex = this.mongoURI.lastIndexOf('@'); + var encodedMongoURI = this.mongoURI; + var username = null; + var password = null; + var split = null + if (lastAtIndex > 0) { + split = this.mongoURI.slice(usernameStart, lastAtIndex).split(':'); + encodedMongoURI = this.mongoURI.slice(0, usernameStart) + encodeURIComponent(split[0]) + ':' + encodeURIComponent(split[1]) + this.mongoURI.slice(lastAtIndex); + } + this.connectionPromise = Promise.resolve().then(() => { - return MongoClient.connect(this.mongoURI); + return MongoClient.connect(encodedMongoURI, {uri_decode_auth:true}); }).then((db) => { this.db = db; }); From 8e1f632e31acf121a068228777c86d1c7a620da1 Mon Sep 17 00:00:00 2001 From: Alexander Mays Date: Mon, 1 Feb 2016 16:03:44 -0500 Subject: [PATCH 03/10] Correctly uses date instead of string for expiresAt when creating a session Signed-off-by: Alexander Mays --- users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/users.js b/users.js index 76deec7c..00780854 100644 --- a/users.js +++ b/users.js @@ -70,7 +70,7 @@ function handleLogIn(req) { 'authProvider': 'password' }, restricted: false, - expiresAt: Parse._encode(expiresAt).iso + expiresAt: Parse._encode(expiresAt) }; if (req.info.installationId) { From 97cf00b4d01044d48fad37be244b8786fe143195 Mon Sep 17 00:00:00 2001 From: Taylor Stine Date: Tue, 2 Feb 2016 07:31:50 -0500 Subject: [PATCH 04/10] added regex to validate mongo uri and remove unused variables --- ExportAdapter.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ExportAdapter.js b/ExportAdapter.js index ffb493fe..db586d83 100644 --- a/ExportAdapter.js +++ b/ExportAdapter.js @@ -34,12 +34,14 @@ ExportAdapter.prototype.connect = function() { return this.connectionPromise; } + //http://regexr.com/3cn6m + if (!this.mongoURI.match(/^mongodb:\/\/((.+):(.+)@)?([^:@]+):([^:]+)\/(.+?)$/gm)) { + throw new Error("Invalid mongoURI: " + this.mongoURI) + } var usernameStart = this.mongoURI.indexOf('://') + 3; var lastAtIndex = this.mongoURI.lastIndexOf('@'); var encodedMongoURI = this.mongoURI; - var username = null; - var password = null; - var split = null + var split = null; if (lastAtIndex > 0) { split = this.mongoURI.slice(usernameStart, lastAtIndex).split(':'); encodedMongoURI = this.mongoURI.slice(0, usernameStart) + encodeURIComponent(split[0]) + ':' + encodeURIComponent(split[1]) + this.mongoURI.slice(lastAtIndex); From 95cea9230b88feae1f0a6cb51686af7522de0193 Mon Sep 17 00:00:00 2001 From: Taylor Stine Date: Tue, 2 Feb 2016 07:51:19 -0500 Subject: [PATCH 05/10] Added detail comment to the ParseServer constructor for cloud function --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index ae526e19..209110af 100644 --- a/index.js +++ b/index.js @@ -23,7 +23,9 @@ addParseCloud(); // and delete // "databaseURI": a uri like mongodb://localhost:27017/dbname to tell us // what database this Parse API connects to. -// "cloud": relative location to cloud code to require +// "cloud": relative location to cloud code to require, or a function +// that is given an instance of Parse as a parameter. Use this instance of Parse +// to register your cloud code hooks and functions. // "appId": the application id to host // "masterKey": the master key for requests to this app // "facebookAppIds": an array of valid Facebook Application IDs, required From ffa7d1b1f1b3e1495df8210c82e1e3e6d28ab7a9 Mon Sep 17 00:00:00 2001 From: Taylor Stine Date: Tue, 2 Feb 2016 08:13:13 -0500 Subject: [PATCH 06/10] Added req.auth.user to parse cloud functions --- Auth.js | 1 + functions.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Auth.js b/Auth.js index faa1ffd6..ad905654 100644 --- a/Auth.js +++ b/Auth.js @@ -64,6 +64,7 @@ var getAuthForSessionToken = function(config, sessionToken) { var obj = results[0]['user']; delete obj.password; obj['className'] = '_User'; + obj['sessionToken'] = sessionToken; var userObject = Parse.Object.fromJSON(obj); cache.setUser(sessionToken, userObject); return new Auth(config, false, userObject); diff --git a/functions.js b/functions.js index cf4aeb28..74d481b0 100644 --- a/functions.js +++ b/functions.js @@ -13,7 +13,8 @@ function handleCloudFunction(req) { return new Promise(function (resolve, reject) { var response = createResponseObject(resolve, reject); var request = { - params: req.body || {} + params: req.body || {}, + user: req.auth && req.auth.user || {} }; Parse.Cloud.Functions[req.params.functionName](request, response); }); From 5d05c742c95cefcb6b1c55eb7e23337402006c52 Mon Sep 17 00:00:00 2001 From: Alexander Mays Date: Tue, 2 Feb 2016 09:59:20 -0500 Subject: [PATCH 07/10] This fixes an issue exposed during testing with es6 where the scope on the 2nd invocation of handleFollowup isn't set Signed-off-by: Alexander Mays --- RestWrite.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RestWrite.js b/RestWrite.js index ea7b2225..4318880e 100644 --- a/RestWrite.js +++ b/RestWrite.js @@ -362,7 +362,7 @@ RestWrite.prototype.handleFollowup = function() { }; delete this.storage['clearSessions']; return this.config.database.destroy('_Session', sessionQuery) - .then(this.handleFollowup); + .then(this.handleFollowup.bind(this)); } }; From 52769cce29a51728ece096f83c3908ff428f4768 Mon Sep 17 00:00:00 2001 From: Alexander Mays Date: Tue, 2 Feb 2016 10:03:54 -0500 Subject: [PATCH 08/10] Fixed the missing variable declarations on iterators. This makes running the tests in ES6 pass! Signed-off-by: Alexander Mays --- ExportAdapter.js | 2 +- RestQuery.js | 2 +- spec/helper.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ExportAdapter.js b/ExportAdapter.js index 89cb6c59..4030ae40 100644 --- a/ExportAdapter.js +++ b/ExportAdapter.js @@ -232,7 +232,7 @@ ExportAdapter.prototype.handleRelationUpdates = function(className, } if (op.__op == 'Batch') { - for (x of op.ops) { + for (var x of op.ops) { process(x, key); } } diff --git a/RestQuery.js b/RestQuery.js index f136206a..8c9bf712 100644 --- a/RestQuery.js +++ b/RestQuery.js @@ -434,7 +434,7 @@ function includePath(config, auth, response, path) { function findPointers(object, path) { if (object instanceof Array) { var answer = []; - for (x of object) { + for (var x of object) { answer = answer.concat(findPointers(x, path)); } return answer; diff --git a/spec/helper.js b/spec/helper.js index 255d61f8..761796a6 100644 --- a/spec/helper.js +++ b/spec/helper.js @@ -153,7 +153,7 @@ function normalize(obj) { return '[' + obj.map(normalize).join(', ') + ']'; } var answer = '{'; - for (key of Object.keys(obj).sort()) { + for (var key of Object.keys(obj).sort()) { answer += key + ': '; answer += normalize(obj[key]); answer += ', '; @@ -192,7 +192,7 @@ function mockFacebook() { function clearData() { var promises = []; - for (conn in DatabaseAdapter.dbConnections) { + for (var conn in DatabaseAdapter.dbConnections) { promises.push(DatabaseAdapter.dbConnections[conn].deleteEverything()); } return Promise.all(promises); From fa66ac551f4a3828356492a6c48cde4b6afa7061 Mon Sep 17 00:00:00 2001 From: Alexander Mays Date: Tue, 2 Feb 2016 10:12:25 -0500 Subject: [PATCH 09/10] Updated package.json to use the symlinked jasmine binary Signed-off-by: Alexander Mays --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index abdcbca8..62c6aec7 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "jasmine": "^2.3.2" }, "scripts": { - "test": "TESTING=1 jasmine" + "test": "TESTING=1 ./node_modules/.bin/jasmine" }, "engines": { "node": ">=4.1" From 35b6b16918d51302ab74d5c1da79d092cf94f516 Mon Sep 17 00:00:00 2001 From: Taylor Stine Date: Tue, 2 Feb 2016 16:14:42 -0500 Subject: [PATCH 10/10] Removed user todo from cloud function --- functions.js | 1 - 1 file changed, 1 deletion(-) diff --git a/functions.js b/functions.js index 74d481b0..ee2ac541 100644 --- a/functions.js +++ b/functions.js @@ -8,7 +8,6 @@ var express = require('express'), var router = new PromiseRouter(); function handleCloudFunction(req) { - // TODO: set user from req.auth if (Parse.Cloud.Functions[req.params.functionName]) { return new Promise(function (resolve, reject) { var response = createResponseObject(resolve, reject);