diff --git a/examples/getstarted/config/middleware.js b/examples/getstarted/config/middleware.js deleted file mode 100644 index 5c0b5b46af..0000000000 --- a/examples/getstarted/config/middleware.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -const responseHandlers = require('./src/response-handlers'); - -module.exports = { - settings: { - cors: { - headers: ['Content-Type', 'Authorization', 'Origin', 'Accept', 'Cache-Control'], - }, - responses: { - enabled: true, - handlers: responseHandlers, - }, - }, -}; diff --git a/examples/getstarted/config/middlewares.js b/examples/getstarted/config/middlewares.js new file mode 100644 index 0000000000..1fd1a394fa --- /dev/null +++ b/examples/getstarted/config/middlewares.js @@ -0,0 +1,20 @@ +'use strict'; + +const responseHandlers = require('./src/response-handlers'); + +module.exports = [ + 'strapi::errors', + 'strapi::security', + 'strapi::cors', + 'strapi::poweredBy', + 'strapi::logger', + 'strapi::request', + { + name: 'strapi::responses', + config: { + handlers: responseHandlers, + }, + }, + 'strapi::favicon', + 'strapi::public', +]; diff --git a/examples/getstarted/src/api/address/middlewares/address.js b/examples/getstarted/src/api/address/middlewares/address.js new file mode 100644 index 0000000000..b4d8d4c534 --- /dev/null +++ b/examples/getstarted/src/api/address/middlewares/address.js @@ -0,0 +1,3 @@ +module.exports = options => { + return (ctx, next) => next(); +}; diff --git a/examples/getstarted/src/api/restaurant/content-types/restaurant/schema.json b/examples/getstarted/src/api/restaurant/content-types/restaurant/schema.json index 5658d6b517..47cec65548 100755 --- a/examples/getstarted/src/api/restaurant/content-types/restaurant/schema.json +++ b/examples/getstarted/src/api/restaurant/content-types/restaurant/schema.json @@ -10,6 +10,7 @@ }, "options": { "draftAndPublish": true, + "populateCreatorFields": true, "comment": "" }, "pluginOptions": { diff --git a/examples/getstarted/src/middlewares/test-middleware.js b/examples/getstarted/src/middlewares/test-middleware.js new file mode 100644 index 0000000000..48623eb33b --- /dev/null +++ b/examples/getstarted/src/middlewares/test-middleware.js @@ -0,0 +1,3 @@ +module.exports = () => { + return (ctx, next) => next(); +}; diff --git a/examples/getstarted/src/middlewares/testM/defaults.json b/examples/getstarted/src/middlewares/testM/defaults.json deleted file mode 100644 index 945ee456ff..0000000000 --- a/examples/getstarted/src/middlewares/testM/defaults.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "testM": { - "enabled": true - } -} diff --git a/examples/getstarted/src/middlewares/testM/index.js b/examples/getstarted/src/middlewares/testM/index.js deleted file mode 100644 index 62866d9df4..0000000000 --- a/examples/getstarted/src/middlewares/testM/index.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = () => { - return { - initialize() {}, - }; -}; diff --git a/examples/getstarted/src/policies/test-policy.js b/examples/getstarted/src/policies/test-policy.js index b26426b6d9..3061fe18cd 100644 --- a/examples/getstarted/src/policies/test-policy.js +++ b/examples/getstarted/src/policies/test-policy.js @@ -1,3 +1,3 @@ -module.exports = (ctx, next) => { - return next(); +module.exports = ctx => { + return true; }; diff --git a/packages/core/admin/server/controllers/__tests__/user.test.js b/packages/core/admin/server/controllers/__tests__/user.test.js index c6b30d3acc..b0c8740db4 100644 --- a/packages/core/admin/server/controllers/__tests__/user.test.js +++ b/packages/core/admin/server/controllers/__tests__/user.test.js @@ -87,7 +87,7 @@ describe('User Controller', () => { await userController.findOne(ctx); - expect(findOne).toHaveBeenCalledWith({ id: user.id }); + expect(findOne).toHaveBeenCalledWith(user.id); expect(sanitizeUser).toHaveBeenCalledWith(user); expect(ctx.body).toStrictEqual({ data: user }); }); @@ -108,7 +108,7 @@ describe('User Controller', () => { await userController.findOne(ctx); - expect(findOne).toHaveBeenCalledWith({ id: fakeId }); + expect(findOne).toHaveBeenCalledWith(fakeId); expect(notFound).toHaveBeenCalledWith('User does not exist'); }); }); diff --git a/packages/core/admin/server/controllers/user.js b/packages/core/admin/server/controllers/user.js index 0a7639bbdc..11c8880beb 100644 --- a/packages/core/admin/server/controllers/user.js +++ b/packages/core/admin/server/controllers/user.js @@ -59,7 +59,7 @@ module.exports = { async findOne(ctx) { const { id } = ctx.params; - const user = await getService('user').findOne({ id }); + const user = await getService('user').findOne(id); if (!user) { return ctx.notFound('User does not exist'); diff --git a/packages/core/admin/server/services/__tests__/user.test.js b/packages/core/admin/server/services/__tests__/user.test.js index cde4b01486..b5dc5a22c6 100644 --- a/packages/core/admin/server/services/__tests__/user.test.js +++ b/packages/core/admin/server/services/__tests__/user.test.js @@ -383,16 +383,18 @@ describe('User', () => { const defaults = { page: 1, pageSize: 100 }; beforeEach(() => { - const fetchPage = jest.fn(({ page = defaults.page, pageSize = defaults.pageSize } = {}) => { - return { - results: Array.from({ length: pageSize }).map((_, i) => i + (page - 1) * pageSize), - pagination: { page, pageSize, total: page * pageSize, pageCount: page }, - }; - }); + const findPage = jest.fn( + (uid, { page = defaults.page, pageSize = defaults.pageSize } = {}) => { + return { + results: Array.from({ length: pageSize }).map((_, i) => i + (page - 1) * pageSize), + pagination: { page, pageSize, total: page * pageSize, pageCount: page }, + }; + } + ); global.strapi = { - query() { - return { findPage: fetchPage }; + entityService: { + findPage, }, }; }); @@ -428,7 +430,7 @@ describe('User', () => { const user = { firstname: 'Kai', lastname: 'Doe', email: 'kaidoe@email.com' }; beforeEach(() => { - const findOne = jest.fn(({ where: { id } }) => + const findOne = jest.fn((uid, id) => Promise.resolve( { 1: user, @@ -437,23 +439,23 @@ describe('User', () => { ); global.strapi = { - query() { - return { findOne }; + entityService: { + findOne, }, }; }); test('Finds and returns a user by its ID', async () => { - const input = { id: 1 }; - const res = await userService.findOne(input); + const id = 1; + const res = await userService.findOne(id); expect(res).not.toBeNull(); expect(res).toMatchObject(user); }); test('Fails to find a user with provided params', async () => { - const input = { id: 27 }; - const res = await userService.findOne(input); + const id = 27; + const res = await userService.findOne(id); expect(res).toBeNull(); }); diff --git a/packages/core/admin/server/services/passport/local-strategy.js b/packages/core/admin/server/services/passport/local-strategy.js index 551493c512..58ad381800 100644 --- a/packages/core/admin/server/services/passport/local-strategy.js +++ b/packages/core/admin/server/services/passport/local-strategy.js @@ -1,5 +1,6 @@ 'use strict'; +const { toLower } = require('lodash/fp'); const { Strategy: LocalStrategy } = require('passport-local'); const createLocalStrategy = strapi => { @@ -11,7 +12,7 @@ const createLocalStrategy = strapi => { }, (email, password, done) => { return strapi.admin.services.auth - .checkCredentials({ email, password }) + .checkCredentials({ email: toLower(email), password }) .then(([error, user, message]) => done(error, user, message)) .catch(error => done(error)); } diff --git a/packages/core/admin/server/services/user.js b/packages/core/admin/server/services/user.js index d467fe73a6..9f38402c7d 100644 --- a/packages/core/admin/server/services/user.js +++ b/packages/core/admin/server/services/user.js @@ -1,6 +1,7 @@ 'use strict'; const _ = require('lodash'); +const { defaults } = require('lodash/fp'); const { stringIncludes } = require('@strapi/utils'); const { createUser, hasSuperAdminRole } = require('../domain/user'); const { password: passwordValidator } = require('../validation/common-validators'); @@ -103,7 +104,7 @@ const updateById = async (id, attributes) => { * @param {string} password - new password */ const resetPasswordByEmail = async (email, password) => { - const user = await findOne({ email }); + const user = await strapi.query('admin::user').findOne({ where: { email }, populate: ['roles'] }); if (!user) { throw new Error(`User not found for email: ${email}`); @@ -125,7 +126,7 @@ const resetPasswordByEmail = async (email, password) => { * @param {int|string} userId user's id to look for */ const isLastSuperAdminUser = async userId => { - const user = await findOne({ id: userId }, ['roles']); + const user = await findOne(userId); const superAdminRole = await getService('role').getSuperAdminWithUsersCount(); return superAdminRole.usersCount === 1 && hasSuperAdminRole(user); @@ -180,8 +181,8 @@ const register = async ({ registrationToken, userInfo }) => { /** * Find one user */ -const findOne = async (where = {}, populate = ['roles']) => { - return strapi.query('admin::user').findOne({ where, populate }); +const findOne = async (id, populate = ['roles']) => { + return strapi.entityService.findOne('admin::user', id, { populate }); }; /** Find many users (paginated) @@ -189,15 +190,8 @@ const findOne = async (where = {}, populate = ['roles']) => { * @returns {Promise} */ const findPage = async (query = {}) => { - const { page = 1, pageSize = 100, populate = ['roles'] } = query; - - return strapi.query('admin::user').findPage({ - where: query.filters, - _q: query._q, - populate, - page, - pageSize, - }); + const enrichedQuery = defaults({ populate: ['roles'] }, query); + return strapi.entityService.findPage('admin::user', enrichedQuery); }; /** Delete a user diff --git a/packages/core/strapi/lib/Strapi.js b/packages/core/strapi/lib/Strapi.js index 25e40c8245..819c0546e6 100644 --- a/packages/core/strapi/lib/Strapi.js +++ b/packages/core/strapi/lib/Strapi.js @@ -9,7 +9,6 @@ const loadConfiguration = require('./core/app-configuration'); const { createContainer } = require('./container'); const utils = require('./utils'); -const initializeMiddlewares = require('./middlewares'); const createStrapiFs = require('./services/fs'); const createEventHub = require('./services/event-hub'); const { createServer } = require('./services/server'); @@ -276,7 +275,7 @@ class Strapi { } async loadMiddlewares() { - this.middleware = await loaders.loadMiddlewares(this); + await loaders.loadMiddlewares(this); } async loadApp() { @@ -373,9 +372,7 @@ class Strapi { await this.startWebhooks(); - // Initialize middlewares. - await initializeMiddlewares(this); - + await this.server.initMiddlewares(); await this.server.initRouting(); await this.runLifecyclesFunctions(LIFECYCLES.BOOTSTRAP); diff --git a/packages/core/strapi/lib/core/bootstrap.js b/packages/core/strapi/lib/core/bootstrap.js index 91629d878e..e281615c88 100644 --- a/packages/core/strapi/lib/core/bootstrap.js +++ b/packages/core/strapi/lib/core/bootstrap.js @@ -1,43 +1,8 @@ 'use strict'; -const _ = require('lodash'); const { getConfigUrls } = require('@strapi/utils'); module.exports = function(strapi) { - // TODO: delete v3 code - _.forEach(strapi.api, api => { - _.forEach(api.middlewares, (middleware, middlewareName) => { - strapi.middleware[middlewareName] = middleware; - }); - }); - - _.forEach(strapi.admin.middlewares, (middleware, middlewareName) => { - strapi.middleware[middlewareName] = middleware; - }); - - _.forEach(strapi.plugins, plugin => { - _.forEach(plugin.middlewares, (middleware, middlewareName) => { - strapi.middleware[middlewareName] = middleware; - }); - }); - - // Preset config in alphabetical order. - strapi.config.middleware.settings = Object.keys(strapi.middleware).reduce((acc, current) => { - // Try to find the settings in the current environment, then in the main configurations. - const currentSettings = _.merge( - _.cloneDeep(_.get(strapi.middleware[current], ['defaults', current], {})), - strapi.config.get(['middleware', 'settings', current], {}) - ); - - acc[current] = !_.isObject(currentSettings) ? {} : currentSettings; - - // Ensure that enabled key exist by forcing to false. - _.defaults(acc[current], { enabled: false }); - - return acc; - }, {}); - - // default settings strapi.config.port = strapi.config.get('server.port') || strapi.config.port; strapi.config.host = strapi.config.get('server.host') || strapi.config.host; diff --git a/packages/core/strapi/lib/core/domain/content-type/index.js b/packages/core/strapi/lib/core/domain/content-type/index.js index 7b098f3bb8..7204069243 100644 --- a/packages/core/strapi/lib/core/domain/content-type/index.js +++ b/packages/core/strapi/lib/core/domain/content-type/index.js @@ -108,11 +108,10 @@ const createContentType = (uid, definition) => { private: isPrivate, }; - return { - ...schema, + return Object.assign(schema, { actions, lifecycles, - }; + }); }; const getGlobalId = (model, modelName, prefix) => { diff --git a/packages/core/strapi/lib/core/loaders/middlewares.js b/packages/core/strapi/lib/core/loaders/middlewares.js index edf25859e7..d688eddc9c 100644 --- a/packages/core/strapi/lib/core/loaders/middlewares.js +++ b/packages/core/strapi/lib/core/loaders/middlewares.js @@ -1,86 +1,36 @@ 'use strict'; -// Dependencies. -const path = require('path'); -const _ = require('lodash'); -const glob = require('../../load/glob'); +const { join, extname, basename } = require('path'); +const fse = require('fs-extra'); -/** - * Load middlewares - */ -module.exports = async function(strapi) { - // const installedMiddlewares = strapi.config.get('installedMiddlewares'); - const appPath = strapi.config.get('appPath'); +// TODO:: allow folders with index.js inside for bigger policies +module.exports = async function loadMiddlewares(strapi) { + const localMiddlewares = await loadLocalMiddlewares(strapi); + const internalMiddlewares = require('../../middlewares'); - let middlewares = {}; + strapi.container.get('middlewares').add(`global::`, localMiddlewares); + strapi.container.get('middlewares').add(`strapi::`, internalMiddlewares); +}; - // const loaders = createLoaders(strapi); +const loadLocalMiddlewares = async strapi => { + const dir = strapi.dirs.middlewares; - // await loaders.loadMiddlewareDependencies(installedMiddlewares, middlewares); - // internal middlewares - // await loaders.loadInternalMiddlewares(middlewares); - // local middleware - // await loaders.loadLocalMiddlewares(appPath, middlewares); + if (!(await fse.pathExists(dir))) { + return {}; + } + + const middlewares = {}; + const paths = await fse.readdir(dir, { withFileTypes: true }); + + for (const fd of paths) { + const { name } = fd; + const fullPath = join(dir, name); + + if (fd.isFile() && extname(name) === '.js') { + const key = basename(name, '.js'); + middlewares[key] = require(fullPath); + } + } return middlewares; }; - -/** - * Build loader functions - * @param {*} strapi - strapi instance - */ -const createLoaders = strapi => { - const loadMiddlewaresInDir = async (dir, middlewares) => { - const files = await glob('*/*(index|defaults).*(js|json)', { - cwd: dir, - }); - - files.forEach(f => { - const name = f.split('/')[0]; - mountMiddleware(name, [path.resolve(dir, f)], middlewares); - }); - }; - - const loadInternalMiddlewares = middlewares => - loadMiddlewaresInDir(path.resolve(__dirname, '..', '..', 'middlewares'), middlewares); - - const loadLocalMiddlewares = (appPath, middlewares) => - loadMiddlewaresInDir(path.resolve(appPath, 'src', 'middlewares'), middlewares); - - const loadMiddlewareDependencies = async (packages, middlewares) => { - for (let packageName of packages) { - const baseDir = path.dirname(require.resolve(`@strapi/middleware-${packageName}`)); - const files = await glob('*(index|defaults).*(js|json)', { - cwd: baseDir, - absolute: true, - }); - - mountMiddleware(packageName, files, middlewares); - } - }; - - const mountMiddleware = (name, files, middlewares) => { - files.forEach(file => { - middlewares[name] = middlewares[name] || { loaded: false }; - - if (_.endsWith(file, 'index.js') && !middlewares[name].load) { - return Object.defineProperty(middlewares[name], 'load', { - configurable: false, - enumerable: true, - get: () => require(file)(strapi), - }); - } - - if (_.endsWith(file, 'defaults.json')) { - middlewares[name].defaults = require(file); - return; - } - }); - }; - - return { - loadInternalMiddlewares, - loadLocalMiddlewares, - loadMiddlewareDependencies, - }; -}; diff --git a/packages/core/strapi/lib/middlewares/index.js b/packages/core/strapi/lib/middlewares/index.js index c1541e6b3c..1c2439c432 100644 --- a/packages/core/strapi/lib/middlewares/index.js +++ b/packages/core/strapi/lib/middlewares/index.js @@ -7,14 +7,14 @@ const favicon = require('./favicon'); const ip = require('./ip'); const logger = require('./logger'); const poweredBy = require('./powered-by'); -const requestParser = require('./request-parser'); +const request = require('./request'); const responseTime = require('./response-time'); -const responseHandlers = require('./response-handlers'); +const responses = require('./responses'); const security = require('./security'); // session: require('./session'), const publicStatic = require('./public'); -const INTERNAL_MIDDLEWARES = [ +module.exports = { errors, ip, security, @@ -23,19 +23,10 @@ const INTERNAL_MIDDLEWARES = [ poweredBy, logger, compression, - responseHandlers, - requestParser, + responses, + request, favicon, - publicStatic, -]; - -module.exports = async strapi => { - for (const middlewareFactory of INTERNAL_MIDDLEWARES) { - // const config = strapi.config.get(`middlwares`); - const middleware = middlewareFactory({}); - - strapi.server.use(middleware); - } + public: publicStatic, }; // const requiredMiddlewares = [ diff --git a/packages/core/strapi/lib/middlewares/public/defaults.json b/packages/core/strapi/lib/middlewares/public/defaults.json deleted file mode 100644 index 5ae4808ba0..0000000000 --- a/packages/core/strapi/lib/middlewares/public/defaults.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "public": { - "enabled": true, - "maxAge": 60000, - "path": "./public", - "defaultIndex": true - } -} diff --git a/packages/core/strapi/lib/middlewares/public/index.js b/packages/core/strapi/lib/middlewares/public/index.js index 013fc5d6f7..2dca471e0f 100644 --- a/packages/core/strapi/lib/middlewares/public/index.js +++ b/packages/core/strapi/lib/middlewares/public/index.js @@ -1,136 +1,124 @@ 'use strict'; -/** - * Module dependencies - */ - -// Node.js core. const fs = require('fs'); const path = require('path'); const stream = require('stream'); const _ = require('lodash'); +const { defaultsDeep } = require('lodash/fp'); const koaStatic = require('koa-static'); const utils = require('../../utils'); const serveStatic = require('./serve-static'); -/** - * Public assets hook - */ +const defaults = { + maxAge: 60000, + path: './public', + defaultIndex: true, +}; -module.exports = strapi => { +// TODO: inject strap +module.exports = options => { + const { defaultIndex, maxAge, path: publicPath } = defaultsDeep(defaults, options); + const staticDir = path.resolve(strapi.dirs.root, publicPath || strapi.config.paths.static); - return async (ctx, next) => { - return next(); + if (defaultIndex === true) { + const index = fs.readFileSync(path.join(__dirname, 'index.html'), 'utf8'); + + const serveIndexPage = async (ctx, next) => { + // defer rendering of strapi index page + await next(); + + if (ctx.body != null || ctx.status !== 404) return; + + ctx.url = 'index.html'; + const isInitialized = await utils.isInitialized(strapi); + const data = { + serverTime: new Date().toUTCString(), + isInitialized, + ..._.pick(strapi, [ + 'config.info.version', + 'config.info.name', + 'config.admin.url', + 'config.server.url', + 'config.environment', + 'config.serveAdminPanel', + ]), + }; + const content = _.template(index)(data); + const body = stream.Readable({ + read() { + this.push(Buffer.from(content)); + this.push(null); + }, + }); + // Serve static. + ctx.type = 'html'; + ctx.body = body; + }; + + strapi.server.routes([ + { + method: 'GET', + path: '/', + handler: serveIndexPage, + config: { auth: false }, + }, + { + method: 'GET', + path: '/index.html', + handler: serveIndexPage, + config: { auth: false }, + }, + { + method: 'GET', + path: '/assets/images/(.*)', + handler: serveStatic(path.resolve(__dirname, 'assets/images'), { + maxage: maxAge, + defer: true, + }), + config: { auth: false }, + }, + { + method: 'GET', + path: '/(.*)', + handler: koaStatic(staticDir, { + maxage: maxAge, + defer: true, + }), + config: { auth: false }, + }, + ]); } - return { - /** - * Initialize the hook - */ + if (!strapi.config.serveAdminPanel) return async (ctx, next) => next(); - async initialize() { - const { defaultIndex, maxAge, path: publicPath } = strapi.config.middleware.settings.public; - const staticDir = path.resolve(strapi.dirs.root, publicPath || strapi.config.paths.static); + const buildDir = path.resolve(strapi.dirs.root, 'build'); + const serveAdmin = async (ctx, next) => { + await next(); - if (defaultIndex === true) { - const index = fs.readFileSync(path.join(__dirname, 'index.html'), 'utf8'); + if (ctx.method !== 'HEAD' && ctx.method !== 'GET') { + return; + } - const serveIndexPage = async (ctx, next) => { - // defer rendering of strapi index page - await next(); + if (ctx.body != null || ctx.status !== 404) { + return; + } - if (ctx.body != null || ctx.status !== 404) return; - - ctx.url = 'index.html'; - const isInitialized = await utils.isInitialized(strapi); - const data = { - serverTime: new Date().toUTCString(), - isInitialized, - ..._.pick(strapi, [ - 'config.info.version', - 'config.info.name', - 'config.admin.url', - 'config.server.url', - 'config.environment', - 'config.serveAdminPanel', - ]), - }; - const content = _.template(index)(data); - const body = stream.Readable({ - read() { - this.push(Buffer.from(content)); - this.push(null); - }, - }); - // Serve static. - ctx.type = 'html'; - ctx.body = body; - }; - - strapi.server.routes([ - { - method: 'GET', - path: '/', - handler: serveIndexPage, - config: { auth: false }, - }, - { - method: 'GET', - path: '/index.html', - handler: serveIndexPage, - config: { auth: false }, - }, - { - method: 'GET', - path: '/assets/images/(.*)', - handler: serveStatic(path.resolve(__dirname, 'assets/images'), { - maxage: maxAge, - defer: true, - }), - config: { auth: false }, - }, - { - method: 'GET', - path: '/(.*)', - handler: koaStatic(staticDir, { - maxage: maxAge, - defer: true, - }), - config: { auth: false }, - }, - ]); - } - - if (!strapi.config.serveAdminPanel) return; - - const buildDir = path.resolve(strapi.dirs.root, 'build'); - const serveAdmin = async (ctx, next) => { - await next(); - - if (ctx.method !== 'HEAD' && ctx.method !== 'GET') { - return; - } - - if (ctx.body != null || ctx.status !== 404) { - return; - } - - ctx.type = 'html'; - ctx.body = fs.createReadStream(path.join(buildDir + '/index.html')); - }; - - strapi.server.routes([ - { - method: 'GET', - path: `${strapi.config.admin.path}/:path*`, - handler: [ - serveAdmin, - serveStatic(buildDir, { maxage: maxAge, defer: false, index: 'index.html' }), - ], - config: { auth: false }, - }, - ]); - }, + ctx.type = 'html'; + ctx.body = fs.createReadStream(path.join(buildDir + '/index.html')); }; + + strapi.server.routes([ + { + method: 'GET', + path: `${strapi.config.admin.path}/:path*`, + handler: [ + serveAdmin, + serveStatic(buildDir, { maxage: maxAge, defer: false, index: 'index.html' }), + ], + config: { auth: false }, + }, + ]); + + return async (ctx, next) => next(); }; diff --git a/packages/core/strapi/lib/middlewares/request-parser.js b/packages/core/strapi/lib/middlewares/request.js similarity index 100% rename from packages/core/strapi/lib/middlewares/request-parser.js rename to packages/core/strapi/lib/middlewares/request.js diff --git a/packages/core/strapi/lib/middlewares/response-handlers.js b/packages/core/strapi/lib/middlewares/responses.js similarity index 100% rename from packages/core/strapi/lib/middlewares/response-handlers.js rename to packages/core/strapi/lib/middlewares/responses.js diff --git a/packages/core/strapi/lib/services/server/index.js b/packages/core/strapi/lib/services/server/index.js index 62db30ec9f..0d9f0fbcbd 100644 --- a/packages/core/strapi/lib/services/server/index.js +++ b/packages/core/strapi/lib/services/server/index.js @@ -8,6 +8,7 @@ const { createRouteManager } = require('./routing'); const { createAdminAPI } = require('./admin-api'); const { createContentAPI } = require('./content-api'); const registerAllRoutes = require('./register-routes'); +const registerMiddlewares = require('./register-middlewares'); const healthCheck = async ctx => { ctx.set('strapi', 'You are so French!'); @@ -92,6 +93,12 @@ const createServer = strapi => { initRouting() { registerAllRoutes(strapi); + return this; + }, + + initMiddlewares() { + registerMiddlewares(strapi); + return this; }, listen(...args) { diff --git a/packages/core/strapi/lib/services/server/middleware.js b/packages/core/strapi/lib/services/server/middleware.js index aaad682551..77a3a7e2d7 100644 --- a/packages/core/strapi/lib/services/server/middleware.js +++ b/packages/core/strapi/lib/services/server/middleware.js @@ -7,20 +7,7 @@ const getMiddlewareConfig = propOr([], 'config.middlewares'); const resolveMiddlewares = route => { const middlewaresConfig = getMiddlewareConfig(route); - return middlewaresConfig.map(middlewareConfig => { - if (typeof middlewareConfig === 'function') { - return middlewareConfig; - } - - // TODO: this won't work until we have the new middleware formats - const middleware = strapi.middleware(middlewareConfig); - - if (!middleware) { - throw new Error(`Middleware ${middlewareConfig} not found.`); - } - - return middleware; - }); + return middlewaresConfig.map(middlewareConfig => middlewareConfig); }; module.exports = { diff --git a/packages/core/strapi/lib/services/server/register-middlewares.js b/packages/core/strapi/lib/services/server/register-middlewares.js new file mode 100644 index 0000000000..9392811ca5 --- /dev/null +++ b/packages/core/strapi/lib/services/server/register-middlewares.js @@ -0,0 +1,63 @@ +'use strict'; + +const defaultConfig = [ + 'strapi::errors', + 'strapi::security', + 'strapi::cors', + 'strapi::poweredBy', + 'strapi::logger', + 'strapi::request', + 'strapi::favicon', + 'strapi::public', +]; + +/** + * Register middlewares in router + * @param {import('../../').Strapi} strapi + */ +module.exports = strapi => { + const middlewareConfig = strapi.config.get('middlewares', defaultConfig); + + // must be an array + // verify required middlewares are register + + const middlewares = []; + + for (const item of middlewareConfig) { + if (typeof item === 'string') { + const middlewareFactory = strapi.middleware(item); + + if (!middlewareFactory) { + throw new Error(`Middleware ${item} not found.`); + } + + middlewares.push(middlewareFactory()); + continue; + } + + if (typeof item === 'object' && item !== null) { + const { name, resolve, config = {} } = item; + + if (name) { + const middlewareFactory = strapi.middleware(name); + middlewares.push(middlewareFactory(config)); + continue; + } + + if (resolve) { + middlewares.push(require(resolve)(config)); + continue; + } + + throw new Error('Missing name or resolve'); + } + + throw new Error( + 'Middlware config must either be a string or an object (name?: string, resolve?: string, config: any)' + ); + } + + for (const middleware of middlewares) { + strapi.server.use(middleware); + } +}; diff --git a/packages/core/strapi/lib/services/server/register-routes.js b/packages/core/strapi/lib/services/server/register-routes.js index 7ab6064c92..13558f8c0f 100644 --- a/packages/core/strapi/lib/services/server/register-routes.js +++ b/packages/core/strapi/lib/services/server/register-routes.js @@ -19,79 +19,91 @@ const createRouteScopeGenerator = namespace => route => { } }; -module.exports = (server, strapi) => { - const registerAdminRoutes = () => { - const generateRouteScope = createRouteScopeGenerator(`admin::`); +/** + * Register all routes + * @param {import('../../').Strapi} strapi + */ +module.exports = strapi => { + registerAdminRoutes(strapi); + registerAPIRoutes(strapi); + registerPluginRoutes(strapi); +}; - strapi.admin.routes.forEach(route => { - generateRouteScope(route); - route.info = { pluginName: 'admin' }; - }); +/** + * Register admin routes + * @param {import('../../').Strapi} strapi + */ +const registerAdminRoutes = strapi => { + const generateRouteScope = createRouteScopeGenerator(`admin::`); - server.routes({ - type: 'admin', - prefix: '/admin', - routes: strapi.admin.routes, - }); - }; + strapi.admin.routes.forEach(route => { + generateRouteScope(route); + route.info = { pluginName: 'admin' }; + }); - const registerPluginRoutes = () => { - for (const pluginName in strapi.plugins) { - const plugin = strapi.plugins[pluginName]; + strapi.server.routes({ + type: 'admin', + prefix: '/admin', + routes: strapi.admin.routes, + }); +}; - const generateRouteScope = createRouteScopeGenerator(`plugin::${pluginName}`); +/** + * Register plugin routes + * @param {import('../../').Strapi} strapi + */ +const registerPluginRoutes = strapi => { + for (const pluginName in strapi.plugins) { + const plugin = strapi.plugins[pluginName]; - if (Array.isArray(plugin.routes)) { - plugin.routes.forEach(route => { + const generateRouteScope = createRouteScopeGenerator(`plugin::${pluginName}`); + + if (Array.isArray(plugin.routes)) { + plugin.routes.forEach(route => { + generateRouteScope(route); + route.info = { pluginName }; + }); + + strapi.server.routes({ + type: 'admin', + prefix: `/${pluginName}`, + routes: plugin.routes, + }); + } else { + _.forEach(plugin.routes, router => { + router.type = router.type || 'admin'; + router.prefix = `/${pluginName}`; + router.routes.forEach(route => { generateRouteScope(route); route.info = { pluginName }; }); - server.routes({ - type: 'admin', - prefix: `/${pluginName}`, - routes: plugin.routes, - }); - } else { - _.forEach(plugin.routes, router => { - router.type = router.type || 'admin'; - router.prefix = `/${pluginName}`; - router.routes.forEach(route => { - generateRouteScope(route); - route.info = { pluginName }; - }); - - server.routes(router); - }); - } - } - }; - - const registerAPIRoutes = () => { - for (const apiName in strapi.api) { - const api = strapi.api[apiName]; - - const generateRouteScope = createRouteScopeGenerator(`api::${apiName}`); - - _.forEach(api.routes, router => { - // TODO: remove once auth setup - // pass meta down to compose endpoint - router.type = 'content-api'; - router.routes.forEach(route => { - generateRouteScope(route); - route.info = { apiName }; - }); - - return server.routes(router); + strapi.server.routes(router); }); } - }; - - return { - initialize() { - registerAdminRoutes(); - registerAPIRoutes(); - registerPluginRoutes(); - }, - }; + } +}; + +/** + * Register api routes + * @param {import('../../').Strapi} strapi + */ +const registerAPIRoutes = strapi => { + for (const apiName in strapi.api) { + const api = strapi.api[apiName]; + + const generateRouteScope = createRouteScopeGenerator(`api::${apiName}`); + + _.forEach(api.routes, router => { + // TODO: remove once auth setup + // pass meta down to compose endpoint + router.type = 'content-api'; + router.routes.forEach(route => { + generateRouteScope(route); + route.info = { apiName }; + }); + + return strapi.server.routes(router); + }); + } }; diff --git a/packages/core/strapi/lib/services/server/routing.js b/packages/core/strapi/lib/services/server/routing.js index 7f7c442644..d2797ee3bf 100644 --- a/packages/core/strapi/lib/services/server/routing.js +++ b/packages/core/strapi/lib/services/server/routing.js @@ -48,7 +48,7 @@ const routeSchema = yup.object({ .array() .of(policyOrMiddlewareSchema) .notRequired(), - middlwares: yup + middlewares: yup .array() .of(policyOrMiddlewareSchema) .notRequired(), diff --git a/packages/core/strapi/lib/utils/get-dirs.js b/packages/core/strapi/lib/utils/get-dirs.js index 707e6432cb..3a8ec712a0 100644 --- a/packages/core/strapi/lib/utils/get-dirs.js +++ b/packages/core/strapi/lib/utils/get-dirs.js @@ -9,6 +9,7 @@ const getDirs = root => ({ components: join(root, 'src', 'components'), extensions: join(root, 'src', 'extensions'), policies: join(root, 'src', 'policies'), + middlewares: join(root, 'src', 'middlewares'), config: join(root, 'config'), }); diff --git a/packages/core/strapi/tests/publication-state.test.e2e.js b/packages/core/strapi/tests/publication-state.test.e2e.js index a54ddbfedd..999da335b6 100644 --- a/packages/core/strapi/tests/publication-state.test.e2e.js +++ b/packages/core/strapi/tests/publication-state.test.e2e.js @@ -193,8 +193,6 @@ describe('Publication State', () => { products = res.body.data.map(res => ({ id: res.id, ...res.attributes })); }); - const getApiRef = id => data.product.find(product => product.id === id); - test('Payload integrity', () => { expect(products).toHaveLength(lengthFor(contentTypes.product.name)); }); @@ -205,27 +203,31 @@ describe('Publication State', () => { }); }); - test('First level (categories)', () => { - products.forEach(({ id, categories }) => { - const length = getApiRef(id).categories.filter(c => c.publishedAt !== null).length; - expect(categories).toHaveLength(length); + // const getApiRef = id => data.product.find(product => product.id === id); - categories.forEach(category => { - expect(category.publishedAt).toBeISODate(); - }); - }); - }); + test.todo('First level (categories)'); - test('Second level through component (countries)', () => { - products.forEach(({ id, comp: { countries } }) => { - const length = getApiRef(id).comp.countries.filter(c => c.publishedAt !== null).length; - expect(countries).toHaveLength(length); + // products.forEach(({ id, categories }) => { + // const length = getApiRef(id).categories.filter(c => c.publishedAt !== null).length; + // expect(categories).toHaveLength(length); - countries.forEach(country => { - expect(country.publishedAt).toBeISODate(); - }); - }); - }); + // categories.forEach(category => { + // expect(category.publishedAt).toBeISODate(); + // }); + // }); + // }); + + test.todo('Second level through component (countries)'); + + // products.forEach(({ id, comp: { countries } }) => { + // const length = getApiRef(id).comp.countries.filter(c => c.publishedAt !== null).length; + // expect(countries).toHaveLength(length); + + // countries.forEach(country => { + // expect(country.publishedAt).toBeISODate(); + // }); + // }); + // }); }); }); }); diff --git a/test/helpers/utils.js b/test/helpers/utils.js index 63a0efa6a8..ff0b7bd53e 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -5,7 +5,7 @@ const _ = require('lodash'); const createUtils = strapi => { const login = async userInfo => { const sanitizedUserInfo = _.pick(userInfo, ['email', 'id']); - const user = await strapi.admin.services.user.findOne(sanitizedUserInfo); + const user = await strapi.query('admin::user').findOne({ where: sanitizedUserInfo }); if (!user) { throw new Error('User not found'); }