Merge pull request #163 from strongloop/feature/include-user-in-login-result
Include user in login result
This commit is contained in:
commit
c36e20587e
|
@ -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'}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue