In this section we will be covering how to protect resources.
The first thing we need to do is create a way to establish roles for our user. Lets create a test.
roles
attribute to the user modelCreate user roles tests:
test/users/models.js
//... imports
describe('Users: models', function () {
//... previous tests
describe('#hasRole', function () {
// we will set this value in the beforeEach function
var user;
// beforeEach test create a user
beforeEach(function (done) {
var u = {
roles: ['admin', 'mod']
};
User.create(u, function (err, createdUser) {
user = createdUser;
done();
});
});
it('should return true if the user has role', function (done) {
user.hasRole('admin').should.be.true;
user.hasRole('mod').should.be.true;
done();
});
it('should return false if the user does not have role', function (done) {
user.hasRole('astronaut').should.be.false;
user.hasRole('cowboy').should.be.false;
done();
});
});
});
Tests will fail:
2) Users: models #hasRole should return false if the user does not have role:
TypeError: Object { __v: 0, _id: 507b2b20f74953000000000a, emails: [] } has no method 'hasRole'
Write the code:
users/modles.js
//... previous code
var userSchema = new Schema({
//... previous attributes
roles: Array
});
//... previous static methods
userSchema.methods.hasRole = function (role) {
for (var i = 0; i < this.roles.length; i++) {
if (this.roles[i] === role) {
// if the role that we are checking matches the 'role' we are
// looking for return true
return true;
}
};
// if the role does not match return false
return false;
};
We are using mongoose methods to add a hasRole
method to our
user
schema.
Our tests are now passing.
✔ 13 tests complete (235 ms)
Create the test:
test/auth/middlewares.js
TODO: there was a problem when calling supertest multiple times. I.e. first logging in a user, then checking credentials. This test will have to wait until after this test is resolved.
Tests are now failing:
1) Passport: middleware user not logged in should redirect to "/login":
AssertionError: expected [Error: expected 302 "Moved Temporarily", got 404 "Not Found"] to not exist
Add the route:
app.js
//...
var admin = require('./routes/admin');
//...
app.get('/admin', admin.index);
//...
/routes/admin.js
'use strict';
// GET admin index.
exports.index = function (req, res) {
res.send("welcome to the admin");
};
The test is now failing with:
1) Passport: middleware user not logged in should redirect to "/login":
AssertionError: expected [Error: expected 302 "Moved Temporarily", got 200 "OK"] to not exist
Create the ensureAuthenticated
and ensureAdmin
middleware:
auth/middlewares.js
'use strict';
// Simple route middleware to ensure user is authenticated.
// Use this route middleware on any resource that needs to be protected. If
// the request is authenticated (typically via a persistent login session),
// the request will proceed. Otherwise, the user will be redirected to the
// login page.
exports.ensureAuthenticated = function (req, res, next) {
if (req.isAuthenticated()) {
return next();
}
return res.redirect('/login');
};
exports.ensureAdmin = function (req, res, next) {
// make sure the user is logged in.
if (req.isAuthenticated()) {
// make sure the user has role 'admin'
if (req.user.hasRole('admin')) {
return next();
}
}
// otherwise redirect to login
return res.redirect('/login');
};
For more info on express middleware
Add the ensureAdmin
middleware to our '/auth'
routes:
app.js
//... imports
var ensureAuthenticated = require('./auth/middlewares').ensureAuthenticated;
//... routes
app.get('/admin', ensureAdmin, admin.index);
Tests are now passing:
✔ 17 tests complete (645 ms)