c1a2601514
- Refactor SSL middleware into separate module. - Refactor redirectToSetup to separate module + tests - Refactor serveStaticFile + tests - Refactor authentication middleware + tests - Refactor private blogging middleware refs #5286
253 lines
9.0 KiB
JavaScript
253 lines
9.0 KiB
JavaScript
/*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);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|