Skip to content

Commit 0518a06

Browse files
committed
Adds ability to login with email when provided as username (#4420)
1 parent 4da8edb commit 0518a06

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

spec/ParseUser.spec.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3432,6 +3432,60 @@ describe('Parse.User testing', () => {
34323432
});
34333433
});
34343434

3435+
it('allows login when providing email as username', (done) => {
3436+
const user = new Parse.User();
3437+
user.save({
3438+
username: 'yolo',
3439+
password: 'yolopass',
3440+
3441+
}).then(() => {
3442+
return Parse.User.logIn('[email protected]', 'yolopass');
3443+
}).then((user) => {
3444+
expect(user.get('username')).toBe('yolo');
3445+
}).then(done).catch(done.fail);
3446+
});
3447+
3448+
it('handles properly when 2 users share username / email pairs', (done) => {
3449+
const user = new Parse.User({
3450+
username: '[email protected]',
3451+
password: 'yolopass',
3452+
3453+
});
3454+
const user2 = new Parse.User({
3455+
username: '[email protected]',
3456+
3457+
password: 'yolopass2' // different passwords
3458+
});
3459+
3460+
Parse.Object.saveAll([user, user2]).then(() => {
3461+
return Parse.User.logIn('[email protected]', 'yolopass');
3462+
}).then((user) => {
3463+
// the username takes precedence over the email,
3464+
// so we get the user with username as passed in
3465+
expect(user.get('username')).toBe('[email protected]');
3466+
}).then(done).catch(done.fail);
3467+
});
3468+
3469+
it('handles properly when 2 users share username / email pairs, counterpart', (done) => {
3470+
const user = new Parse.User({
3471+
username: '[email protected]',
3472+
password: 'yolopass',
3473+
3474+
});
3475+
const user2 = new Parse.User({
3476+
username: '[email protected]',
3477+
3478+
password: 'yolopass2' // different passwords
3479+
});
3480+
3481+
Parse.Object.saveAll([user, user2]).then(() => {
3482+
return Parse.User.logIn('[email protected]', 'yolopass2');
3483+
}).then(done.fail).catch((err) => {
3484+
expect(err.message).toEqual('Invalid username/password.');
3485+
done();
3486+
});
3487+
});
3488+
34353489
it('fails to login when password is not provided', (done) => {
34363490
const user = new Parse.User();
34373491
user.save({

src/Routers/UsersRouter.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,26 @@ export class UsersRouter extends ClassesRouter {
8484

8585
let user;
8686
let isValidPassword = false;
87-
const query = Object.assign({}, username ? { username } : {}, email ? { email } : {});
87+
let query;
88+
if (email && username) {
89+
query = { email, username };
90+
} else if (email) {
91+
query = { email };
92+
} else {
93+
query = { $or: [{ username } , { email: username }] };
94+
}
8895
return req.config.database.find('_User', query)
8996
.then((results) => {
9097
if (!results.length) {
9198
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid username/password.');
9299
}
93-
user = results[0];
100+
101+
if (results.length > 1) { // corner case where user1 has username == user2 email
102+
req.config.loggerController.warn('There is a user which email is the same as another user\'s username, logging in based on username');
103+
user = results.filter((user) => user.username === username)[0];
104+
} else {
105+
user = results[0];
106+
}
94107

95108
if (req.config.verifyUserEmails && req.config.preventLoginWithUnverifiedEmail && !user.emailVerified) {
96109
throw new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, 'User email is not verified.');

0 commit comments

Comments
 (0)