From 1b8e613dfb6f114878779e1012a33973fa273c2e Mon Sep 17 00:00:00 2001 From: yuzeh Date: Fri, 25 Mar 2016 16:11:27 -0700 Subject: [PATCH] Clean authData of null values on _User update Adds a step to the RestWrite#execute chain: it cleans the response authData object of null values. For example, this: {"authData": {"anonymous": null}, "updatedAt", ...} will be transformed to this: {"updatedAt", ...} And this: {"authData": {"anonymous": null, "twitter": ...}, "updatedAt", ...} will be transformed to this: {"authData": {"twitter": ...}, "updatedAt", ...} Fixing this issue will fix anonymous user upgrades from the Android SDK. --- spec/ParseUser.spec.js | 59 ++++++++++++++++++++++++++++++++++++++++++ src/RestWrite.js | 18 +++++++++++++ 2 files changed, 77 insertions(+) diff --git a/spec/ParseUser.spec.js b/spec/ParseUser.spec.js index ccfdb4b39e..941e1a0c55 100644 --- a/spec/ParseUser.spec.js +++ b/spec/ParseUser.spec.js @@ -2061,6 +2061,65 @@ describe('Parse.User testing', () => { }) }); + // https://github.com/ParsePlatform/parse-server/issues/1198 + it('should cleanup null authData keys ParseUser update', (done) => { + Parse.Cloud.beforeSave('_User', (req, res) => { + req.object.set('foo', 'bar'); + res.success(); + }); + + // Simulate anonymous user save + new Promise((resolve, reject) => { + request.post({ + url: 'http://localhost:8378/1/classes/_User', + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-REST-API-Key': 'rest', + }, + json: {authData: {anonymous: {id: '00000000-0000-0000-0000-000000000001'}}} + }, (err, res, body) => { + if (err) { + reject(err); + } else { + resolve(body); + } + }); + }).then((user) => { + // Simulate registration + return new Promise((resolve, reject) => { + request.put({ + url: 'http://localhost:8378/1/classes/_User/' + user.objectId, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Session-Token': user.sessionToken, + 'X-Parse-REST-API-Key': 'rest', + }, + json: { + authData: {anonymous: null}, + user: 'user', + password: 'password', + } + }, (err, res, body) => { + if (err) { + reject(err); + } else { + resolve(body); + } + }); + }); + }).then((user) => { + expect(typeof user).toEqual('object'); + expect(user.authData).toBeUndefined(); + Parse.Cloud._removeHook('Triggers', 'beforeSave', '_User'); + done(); + }).catch((err) => { + fail('no request should fail: ' + JSON.stringify(err)); + Parse.Cloud._removeHook('Triggers', 'beforeSave', '_User'); + done(); + }); + }); + + it('should aftersave with full object', (done) => { var hit = 0; Parse.Cloud.afterSave('_User', (req, res) => { diff --git a/src/RestWrite.js b/src/RestWrite.js index f00d852bc9..ba1bfdca1c 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -83,6 +83,8 @@ RestWrite.prototype.execute = function() { return this.handleFollowup(); }).then(() => { return this.runAfterTrigger(); + }).then(() => { + return this.cleanUserAuthData(); }).then(() => { return this.response; }); @@ -824,5 +826,21 @@ RestWrite.prototype.sanitizedData = function() { return Parse._decode(undefined, data); } +RestWrite.prototype.cleanUserAuthData = function() { + if (this.response && this.response.response && this.className === '_User') { + let user = this.response.response; + if (user.authData) { + Object.keys(user.authData).forEach((provider) => { + if (user.authData[provider] === null) { + delete user.authData[provider]; + } + }); + if (Object.keys(user.authData).length == 0) { + delete user.authData; + } + } + } +}; + export default RestWrite; module.exports = RestWrite;