mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-22 02:11:44 +03:00
7b761a8751
no issue Adds new canary api endpoint, currently replicating v2 endpoint but paving way for future updates to new version
103 lines
4.0 KiB
JavaScript
103 lines
4.0 KiB
JavaScript
const debug = require('ghost-ignition').debug('api:canary: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}
|
|
*/
|
|
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
|
|
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);
|
|
|
|
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
|
|
module.exports = {
|
|
/**
|
|
* @description Handle permission stage for canary API.
|
|
*
|
|
* @param {Object} apiConfig - Docname & method of target ctrl.
|
|
* @param {Object} frame
|
|
* @return {Promise}
|
|
*/
|
|
handle(apiConfig, frame) {
|
|
debug('handle');
|
|
|
|
// @TODO: https://github.com/TryGhost/Ghost/issues/10099
|
|
frame.options.context = permissions.parseContext(frame.options.context);
|
|
|
|
// CASE: Content API access
|
|
if (frame.options.context.public) {
|
|
debug('check content permissions');
|
|
|
|
// @TODO: Remove when we drop v0.1
|
|
// @TODO: https://github.com/TryGhost/Ghost/issues/10733
|
|
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);
|
|
}
|
|
};
|