Skip to content

Commit

Permalink
fix #3451 duplicate session upon login (#4337)
Browse files Browse the repository at this point in the history
* Adds failing test for #3451 (on multiple logins)

* Factor sessionDestruction as part of Session creation flow in RestWrite

* nits
  • Loading branch information
flovilmart authored Nov 11, 2017
1 parent 932a474 commit 72e20be
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 8 deletions.
30 changes: 30 additions & 0 deletions spec/ParseUser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3453,4 +3453,34 @@ describe('Parse.User testing', () => {
done();
});
});

it('does not duplicate session when logging in multiple times #3451', (done) => {
const user = new Parse.User();
user.signUp({
username: 'yolo',
password: 'yolo',
email: 'yo@lo.com'
}).then(() => {
const promises = [];
while(promises.length != 5) {
Parse.User.logIn('yolo', 'yolo')
promises.push(Parse.User.logIn('yolo', 'yolo').then((res) => {
// ensure a new session token is generated at each login
expect(res.getSessionToken()).not.toBe(user.getSessionToken());
}));
}
return Promise.all(promises);
}).then(() => {
// wait because session destruction is not synchronous
return new Promise((resolve) => {
setTimeout(resolve, 100);
});
}).then(() => {
const query = new Parse.Query('_Session');
return query.find({ useMasterKey: true });
}).then((results) => {
// only one session in the end
expect(results.length).toBe(1);
}).then(done, done.fail);
});
});
32 changes: 24 additions & 8 deletions src/RestWrite.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ RestWrite.prototype.execute = function() {
return this.transformUser();
}).then(() => {
return this.expandFilesForExistingObjects();
}).then(() => {
return this.destroyDuplicatedSessions();
}).then(() => {
return this.runDatabaseOperation();
}).then(() => {
Expand Down Expand Up @@ -588,17 +590,31 @@ RestWrite.prototype.createSessionToken = function() {
this.response.response.sessionToken = token;
}

return new RestWrite(this.config, Auth.master(this.config), '_Session', null, sessionData).execute();
}

RestWrite.prototype.destroyDuplicatedSessions = function() {
// Only for _Session, and at creation time
if (this.className != '_Session' || this.query) {
return;
}
// Destroy the sessions in 'Background'
const {
user,
installationId,
sessionToken,
} = this.data;
if (!user || !installationId) {
return;
}
if (!user.objectId) {
return;
}
this.config.database.destroy('_Session', {
user: {
__type: 'Pointer',
className: '_User',
objectId: this.objectId()
},
installationId: this.auth.installationId,
sessionToken: { '$ne': token },
user,
installationId,
sessionToken: { '$ne': sessionToken },
});
return new RestWrite(this.config, Auth.master(this.config), '_Session', null, sessionData).execute();
}

// Handles any followup logic
Expand Down

0 comments on commit 72e20be

Please sign in to comment.