Ghost/core/server/api/v2/utils/permissions.js

103 lines
4.0 KiB
JavaScript
Raw Normal View History

Added tiny framework to support multiple API versions (#9933) refs #9326, refs #9866 **ATTENTION: This is the first iteration. Bugs are expected.** Main Goals: - add support for multiple API versions. - do not touch v0.1 implementation - do not break v0.1 ## Problems with the existing v0.1 implementation 1. It tried to be generic and helpful, but it was a mixture of generic and explicit logic living in basically two files: utils.js and index.js. 2. Supporting multiple api versions means, you want to have as less as possible code per API version. With v0.1 it is impossible to reduce the API controller implementation. ---- This commit adds three things: 1. The tiny framework with well-defined API stages. 2. An example implementation of serving static pages via /pages for the content v2 API. 3. Unit tests to prove that the API framework works in general. ## API Stages - validation - input serialization - permissions - query - output serialization Each request should go through these stages. It is possible to disable stages, but it's not recommended. The code for each stage will either live in a shared folder or in the API version itself. It depends how API specific the validation or serialization is. Depends on the use case. We should add a specific API validator or serializer if the use case is API format specific. We should put everything else to shared. The goal is to add as much as possible into the shared API layer to reduce the logic per API version. --- Serializers and validators can be added: - for each request - for specific controllers - for specific actions --- There is room for improvements/extensions: 1. Remove http header configuration from the API controller, because the API controller should not know about http - decouple. 2. Put permissions helpers into shared. I've just extracted and capsulated the permissions helpers into a single file for now. It had no priority. The focus was on the framework itself. etc. --- You can find more information about it in the API README.md (api/README.md) - e.g. find more information about the structure - e.g. example controllers The docs are not perfect. We will improve the docs in the next two weeks. --- Upcoming tasks: - prepare test env to test multiple API versions - copy over the controllers from v0.1 to v2 - adapt the v2 express app to use the v2 controllers
2018-10-05 01:50:45 +03:00
const debug = require('ghost-ignition').debug('api:v2:utils:permissions');
const Promise = require('bluebird');
const _ = require('lodash');
const permissions = require('../../../services/permissions');
const common = require('../../../lib/common');
/**
* @description Handle requests, which need authentication.
*
* @param {Object} apiConfig - Docname & method of API ctrl
* @param {Object} frame
* @return {Promise}
*/
Added tiny framework to support multiple API versions (#9933) refs #9326, refs #9866 **ATTENTION: This is the first iteration. Bugs are expected.** Main Goals: - add support for multiple API versions. - do not touch v0.1 implementation - do not break v0.1 ## Problems with the existing v0.1 implementation 1. It tried to be generic and helpful, but it was a mixture of generic and explicit logic living in basically two files: utils.js and index.js. 2. Supporting multiple api versions means, you want to have as less as possible code per API version. With v0.1 it is impossible to reduce the API controller implementation. ---- This commit adds three things: 1. The tiny framework with well-defined API stages. 2. An example implementation of serving static pages via /pages for the content v2 API. 3. Unit tests to prove that the API framework works in general. ## API Stages - validation - input serialization - permissions - query - output serialization Each request should go through these stages. It is possible to disable stages, but it's not recommended. The code for each stage will either live in a shared folder or in the API version itself. It depends how API specific the validation or serialization is. Depends on the use case. We should add a specific API validator or serializer if the use case is API format specific. We should put everything else to shared. The goal is to add as much as possible into the shared API layer to reduce the logic per API version. --- Serializers and validators can be added: - for each request - for specific controllers - for specific actions --- There is room for improvements/extensions: 1. Remove http header configuration from the API controller, because the API controller should not know about http - decouple. 2. Put permissions helpers into shared. I've just extracted and capsulated the permissions helpers into a single file for now. It had no priority. The focus was on the framework itself. etc. --- You can find more information about it in the API README.md (api/README.md) - e.g. find more information about the structure - e.g. example controllers The docs are not perfect. We will improve the docs in the next two weeks. --- Upcoming tasks: - prepare test env to test multiple API versions - copy over the controllers from v0.1 to v2 - adapt the v2 express app to use the v2 controllers
2018-10-05 01:50:45 +03:00
const nonePublicAuth = (apiConfig, frame) => {
debug('check admin permissions');
const singular = apiConfig.docName.replace(/s$/, '');
let permissionIdentifier = frame.options.id;
// CASE: Target ctrl can override the identifier. The identifier is the unique identifier of the target resource
// e.g. edit a setting -> the key of the setting
// e.g. edit a post -> post id from url param
// e.g. change user password -> user id inside of the body structure
2018-10-12 20:44:02 +03:00
if (apiConfig.identifier) {
permissionIdentifier = apiConfig.identifier(frame);
}
const unsafeAttrObject = apiConfig.unsafeAttrs && _.has(frame, `data.[${apiConfig.docName}][0]`) ? _.pick(frame.data[apiConfig.docName][0], apiConfig.unsafeAttrs) : {};
const permsPromise = permissions.canThis(frame.options.context)[apiConfig.method][singular](permissionIdentifier, unsafeAttrObject);
Added tiny framework to support multiple API versions (#9933) refs #9326, refs #9866 **ATTENTION: This is the first iteration. Bugs are expected.** Main Goals: - add support for multiple API versions. - do not touch v0.1 implementation - do not break v0.1 ## Problems with the existing v0.1 implementation 1. It tried to be generic and helpful, but it was a mixture of generic and explicit logic living in basically two files: utils.js and index.js. 2. Supporting multiple api versions means, you want to have as less as possible code per API version. With v0.1 it is impossible to reduce the API controller implementation. ---- This commit adds three things: 1. The tiny framework with well-defined API stages. 2. An example implementation of serving static pages via /pages for the content v2 API. 3. Unit tests to prove that the API framework works in general. ## API Stages - validation - input serialization - permissions - query - output serialization Each request should go through these stages. It is possible to disable stages, but it's not recommended. The code for each stage will either live in a shared folder or in the API version itself. It depends how API specific the validation or serialization is. Depends on the use case. We should add a specific API validator or serializer if the use case is API format specific. We should put everything else to shared. The goal is to add as much as possible into the shared API layer to reduce the logic per API version. --- Serializers and validators can be added: - for each request - for specific controllers - for specific actions --- There is room for improvements/extensions: 1. Remove http header configuration from the API controller, because the API controller should not know about http - decouple. 2. Put permissions helpers into shared. I've just extracted and capsulated the permissions helpers into a single file for now. It had no priority. The focus was on the framework itself. etc. --- You can find more information about it in the API README.md (api/README.md) - e.g. find more information about the structure - e.g. example controllers The docs are not perfect. We will improve the docs in the next two weeks. --- Upcoming tasks: - prepare test env to test multiple API versions - copy over the controllers from v0.1 to v2 - adapt the v2 express app to use the v2 controllers
2018-10-05 01:50:45 +03:00
return permsPromise.then((result) => {
/*
* Allow the permissions function to return a list of excluded attributes.
* If it does, omit those attrs from the data passed through
*
* NOTE: excludedAttrs differ from unsafeAttrs in that they're determined by the model's permissible function,
* and the attributes are simply excluded rather than throwing a NoPermission exception
*
* TODO: This is currently only needed because of the posts model and the contributor role. Once we extend the
* contributor role to be able to edit existing tags, this concept can be removed.
*/
if (result && result.excludedAttrs && _.has(frame, `data.[${apiConfig.docName}][0]`)) {
frame.data[apiConfig.docName][0] = _.omit(frame.data[apiConfig.docName][0], result.excludedAttrs);
}
}).catch((err) => {
if (err instanceof common.errors.NoPermissionError) {
err.message = common.i18n.t('errors.api.utils.noPermissionToCall', {
method: apiConfig.method,
docName: apiConfig.docName
});
return Promise.reject(err);
}
if (common.errors.utils.isIgnitionError(err)) {
return Promise.reject(err);
}
return Promise.reject(new common.errors.GhostError({
err: err
}));
});
};
// @TODO: https://github.com/TryGhost/Ghost/issues/10735
Added tiny framework to support multiple API versions (#9933) refs #9326, refs #9866 **ATTENTION: This is the first iteration. Bugs are expected.** Main Goals: - add support for multiple API versions. - do not touch v0.1 implementation - do not break v0.1 ## Problems with the existing v0.1 implementation 1. It tried to be generic and helpful, but it was a mixture of generic and explicit logic living in basically two files: utils.js and index.js. 2. Supporting multiple api versions means, you want to have as less as possible code per API version. With v0.1 it is impossible to reduce the API controller implementation. ---- This commit adds three things: 1. The tiny framework with well-defined API stages. 2. An example implementation of serving static pages via /pages for the content v2 API. 3. Unit tests to prove that the API framework works in general. ## API Stages - validation - input serialization - permissions - query - output serialization Each request should go through these stages. It is possible to disable stages, but it's not recommended. The code for each stage will either live in a shared folder or in the API version itself. It depends how API specific the validation or serialization is. Depends on the use case. We should add a specific API validator or serializer if the use case is API format specific. We should put everything else to shared. The goal is to add as much as possible into the shared API layer to reduce the logic per API version. --- Serializers and validators can be added: - for each request - for specific controllers - for specific actions --- There is room for improvements/extensions: 1. Remove http header configuration from the API controller, because the API controller should not know about http - decouple. 2. Put permissions helpers into shared. I've just extracted and capsulated the permissions helpers into a single file for now. It had no priority. The focus was on the framework itself. etc. --- You can find more information about it in the API README.md (api/README.md) - e.g. find more information about the structure - e.g. example controllers The docs are not perfect. We will improve the docs in the next two weeks. --- Upcoming tasks: - prepare test env to test multiple API versions - copy over the controllers from v0.1 to v2 - adapt the v2 express app to use the v2 controllers
2018-10-05 01:50:45 +03:00
module.exports = {
/**
* @description Handle permission stage for API version v2.
*
* @param {Object} apiConfig - Docname & method of target ctrl.
* @param {Object} frame
* @return {Promise}
*/
Added tiny framework to support multiple API versions (#9933) refs #9326, refs #9866 **ATTENTION: This is the first iteration. Bugs are expected.** Main Goals: - add support for multiple API versions. - do not touch v0.1 implementation - do not break v0.1 ## Problems with the existing v0.1 implementation 1. It tried to be generic and helpful, but it was a mixture of generic and explicit logic living in basically two files: utils.js and index.js. 2. Supporting multiple api versions means, you want to have as less as possible code per API version. With v0.1 it is impossible to reduce the API controller implementation. ---- This commit adds three things: 1. The tiny framework with well-defined API stages. 2. An example implementation of serving static pages via /pages for the content v2 API. 3. Unit tests to prove that the API framework works in general. ## API Stages - validation - input serialization - permissions - query - output serialization Each request should go through these stages. It is possible to disable stages, but it's not recommended. The code for each stage will either live in a shared folder or in the API version itself. It depends how API specific the validation or serialization is. Depends on the use case. We should add a specific API validator or serializer if the use case is API format specific. We should put everything else to shared. The goal is to add as much as possible into the shared API layer to reduce the logic per API version. --- Serializers and validators can be added: - for each request - for specific controllers - for specific actions --- There is room for improvements/extensions: 1. Remove http header configuration from the API controller, because the API controller should not know about http - decouple. 2. Put permissions helpers into shared. I've just extracted and capsulated the permissions helpers into a single file for now. It had no priority. The focus was on the framework itself. etc. --- You can find more information about it in the API README.md (api/README.md) - e.g. find more information about the structure - e.g. example controllers The docs are not perfect. We will improve the docs in the next two weeks. --- Upcoming tasks: - prepare test env to test multiple API versions - copy over the controllers from v0.1 to v2 - adapt the v2 express app to use the v2 controllers
2018-10-05 01:50:45 +03:00
handle(apiConfig, frame) {
debug('handle');
// @TODO: https://github.com/TryGhost/Ghost/issues/10099
Added tiny framework to support multiple API versions (#9933) refs #9326, refs #9866 **ATTENTION: This is the first iteration. Bugs are expected.** Main Goals: - add support for multiple API versions. - do not touch v0.1 implementation - do not break v0.1 ## Problems with the existing v0.1 implementation 1. It tried to be generic and helpful, but it was a mixture of generic and explicit logic living in basically two files: utils.js and index.js. 2. Supporting multiple api versions means, you want to have as less as possible code per API version. With v0.1 it is impossible to reduce the API controller implementation. ---- This commit adds three things: 1. The tiny framework with well-defined API stages. 2. An example implementation of serving static pages via /pages for the content v2 API. 3. Unit tests to prove that the API framework works in general. ## API Stages - validation - input serialization - permissions - query - output serialization Each request should go through these stages. It is possible to disable stages, but it's not recommended. The code for each stage will either live in a shared folder or in the API version itself. It depends how API specific the validation or serialization is. Depends on the use case. We should add a specific API validator or serializer if the use case is API format specific. We should put everything else to shared. The goal is to add as much as possible into the shared API layer to reduce the logic per API version. --- Serializers and validators can be added: - for each request - for specific controllers - for specific actions --- There is room for improvements/extensions: 1. Remove http header configuration from the API controller, because the API controller should not know about http - decouple. 2. Put permissions helpers into shared. I've just extracted and capsulated the permissions helpers into a single file for now. It had no priority. The focus was on the framework itself. etc. --- You can find more information about it in the API README.md (api/README.md) - e.g. find more information about the structure - e.g. example controllers The docs are not perfect. We will improve the docs in the next two weeks. --- Upcoming tasks: - prepare test env to test multiple API versions - copy over the controllers from v0.1 to v2 - adapt the v2 express app to use the v2 controllers
2018-10-05 01:50:45 +03:00
frame.options.context = permissions.parseContext(frame.options.context);
// CASE: Content API access
Added tiny framework to support multiple API versions (#9933) refs #9326, refs #9866 **ATTENTION: This is the first iteration. Bugs are expected.** Main Goals: - add support for multiple API versions. - do not touch v0.1 implementation - do not break v0.1 ## Problems with the existing v0.1 implementation 1. It tried to be generic and helpful, but it was a mixture of generic and explicit logic living in basically two files: utils.js and index.js. 2. Supporting multiple api versions means, you want to have as less as possible code per API version. With v0.1 it is impossible to reduce the API controller implementation. ---- This commit adds three things: 1. The tiny framework with well-defined API stages. 2. An example implementation of serving static pages via /pages for the content v2 API. 3. Unit tests to prove that the API framework works in general. ## API Stages - validation - input serialization - permissions - query - output serialization Each request should go through these stages. It is possible to disable stages, but it's not recommended. The code for each stage will either live in a shared folder or in the API version itself. It depends how API specific the validation or serialization is. Depends on the use case. We should add a specific API validator or serializer if the use case is API format specific. We should put everything else to shared. The goal is to add as much as possible into the shared API layer to reduce the logic per API version. --- Serializers and validators can be added: - for each request - for specific controllers - for specific actions --- There is room for improvements/extensions: 1. Remove http header configuration from the API controller, because the API controller should not know about http - decouple. 2. Put permissions helpers into shared. I've just extracted and capsulated the permissions helpers into a single file for now. It had no priority. The focus was on the framework itself. etc. --- You can find more information about it in the API README.md (api/README.md) - e.g. find more information about the structure - e.g. example controllers The docs are not perfect. We will improve the docs in the next two weeks. --- Upcoming tasks: - prepare test env to test multiple API versions - copy over the controllers from v0.1 to v2 - adapt the v2 express app to use the v2 controllers
2018-10-05 01:50:45 +03:00
if (frame.options.context.public) {
debug('check content permissions');
// @TODO: Remove when we drop v0.1
// @TODO: https://github.com/TryGhost/Ghost/issues/10733
Added tiny framework to support multiple API versions (#9933) refs #9326, refs #9866 **ATTENTION: This is the first iteration. Bugs are expected.** Main Goals: - add support for multiple API versions. - do not touch v0.1 implementation - do not break v0.1 ## Problems with the existing v0.1 implementation 1. It tried to be generic and helpful, but it was a mixture of generic and explicit logic living in basically two files: utils.js and index.js. 2. Supporting multiple api versions means, you want to have as less as possible code per API version. With v0.1 it is impossible to reduce the API controller implementation. ---- This commit adds three things: 1. The tiny framework with well-defined API stages. 2. An example implementation of serving static pages via /pages for the content v2 API. 3. Unit tests to prove that the API framework works in general. ## API Stages - validation - input serialization - permissions - query - output serialization Each request should go through these stages. It is possible to disable stages, but it's not recommended. The code for each stage will either live in a shared folder or in the API version itself. It depends how API specific the validation or serialization is. Depends on the use case. We should add a specific API validator or serializer if the use case is API format specific. We should put everything else to shared. The goal is to add as much as possible into the shared API layer to reduce the logic per API version. --- Serializers and validators can be added: - for each request - for specific controllers - for specific actions --- There is room for improvements/extensions: 1. Remove http header configuration from the API controller, because the API controller should not know about http - decouple. 2. Put permissions helpers into shared. I've just extracted and capsulated the permissions helpers into a single file for now. It had no priority. The focus was on the framework itself. etc. --- You can find more information about it in the API README.md (api/README.md) - e.g. find more information about the structure - e.g. example controllers The docs are not perfect. We will improve the docs in the next two weeks. --- Upcoming tasks: - prepare test env to test multiple API versions - copy over the controllers from v0.1 to v2 - adapt the v2 express app to use the v2 controllers
2018-10-05 01:50:45 +03:00
return permissions.applyPublicRules(apiConfig.docName, apiConfig.method, {
status: frame.options.status,
id: frame.options.id,
uuid: frame.options.uuid,
slug: frame.options.slug,
data: {
status: frame.data.status,
id: frame.data.id,
uuid: frame.data.uuid,
slug: frame.data.slug
}
});
}
return nonePublicAuth(apiConfig, frame);
}
};