Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions spec/ParseUser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3200,4 +3200,166 @@ describe('Parse.User testing', () => {
.then(done)
.catch(done.fail);
});

it('can login with email', (done) => {
const user = new Parse.User();
user.save({
username: 'yolo',
password: 'yolopass',
email: '[email protected]'
}).then(() => {
const options = {
url: `http://localhost:8378/1/login`,
headers: {
'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest',
},
json: { email: "[email protected]", password: 'yolopass'}
}
return rp.get(options);
}).then(done).catch(done.fail);
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could have an additional test here for trying cannot login with email and bad password, just to cover if a possible bug were introduced regarding password validation with an email at any point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the test on the next line.

it('cannot login with email and invalid password', (done) => {
const user = new Parse.User();
user.save({
username: 'yolo',
password: 'yolopass',
email: '[email protected]'
}).then(() => {
const options = {
url: `http://localhost:8378/1/login`,
headers: {
'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest',
},
json: { email: "[email protected]", password: 'yolopass2'}
}
return rp.get(options);
}).then(done.fail).catch(done);
});

it('can login with email through query string', (done) => {
const user = new Parse.User();
user.save({
username: 'yolo',
password: 'yolopass',
email: '[email protected]'
}).then(() => {
const options = {
url: `http://localhost:8378/1/[email protected]&password=yolopass`,
headers: {
'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest',
},
}
return rp.get(options);
}).then(done).catch(done.fail);
});

it('can login when both email and username are passed', (done) => {
const user = new Parse.User();
user.save({
username: 'yolo',
password: 'yolopass',
email: '[email protected]'
}).then(() => {
const options = {
url: `http://localhost:8378/1/[email protected]&username=yolo&password=yolopass`,
headers: {
'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest',
},
}
return rp.get(options);
}).then(done).catch(done.fail);
});

it("fails to login when username doesn't match email", (done) => {
const user = new Parse.User();
user.save({
username: 'yolo',
password: 'yolopass',
email: '[email protected]'
}).then(() => {
const options = {
url: `http://localhost:8378/1/[email protected]&username=yolo2&password=yolopass`,
headers: {
'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest',
},
json: true,
}
return rp.get(options);
}).then(done.fail).catch((err) => {
expect(err.response.body.error).toEqual('Invalid username/password.');
done();
});
});

it("fails to login when email doesn't match username", (done) => {
const user = new Parse.User();
user.save({
username: 'yolo',
password: 'yolopass',
email: '[email protected]'
}).then(() => {
const options = {
url: `http://localhost:8378/1/[email protected]&username=yolo&password=yolopass`,
headers: {
'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest',
},
json: true,
}
return rp.get(options);
}).then(done.fail).catch((err) => {
expect(err.response.body.error).toEqual('Invalid username/password.');
done();
});
});

it('fails to login when email and username are not provided', (done) => {
const user = new Parse.User();
user.save({
username: 'yolo',
password: 'yolopass',
email: '[email protected]'
}).then(() => {
const options = {
url: `http://localhost:8378/1/login?password=yolopass`,
headers: {
'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest',
},
json: true,
}
return rp.get(options);
}).then(done.fail).catch((err) => {
expect(err.response.body.error).toEqual('username/email is required.');
done();
});
});

it('fails to login when password is not provided', (done) => {
const user = new Parse.User();
user.save({
username: 'yolo',
password: 'yolopass',
email: '[email protected]'
}).then(() => {
const options = {
url: `http://localhost:8378/1/login?username=yolo`,
headers: {
'X-Parse-Application-Id': Parse.applicationId,
'X-Parse-REST-API-Key': 'rest',
},
json: true,
}
return rp.get(options);
}).then(done.fail).catch((err) => {
expect(err.response.body.error).toEqual('password is required.');
done();
});
});
});
26 changes: 17 additions & 9 deletions src/Routers/UsersRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,25 +51,33 @@ export class UsersRouter extends ClassesRouter {

handleLogIn(req) {
// Use query parameters instead if provided in url
if (!req.body.username && req.query.username) {
req.body = req.query;
let payload = req.body;
if (!payload.username && req.query.username || !payload.email && req.query.email) {
payload = req.query;
}
const {
username,
email,
password,
} = payload;

// TODO: use the right error codes / descriptions.
if (!req.body.username) {
throw new Parse.Error(Parse.Error.USERNAME_MISSING, 'username is required.');
if (!username && !email) {
throw new Parse.Error(Parse.Error.USERNAME_MISSING, 'username/email is required.');
}
if (!req.body.password) {
if (!password) {
throw new Parse.Error(Parse.Error.PASSWORD_MISSING, 'password is required.');
}
if (typeof req.body.username !== 'string' || typeof req.body.password !== 'string') {
if (typeof password !== 'string'
|| email && typeof email !== 'string'
|| username && typeof username !== 'string') {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid username/password.');
}

let user;
let isValidPassword = false;

return req.config.database.find('_User', { username: req.body.username })
const query = Object.assign({}, username ? { username } : {}, email ? { email } : {});
return req.config.database.find('_User', query)
.then((results) => {
if (!results.length) {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid username/password.');
Expand All @@ -79,7 +87,7 @@ export class UsersRouter extends ClassesRouter {
if (req.config.verifyUserEmails && req.config.preventLoginWithUnverifiedEmail && !user.emailVerified) {
throw new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, 'User email is not verified.');
}
return passwordCrypto.compare(req.body.password, user.password);
return passwordCrypto.compare(password, user.password);
})
.then((correct) => {
isValidPassword = correct;
Expand Down