mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-06 22:40:14 -05:00
🔒 Added admin:redirects
config option for disabling admin redirects
no issue - adds `config:redirects` config option that defaults to `true` - when set to `false` - `/ghost/` will 404 on the front-end when a separate admin url is configured - all `{resource}/edit/` URLs on the front-end will 404
This commit is contained in:
parent
95ea5265d5
commit
7e92b07233
9 changed files with 273 additions and 30 deletions
|
@ -1,4 +1,5 @@
|
|||
const debug = require('ghost-ignition').debug('services:routing:taxonomy-router');
|
||||
const config = require('../../../server/config');
|
||||
const common = require('../../../server/lib/common');
|
||||
const ParentRouter = require('./ParentRouter');
|
||||
const RSSRouter = require('./RSSRouter');
|
||||
|
@ -53,7 +54,9 @@ class TaxonomyRouter extends ParentRouter {
|
|||
this.mountRoute(urlUtils.urlJoin(this.permalinks.value, 'page', ':page(\\d+)'), controllers.channel);
|
||||
|
||||
// REGISTER: edit redirect to admin client e.g. /tag/:slug/edit
|
||||
this.mountRoute(urlUtils.urlJoin(this.permalinks.value, 'edit'), this._redirectEditOption.bind(this));
|
||||
if (config.get('admin:redirects')) {
|
||||
this.mountRoute(urlUtils.urlJoin(this.permalinks.value, 'edit'), this._redirectEditOption.bind(this));
|
||||
}
|
||||
|
||||
common.events.emit('router.created', this);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
const debug = require('ghost-ignition').debug('services:routing:controllers:entry'),
|
||||
url = require('url'),
|
||||
urlService = require('../../../services/url'),
|
||||
urlUtils = require('../../../../server/lib/url-utils'),
|
||||
helpers = require('../helpers');
|
||||
const debug = require('ghost-ignition').debug('services:routing:controllers:entry');
|
||||
const url = require('url');
|
||||
const config = require('../../../../server/config');
|
||||
const urlService = require('../../../services/url');
|
||||
const urlUtils = require('../../../../server/lib/url-utils');
|
||||
const helpers = require('../helpers');
|
||||
|
||||
/**
|
||||
* @description Entry controller.
|
||||
|
@ -32,6 +33,11 @@ module.exports = function entryController(req, res, next) {
|
|||
|
||||
// CASE: last param is of url is /edit, redirect to admin
|
||||
if (lookup.isEditURL) {
|
||||
if (!config.get('admin:redirects')) {
|
||||
debug('is edit url but admin redirects are disabled');
|
||||
return next();
|
||||
}
|
||||
|
||||
debug('redirect. is edit url');
|
||||
const resourceType = entry.page ? 'page' : 'post';
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
const debug = require('ghost-ignition').debug('services:routing:controllers:preview'),
|
||||
urlService = require('../../url'),
|
||||
urlUtils = require('../../../../server/lib/url-utils'),
|
||||
helpers = require('../helpers');
|
||||
const debug = require('ghost-ignition').debug('services:routing:controllers:preview');
|
||||
const config = require('../../../../server/config');
|
||||
const urlService = require('../../url');
|
||||
const urlUtils = require('../../../../server/lib/url-utils');
|
||||
const helpers = require('../helpers');
|
||||
|
||||
/**
|
||||
* @description Preview Controller.
|
||||
|
@ -31,6 +32,11 @@ module.exports = function previewController(req, res, next) {
|
|||
}
|
||||
|
||||
if (req.params.options && req.params.options.toLowerCase() === 'edit') {
|
||||
// CASE: last param of the url is /edit but admin redirects are disabled
|
||||
if (!config.get('admin:redirects')) {
|
||||
return next();
|
||||
}
|
||||
|
||||
// @TODO: we don't know which resource type it is, because it's a generic preview handler and the
|
||||
// preview API returns {previews: []}
|
||||
// @TODO: figure out how to solve better
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
"host": "127.0.0.1",
|
||||
"port": 2368
|
||||
},
|
||||
"admin": {
|
||||
"redirects": true
|
||||
},
|
||||
"updateCheck": {
|
||||
"url": "https://updates.ghost.org",
|
||||
"forceUpdate": false
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const express = require('express');
|
||||
const config = require('../../../config');
|
||||
const urlUtils = require('../../../lib/url-utils');
|
||||
|
||||
const adminRedirect = (path) => {
|
||||
|
@ -10,6 +11,10 @@ const adminRedirect = (path) => {
|
|||
// redirect to /ghost to the admin
|
||||
module.exports = function adminRedirects() {
|
||||
const router = express.Router();
|
||||
router.get(/^\/ghost\/?$/, adminRedirect('/'));
|
||||
|
||||
if (config.get('admin:redirects')) {
|
||||
router.get(/^\/ghost\/?$/, adminRedirect('/'));
|
||||
}
|
||||
|
||||
return router;
|
||||
};
|
||||
|
|
|
@ -2,17 +2,18 @@
|
|||
// As it stands, these tests depend on the database, and as such are integration tests.
|
||||
// These tests are here to cover the headers sent with requests and high-level redirects that can't be
|
||||
// tested with the unit tests
|
||||
const should = require('should'),
|
||||
supertest = require('supertest'),
|
||||
sinon = require('sinon'),
|
||||
moment = require('moment'),
|
||||
path = require('path'),
|
||||
testUtils = require('../../utils'),
|
||||
cheerio = require('cheerio'),
|
||||
config = require('../../../server/config'),
|
||||
api = require('../../../server/api'),
|
||||
settingsCache = require('../../../server/services/settings/cache'),
|
||||
ghost = testUtils.startGhost;
|
||||
const should = require('should');
|
||||
const supertest = require('supertest');
|
||||
const sinon = require('sinon');
|
||||
const moment = require('moment');
|
||||
const path = require('path');
|
||||
const testUtils = require('../../utils');
|
||||
const configUtils = require('../../utils/configUtils');
|
||||
const cheerio = require('cheerio');
|
||||
const config = require('../../../server/config');
|
||||
const api = require('../../../server/api');
|
||||
const settingsCache = require('../../../server/services/settings/cache');
|
||||
const ghost = testUtils.startGhost;
|
||||
|
||||
let request;
|
||||
|
||||
|
@ -284,6 +285,43 @@ describe('Dynamic Routing', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Edit with admin redirects disabled', function () {
|
||||
before(function () {
|
||||
configUtils.set('admin:redirects', false);
|
||||
|
||||
return ghost({forceStart: true})
|
||||
.then(function (_ghostServer) {
|
||||
ghostServer = _ghostServer;
|
||||
request = supertest.agent(config.get('url'));
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
configUtils.restore();
|
||||
|
||||
return ghost({forceStart: true})
|
||||
.then(function (_ghostServer) {
|
||||
ghostServer = _ghostServer;
|
||||
request = supertest.agent(config.get('url'));
|
||||
});
|
||||
});
|
||||
|
||||
it('should redirect without slash', function (done) {
|
||||
request.get('/tag/getting-started/edit')
|
||||
.expect('Location', '/tag/getting-started/edit/')
|
||||
.expect('Cache-Control', testUtils.cacheRules.year)
|
||||
.expect(301)
|
||||
.end(doEnd(done));
|
||||
});
|
||||
|
||||
it('should not redirect to admin', function (done) {
|
||||
request.get('/tag/getting-started/edit/')
|
||||
.expect(404)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.end(doEnd(done));
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip('Paged', function () {
|
||||
// Inserting more posts takes a bit longer
|
||||
this.timeout(20000);
|
||||
|
@ -529,6 +567,43 @@ describe('Dynamic Routing', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Edit with admin redirects disabled', function () {
|
||||
before(function () {
|
||||
configUtils.set('admin:redirects', false);
|
||||
|
||||
return ghost({forceStart: true})
|
||||
.then(function (_ghostServer) {
|
||||
ghostServer = _ghostServer;
|
||||
request = supertest.agent(config.get('url'));
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
configUtils.restore();
|
||||
|
||||
return ghost({forceStart: true})
|
||||
.then(function (_ghostServer) {
|
||||
ghostServer = _ghostServer;
|
||||
request = supertest.agent(config.get('url'));
|
||||
});
|
||||
});
|
||||
|
||||
it('should redirect without slash', function (done) {
|
||||
request.get('/author/ghost-owner/edit')
|
||||
.expect('Location', '/author/ghost-owner/edit/')
|
||||
.expect('Cache-Control', testUtils.cacheRules.year)
|
||||
.expect(301)
|
||||
.end(doEnd(done));
|
||||
});
|
||||
|
||||
it('should not redirect to admin', function (done) {
|
||||
request.get('/author/ghost-owner/edit/')
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(404)
|
||||
.end(doEnd(done));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Paged', function () {
|
||||
// Add enough posts to trigger pages
|
||||
before(function (done) {
|
||||
|
|
|
@ -193,6 +193,41 @@ describe('Frontend Routing', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Post edit with admin redirects disabled', function () {
|
||||
before(function () {
|
||||
configUtils.set('admin:redirects', false);
|
||||
|
||||
return ghost({forceStart: true})
|
||||
.then(function () {
|
||||
request = supertest.agent(config.get('url'));
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
configUtils.restore();
|
||||
|
||||
return ghost({forceStart: true})
|
||||
.then(function () {
|
||||
request = supertest.agent(config.get('url'));
|
||||
});
|
||||
});
|
||||
|
||||
it('should redirect without slash', function (done) {
|
||||
request.get('/welcome/edit')
|
||||
.expect('Location', '/welcome/edit/')
|
||||
.expect('Cache-Control', testUtils.cacheRules.year)
|
||||
.expect(301)
|
||||
.end(doEnd(done));
|
||||
});
|
||||
|
||||
it('should not redirect to editor', function (done) {
|
||||
request.get('/welcome/edit/')
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(404)
|
||||
.end(doEnd(done));
|
||||
});
|
||||
});
|
||||
|
||||
describe('AMP post', function () {
|
||||
it('should redirect without slash', function (done) {
|
||||
request.get('/welcome/amp')
|
||||
|
@ -357,6 +392,43 @@ describe('Frontend Routing', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('edit with admin redirects disabled', function () {
|
||||
before(function (done) {
|
||||
configUtils.set('admin:redirects', false);
|
||||
|
||||
ghost({forceStart: true})
|
||||
.then(function () {
|
||||
request = supertest.agent(config.get('url'));
|
||||
addPosts(done);
|
||||
});
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
configUtils.restore();
|
||||
|
||||
ghost({forceStart: true})
|
||||
.then(function () {
|
||||
request = supertest.agent(config.get('url'));
|
||||
addPosts(done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should redirect without slash', function (done) {
|
||||
request.get('/static-page-test/edit')
|
||||
.expect('Location', '/static-page-test/edit/')
|
||||
.expect('Cache-Control', testUtils.cacheRules.year)
|
||||
.expect(301)
|
||||
.end(doEnd(done));
|
||||
});
|
||||
|
||||
it('should not redirect to editor', function (done) {
|
||||
request.get('/static-page-test/edit/')
|
||||
.expect(404)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.end(doEnd(done));
|
||||
});
|
||||
});
|
||||
|
||||
describe('amp', function () {
|
||||
it('should 404 for amp parameter', function (done) {
|
||||
// NOTE: only post pages are supported so the router doesn't have a way to distinguish if
|
||||
|
|
|
@ -5397,6 +5397,54 @@ describe('Integration - Web - Site', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('separate admin host w/ admin redirects disabled', function () {
|
||||
before(function () {
|
||||
testUtils.integrationTesting.urlService.resetGenerators();
|
||||
testUtils.integrationTesting.defaultMocks(sinon, {amp: true, apps: true});
|
||||
testUtils.integrationTesting.overrideGhostConfig(configUtils);
|
||||
|
||||
configUtils.set('url', 'http://example.com');
|
||||
configUtils.set('admin:url', 'https://admin.example.com');
|
||||
configUtils.set('admin:redirects', false);
|
||||
|
||||
return testUtils.integrationTesting.initGhost()
|
||||
.then(function () {
|
||||
sinon.stub(themeService.getActive(), 'engine').withArgs('ghost-api').returns('v2');
|
||||
sinon.stub(themeService.getActive(), 'config').withArgs('posts_per_page').returns(2);
|
||||
|
||||
app = siteApp({start: true});
|
||||
return testUtils.integrationTesting.urlService.waitTillFinished();
|
||||
})
|
||||
.then(() => {
|
||||
return appsService.init();
|
||||
});
|
||||
});
|
||||
|
||||
before(function () {
|
||||
urlUtils.stubUrlUtilsFromConfig();
|
||||
});
|
||||
|
||||
after(function () {
|
||||
configUtils.restore();
|
||||
urlUtils.restore();
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('does not redirect /ghost/ on configured url', function () {
|
||||
const req = {
|
||||
secure: false,
|
||||
method: 'GET',
|
||||
url: '/ghost/',
|
||||
host: 'example.com'
|
||||
};
|
||||
|
||||
return testUtils.mocks.express.invoke(app, req)
|
||||
.then(function (response) {
|
||||
response.statusCode.should.eql(404);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('same host separate protocol', function () {
|
||||
before(function () {
|
||||
testUtils.integrationTesting.urlService.resetGenerators();
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
const should = require('should'),
|
||||
sinon = require('sinon'),
|
||||
testUtils = require('../../../../utils'),
|
||||
urlService = require('../../../../../frontend/services/url'),
|
||||
urlUtils = require('../../../../../server/lib/url-utils'),
|
||||
controllers = require('../../../../../frontend/services/routing/controllers'),
|
||||
helpers = require('../../../../../frontend/services/routing/helpers'),
|
||||
EDITOR_URL = `/editor/post/`;
|
||||
const should = require('should');
|
||||
const sinon = require('sinon');
|
||||
const testUtils = require('../../../../utils');
|
||||
const configUtils = require('../../../../utils/configUtils');
|
||||
const urlService = require('../../../../../frontend/services/url');
|
||||
const urlUtils = require('../../../../../server/lib/url-utils');
|
||||
const controllers = require('../../../../../frontend/services/routing/controllers');
|
||||
const helpers = require('../../../../../frontend/services/routing/helpers');
|
||||
const EDITOR_URL = `/editor/post/`;
|
||||
|
||||
describe('Unit - services/routing/controllers/entry', function () {
|
||||
let req, res, entryLookUpStub, secureStub, renderStub, post, page;
|
||||
|
@ -126,6 +127,30 @@ describe('Unit - services/routing/controllers/entry', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('isEditURL: true with admin redirects disabled', function (done) {
|
||||
configUtils.set('admin:redirects', false);
|
||||
|
||||
req.path = post.url;
|
||||
|
||||
entryLookUpStub.withArgs(req.path, res.routerOptions)
|
||||
.resolves({
|
||||
isEditURL: true,
|
||||
entry: post
|
||||
});
|
||||
|
||||
urlUtils.redirectToAdmin.callsFake(function (statusCode, res, editorUrl) {
|
||||
configUtils.restore();
|
||||
done(new Error('redirectToAdmin was called'));
|
||||
});
|
||||
|
||||
controllers.entry(req, res, (err) => {
|
||||
configUtils.restore();
|
||||
urlUtils.redirectToAdmin.called.should.eql(false);
|
||||
should.not.exist(err);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it('type of router !== type of resource', function (done) {
|
||||
req.path = post.url;
|
||||
res.routerOptions.resourceType = 'posts';
|
||||
|
|
Loading…
Reference in a new issue