0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-20 22:42:53 -05:00

🐛 fix cors middleware (#8094)

no issue

- same fix as https://github.com/TryGhost/Ghost/pull/8066
- just for master
This commit is contained in:
Katharina Irrgang 2017-03-03 17:41:20 +01:00 committed by Hannah Wolfe
parent 0fd0807f7b
commit 773eb92960
4 changed files with 69 additions and 11 deletions

View file

@ -30,18 +30,28 @@ var debug = require('debug')('ghost:api'),
// @TODO find a more appy way to do this!
labs = require('../middleware/labs'),
// @TODO find a better way to bundle these authentication packages
// Authentication for public endpoints
/**
* Authentication for public endpoints
* @TODO find a better way to bundle these authentication packages
*
* IMPORTANT
* - cors middleware MUST happen before pretty urls, because otherwise cors header can get lost
* - cors middleware MUST happen after authenticateClient, because authenticateClient reads the trusted domains
*/
authenticatePublic = [
auth.authenticate.authenticateClient,
auth.authenticate.authenticateUser,
auth.authorize.requiresAuthorizedUserPublicAPI
auth.authorize.requiresAuthorizedUserPublicAPI,
cors,
prettyURLs
],
// Require user for private endpoints
authenticatePrivate = [
auth.authenticate.authenticateClient,
auth.authenticate.authenticateUser,
auth.authorize.requiresAuthorizedUser
auth.authorize.requiresAuthorizedUser,
cors,
prettyURLs
];
// @TODO refactor/clean this up - how do we want the routing to work long term?
@ -230,8 +240,6 @@ module.exports = function setupApiApp() {
apiApp.use(bodyParser.json({limit: '1mb'}));
apiApp.use(bodyParser.urlencoded({extended: true, limit: '1mb'}));
apiApp.use(cors);
// send 503 json response in case of maintenance
apiApp.use(maintenance);
@ -239,10 +247,6 @@ module.exports = function setupApiApp() {
// must happen AFTER asset loading and BEFORE routing
apiApp.use(urlRedirects);
// Add in all trailing slashes & remove uppercase
// must happen AFTER asset loading and BEFORE routing
apiApp.use(prettyURLs);
// Check version matches for API requests, depends on res.locals.safeVersion being set
// Therefore must come after themeHandler.ghostLocals, for now
apiApp.use(versionMatch);

View file

@ -22,7 +22,7 @@ describe('Public API', function () {
}).then(function () {
request = supertest.agent(config.get('url'));
}).then(function () {
return testUtils.doAuth(request, 'posts', 'tags');
return testUtils.doAuth(request, 'posts', 'tags', 'client:trusted-domain');
}).then(function (token) {
// enable public API
request.put(testUtils.API.getApiQuery('settings/'))
@ -58,7 +58,37 @@ describe('Public API', function () {
return done(err);
}
res.headers.vary.should.eql('Origin, Accept-Encoding');
should.exist(res.headers['access-control-allow-origin']);
should.not.exist(res.headers['x-cache-invalidate']);
var jsonResponse = res.body;
should.exist(jsonResponse.posts);
testUtils.API.checkResponse(jsonResponse, 'posts');
jsonResponse.posts.should.have.length(5);
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
testUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
_.isBoolean(jsonResponse.posts[0].page).should.eql(true);
done();
});
});
it('browse posts from different origin', function (done) {
request.get(testUtils.API.getApiQuery('posts/?client_id=ghost-test&client_secret=not_available'))
.set('Origin', 'https://example.com')
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
res.headers.vary.should.eql('Origin, Accept-Encoding');
should.exist(res.headers['access-control-allow-origin']);
should.not.exist(res.headers['x-cache-invalidate']);
var jsonResponse = res.body;
should.exist(jsonResponse.posts);
testUtils.API.checkResponse(jsonResponse, 'posts');

View file

@ -406,6 +406,7 @@ DataGenerator.forKnex = (function () {
secret: 'not_available',
redirection_uri: 'http://localhost:9999',
client_uri: 'http://localhost:9000',
slug: 'client',
name: 'client',
type: 'ua',
status: 'enabled'
@ -480,6 +481,16 @@ DataGenerator.forKnex = (function () {
});
}
function createTrustedDomain(overrides) {
var newObj = _.cloneDeep(overrides);
return _.defaults(newObj, {
id: ObjectId.generate(),
client_id: clients[0].id,
trusted_domain: 'https://example.com'
});
}
posts = [
createPost(DataGenerator.Content.posts[0]),
createPost(DataGenerator.Content.posts[1]),
@ -600,6 +611,7 @@ DataGenerator.forKnex = (function () {
createToken: createToken,
createSubscriber: createBasic,
createInvite: createInvite,
createTrustedDomain: createTrustedDomain,
invites: invites,
posts: posts,

View file

@ -387,6 +387,17 @@ fixtures = {
return db.knex('clients').insert(DataGenerator.forKnex.clients);
},
insertClientWithTrustedDomain: function insertClientWithTrustedDomain() {
var client = DataGenerator.forKnex.createClient({slug: 'ghost-test'});
return db.knex('clients')
.insert(client)
.then(function () {
return db.knex('client_trusted_domains')
.insert(DataGenerator.forKnex.createTrustedDomain({client_id: client.id}));
});
},
insertAccessToken: function insertAccessToken(override) {
return db.knex('accesstokens').insert(DataGenerator.forKnex.createToken(override));
},
@ -447,6 +458,7 @@ toDoList = {
return function permissionsForObj() { return fixtures.permissionsFor(obj); };
},
clients: function insertClients() { return fixtures.insertClients(); },
'client:trusted-domain': function insertClients() { return fixtures.insertClientWithTrustedDomain(); },
filter: function createFilterParamFixtures() { return filterData(DataGenerator); },
invites: function insertInvites() { return fixtures.insertInvites(); },
themes: function loadThemes() { return themes.loadAll(); }