Ghost/core/test/unit/middleware/private-blogging_spec.js

253 lines
9.0 KiB
JavaScript
Raw Normal View History

/*globals describe, beforeEach, afterEach, it*/
/*jshint expr:true*/
var crypto = require('crypto'),
should = require('should'),
sinon = require('sinon'),
Promise = require('bluebird'),
privateBlogging = require('../../../server/middleware/private-blogging'),
api = require('../../../server/api'),
errors = require('../../../server/errors'),
fs = require('fs');
should.equal(true, true);
function hash(password, salt) {
var hasher = crypto.createHash('sha256');
hasher.update(password + salt, 'utf8');
return hasher.digest('hex');
}
describe('Private Blogging', function () {
var sandbox,
apiSettingsStub;
beforeEach(function () {
sandbox = sinon.sandbox.create();
});
afterEach(function () {
sandbox.restore();
});
describe('passProtect', function () {
var req, res, next;
beforeEach(function () {
req = {}, res = {};
apiSettingsStub = sandbox.stub(api.settings, 'read');
next = sinon.spy();
});
it('checkIsPrivate should call next if not private', function (done) {
apiSettingsStub.withArgs(sinon.match.has('key', 'isPrivate')).returns(Promise.resolve({
settings: [{
key: 'isPrivate',
value: 'false'
}]
}));
privateBlogging.checkIsPrivate(req, res, next).then(function () {
next.called.should.be.true;
res.isPrivateBlog.should.be.false;
done();
}).catch(done);
});
it('checkIsPrivate should load session if private', function (done) {
apiSettingsStub.withArgs(sinon.match.has('key', 'isPrivate')).returns(Promise.resolve({
settings: [{
key: 'isPrivate',
value: 'true'
}]
}));
privateBlogging.checkIsPrivate(req, res, next).then(function () {
res.isPrivateBlog.should.be.true;
done();
}).catch(done);
});
describe('not private', function () {
beforeEach(function () {
res.isPrivateBlog = false;
});
it('filterPrivateRoutes should call next if not private', function () {
privateBlogging.filterPrivateRoutes(req, res, next);
next.called.should.be.true;
});
it('isPrivateSessionAuth should redirect if blog is not private', function () {
res = {
redirect: sinon.spy(),
isPrivateBlog: false
};
privateBlogging.isPrivateSessionAuth(req, res, next);
res.redirect.called.should.be.true;
});
});
describe('private', function () {
var errorSpy;
beforeEach(function () {
res.isPrivateBlog = true;
errorSpy = sandbox.spy(errors, 'error404');
res = {
status: function () {
return this;
},
send: function () {},
set: function () {},
isPrivateBlog: true
};
});
it('filterPrivateRoutes should call next if admin', function () {
res.isAdmin = true;
privateBlogging.filterPrivateRoutes(req, res, next);
next.called.should.be.true;
});
it('filterPrivateRoutes should call next if is the "private" route', function () {
req.url = '/private/';
privateBlogging.filterPrivateRoutes(req, res, next);
next.called.should.be.true;
});
it('filterPrivateRoutes should throw 404 if url is sitemap', function () {
req.url = '/sitemap.xml';
privateBlogging.filterPrivateRoutes(req, res, next);
errorSpy.called.should.be.true;
});
it('filterPrivateRoutes should throw 404 if url is rss', function () {
req.url = '/rss';
privateBlogging.filterPrivateRoutes(req, res, next);
errorSpy.called.should.be.true;
});
it('filterPrivateRoutes should throw 404 if url is rss plus something', function () {
req.url = '/rss/sometag';
privateBlogging.filterPrivateRoutes(req, res, next);
errorSpy.called.should.be.true;
});
it('filterPrivateRoutes should render custom robots.txt', function () {
req.url = '/robots.txt';
res.writeHead = sinon.spy();
res.end = sinon.spy();
sandbox.stub(fs, 'readFile', function (file, cb) {
cb(null, 'User-agent: * Disallow: /');
});
privateBlogging.filterPrivateRoutes(req, res, next);
res.writeHead.called.should.be.true;
res.end.called.should.be.true;
});
it('authenticateProtection should call next if error', function () {
res.error = 'Test Error';
privateBlogging.authenticateProtection(req, res, next);
next.called.should.be.true;
});
describe('with hash verification', function () {
beforeEach(function () {
apiSettingsStub.withArgs(sinon.match.has('key', 'password')).returns(Promise.resolve({
settings: [{
key: 'password',
value: 'rightpassword'
}]
}));
});
it('authenticatePrivateSession should return next if hash is verified', function (done) {
var salt = Date.now().toString();
req.session = {
token: hash('rightpassword', salt),
salt: salt
};
privateBlogging.authenticatePrivateSession(req, res, next).then(function () {
next.called.should.be.true;
done();
}).catch(done);
});
it('authenticatePrivateSession should redirect if hash is not verified', function (done) {
req.url = '/welcome-to-ghost';
req.session = {
token: 'wrongpassword',
salt: Date.now().toString()
};
res.redirect = sinon.spy();
privateBlogging.authenticatePrivateSession(req, res, next).then(function () {
res.redirect.called.should.be.true;
done();
}).catch(done);
});
it('isPrivateSessionAuth should redirect if hash is verified', function (done) {
var salt = Date.now().toString();
req.session = {
token: hash('rightpassword', salt),
salt: salt
};
res.redirect = sandbox.spy();
privateBlogging.isPrivateSessionAuth(req, res, next).then(function () {
res.redirect.called.should.be.true;
done();
}).catch(done);
});
it('isPrivateSessionAuth should return next if hash is not verified', function (done) {
req.session = {
token: 'wrongpassword',
salt: Date.now().toString()
};
privateBlogging.isPrivateSessionAuth(req, res, next).then(function () {
next.called.should.be.true;
done();
}).catch(done);
});
it('authenticateProtection should return next if password is incorrect', function (done) {
req.body = {password: 'wrongpassword'};
privateBlogging.authenticateProtection(req, res, next).then(function () {
res.error.should.not.be.empty;
next.called.should.be.true;
done();
}).catch(done);
});
it('authenticateProtection should redirect if password is correct', function (done) {
req.body = {password: 'rightpassword'};
req.session = {};
res.redirect = sandbox.spy();
privateBlogging.authenticateProtection(req, res, next).then(function () {
res.redirect.called.should.be.true;
done();
}).catch(done);
});
});
});
});
});