mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-27 22:49:56 -05:00
Merge pull request #6789 from ErisDS/postlookup
Split post lookup out of frontend controller
This commit is contained in:
commit
ddb18e68f2
3 changed files with 275 additions and 77 deletions
|
@ -4,21 +4,17 @@
|
||||||
|
|
||||||
/*global require, module */
|
/*global require, module */
|
||||||
|
|
||||||
var _ = require('lodash'),
|
var api = require('../../api'),
|
||||||
api = require('../../api'),
|
|
||||||
config = require('../../config'),
|
config = require('../../config'),
|
||||||
errors = require('../../errors'),
|
|
||||||
filters = require('../../filters'),
|
filters = require('../../filters'),
|
||||||
Promise = require('bluebird'),
|
|
||||||
templates = require('./templates'),
|
templates = require('./templates'),
|
||||||
routeMatch = require('path-match')(),
|
|
||||||
handleError = require('./error'),
|
handleError = require('./error'),
|
||||||
formatResponse = require('./format-response'),
|
formatResponse = require('./format-response'),
|
||||||
|
postLookup = require('./post-lookup'),
|
||||||
setResponseContext = require('./context'),
|
setResponseContext = require('./context'),
|
||||||
setRequestIsSecure = require('./secure'),
|
setRequestIsSecure = require('./secure'),
|
||||||
|
|
||||||
frontendControllers,
|
frontendControllers;
|
||||||
staticPostPermalink = routeMatch('/:slug/:edit?');
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets the response context around a post and renders it
|
* Sets the response context around a post and renders it
|
||||||
|
@ -62,85 +58,23 @@ frontendControllers = {
|
||||||
}).catch(handleError(next));
|
}).catch(handleError(next));
|
||||||
},
|
},
|
||||||
single: function single(req, res, next) {
|
single: function single(req, res, next) {
|
||||||
var postPath = req.path,
|
|
||||||
params,
|
|
||||||
usingStaticPermalink = false,
|
|
||||||
permalink = config.theme.permalinks,
|
|
||||||
editFormat = permalink.substr(permalink.length - 1) === '/' ? ':edit?' : '/:edit?',
|
|
||||||
postLookup,
|
|
||||||
match;
|
|
||||||
|
|
||||||
// Convert saved permalink into a path-match function
|
|
||||||
permalink = routeMatch(permalink + editFormat);
|
|
||||||
match = permalink(postPath);
|
|
||||||
|
|
||||||
// Check if the path matches the permalink structure.
|
|
||||||
//
|
|
||||||
// If there are no matches found we then
|
|
||||||
// need to verify it's not a static post,
|
|
||||||
// and test against that permalink structure.
|
|
||||||
if (match === false) {
|
|
||||||
match = staticPostPermalink(postPath);
|
|
||||||
// If there are still no matches then call next.
|
|
||||||
if (match === false) {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
usingStaticPermalink = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
params = match;
|
|
||||||
|
|
||||||
// Sanitize params we're going to use to lookup the post.
|
|
||||||
postLookup = _.pick(params, 'slug', 'id');
|
|
||||||
// Add author & tag
|
|
||||||
postLookup.include = 'author,tags';
|
|
||||||
|
|
||||||
// Query database to find post
|
// Query database to find post
|
||||||
return api.posts.read(postLookup).then(function then(result) {
|
return postLookup(req.path).then(function then(lookup) {
|
||||||
var post = result.posts[0],
|
var post = lookup ? lookup.post : false;
|
||||||
postUrl = (params.edit) ? postPath.replace(params.edit + '/', '') : postPath;
|
|
||||||
|
|
||||||
if (!post) {
|
if (!post) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
function render() {
|
|
||||||
// If we're ready to render the page but the last param is 'edit' then we'll send you to the edit page.
|
// If we're ready to render the page but the last param is 'edit' then we'll send you to the edit page.
|
||||||
if (params.edit) {
|
if (lookup.isEditURL) {
|
||||||
params.edit = params.edit.toLowerCase();
|
|
||||||
}
|
|
||||||
if (params.edit === 'edit') {
|
|
||||||
return res.redirect(config.paths.subdir + '/ghost/editor/' + post.id + '/');
|
return res.redirect(config.paths.subdir + '/ghost/editor/' + post.id + '/');
|
||||||
} else if (params.edit !== undefined) {
|
|
||||||
// reject with type: 'NotFound'
|
|
||||||
return Promise.reject(new errors.NotFoundError());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setRequestIsSecure(req, post);
|
setRequestIsSecure(req, post);
|
||||||
|
|
||||||
filters.doFilter('prePostsRender', post, res.locals)
|
filters.doFilter('prePostsRender', post, res.locals)
|
||||||
.then(renderPost(req, res));
|
.then(renderPost(req, res));
|
||||||
}
|
|
||||||
|
|
||||||
// If we've checked the path with the static permalink structure
|
|
||||||
// then the post must be a static post.
|
|
||||||
// If it is not then we must return.
|
|
||||||
if (usingStaticPermalink) {
|
|
||||||
if (post.page) {
|
|
||||||
return render();
|
|
||||||
}
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the url provided with the post object matches req.path
|
|
||||||
// If it does, render the post
|
|
||||||
// If not, return 404
|
|
||||||
if (post.url && post.url === postUrl) {
|
|
||||||
return render();
|
|
||||||
} else {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
}).catch(handleError(next));
|
}).catch(handleError(next));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
69
core/server/controllers/frontend/post-lookup.js
Normal file
69
core/server/controllers/frontend/post-lookup.js
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
var _ = require('lodash'),
|
||||||
|
Promise = require('bluebird'),
|
||||||
|
url = require('url'),
|
||||||
|
routeMatch = require('path-match')(),
|
||||||
|
api = require('../../api'),
|
||||||
|
config = require('../../config'),
|
||||||
|
|
||||||
|
editFormat = '/:edit?';
|
||||||
|
|
||||||
|
function getEditFormat(linkStructure) {
|
||||||
|
return linkStructure.replace(/\/$/, '') + editFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
function postLookup(postUrl) {
|
||||||
|
var postPath = url.parse(postUrl).path,
|
||||||
|
postPermalink = config.theme.permalinks,
|
||||||
|
pagePermalink = '/:slug/',
|
||||||
|
isEditURL = false,
|
||||||
|
matchFunc,
|
||||||
|
params;
|
||||||
|
|
||||||
|
// Convert saved permalink into a path-match function
|
||||||
|
matchFunc = routeMatch(getEditFormat(postPermalink));
|
||||||
|
params = matchFunc(postPath);
|
||||||
|
|
||||||
|
// Check if the path matches the permalink structure.
|
||||||
|
// If there are no matches found, test to see if this is a page instead
|
||||||
|
if (params === false) {
|
||||||
|
matchFunc = routeMatch(getEditFormat(pagePermalink));
|
||||||
|
params = matchFunc(postPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are still no matches then return empty.
|
||||||
|
if (params === false) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If params contains edit, and it is equal to 'edit' this is an edit URL
|
||||||
|
if (params.edit && params.edit.toLowerCase() === 'edit') {
|
||||||
|
postPath = postPath.replace(params.edit + '/', '');
|
||||||
|
isEditURL = true;
|
||||||
|
} else if (params.edit !== undefined) {
|
||||||
|
// Unknown string in URL, return empty
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanitize params we're going to use to lookup the post.
|
||||||
|
params = _.pick(params, 'slug', 'id');
|
||||||
|
// Add author & tag
|
||||||
|
params.include = 'author,tags';
|
||||||
|
|
||||||
|
// Query database to find post
|
||||||
|
return api.posts.read(params).then(function then(result) {
|
||||||
|
var post = result.posts[0];
|
||||||
|
|
||||||
|
// If there is no post, or the post has no URL, or it isn't a match for our original lookup, return empty
|
||||||
|
// This also catches the case where we use the pagePermalink but the post is not a page
|
||||||
|
if (!post || !post.url || post.url !== postPath) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
post: post,
|
||||||
|
isEditURL: isEditURL
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = postLookup;
|
195
core/test/unit/controllers/frontend/post-lookup_spec.js
Normal file
195
core/test/unit/controllers/frontend/post-lookup_spec.js
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
/*globals describe, it, beforeEach, afterEach */
|
||||||
|
var should = require('should'),
|
||||||
|
sinon = require('sinon'),
|
||||||
|
Promise = require('bluebird'),
|
||||||
|
configUtils = require('../../../utils/configUtils'),
|
||||||
|
|
||||||
|
// Things we are testing
|
||||||
|
api = require('../../../../server/api'),
|
||||||
|
postLookup = require('../../../../server/controllers/frontend/post-lookup'),
|
||||||
|
|
||||||
|
sandbox = sinon.sandbox.create();
|
||||||
|
|
||||||
|
describe('postLookup', function () {
|
||||||
|
var postAPIStub;
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
sandbox.restore();
|
||||||
|
configUtils.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
postAPIStub = sandbox.stub(api.posts, 'read');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Permalinks: /:slug/', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
configUtils.set({theme: {permalinks: '/:slug/'}});
|
||||||
|
|
||||||
|
postAPIStub.withArgs({slug: 'welcome-to-ghost', include: 'author,tags'})
|
||||||
|
.returns(new Promise.resolve({posts: [{
|
||||||
|
url: '/welcome-to-ghost/',
|
||||||
|
published_at: new Date('2016-01-01').valueOf()
|
||||||
|
}]}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can lookup absolute url: /:slug/', function (done) {
|
||||||
|
var testUrl = 'http://127.0.0.1:2369/welcome-to-ghost/';
|
||||||
|
|
||||||
|
postLookup(testUrl).then(function (lookup) {
|
||||||
|
postAPIStub.calledOnce.should.be.true();
|
||||||
|
should.exist(lookup.post);
|
||||||
|
lookup.post.should.have.property('url', '/welcome-to-ghost/');
|
||||||
|
lookup.isEditURL.should.be.false();
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can lookup relative url: /:slug/', function (done) {
|
||||||
|
var testUrl = '/welcome-to-ghost/';
|
||||||
|
|
||||||
|
postLookup(testUrl).then(function (lookup) {
|
||||||
|
postAPIStub.calledOnce.should.be.true();
|
||||||
|
should.exist(lookup.post);
|
||||||
|
lookup.post.should.have.property('url', '/welcome-to-ghost/');
|
||||||
|
lookup.isEditURL.should.be.false();
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot lookup absolute url: /:year/:month/:day/:slug/', function (done) {
|
||||||
|
var testUrl = 'http://127.0.0.1:2369/2016/01/01/welcome-to-ghost/';
|
||||||
|
|
||||||
|
postLookup(testUrl).then(function (lookup) {
|
||||||
|
should.not.exist(lookup);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot lookup relative url: /:year/:month/:day/:slug/', function (done) {
|
||||||
|
var testUrl = '/2016/01/01/welcome-to-ghost/';
|
||||||
|
|
||||||
|
postLookup(testUrl).then(function (lookup) {
|
||||||
|
should.not.exist(lookup);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Permalinks: /:year/:month/:day/:slug/', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
configUtils.set({theme: {permalinks: '/:year/:month/:day/:slug/'}});
|
||||||
|
|
||||||
|
postAPIStub.withArgs({slug: 'welcome-to-ghost', include: 'author,tags'})
|
||||||
|
.returns(new Promise.resolve({posts: [{
|
||||||
|
url: '/2016/01/01/welcome-to-ghost/',
|
||||||
|
published_at: new Date('2016-01-01').valueOf()
|
||||||
|
}]}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot lookup absolute url: /:slug/', function (done) {
|
||||||
|
var testUrl = 'http://127.0.0.1:2369/welcome-to-ghost/';
|
||||||
|
|
||||||
|
postLookup(testUrl).then(function (lookup) {
|
||||||
|
should.not.exist(lookup);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot lookup relative url: /:slug/', function (done) {
|
||||||
|
var testUrl = '/welcome-to-ghost/';
|
||||||
|
|
||||||
|
postLookup(testUrl).then(function (lookup) {
|
||||||
|
should.not.exist(lookup);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can lookup absolute url: /:year/:month/:day/:slug/', function (done) {
|
||||||
|
var testUrl = 'http://127.0.0.1:2369/2016/01/01/welcome-to-ghost/';
|
||||||
|
|
||||||
|
postLookup(testUrl).then(function (lookup) {
|
||||||
|
postAPIStub.calledOnce.should.be.true();
|
||||||
|
should.exist(lookup.post);
|
||||||
|
lookup.post.should.have.property('url', '/2016/01/01/welcome-to-ghost/');
|
||||||
|
lookup.isEditURL.should.be.false();
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can lookup relative url: /:year/:month/:day/:slug/', function (done) {
|
||||||
|
var testUrl = '/2016/01/01/welcome-to-ghost/';
|
||||||
|
|
||||||
|
postLookup(testUrl).then(function (lookup) {
|
||||||
|
postAPIStub.calledOnce.should.be.true();
|
||||||
|
should.exist(lookup.post);
|
||||||
|
lookup.post.should.have.property('url', '/2016/01/01/welcome-to-ghost/');
|
||||||
|
lookup.isEditURL.should.be.false();
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Edit URLs', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
configUtils.set({theme: {permalinks: '/:slug/'}});
|
||||||
|
|
||||||
|
postAPIStub.withArgs({slug: 'welcome-to-ghost', include: 'author,tags'})
|
||||||
|
.returns(new Promise.resolve({posts: [{
|
||||||
|
url: '/welcome-to-ghost/',
|
||||||
|
published_at: new Date('2016-01-01').valueOf()
|
||||||
|
}]}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can lookup absolute url: /:slug/edit/', function (done) {
|
||||||
|
var testUrl = 'http://127.0.0.1:2369/welcome-to-ghost/edit/';
|
||||||
|
|
||||||
|
postLookup(testUrl).then(function (lookup) {
|
||||||
|
lookup.post.should.have.property('url', '/welcome-to-ghost/');
|
||||||
|
lookup.isEditURL.should.be.true();
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can lookup relative url: /:slug/edit/', function (done) {
|
||||||
|
var testUrl = '/welcome-to-ghost/edit/';
|
||||||
|
|
||||||
|
postLookup(testUrl).then(function (lookup) {
|
||||||
|
lookup.post.should.have.property('url', '/welcome-to-ghost/');
|
||||||
|
lookup.isEditURL.should.be.true();
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot lookup absolute url: /:year/:month/:day/:slug/edit/', function (done) {
|
||||||
|
var testUrl = 'http://127.0.0.1:2369/2016/01/01/welcome-to-ghost/edit/';
|
||||||
|
|
||||||
|
postLookup(testUrl).then(function (lookup) {
|
||||||
|
should.not.exist(lookup);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot lookup relative url: /:year/:month/:day/:slug/edit/', function (done) {
|
||||||
|
var testUrl = '/2016/01/01/welcome-to-ghost/edit/';
|
||||||
|
|
||||||
|
postLookup(testUrl).then(function (lookup) {
|
||||||
|
should.not.exist(lookup);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot lookup relative url: /:slug/notedit/', function (done) {
|
||||||
|
var testUrl = '/welcome-to-ghost/notedit/';
|
||||||
|
|
||||||
|
postLookup(testUrl).then(function (lookup) {
|
||||||
|
should.not.exist(lookup);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Reference in a new issue