Merge pull request #163 from strongloop/feature/include-user-in-login-result

Include user in login result
This commit is contained in:
Miroslav Bajtoš 2014-01-30 10:24:14 -08:00
commit c36e20587e
2 changed files with 58 additions and 11 deletions

View File

@ -128,10 +128,15 @@ var User = module.exports = Model.extend('User', properties, options);
* @param {AccessToken} token
*/
User.login = function (credentials, fn) {
var UserCtor = this;
var query = {};
User.login = function (credentials, include, fn) {
if (typeof include === 'function') {
fn = include;
include = undefined;
}
include = (include || '').toLowerCase();
var query = {};
if(credentials.email) {
query.email = credentials.email;
} else if(credentials.username) {
@ -154,7 +159,19 @@ User.login = function (credentials, fn) {
} else if(isMatch) {
user.accessTokens.create({
ttl: Math.min(credentials.ttl || User.settings.ttl, User.settings.maxTTL)
}, fn);
}, function(err, token) {
if (err) return fn(err);
if (include === 'user') {
// NOTE(bajtos) We can't set token.user here:
// 1. token.user already exists, it's a function injected by
// "AccessToken belongsTo User" relation
// 2. ModelBaseClass.toJSON() ignores own properties, thus
// the value won't be included in the HTTP response
// See also loopback#161 and loopback#162
token.__data.user = user;
}
fn(err, token);
});
} else {
debug('The password is invalid for user %s', query.email || query.username);
fn(defaultError);
@ -391,9 +408,18 @@ User.setup = function () {
UserModel.login,
{
accepts: [
{arg: 'credentials', type: 'object', required: true, http: {source: 'body'}}
{arg: 'credentials', type: 'object', required: true, http: {source: 'body'}},
{arg: 'include', type: 'string', http: {source: 'query' }, description:
'Related objects to include in the response. ' +
'See the description of return value for more details.'}
],
returns: {arg: 'accessToken', type: 'object', root: true},
returns: {
arg: 'accessToken', type: 'object', root: true, description:
'The response body contains properties of the AccessToken created on login.\n' +
'Depending on the value of `include` parameter, the body may contain ' +
'additional properties:\n\n' +
' - `user` - `{User}` - Data of the currently logged in user. (`include=user`)\n\n'
},
http: {verb: 'post'}
}
);
@ -408,7 +434,10 @@ User.setup = function () {
var tokenID = accessToken && accessToken.id;
return tokenID;
}}
}, description:
'Do not supply this argument, it is automatically extracted ' +
'from request headers.'
}
],
http: {verb: 'all'}
}

View File

@ -8,6 +8,7 @@ var userMemory = loopback.createDataSource({
});
describe('User', function(){
var validCredentials = {email: 'foo@bar.com', password: 'bar'};
beforeEach(function() {
User = loopback.User.extend('user');
User.email = loopback.Email.extend('email');
@ -25,7 +26,7 @@ describe('User', function(){
app.use(loopback.rest());
app.model(User);
User.create({email: 'foo@bar.com', password: 'bar'}, done);
User.create(validCredentials, done);
});
afterEach(function (done) {
@ -105,7 +106,7 @@ describe('User', function(){
describe('User.login', function() {
it('Login a user by providing credentials', function(done) {
User.login({email: 'foo@bar.com', password: 'bar'}, function (err, accessToken) {
User.login(validCredentials, function (err, accessToken) {
assert(accessToken.userId);
assert(accessToken.id);
assert.equal(accessToken.id.length, 64);
@ -119,7 +120,7 @@ describe('User', function(){
.post('/users/login')
.expect('Content-Type', /json/)
.expect(200)
.send({email: 'foo@bar.com', password: 'bar'})
.send(validCredentials)
.end(function(err, res){
if(err) return done(err);
var accessToken = res.body;
@ -127,11 +128,28 @@ describe('User', function(){
assert(accessToken.userId);
assert(accessToken.id);
assert.equal(accessToken.id.length, 64);
assert(accessToken.user === undefined);
done();
});
});
it('Returns current user when `include` is `USER`', function(done) {
request(app)
.post('/users/login?include=USER')
.send(validCredentials)
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if (err) return done(err);
var token = res.body;
expect(token.user, 'body.user').to.not.equal(undefined);
expect(token.user, 'body.user')
.to.have.property('email', validCredentials.email);
done();
});
});
it('Login should only allow correct credentials', function(done) {
User.create({email: 'foo22@bar.com', password: 'bar'}, function(user, err) {
User.login({email: 'foo44@bar.com', password: 'bar'}, function(err, accessToken) {