0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

Reverted & Solved apiType differently

no issue

- was unable to revert 9dd7aff9c6, because it contains members changes
- functional calls did not work correctly, because the content and admin ctrl differentiation happend in the web layer
- `isContentAPI` returned true for `api.v2.settings.edit(data, {context: {internal:true{})`
- content & admin API are using different controllers
- we can just tell which ctrl is content API and which is not
- the direction fits for the content & admin API split
This commit is contained in:
kirrg001 2019-02-25 19:52:45 +01:00 committed by Katharina Irrgang
parent 46d7a5666e
commit 38e93c19b5
12 changed files with 55 additions and 72 deletions

View file

@ -10,7 +10,7 @@ class Frame {
this.user = {};
this.file = {};
this.files = [];
this.apiType = obj.apiType;
this.apiType = null;
}
/**

View file

@ -2,7 +2,7 @@ const debug = require('ghost-ignition').debug('api:shared:http');
const shared = require('../shared');
const models = require('../../models');
const http = (apiImpl, apiType) => {
const http = (apiImpl) => {
return (req, res, next) => {
debug('request');
@ -36,8 +36,7 @@ const http = (apiImpl, apiType) => {
user: user,
integration: integration,
member: (req.member || null)
},
apiType
}
});
frame.configure({

View file

@ -92,7 +92,7 @@ const STAGES = {
}
};
const pipeline = (apiController, apiUtils) => {
const pipeline = (apiController, apiUtils, apiType) => {
const keys = Object.keys(apiController);
// CASE: api controllers are objects with configuration.
@ -138,6 +138,7 @@ const pipeline = (apiController, apiUtils) => {
return apiImpl(frame);
}
frame.apiType = apiType;
frame.docName = docName;
frame.method = method;

View file

@ -19,10 +19,6 @@ module.exports = {
return require('./session');
},
get pagesPublic() {
return shared.pipeline(require('./pages-public'), localUtils);
},
get pages() {
return shared.pipeline(require('./pages'), localUtils);
},
@ -47,10 +43,6 @@ module.exports = {
return shared.pipeline(require('./posts'), localUtils);
},
get postsPublic() {
return shared.pipeline(require('./posts-public'), localUtils);
},
get invites() {
return shared.pipeline(require('./invites'), localUtils);
},
@ -83,10 +75,6 @@ module.exports = {
return shared.pipeline(require('./tags'), localUtils);
},
get tagsPublic() {
return shared.pipeline(require('./tags-public'), localUtils);
},
get users() {
return shared.pipeline(require('./users'), localUtils);
},
@ -107,10 +95,6 @@ module.exports = {
return shared.pipeline(require('./config'), localUtils);
},
get publicSettings() {
return shared.pipeline(require('./settings-public'), localUtils);
},
get themes() {
return shared.pipeline(require('./themes'), localUtils);
},
@ -119,15 +103,39 @@ module.exports = {
return shared.pipeline(require('./actions'), localUtils);
},
get authorsPublic() {
return shared.pipeline(require('./authors-public'), localUtils, 'content');
},
get site() {
return shared.pipeline(require('./site'), localUtils);
},
get serializers() {
return require('./utils/serializers');
},
/**
* Content API Controllers
*
* @NOTE:
*
* Please create separate controllers for Content & Admin API. The goal is to expose `api.v2.content` and
* `api.v2.admin` soon. Need to figure out how serializers & validation works then.
*/
get pagesPublic() {
return shared.pipeline(require('./pages-public'), localUtils, 'content');
},
get tagsPublic() {
return shared.pipeline(require('./tags-public'), localUtils, 'content');
},
get publicSettings() {
return shared.pipeline(require('./settings-public'), localUtils, 'content');
},
get postsPublic() {
return shared.pipeline(require('./posts-public'), localUtils, 'content');
},
get authorsPublic() {
return shared.pipeline(require('./authors-public'), localUtils, 'content');
}
};

View file

@ -11,18 +11,8 @@ module.exports = {
return require('./validators');
},
/**
* TODO: We need to check for public context as permission stage overrides
* the whole context object currently: https://github.com/TryGhost/Ghost/issues/10099
*/
isContentAPI: (frame) => {
const context = frame.options && frame.options.context || {};
// CASE: An empty context is considered public by the core/server/services/permissions/parse-context.js
// module, replicated here because the context is unparsed until after the permissions layer of the pipeline
const isPublic = context.public || Object.keys(context).length === 0;
// CASE: apiType = 'content' for HTTP Content API
return frame.apiType === 'content' || isPublic;
return frame.apiType === 'content';
},
isAdminAPIKey: (frame) => {

View file

@ -18,7 +18,7 @@ module.exports = function apiRoutes() {
// ## CORS pre-flight check
router.options('*', shared.middlewares.api.cors);
const http = apiImpl => apiv2.http(apiImpl, 'admin');
const http = apiv2.http;
// ## Public
router.get('/site', http(apiv2.site.read));

View file

@ -8,7 +8,7 @@ module.exports = function apiRoutes() {
router.options('*', cors());
const http = apiImpl => apiv2.http(apiImpl, 'content');
const http = apiv2.http;
// ## Posts
router.get('/posts', mw.authenticatePublic, http(apiv2.postsPublic.browse));

View file

@ -15,27 +15,7 @@ describe('Unit: v2/utils/index', function () {
should(utils.isContentAPI(frame)).equal(true);
});
it('is true when options.context.public is true', function () {
const frame = {
options: {
context: {
public: true
}
}
};
should(utils.isContentAPI(frame)).equal(true);
});
it('is true when options.context is empty', function () {
const frame = {
options: {
context: {}
}
};
should(utils.isContentAPI(frame)).equal(true);
});
it('is false when options.context has no public value and apiType is not content', function () {
it('is false when apiType is admin', function () {
const frame = {
apiType: 'admin',
options: {

View file

@ -6,6 +6,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
it('default', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
context: {}
},
@ -18,6 +19,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
it('combine filters', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
filter: 'status:published+tag:eins',
context: {}
@ -31,6 +33,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
it('combine filters', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
filter: 'page:false+tag:eins',
context: {}
@ -44,6 +47,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
it('combine filters', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
filter: 'page:false',
context: {}
@ -57,6 +61,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
it('remove mobiledoc option from formats', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
formats: ['html', 'mobiledoc', 'plaintext'],
context: {}
@ -74,6 +79,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
it('content api default', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
context: {}
},
@ -127,6 +133,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
it('custom page filter', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
filter: 'page:false',
context: {}
@ -162,6 +169,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
it('remove mobiledoc option from formats', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
formats: ['html', 'mobiledoc', 'plaintext'],
context: {}
@ -184,6 +192,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {},
data: {
pages: [
@ -206,6 +215,7 @@ describe('Unit: v2/utils/serializers/input/pages', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {},
data: {
pages: [

View file

@ -121,6 +121,7 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
it('remove mobiledoc option from formats', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
formats: ['html', 'mobiledoc', 'plaintext'],
context: {}
@ -203,6 +204,7 @@ describe('Unit: v2/utils/serializers/input/posts', function () {
it('remove mobiledoc option from formats', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
formats: ['html', 'mobiledoc', 'plaintext'],
context: {}

View file

@ -23,9 +23,7 @@ describe('Unit: v2/utils/serializers/output/tags', () => {
const apiConfig = {};
const frame = {
options: {
context: {
public: true
}
context: {}
}
};
@ -41,9 +39,7 @@ describe('Unit: v2/utils/serializers/output/tags', () => {
const apiConfig = {};
const frame = {
options: {
context: {
public: true
}
context: {}
}
};

View file

@ -41,10 +41,9 @@ describe('Unit: v2/utils/serializers/output/utils/mapper', () => {
const frame = {
options: {
withRelated: ['tags', 'authors'],
context: {
public: true
}
}
context: {}
},
apiType: 'content'
};
const post = postModel(testUtils.DataGenerator.forKnex.createPost({
@ -120,9 +119,7 @@ describe('Unit: v2/utils/serializers/output/utils/mapper', () => {
it('calls utils', () => {
const frame = {
options: {
context: {
public: true
}
context: {}
},
};