diff --git a/packages/strapi/lib/configuration/hooks/core/router/index.js b/packages/strapi/lib/configuration/hooks/core/router/index.js index 048e0196ff..2d33506612 100644 --- a/packages/strapi/lib/configuration/hooks/core/router/index.js +++ b/packages/strapi/lib/configuration/hooks/core/router/index.js @@ -72,7 +72,7 @@ module.exports = strapi => { strapi.router.route(_.omitBy({ method: value.method, path: value.path, - handler: _.union(policies, [action]), + handler: _.remove([strapi.middlewares.compose(policies), action], o => _.isFunction(o)), validate }, _.isEmpty)); } catch (err) { @@ -80,6 +80,43 @@ module.exports = strapi => { } }); + // Create router for admin. + // Prefix router with the admin's name. + const routerAdmin = strapi.middlewares.joiRouter(); + + _.forEach(strapi.admin.config.routes, value => { + if (_.isEmpty(_.get(value, 'method')) || _.isEmpty(_.get(value, 'path'))) { + return; + } + + const endpoint = `${value.method} ${value.path}`; + + try { + const {route, policies, action, validate} = routerChecker(value, endpoint); + + if (_.isUndefined(action) || !_.isFunction(action)) { + return strapi.log.warn('Ignored attempt to bind route `' + endpoint + '` to unknown controller/action.'); + } + + routerAdmin.route(_.omitBy({ + method: value.method, + path: value.path, + handler: _.remove([strapi.middlewares.compose(policies), action], o => _.isFunction(o)), + validate + }, _.isEmpty)); + } catch (err) { + cb(err); + } + }); + + routerAdmin.prefix(strapi.config.admin); + + // TODO: + // - Mount on main router `strapi.router.use(routerAdmin.middleware());` + + // Mount admin router on Strapi router + strapi.app.use(routerAdmin.middleware()); + // Parse each plugin's routes. _.forEach(strapi.config.plugins.routes, (value, plugin) => { // Create router for each plugin. @@ -145,8 +182,11 @@ module.exports = strapi => { }); } - // Mount plugin router on Strapi router - strapi.router.use(router.middleware()); + // TODO: + // - Mount on main router `strapi.router.use(router.middleware());` + + // Mount plugin router + strapi.app.use(router.middleware()); }); // Wrap error into Boom object @@ -165,6 +205,8 @@ module.exports = strapi => { } }); + console.log(strapi.router.routes); + // Let the router use our routes and allowed methods. strapi.app.use(strapi.router.middleware()); strapi.app.use(strapi.router.router.allowedMethods({ @@ -172,6 +214,7 @@ module.exports = strapi => { notImplemented: () => Boom.notImplemented(), methodNotAllowed: () => Boom.methodNotAllowed() })); + } cb(); @@ -194,10 +237,18 @@ module.exports = strapi => { function routerChecker(value, endpoint, plugin) { const route = regex.detectRoute(endpoint); + let pluginControllers; // Define controller and action names. const handler = _.trim(value.handler).split('.'); - const controller = strapi.controllers[handler[0].toLowerCase()] || strapi.plugins[plugin].controllers[handler[0].toLowerCase()]; + + try { + pluginControllers = strapi.plugins[plugin].controllers[handler[0].toLowerCase()]; + } catch (err) { + pluginControllers = undefined; + } + + const controller = strapi.controllers[handler[0].toLowerCase()] || pluginControllers || strapi.admin.controllers[handler[0].toLowerCase()]; const action = controller[handler[1]]; // Retrieve the API's name where the controller is located diff --git a/packages/strapi/lib/configuration/hooks/defaultHooks.js b/packages/strapi/lib/configuration/hooks/defaultHooks.js index a8c9ce89eb..48a977ab09 100644 --- a/packages/strapi/lib/configuration/hooks/defaultHooks.js +++ b/packages/strapi/lib/configuration/hooks/defaultHooks.js @@ -8,6 +8,7 @@ module.exports = { dictionary: { _config: true, _api: true, + _admin: true, _plugins: true, _externalHooks: true }, diff --git a/packages/strapi/lib/configuration/hooks/dictionary/_admin/index.js b/packages/strapi/lib/configuration/hooks/dictionary/_admin/index.js new file mode 100644 index 0000000000..3a7e83eee9 --- /dev/null +++ b/packages/strapi/lib/configuration/hooks/dictionary/_admin/index.js @@ -0,0 +1,145 @@ +'use strict'; + +/** + * Module dependencies + */ + +// Node.js core. +const path = require('path'); + +// Public node modules. +const _ = require('lodash'); +const async = require('async'); + +// Strapi utilities. +const dictionary = require('strapi-utils').dictionary; + +/** + * Async module loader to create a + * dictionary of the user plugins. + */ + +module.exports = strapi => { + return { + + /** + * Initialize the hook + */ + + initialize: cb => { + async.auto({ + // Expose the `name` of the plugin for the callback. + 'name': cb => { + cb(null, 'admin'); + }, + + // Load API controllers from `./admin/controllers/*.js`. + 'controllers/*': cb => { + dictionary.optional({ + dirname: path.resolve(strapi.config.appPath, strapi.config.paths.admin, strapi.config.paths.controllers), + filter: /(.+)\.(js)$/, + depth: 1 + }, cb); + }, + + // Load API models from `./plugins/models/*.js` and `./plugins/models/*.settings.json`. + 'models/*': cb => { + async.parallel({ + settings: cb => { + dictionary.optional({ + dirname: path.resolve(strapi.config.appPath, strapi.config.paths.admin, strapi.config.paths.models), + filter: /(.+)\.settings.json$/, + depth: 1 + }, cb); + }, + functions: cb => { + dictionary.optional({ + dirname: path.resolve(strapi.config.appPath, strapi.config.paths.admin, strapi.config.paths.models), + filter: /(.+)\.js$/, + depth: 1 + }, cb); + } + }, (err, models) => { + if (err) { + return cb(err); + } + + return cb(null, _.merge(models.settings, models.functions)); + }); + }, + + // Load API services from `./plugins/services/*.js`. + 'services/*': cb => { + dictionary.optional({ + dirname: path.resolve(strapi.config.appPath, strapi.config.paths.admin, strapi.config.paths.services), + filter: /(.+)\.(js)$/, + depth: 1 + }, cb); + }, + + // Load API policies from `./plugins/policies/*.js`. + 'policies/*': cb => { + dictionary.aggregate({ + dirname: path.resolve(strapi.config.appPath, strapi.config.paths.admin, strapi.config.paths.policies), + filter: /(.+)\.(js)$/, + depth: 1 + }, cb); + }, + + // Load API config from `./admin/config/*.js|json` and `./admin/config/environments/**/*.js|json`. + 'config/**': cb => { + async.parallel({ + common: cb => { + dictionary.aggregate({ + dirname: path.resolve(strapi.config.appPath, strapi.config.paths.admin, strapi.config.paths.config), + filter: /(.+)\.(js|json)$/, + depth: 2 + }, cb); + }, + specific: cb => { + dictionary.aggregate({ + dirname: path.resolve(strapi.config.appPath, strapi.config.paths.admin, strapi.config.paths.config, 'environments', strapi.config.environment), + filter: /(.+)\.(js|json)$/, + depth: 2 + }, cb); + } + }, (err, config) => { + if (err) { + return cb(err); + } + + return cb(null, _.merge(config.common, config.specific)); + }); + } + }, + + // Callback. + (err, admin) => { + + // Just in case there is an error. + if (err) { + return cb(err); + } + + // Expose the API dictionary. + strapi.admin = { + controllers: admin['controllers/*'], + models: admin['models/*'], + services: admin['services/*'], + policies: admin['policies/*'], + config: admin['config/**'] + }; + + console.log(strapi.admin); + + // If the module doesn't have a definition at all + // just remove it completely from the dictionary. + if (_.isEmpty(strapi.admin)) { + delete strapi.admin; + } + + cb(); + }); + } + }; +}; diff --git a/packages/strapi/lib/configuration/hooks/dictionary/_config/index.js b/packages/strapi/lib/configuration/hooks/dictionary/_config/index.js index f9f8f71f7d..94f950b356 100644 --- a/packages/strapi/lib/configuration/hooks/dictionary/_config/index.js +++ b/packages/strapi/lib/configuration/hooks/dictionary/_config/index.js @@ -97,6 +97,16 @@ module.exports = strapi => { }, cb); }, + // // Load admin from `./admin/**/*.js|json`. + // 'admin/**': cb => { + // dictionary.optional({ + // dirname: path.resolve(strapi.config.appPath, strapi.config.paths.admin), + // excludeDirs: /(public)$/, + // filter: /(.+)\.(js|json)$/, + // depth: 3 + // }, cb); + // }, + // Load plugins from `./plugins/**/*.js|json`. 'plugins/**': cb => { dictionary.optional({ @@ -113,7 +123,7 @@ module.exports = strapi => { // Just in case there is an error. if (err) { - return cb(err); + // return cb(err); } // Template literal string diff --git a/packages/strapi/lib/configuration/index.js b/packages/strapi/lib/configuration/index.js index e6d8eb5ad5..dda3d6b1b0 100644 --- a/packages/strapi/lib/configuration/index.js +++ b/packages/strapi/lib/configuration/index.js @@ -64,7 +64,8 @@ module.exports = class Configuration { policies: 'policies', models: 'models', plugins: 'plugins', - validators: 'validators' + validators: 'validators', + admin: 'admin' }, // Start off needed empty objects and strings.