Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update deprecated dep version #3343

Closed
wants to merge 6 commits into from
Closed
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
2 changes: 1 addition & 1 deletion common/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -886,7 +886,7 @@ module.exports = function(User) {
where[pkName] = ctx.instance[pkName];
}

ctx.Model.find({where: where}, function(err, userInstances) {
ctx.Model.find({where: where}, ctx.options, function(err, userInstances) {
if (err) return next(err);
ctx.hookState.originalUserData = userInstances.map(function(u) {
var user = {};
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
"grunt-karma": "^2.0.0",
"grunt-mocha-test": "^0.12.7",
"karma": "^1.1.2",
"karma-browserify": "^4.4.2",
"karma-browserify": "^5.1.1",
"karma-chrome-launcher": "^1.0.1",
"karma-firefox-launcher": "^1.0.0",
"karma-html2js-preprocessor": "^1.0.0",
Expand Down
38 changes: 28 additions & 10 deletions server/middleware/token.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
* Module dependencies.
*/

'use strict';
var g = require('strong-globalize')();
var loopback = require('../../lib/loopback');
var assert = require('assert');
var debug = require('debug')('loopback:middleware:token');
Expand All @@ -20,18 +22,33 @@ module.exports = token;
/*
* Rewrite the url to replace current user literal with the logged in user id
*/
function rewriteUserLiteral(req, currentUserLiteral) {
if (req.accessToken && req.accessToken.userId && currentUserLiteral) {
function rewriteUserLiteral(req, currentUserLiteral, next) {
if (!currentUserLiteral) return next();
var literalRegExp = new RegExp('/' + currentUserLiteral + '(/|$|\\?)', 'g');

if (req.accessToken && req.accessToken.userId) {
// Replace /me/ with /current-user-id/
var urlBeforeRewrite = req.url;
req.url = req.url.replace(
new RegExp('/' + currentUserLiteral + '(/|$|\\?)', 'g'),
req.url = req.url.replace(literalRegExp,
'/' + req.accessToken.userId + '$1');

if (req.url !== urlBeforeRewrite) {
debug('req.url has been rewritten from %s to %s', urlBeforeRewrite,
req.url);
}
} else if (!req.accessToken && literalRegExp.test(req.url)) {
debug(
'URL %s matches current-user literal %s,' +
' but no (valid) access token was provided.',
req.url, currentUserLiteral);

var e = new Error(g.f('Authorization Required'));
e.status = e.statusCode = 401;
e.code = 'AUTHORIZATION_REQUIRED';
return next(e);
}

next();
}

function escapeRegExp(str) {
Expand Down Expand Up @@ -110,23 +127,24 @@ function token(options) {
if (!enableDoublecheck) {
// req.accessToken is defined already (might also be "null" or "false") and enableDoublecheck
// has not been set --> skip searching for credentials
rewriteUserLiteral(req, currentUserLiteral);
return next();
return rewriteUserLiteral(req, currentUserLiteral, next);
}
if (req.accessToken && req.accessToken.id && !overwriteExistingToken) {
// req.accessToken.id is defined, which means that some other middleware has identified a valid user.
// when overwriteExistingToken is not set to a truthy value, skip searching for credentials.
rewriteUserLiteral(req, currentUserLiteral);
return next();
return rewriteUserLiteral(req, currentUserLiteral, next);
}
// continue normal operation (as if req.accessToken was undefined)
}

TokenModel.findForRequest(req, options, function(err, token) {
req.accessToken = token || null;
rewriteUserLiteral(req, currentUserLiteral);

var ctx = req.loopbackContext;
if (ctx && ctx.active) ctx.set('accessToken', token);
next(err);

if (err) return next(err);
rewriteUserLiteral(req, currentUserLiteral, next);
});
};
}
20 changes: 20 additions & 0 deletions test/access-token.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,26 @@ describe('loopback.token(options)', function() {
});
});

it('should generate a 401 on a current user literal route without an authToken',
function(done) {
var app = createTestApp(null, done);
request(app)
.get('/users/me')
.set('authorization', null)
.expect(401)
.end(done);
});

it('should generate a 401 on a current user literal route with invalid authToken',
function(done) {
var app = createTestApp(this.token, done);
request(app)
.get('/users/me')
.set('Authorization', 'invald-token-id')
.expect(401)
.end(done);
});

it('should skip when req.token is already present', function(done) {
var tokenStub = { id: 'stub id' };
app.use(function(req, res, next) {
Expand Down
32 changes: 32 additions & 0 deletions test/user.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var loopback = require('../');
var User, AccessToken;
var async = require('async');
var url = require('url');
var extend = require('util')._extend;

describe('User', function() {
this.timeout(10000);
Expand Down Expand Up @@ -2379,6 +2380,37 @@ describe('User', function() {
});
});

it('forwards the "options" argument', function(done) {
var options = {testFlag: true};
var observedOptions = [];

saveObservedOptionsForHook('access', User);
saveObservedOptionsForHook('before delete', AccessToken);

user.updateAttribute('password', 'newPass', options, function(err, updated) {
if (err) return done(err);

expect(observedOptions).to.eql([
// prepareForTokenInvalidation - load current instance data
{hook: 'access', testFlag: true},

// validate uniqueness of User.email
{hook: 'access', testFlag: true},

// _invalidateAccessTokensOfUsers - deleteAll
{hook: 'before delete', testFlag: true},
]);
done();
});

function saveObservedOptionsForHook(name, model) {
model.observe(name, function(ctx, next) {
observedOptions.push(extend({hook: name}, ctx.options));
next();
});
}
});

it('preserves other user sessions if their password is untouched', function(done) {
var user1, user2, user1Token;
async.series([
Expand Down