From 2e1ba66fd2e49d5cd80c0fe8a060d0ddc46a4968 Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Tue, 29 Aug 2017 16:34:59 -0400 Subject: [PATCH] Fix/user update issue (#4123) * Adds failing test, the _User object is not updated as soon as you pass some authData part of the PUT * Do not run the DB call when updating the user with new auth data, just part of the rest --- spec/ParseUser.spec.js | 54 ++++++++++++++++++++++++++++++++++++++++++ src/RestWrite.js | 34 +++++++++++++++----------- 2 files changed, 74 insertions(+), 14 deletions(-) diff --git a/spec/ParseUser.spec.js b/spec/ParseUser.spec.js index 69f3de62..fbf7adf9 100644 --- a/spec/ParseUser.spec.js +++ b/spec/ParseUser.spec.js @@ -3116,4 +3116,58 @@ describe('Parse.User testing', () => { }); }); }); + + it('should be able to update user with authData passed', (done) => { + let objectId; + let sessionToken; + + function validate(block) { + return rp.get({ + url: `http://localhost:8378/1/classes/_User/${objectId}`, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-REST-API-Key': 'rest', + 'X-Parse-Session-Token': sessionToken + }, + json: true, + }).then(block); + } + + rp.post({ + url: 'http://localhost:8378/1/classes/_User', + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-REST-API-Key': 'rest', + }, + json: { key: "value", authData: {anonymous: {id: '00000000-0000-0000-0000-000000000001'}}} + }).then((body) => { + objectId = body.objectId; + sessionToken = body.sessionToken; + expect(sessionToken).toBeDefined(); + expect(objectId).toBeDefined(); + return validate((user) => { // validate that keys are set on creation + expect(user.key).toBe("value"); + }); + }).then(() => { + // update the user + const options = { + url: `http://localhost:8378/1/classes/_User/${objectId}`, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-REST-API-Key': 'rest', + 'X-Parse-Session-Token': sessionToken + }, + json: { key: "otherValue", authData: {anonymous: {id: '00000000-0000-0000-0000-000000000001'}}} + } + return rp.put(options); + }).then(() => { + return validate((user) => { // validate that keys are set on update + expect(user.key).toBe("otherValue"); + }); + }).then(() => { + done(); + }) + .then(done) + .catch(done.fail); + }); }); diff --git a/src/RestWrite.js b/src/RestWrite.js index 199cd62f..686437bc 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -311,13 +311,12 @@ RestWrite.prototype.handleAuthData = function(authData) { // need to set the objectId first otherwise location has trailing undefined this.data.objectId = userResult.objectId; - // Determine if authData was updated - - this.response = { - response: userResult, - location: this.location() - }; - + if (!this.query || !this.query.objectId) { // this a login call, no userId passed + this.response = { + response: userResult, + location: this.location() + }; + } // If we didn't change the auth data, just keep going if (!hasMutatedAuthData) { return; @@ -327,13 +326,20 @@ RestWrite.prototype.handleAuthData = function(authData) { // We should update the token and let the user in // We should only check the mutated keys return this.handleAuthDataValidation(mutatedAuthData).then(() => { - // Assign the new authData in the response - Object.keys(mutatedAuthData).forEach((provider) => { - this.response.response.authData[provider] = mutatedAuthData[provider]; - }); - // Run the DB update directly, as 'master' - // Just update the authData part - return this.config.database.update(this.className, {objectId: this.data.objectId}, {authData: mutatedAuthData}, {}); + // IF we have a response, we'll skip the database operation / beforeSave / afterSave etc... + // we need to set it up there. + // We are supposed to have a response only on LOGIN with authData, so we skip those + // If we're not logging in, but just updating the current user, we can safely skip that part + if (this.response) { + // Assign the new authData in the response + Object.keys(mutatedAuthData).forEach((provider) => { + this.response.response.authData[provider] = mutatedAuthData[provider]; + }); + // Run the DB update directly, as 'master' + // Just update the authData part + // Then we're good for the user, early exit of sorts + return this.config.database.update(this.className, {objectId: this.data.objectId}, {authData: mutatedAuthData}, {}); + } }); } else if (userId) { // Trying to update auth data but users