From daad05a00f890630203b9e2685e3c3d55b56d38f Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Fri, 11 Mar 2016 14:50:33 -0500 Subject: [PATCH] removes key transformation for authData from restWrite, ensures authData is set in hooks --- spec/ParseUser.spec.js | 37 ++++++++++++++++++++++++++++++++++++ spec/RestCreate.spec.js | 2 +- src/RestWrite.js | 25 +++++++++--------------- src/authDataManager/index.js | 2 +- src/transform.js | 19 +++++++++++++++++- 5 files changed, 66 insertions(+), 19 deletions(-) diff --git a/spec/ParseUser.spec.js b/spec/ParseUser.spec.js index 50f29331..1776ad56 100644 --- a/spec/ParseUser.spec.js +++ b/spec/ParseUser.spec.js @@ -1436,6 +1436,43 @@ describe('Parse.User testing', () => { } }); }); + + it('should have authData in beforeSave and afterSave', (done) => { + + Parse.Cloud.beforeSave('_User', (request, response) => { + let authData = request.object.get('authData'); + expect(authData).not.toBeUndefined(); + if (authData) { + expect(authData.facebook.id).toEqual('8675309'); + expect(authData.facebook.access_token).toEqual('jenny'); + } else { + fail('authData should be set'); + } + response.success(); + }); + + Parse.Cloud.afterSave('_User', (request, response) => { + let authData = request.object.get('authData'); + expect(authData).not.toBeUndefined(); + if (authData) { + expect(authData.facebook.id).toEqual('8675309'); + expect(authData.facebook.access_token).toEqual('jenny'); + } else { + fail('authData should be set'); + } + response.success(); + }); + + var provider = getMockFacebookProvider(); + Parse.User._registerAuthenticationProvider(provider); + Parse.User._logInWith("facebook", { + success: function(model) { + Parse.Cloud._removeHook('Triggers', 'beforeSave', Parse.User.className); + Parse.Cloud._removeHook('Triggers', 'afterSave', Parse.User.className); + done(); + } + }); + }); it('set password then change password', (done) => { Parse.User.signUp('bob', 'barker').then((bob) => { diff --git a/spec/RestCreate.spec.js b/spec/RestCreate.spec.js index 553d37ad..d07e18ed 100644 --- a/spec/RestCreate.spec.js +++ b/spec/RestCreate.spec.js @@ -200,7 +200,7 @@ describe('rest create', () => { done(); }); }); - + it('stores pointers with a _p_ prefix', (done) => { var obj = { foo: 'bar', diff --git a/src/RestWrite.js b/src/RestWrite.js index a31c8e5b..c2be50af 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -212,10 +212,12 @@ RestWrite.prototype.validateAuthData = function() { var authData = this.data.authData; var providers = Object.keys(authData); if (providers.length > 0) { - var provider = providers[providers.length-1]; - var providerAuthData = authData[provider]; - var hasToken = (providerAuthData && providerAuthData.id); - if (providerAuthData === null || hasToken) { + let canHandleAuthData = providers.reduce((canHandle, provider) => { + var providerAuthData = authData[provider]; + var hasToken = (providerAuthData && providerAuthData.id); + return canHandle && (hasToken || providerAuthData == null); + }, true); + if (canHandleAuthData) { return this.handleAuthData(authData); } } @@ -274,11 +276,9 @@ RestWrite.prototype.handleAuthData = function(authData) { throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED, 'this auth is already used'); } - // set the proper keys - Object.keys(authData).forEach((provider) => { - this.data[`_auth_data_${provider}`] = authData[provider]; - }); - + + this.storage['authProvider'] = Object.keys(authData).join(','); + if (results.length == 0) { this.data.username = cryptoUtils.newToken(); } else if (!this.query) { @@ -294,9 +294,6 @@ RestWrite.prototype.handleAuthData = function(authData) { // Trying to update auth data but users // are different if (results[0].objectId !== this.query.objectId) { - Object.keys(authData).forEach((provider) => { - delete this.data[`_auth_data_${provider}`]; - }); throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED, 'this auth is already used'); } @@ -708,10 +705,6 @@ RestWrite.prototype.runDatabaseOperation = function() { if (this.data.ACL && this.data.ACL['*unresolved']) { throw new Parse.Error(Parse.Error.INVALID_ACL, 'Invalid ACL.'); } - - if (this.className === '_User') { - delete this.data.authData; - } if (this.query) { // Run an update diff --git a/src/authDataManager/index.js b/src/authDataManager/index.js index 04ef8971..77ee7473 100644 --- a/src/authDataManager/index.js +++ b/src/authDataManager/index.js @@ -91,4 +91,4 @@ module.exports = function(oauthOptions = {}, enableAnonymousUsers = true) { getValidatorForProvider, setEnableAnonymousUsers, }) -} \ No newline at end of file +} diff --git a/src/transform.js b/src/transform.js index 738f2453..aae5cc2a 100644 --- a/src/transform.js +++ b/src/transform.js @@ -87,7 +87,7 @@ export function transformKeyValue(schema, className, restKey, restValue, options return transformWhere(schema, className, s); }); return {key: '$and', value: mongoSubqueries}; - default: + default: // Other auth data var authDataMatch = key.match(/^authData\.([a-zA-Z0-9_]+)\.id$/); if (authDataMatch) { @@ -203,6 +203,9 @@ function transformWhere(schema, className, restWhere) { // restCreate is the "create" clause in REST API form. // Returns the mongo form of the object. function transformCreate(schema, className, restCreate) { + if (className == '_User') { + restCreate = transformAuthData(restCreate); + } var mongoCreate = transformACL(restCreate); for (var restKey in restCreate) { var out = transformKeyValue(schema, className, restKey, restCreate[restKey]); @@ -218,6 +221,10 @@ function transformUpdate(schema, className, restUpdate) { if (!restUpdate) { throw 'got empty restUpdate'; } + if (className == '_User') { + restUpdate = transformAuthData(restUpdate); + } + var mongoUpdate = {}; var acl = transformACL(restUpdate); if (acl._rperm || acl._wperm) { @@ -250,6 +257,16 @@ function transformUpdate(schema, className, restUpdate) { return mongoUpdate; } +function transformAuthData(restObject) { + if (restObject.authData) { + Object.keys(restObject.authData).forEach((provider) => { + restObject[`_auth_data_${provider}`] = restObject.authData[provider]; + }); + delete restObject.authData; + } + return restObject; +} + // Transforms a REST API formatted ACL object to our two-field mongo format. // This mutates the restObject passed in to remove the ACL key. function transformACL(restObject) {