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:
parent
46d7a5666e
commit
38e93c19b5
12 changed files with 55 additions and 72 deletions
|
@ -10,7 +10,7 @@ class Frame {
|
|||
this.user = {};
|
||||
this.file = {};
|
||||
this.files = [];
|
||||
this.apiType = obj.apiType;
|
||||
this.apiType = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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: [
|
||||
|
|
|
@ -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: {}
|
||||
|
|
|
@ -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: {}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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: {}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue