Skip to content

Commit

Permalink
馃帹 add urlFor('admin') and increase usage of urlFor helper (#7935)
Browse files Browse the repository at this point in the history
refs #7488

- to be able to refactor the url configuration in ghost, we need to go step by step making this possible
- reduce the usage of forceAdminSSL
- add a urlFor('admin') helper, which returns the admin url + path e.g. http://my-blog.com/blog/ghost
- increase usage of urlFor helper
- do not expose getBaseUrl, use urlFor('home') (home === blog)
  • Loading branch information
kirrg001 authored and ErisDS committed Feb 2, 2017
1 parent 85c0913 commit 16f5d1f
Show file tree
Hide file tree
Showing 17 changed files with 108 additions and 46 deletions.
2 changes: 1 addition & 1 deletion core/server/api/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ module.exports = function setupApiApp() {

// @TODO finish refactoring this away.
apiApp.use(function setIsAdmin(req, res, next) {
// Api === isAdmin for the purposes of the forceAdminSSL config option.
// api === isAdmin
res.isAdmin = true;
next();
});
Expand Down
4 changes: 2 additions & 2 deletions core/server/api/authentication.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ authentication = {
}

function sendResetNotification(data) {
var baseUrl = config.get('forceAdminSSL') ? globalUtils.url.urlFor('home', {secure: true}, true) : globalUtils.url.urlFor('home', true),
resetUrl = globalUtils.url.urlJoin(baseUrl, '/ghost/reset/', globalUtils.encodeBase64URLsafe(data.resetToken), '/');
var adminUrl = globalUtils.url.urlFor('admin', true),
resetUrl = globalUtils.url.urlJoin(adminUrl, 'reset', globalUtils.encodeBase64URLsafe(data.resetToken), '/');

return mail.utils.generateContent({
data: {
Expand Down
5 changes: 2 additions & 3 deletions core/server/api/invites.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ var _ = require('lodash'),
utils = require('./utils'),
errors = require('../errors'),
logging = require('../logging'),
config = require('../config'),
i18n = require('../i18n'),
docName = 'invites',
allowedIncludes = ['created_by', 'updated_by'],
Expand Down Expand Up @@ -98,14 +97,14 @@ invites = {
return settings.read({key: 'title'});
})
.then(function (response) {
var baseUrl = config.get('forceAdminSSL') ? globalUtils.url.urlFor('home', {secure: true}, true) : globalUtils.url.urlFor('home', true);
var adminUrl = globalUtils.url.urlFor('admin', true);

emailData = {
blogName: response.settings[0].value,
invitedByName: loggedInUser.get('name'),
invitedByEmail: loggedInUser.get('email'),
// @TODO: resetLink sounds weird
resetLink: globalUtils.url.urlJoin(baseUrl, 'ghost/signup', globalUtils.encodeBase64URLsafe(invite.get('token')), '/')
resetLink: globalUtils.url.urlJoin(adminUrl, 'signup', globalUtils.encodeBase64URLsafe(invite.get('token')), '/')
};

return mail.utils.generateContent({data: emailData, template: 'invite-user'});
Expand Down
7 changes: 3 additions & 4 deletions core/server/blog/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@ var express = require('express'),

frontendRoutes = function frontendRoutes() {
var router = express.Router(),
subdir = utils.url.getSubdir(),
routeKeywords = config.get('routeKeywords');

// ### Admin routes
router.get(/^\/(logout|signout)\/$/, function redirectToSignout(req, res) {
utils.redirect301(res, utils.url.urlJoin(subdir, '/ghost/signout/'));
utils.redirect301(res, utils.url.urlJoin(utils.url.urlFor('admin'), 'signout/'));
});
router.get(/^\/signup\/$/, function redirectToSignup(req, res) {
utils.redirect301(res, utils.url.urlJoin(subdir, '/ghost/signup/'));
utils.redirect301(res, utils.url.urlJoin(utils.url.urlFor('admin'), 'signup/'));
});

// redirect to /ghost and let that do the authentication to prevent redirects to /ghost//admin etc.
router.get(/^\/((ghost-admin|admin|wp-admin|dashboard|signin|login)\/?)$/, function redirectToAdmin(req, res) {
utils.redirect301(res, utils.url.urlJoin(subdir, '/ghost/'));
utils.redirect301(res, utils.url.urlFor('admin'));
});

// Post Live Preview
Expand Down
4 changes: 2 additions & 2 deletions core/server/controllers/frontend/channel-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ channelConfig = function channelConfig() {
}
},
slugTemplate: true,
editRedirect: '/ghost/settings/tags/:slug/'
editRedirect: utils.url.urlJoin(utils.url.urlFor('admin'), '/settings/tags/:slug/')
},
author: {
name: 'author',
Expand All @@ -40,7 +40,7 @@ channelConfig = function channelConfig() {
}
},
slugTemplate: true,
editRedirect: '/ghost/team/:slug/'
editRedirect: utils.url.urlJoin(utils.url.urlFor('admin'), '/team/:slug/')
}
};

Expand Down
2 changes: 1 addition & 1 deletion core/server/controllers/frontend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ frontendControllers = {

// CASE: last param is of url is /edit, redirect to admin
if (lookup.isEditURL) {
return res.redirect(utils.url.urlJoin(utils.url.getSubdir(), '/ghost/editor', post.id, '/'));
return res.redirect(utils.url.urlJoin(utils.url.urlFor('admin'), 'editor', post.id, '/'));
}

// CASE: permalink is not valid anymore, we redirect him permanently to the correct one
Expand Down
2 changes: 1 addition & 1 deletion core/server/data/meta/amp_url.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ function getAmplUrl(data) {
var context = data.context ? data.context : null;

if (_.includes(context, 'post') && !_.includes(context, 'amp')) {
return utils.url.urlJoin(utils.url.getBaseUrl(false), getUrl(data, false), 'amp/');
return utils.url.urlJoin(utils.url.urlFor('home', true), getUrl(data, false), 'amp/');
}
return null;
}
Expand Down
4 changes: 2 additions & 2 deletions core/server/data/meta/canonical_url.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ var utils = require('../../utils'),
getUrl = require('./url');

function getCanonicalUrl(data) {
var url = utils.url.urlJoin(utils.url.getBaseUrl(false),
getUrl(data, false));
var url = utils.url.urlJoin(utils.url.urlFor('home', true), getUrl(data, false));

if (url.indexOf('/amp/')) {
url = url.replace(/\/amp\/$/i, '/');
}

return url;
}

Expand Down
2 changes: 1 addition & 1 deletion core/server/data/meta/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function getMetaData(data, root) {

metaData.blog.logo = {};
metaData.blog.logo.url = config.get('theme').logo ?
utils.url.urlFor('image', {image: config.get('theme').logo}, true) : utils.url.urlFor({relativeUrl: '/ghost/img/ghosticon.jpg'}, {}, true);
utils.url.urlFor('image', {image: config.get('theme').logo}, true) : utils.url.urlJoin(utils.url.urlFor('admin'), 'img/ghosticon.jpg');

// TODO: cleanup these if statements
if (data.post && data.post.html) {
Expand Down
3 changes: 1 addition & 2 deletions core/server/data/slack/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ var https = require('https'),
logging = require('../../logging'),
utils = require('../../utils'),
events = require('../../events'),
logging = require('../../logging'),
api = require('../../api/settings'),
i18n = require('../../i18n'),
schema = require('../schema').checks,
Expand Down Expand Up @@ -74,7 +73,7 @@ function ping(post) {
slackData = {
text: message,
unfurl_links: true,
icon_url: utils.url.urlFor({relativeUrl: '/ghost/img/ghosticon.jpg'}, {}, true),
icon_url: utils.url.urlJoin(utils.url.urlFor('admin', true), 'img/ghosticon.jpg'),
username: 'Ghost'
};

Expand Down
4 changes: 2 additions & 2 deletions core/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ function init(options) {
auth.init({
authType: config.get('auth:type'),
ghostAuthUrl: config.get('auth:url'),
redirectUri: utils.url.urlJoin(utils.url.getBaseUrl(), 'ghost', '/'),
clientUri: utils.url.urlJoin(utils.url.getBaseUrl(), '/'),
redirectUri: utils.url.urlFor('admin', true),
clientUri: utils.url.urlFor('home', true),
clientName: api.settings.getSettingSync('title'),
clientDescription: api.settings.getSettingSync('description')
}).then(function (response) {
Expand Down
3 changes: 1 addition & 2 deletions core/server/mail/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ var _ = require('lodash').runInContext(),
Promise = require('bluebird'),
path = require('path'),
htmlToText = require('html-to-text'),
config = require('../config'),
utils = require('../utils'),
templatesDir = path.resolve(__dirname, '..', 'mail', 'templates');

Expand All @@ -14,7 +13,7 @@ exports.generateContent = function generateContent(options) {
data;

defaults = {
siteUrl: config.get('forceAdminSSL') ? utils.url.urlFor('home', {secure: true}, true) : utils.url.urlFor('home', true)
siteUrl: utils.url.urlFor('home', true)
};

data = _.defaults(defaults, options.data);
Expand Down
2 changes: 1 addition & 1 deletion core/server/middleware/redirect-to-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ function redirectToSetup(req, res, next) {

api.authentication.isSetup().then(function then(exists) {
if (!exists.setup[0].status && !isSetupRequest && !isOauthAuthorization) {
return res.redirect(utils.url.getSubdir() + '/ghost/setup/');
return res.redirect(utils.url.urlJoin(utils.url.urlFor('admin') + 'setup/'));
}
next();
}).catch(function handleError(err) {
Expand Down
16 changes: 14 additions & 2 deletions core/server/utils/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ function urlPathForPost(post) {
// - data (optional) - a json object containing data needed to generate a url
// - absolute (optional, default:false) - boolean whether or not the url should be absolute
// This is probably not the right place for this, but it's the best place for now
// @TODO: rewrite, very hard to read!
function urlFor(context, data, absolute) {
var urlPath = '/',
secure, imagePathRe,
Expand Down Expand Up @@ -262,9 +263,21 @@ function urlFor(context, data, absolute) {
absolute = true;
}
}
} else if (context === 'home' && absolute) {
} else if (context === 'home' && absolute) {
urlPath = getBaseUrl(secure);
// other objects are recognised but not yet supported
} else if (context === 'admin') {
if (config.get('forceAdminSSL')) {
urlPath = getBaseUrl(true);
} else {
urlPath = getBaseUrl();
}

if (absolute) {
urlPath += 'ghost/';
} else {
urlPath = '/ghost/';
}
} else if (_.isString(context) && _.indexOf(_.keys(knownPaths), context) !== -1) {
// trying to create a url for a named path
urlPath = knownPaths[context] || '/';
Expand Down Expand Up @@ -314,4 +327,3 @@ module.exports.urlJoin = urlJoin;
module.exports.urlFor = urlFor;
module.exports.urlPathForPost = urlPathForPost;
module.exports.apiUrl = apiUrl;
module.exports.getBaseUrl = getBaseUrl;
12 changes: 6 additions & 6 deletions core/test/unit/auth/passport_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,14 @@ describe('Ghost Passport', function () {
client = new models.Client(testUtils.DataGenerator.forKnex.createClient({
name: 'Ghost',
client_uri: 'http://my-blog.com',
redirection_uri: utils.url.getBaseUrl()
redirection_uri: utils.url.urlFor('home', true)
}));

return GhostPassport.init({
authType: 'ghost',
clientUri: 'http://my-blog.com',
ghostAuthUrl: 'http://devauth.ghost.org',
redirectUri: utils.url.getBaseUrl(),
redirectUri: utils.url.urlFor('home', true),
clientName: 'Ghost'
}).then(function (response) {
should.exist(response.passport);
Expand All @@ -138,7 +138,7 @@ describe('Ghost Passport', function () {
authType: 'ghost',
clientUri: 'http://my-blog.com',
ghostAuthUrl: 'http://devauth.ghost.org',
redirectUri: utils.url.getBaseUrl(),
redirectUri: utils.url.urlFor('home', true),
clientName: 'Ghost'
}).then(function (response) {
should.exist(response.passport);
Expand All @@ -159,7 +159,7 @@ describe('Ghost Passport', function () {
authType: 'ghost',
clientUri: 'http://my-blog.com',
ghostAuthUrl: 'http://devauth.ghost.org',
redirectUri: utils.url.getBaseUrl(),
redirectUri: utils.url.urlFor('home', true),
clientName: 'Ghost'
}).then(function () {
FakeGhostOAuth2Strategy.prototype.registerClient.called.should.eql(true);
Expand Down Expand Up @@ -192,7 +192,7 @@ describe('Ghost Passport', function () {
authType: 'ghost',
clientUri: 'http://my-blog.com',
ghostAuthUrl: 'http://devauth.ghost.org',
redirectUri: utils.url.getBaseUrl(),
redirectUri: utils.url.urlFor('home', true),
clientName: 'custom client name'
}).then(function (response) {
should.exist(response.passport);
Expand Down Expand Up @@ -220,7 +220,7 @@ describe('Ghost Passport', function () {
authType: 'ghost',
clientUri: 'http://my-blog.com',
ghostAuthUrl: 'http://devauth.ghost.org',
redirectUri: utils.url.getBaseUrl()
redirectUri: utils.url.urlFor('home', true)
}).catch(function (err) {
(err instanceof errors.GhostError).should.eql(true);
FakeGhostOAuth2Strategy.prototype.registerClient.callCount.should.eql(1);
Expand Down
32 changes: 18 additions & 14 deletions core/test/unit/slack_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var _ = require('lodash'),
url = require('url'),

// Stuff we test
configUtils = require('../utils/configUtils'),
slack = rewire('../../server/data/slack'),
events = require('../../server/events'),
api = require('../../server/api/settings'),
Expand Down Expand Up @@ -53,6 +54,7 @@ describe('Slack', function () {

afterEach(function () {
sandbox.restore();
configUtils.restore();
});

it('listen() should initialise event correctly', function () {
Expand Down Expand Up @@ -141,7 +143,7 @@ describe('Slack', function () {
describe('ping()', function () {
var makeRequestAssertions,
isPostStub,
urlForStub,
urlForSpy,
settingsAPIStub,
settingsObj,
slackReset,
Expand All @@ -151,36 +153,36 @@ describe('Slack', function () {

beforeEach(function () {
isPostStub = sandbox.stub(schema, 'isPost');
urlForStub = sandbox.stub(utils.url, 'urlFor');
urlForStub.withArgs('post').returns('http://myblog.com/post');
urlForStub.returns('http://myblog.com/someImageurl.jpg');
urlForSpy = sandbox.spy(utils.url, 'urlFor');
settingsObj = {settings: [], meta: {}};
settingsAPIStub = sandbox.stub(api, 'read').returns(Promise.resolve(settingsObj));

makeRequestMock = function () {
makeRequestAssertions.apply(this, arguments);
};

makeRequestSpy = sandbox.spy(makeRequestMock);
slackReset = slack.__set__('makeRequest', makeRequestMock);

configUtils.set('url', 'http://myblog.com');
});

afterEach(function () {
slackReset();
});

it('makes a request for a post if url is provided', function (done) {
// set up
isPostStub.returns(true);
settingsObj.settings[0] = slackObjWithUrl;

// assertions
makeRequestAssertions = function (requestOptions, requestData) {
isPostStub.calledOnce.should.be.true();
urlForStub.calledTwice.should.be.true();
urlForSpy.calledTwice.should.be.true();
settingsAPIStub.calledOnce.should.be.true();
requestOptions.should.have.property('href').and.be.equal('https://hooks.slack.com/services/a-b-c-d');
requestData.should.have.property('text').and.be.equal('http://myblog.com/post');
requestData.should.have.property('icon_url').and.be.equal('http://myblog.com/someImageurl.jpg');
requestData.should.have.property('text').and.be.equal('http://myblog.com/');
requestData.should.have.property('icon_url').and.be.equal('http://myblog.com/ghost/img/ghosticon.jpg');
requestData.should.have.property('username').and.be.equal('Ghost');
done();
};
Expand All @@ -193,14 +195,16 @@ describe('Slack', function () {
isPostStub.returns(false);
settingsObj.settings[0] = slackObjWithUrl;

configUtils.set('forceAdminSSL', true);

// assertions
makeRequestAssertions = function (requestOptions, requestData) {
isPostStub.calledOnce.should.be.true();
urlForStub.calledOnce.should.be.true();
urlForSpy.calledOnce.should.be.true();
settingsAPIStub.calledOnce.should.be.true();
requestOptions.should.have.property('href').and.be.equal('https://hooks.slack.com/services/a-b-c-d');
requestData.should.have.property('text').and.be.equal('Hi!');
requestData.should.have.property('icon_url').and.be.equal('http://myblog.com/someImageurl.jpg');
requestData.should.have.property('icon_url').and.be.equal('https://myblog.com/ghost/img/ghosticon.jpg');
requestData.should.have.property('username').and.be.equal('Ghost');
done();
};
Expand All @@ -217,7 +221,7 @@ describe('Slack', function () {
ping({page: true}).then(function (result) {
// assertions
isPostStub.calledOnce.should.be.true();
urlForStub.calledOnce.should.be.true();
urlForSpy.calledOnce.should.be.true();
settingsAPIStub.calledOnce.should.be.true();
makeRequestSpy.called.should.be.false();
should.not.exist(result);
Expand All @@ -234,7 +238,7 @@ describe('Slack', function () {
ping({}).then(function (result) {
// assertions
isPostStub.calledOnce.should.be.true();
urlForStub.calledOnce.should.be.true();
urlForSpy.calledOnce.should.be.true();
settingsAPIStub.calledOnce.should.be.true();
makeRequestSpy.called.should.be.false();
should.not.exist(result);
Expand All @@ -251,7 +255,7 @@ describe('Slack', function () {
ping({slug: 'welcome-to-ghost'}).then(function (result) {
// assertions
isPostStub.calledOnce.should.be.true();
urlForStub.calledOnce.should.be.true();
urlForSpy.calledOnce.should.be.true();
settingsAPIStub.calledOnce.should.be.true();
makeRequestSpy.called.should.be.false();
should.not.exist(result);
Expand All @@ -266,7 +270,7 @@ describe('Slack', function () {
done('This should not get called');
}).catch(function () {
isPostStub.calledOnce.should.be.true();
urlForStub.calledOnce.should.be.false();
urlForSpy.calledOnce.should.be.false();
settingsAPIStub.calledOnce.should.be.true();
makeRequestSpy.called.should.be.false();
done();
Expand Down
Loading

0 comments on commit 16f5d1f

Please sign in to comment.