From 6b4ebdf6098eac392fa89e372aa53e3f254cf921 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Fri, 6 Jun 2014 14:30:18 -0700 Subject: [PATCH] Allow the creation of access token to be overriden --- lib/models/user.js | 29 +++++++++++++++++++++-------- package.json | 2 -- test/user.test.js | 40 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/lib/models/user.js b/lib/models/user.js index 73a18d39..f7e114d3 100644 --- a/lib/models/user.js +++ b/lib/models/user.js @@ -2,14 +2,12 @@ * Module Dependencies. */ -var Model = require('../loopback').Model - , loopback = require('../loopback') +var loopback = require('../loopback') + , Model = loopback.Model , path = require('path') , SALT_WORK_FACTOR = 10 , crypto = require('crypto') , bcrypt = require('bcryptjs') - , passport = require('passport') - , LocalStrategy = require('passport-local').Strategy , BaseAccessToken = require('./access-token') , DEFAULT_TTL = 1209600 // 2 weeks in seconds , DEFAULT_RESET_PW_TTL = 15 * 60 // 15 mins in seconds @@ -128,6 +126,22 @@ var options = { var User = module.exports = Model.extend('User', properties, options); +/** + * Create access token for the logged in user. This method can be overridden to + * customize how access tokens are generated + * + * @param [Number} ttl The requested ttl + * @callack {Function} cb The callback function + * @param {String|Error} err The error string or object + * @param {AccessToken} token The generated access token object + */ +User.prototype.createAccessToken = function(ttl, cb) { + ttl = Math.min(ttl || User.settings.ttl, User.settings.maxTTL); + this.accessTokens.create({ + ttl: ttl + }, cb); +}; + /** * Login a user by with the given `credentials`. * @@ -144,6 +158,7 @@ var User = module.exports = Model.extend('User', properties, options); */ User.login = function (credentials, include, fn) { + var self = this; if (typeof include === 'function') { fn = include; include = undefined; @@ -162,7 +177,7 @@ User.login = function (credentials, include, fn) { return fn(err); } - this.findOne({where: query}, function(err, user) { + self.findOne({where: query}, function(err, user) { var defaultError = new Error('login failed'); defaultError.statusCode = 401; @@ -175,9 +190,7 @@ User.login = function (credentials, include, fn) { debug('An error is reported from User.hasPassword: %j', err); fn(defaultError); } else if(isMatch) { - user.accessTokens.create({ - ttl: Math.min(credentials.ttl || User.settings.ttl, User.settings.maxTTL) - }, function(err, token) { + user.createAccessToken(credentials.ttl, function(err, token) { if (err) return fn(err); if (include === 'user') { // NOTE(bajtos) We can't set token.user here: diff --git a/package.json b/package.json index bf72e84f..fadc1fd9 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,6 @@ "express": "~3.5.0", "strong-remoting": "~1.5.0", "inflection": "~1.3.5", - "passport": "~0.2.0", - "passport-local": "~1.0.0", "nodemailer": "~0.6.5", "ejs": "~1.0.0", "bcryptjs": "~0.7.12", diff --git a/test/user.test.js b/test/user.test.js index 25b1df8f..2b3805a1 100644 --- a/test/user.test.js +++ b/test/user.test.js @@ -1,6 +1,5 @@ var User; var AccessToken = loopback.AccessToken; -var passport = require('passport'); var MailConnector = require('../lib/connectors/mail'); var userMemory = loopback.createDataSource({ @@ -9,6 +8,7 @@ var userMemory = loopback.createDataSource({ describe('User', function(){ var validCredentials = {email: 'foo@bar.com', password: 'bar'}; + var validCredentialsWithTTL = {email: 'foo@bar.com', password: 'bar', ttl: 3600}; var invalidCredentials = {email: 'foo1@bar.com', password: 'bar1'}; var incompleteCredentials = {password: 'bar1'}; @@ -117,6 +117,44 @@ describe('User', function(){ done(); }); }); + + it('Login a user by providing credentials with TTL', function(done) { + User.login(validCredentialsWithTTL, function (err, accessToken) { + assert(accessToken.userId); + assert(accessToken.id); + assert.equal(accessToken.ttl, validCredentialsWithTTL.ttl); + assert.equal(accessToken.id.length, 64); + + done(); + }); + }); + + it('Login a user using a custom createAccessToken', function(done) { + var createToken = User.prototype.createAccessToken; // Save the original method + // Override createAccessToken + User.prototype.createAccessToken = function(ttl, cb) { + // Reduce the ttl by half for testing purpose + this.accessTokens.create({ttl: ttl /2 }, cb); + }; + User.login(validCredentialsWithTTL, function (err, accessToken) { + assert(accessToken.userId); + assert(accessToken.id); + assert.equal(accessToken.ttl, 1800); + assert.equal(accessToken.id.length, 64); + + User.findById(accessToken.userId, function(err, user) { + user.createAccessToken(120, function (err, accessToken) { + assert(accessToken.userId); + assert(accessToken.id); + assert.equal(accessToken.ttl, 60); + assert.equal(accessToken.id.length, 64); + // Restore create access token + User.prototype.createAccessToken = createToken; + done(); + }); + }); + }); + }); it('Login a user over REST by providing credentials', function(done) { request(app)