From ace5c0634a0f99e561c72713a796619492bbb141 Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Fri, 3 Jul 2015 19:32:25 +0200 Subject: [PATCH] Pipeline-ify configuration/themes/upload APIs refs #5508 --- core/server/api/configuration.js | 62 +++++++--- core/server/api/themes.js | 108 +++++++++++------- core/server/api/upload.js | 58 ++++++---- .../integration/api/api_configuration_spec.js | 2 +- 4 files changed, 154 insertions(+), 76 deletions(-) diff --git a/core/server/api/configuration.js b/core/server/api/configuration.js index 3b1067db6ff1..c8beb7573c93 100644 --- a/core/server/api/configuration.js +++ b/core/server/api/configuration.js @@ -4,6 +4,8 @@ var _ = require('lodash'), config = require('../config'), errors = require('../errors'), Promise = require('bluebird'), + utils = require('./utils'), + pipeline = require('../utils/pipeline'), configuration; @@ -36,29 +38,59 @@ configuration = { * @returns {Promise(Configurations)} */ browse: function browse() { - return Promise.resolve({configuration: _.map(getValidKeys(), function (value, key) { - return { - key: key, - value: value - }; - })}); + function formatResponse(keys) { + return {configuration: _.map(keys, function (value, key) { + return { + key: key, + value: value + }; + })}; + } + + // Pipeline calls each task passing the result of one to be the arguments for the next + return pipeline([getValidKeys, formatResponse]); }, /** * ### Read - * + * Fetch a single configuration by key + * @param {{key}} options + * @returns {Promise} Configuration */ read: function read(options) { - var data = getValidKeys(); + var tasks, + attrs = ['key']; + + function fetchData(options) { + options.config = getValidKeys(); + return options; + } + + function validateOptions(options) { + if (_.has(options.config, options.data.key)) { + return options; + } else { + return Promise.reject(new errors.NotFoundError('Invalid key')); + } + } - if (_.has(data, options.key)) { - return Promise.resolve({configuration: [{ - key: options.key, - value: data[options.key] - }]}); - } else { - return Promise.reject(new errors.NotFoundError('Invalid key')); + function formatResponse(options) { + return {configuration: [{ + key: options.data.key, + value: options.config[options.data.key] + }]}; } + + + tasks = [ + utils.validate('configuration', {attrs: attrs}), + fetchData, + validateOptions, + formatResponse + ]; + + return pipeline(tasks, options); + } }; diff --git a/core/server/api/themes.js b/core/server/api/themes.js index d0dc59f5c011..7ef4c5c3a17e 100644 --- a/core/server/api/themes.js +++ b/core/server/api/themes.js @@ -6,6 +6,9 @@ var Promise = require('bluebird'), config = require('../config'), errors = require('../errors'), settings = require('./settings'), + utils = require('./utils'), + pipeline = require('../utils/pipeline'), + docName = 'themes', themes; /** @@ -21,41 +24,57 @@ themes = { * @returns {Promise(Themes)} */ browse: function browse(options) { - options = options || {}; + var tasks; - return canThis(options.context).browse.theme().then(function () { + function handlePermissions(options) { + return canThis(options.context).browse.theme().then(function () { + return Promise.resolve(); + }, function () { + return Promise.reject(new errors.NoPermissionError('You do not have permission to browse themes.')); + }); + } + + function fetchData() { return Promise.all([ settings.read({key: 'activeTheme', context: {internal: true}}), config.paths.availableThemes - ]).then(function (result) { - var activeTheme = result[0].settings[0].value, - availableThemes = result[1], - themes = [], - themeKeys = Object.keys(availableThemes); - - _.each(themeKeys, function (key) { - if (key.indexOf('.') !== 0 - && key !== '_messages' - && key !== 'README.md' - ) { - var item = { - uuid: key - }; - - if (availableThemes[key].hasOwnProperty('package.json')) { - item = _.merge(item, availableThemes[key]['package.json']); - } - - item.active = item.uuid === activeTheme; - - themes.push(item); + ]); + } + + // Push all of our tasks into a `tasks` array in the correct order + tasks = [ + utils.validate(docName), + handlePermissions, + fetchData + ]; + + // Pipeline calls each task passing the result of one to be the arguments for the next + return pipeline(tasks, options).then(function formatResponse(result) { + var activeTheme = result[0].settings[0].value, + availableThemes = result[1], + themes = [], + themeKeys = Object.keys(availableThemes); + + _.each(themeKeys, function (key) { + if (key.indexOf('.') !== 0 + && key !== '_messages' + && key !== 'README.md' + ) { + var item = { + uuid: key + }; + + if (availableThemes[key].hasOwnProperty('package.json')) { + item = _.merge(item, availableThemes[key]['package.json']); } - }); - return {themes: themes}; + item.active = item.uuid === activeTheme; + + themes.push(item); + } }); - }, function () { - return Promise.reject(new errors.NoPermissionError('You do not have permission to browse themes.')); + + return {themes: themes}; }); }, @@ -67,18 +86,21 @@ themes = { * @returns {Promise(Theme)} */ edit: function edit(object, options) { - var themeName; + var tasks, + attrs = ['uuid']; - // Check whether the request is properly formatted. - if (!_.isArray(object.themes)) { - return Promise.reject({type: 'BadRequest', message: 'Invalid request.'}); + function handlePermissions(options) { + return canThis(options.context).edit.theme().then(function () { + return options; + }, function () { + return Promise.reject(new errors.NoPermissionError('You do not have permission to edit themes.')); + }); } - themeName = object.themes[0].uuid; - - return canThis(options.context).edit.theme().then(function () { + function editTheme(options) { return themes.browse(options).then(function (availableThemes) { - var theme; + var theme, + themeName = object.themes[0].uuid; // Check if the theme exists theme = _.find(availableThemes.themes, function (currentTheme) { @@ -97,9 +119,17 @@ themes = { return {themes: [theme]}; }); }); - }, function () { - return Promise.reject(new errors.NoPermissionError('You do not have permission to edit themes.')); - }); + } + + // Push all of our tasks into a `tasks` array in the correct order + tasks = [ + utils.validate(docName, {attrs: attrs}), + handlePermissions, + editTheme + ]; + + // Pipeline calls each task passing the result of one to be the arguments for the next + return pipeline(tasks, options); } }; diff --git a/core/server/api/upload.js b/core/server/api/upload.js index acac1e2ebae9..c21b457173ce 100644 --- a/core/server/api/upload.js +++ b/core/server/api/upload.js @@ -1,9 +1,10 @@ -var config = require('../config'), - Promise = require('bluebird'), - fs = require('fs-extra'), - storage = require('../storage'), - errors = require('../errors'), - utils = require('./utils'), +var config = require('../config'), + Promise = require('bluebird'), + fs = require('fs-extra'), + storage = require('../storage'), + errors = require('../errors'), + utils = require('./utils'), + pipeline = require('../utils/pipeline'), upload; @@ -22,27 +23,42 @@ upload = { * @returns {Promise} Success */ add: function (options) { - var store = storage.getStorage(), - filepath; + var tasks, + attrs = ['uploadimage']; - // Check if a file was provided - if (!utils.checkFileExists(options, 'uploadimage')) { - return Promise.reject(new errors.NoPermissionError('Please select an image.')); + function validate(options) { + // Check if a file was provided + if (!utils.checkFileExists(options.data, 'uploadimage')) { + return Promise.reject(new errors.NoPermissionError('Please select an image.')); + } + + // Check if the file is valid + if (!utils.checkFileIsValid(options.data.uploadimage, config.uploads.contentTypes, config.uploads.extensions)) { + return Promise.reject(new errors.UnsupportedMediaTypeError('Please select a valid image.')); + } + + return options; } - // Check if the file is valid - if (!utils.checkFileIsValid(options.uploadimage, config.uploads.contentTypes, config.uploads.extensions)) { - return Promise.reject(new errors.UnsupportedMediaTypeError('Please select a valid image.')); + function storeUpload(options) { + var store = storage.getStorage(), + filepath = options.data.uploadimage.path; + + return store.save(options.data.uploadimage).then(function (url) { + return url; + }).finally(function () { + // Remove uploaded file from tmp location + return Promise.promisify(fs.unlink)(filepath); + }); } - filepath = options.uploadimage.path; + tasks = [ + utils.validate('upload', {attrs: attrs}), + validate, + storeUpload + ]; - return store.save(options.uploadimage).then(function (url) { - return url; - }).finally(function () { - // Remove uploaded file from tmp location - return Promise.promisify(fs.unlink)(filepath); - }); + return pipeline(tasks, options); } }; diff --git a/core/test/integration/api/api_configuration_spec.js b/core/test/integration/api/api_configuration_spec.js index a6b3dc7f965a..86420f64f78c 100644 --- a/core/test/integration/api/api_configuration_spec.js +++ b/core/test/integration/api/api_configuration_spec.js @@ -44,7 +44,7 @@ describe('Configuration API', function () { done(); }).catch(function (error) { console.log(JSON.stringify(error)); - done(); + done(error); }).catch(done); });