diff --git a/examples/getstarted/api/country/models/Country.settings.json b/examples/getstarted/api/country/models/Country.settings.json index 961334e5c3..67c6666bc6 100755 --- a/examples/getstarted/api/country/models/Country.settings.json +++ b/examples/getstarted/api/country/models/Country.settings.json @@ -2,9 +2,6 @@ "kind": "collectionType", "collectionName": "countries", "info": { - "displayName": "country", - "singularName": "country", - "pluralName": "countries", "name": "country", "description": "" }, diff --git a/examples/getstarted/config/plugins.js b/examples/getstarted/config/plugins.js index ad014948ab..f36d4dbe72 100644 --- a/examples/getstarted/config/plugins.js +++ b/examples/getstarted/config/plugins.js @@ -5,9 +5,12 @@ const path = require('path'); module.exports = ({ env }) => ({ graphql: { enabled: true, - config: require('./plugins/graphql')({ env }), - }, - i18n: { - config: require('./plugins/i18n')({ env }), + config: { + amountLimit: 50, + depthLimit: 10, + apolloServer: { + tracing: true, + }, + }, }, }); diff --git a/examples/getstarted/config/plugins/graphql.js b/examples/getstarted/config/plugins/graphql.js deleted file mode 100644 index e058fdaf68..0000000000 --- a/examples/getstarted/config/plugins/graphql.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = ({ env }) => ({ - amountLimit: 50, - depthLimit: 10, - apolloServer: { - tracing: true, - }, -}); diff --git a/examples/getstarted/config/plugins/i18n.js b/examples/getstarted/config/plugins/i18n.js deleted file mode 100644 index c381b7503a..0000000000 --- a/examples/getstarted/config/plugins/i18n.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = ({ env }) => ({}); diff --git a/examples/getstarted/extensions/upload/config/settings.js b/examples/getstarted/extensions/upload/config/settings.js deleted file mode 100644 index 621dcbf782..0000000000 --- a/examples/getstarted/extensions/upload/config/settings.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - // provider: 'cloudinary', - // providerOptions: { - // cloud_name: 'cloud-name', - // api_key: 'api-key', - // api_secret: 'api-secret', - // }, -}; diff --git a/examples/getstarted/extensions/users-permissions/config/jwt.js b/examples/getstarted/extensions/users-permissions/config/jwt.js deleted file mode 100644 index babeb1230c..0000000000 --- a/examples/getstarted/extensions/users-permissions/config/jwt.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - jwtSecret: process.env.JWT_SECRET || 'c4dc6f71-db45-49c6-82d0-9ca91cb93fa2', -}; diff --git a/examples/getstarted/extensions/users-permissions/config/policies/customPolicy.js b/examples/getstarted/extensions/users-permissions/config/policies/customPolicy.js deleted file mode 100644 index dacffddbe2..0000000000 --- a/examples/getstarted/extensions/users-permissions/config/policies/customPolicy.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (ctx, next) => { - next(); -}; diff --git a/examples/getstarted/extensions/users-permissions/config/routes.json b/examples/getstarted/extensions/users-permissions/config/routes.json deleted file mode 100644 index fdf5cc7c30..0000000000 --- a/examples/getstarted/extensions/users-permissions/config/routes.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "routes": [ - { - "method": "GET", - "path": "/custom-route", - "handler": "users-permissions.customRoute", - "config": { - "policies": ["plugin::users-permissions.customPolicy"] - } - }, - { - "method": "GET", - "path": "/", - "handler": "users-permissions.index", - "config": { - "policies": ["plugin::users-permissions.customPolicy"] - } - } - ] -} diff --git a/examples/getstarted/extensions/users-permissions/config/schema.graphql.js b/examples/getstarted/extensions/users-permissions/config/schema.graphql.js deleted file mode 100644 index 4d2f931fe0..0000000000 --- a/examples/getstarted/extensions/users-permissions/config/schema.graphql.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - query: ` - userCustomRoute: String - `, - resolver: { - Mutation: { - updateUser: { - description: 'Updates a user', - policies: ['customPolicy'], - }, - }, - Query: { - userCustomRoute: { - resolver: 'plugin::users-permissions.users-permissions.customRoute', - }, - }, - }, -}; diff --git a/examples/getstarted/extensions/users-permissions/models/Role.settings.json b/examples/getstarted/extensions/users-permissions/content-types/role/schema.json similarity index 88% rename from examples/getstarted/extensions/users-permissions/models/Role.settings.json rename to examples/getstarted/extensions/users-permissions/content-types/role/schema.json index bae370ad61..dc66f242f6 100644 --- a/examples/getstarted/extensions/users-permissions/models/Role.settings.json +++ b/examples/getstarted/extensions/users-permissions/content-types/role/schema.json @@ -2,7 +2,10 @@ "collectionName": "up_roles", "info": { "name": "role", - "description": "" + "description": "", + "singularName": "role", + "pluralName": "roles", + "displayName": "Role" }, "options": { "draftAndPublish": false diff --git a/examples/getstarted/extensions/users-permissions/models/User.settings.json b/examples/getstarted/extensions/users-permissions/content-types/user/schema.json similarity index 86% rename from examples/getstarted/extensions/users-permissions/models/User.settings.json rename to examples/getstarted/extensions/users-permissions/content-types/user/schema.json index 2836ffef4c..e834987cd0 100644 --- a/examples/getstarted/extensions/users-permissions/models/User.settings.json +++ b/examples/getstarted/extensions/users-permissions/content-types/user/schema.json @@ -1,8 +1,11 @@ { "collectionName": "up_users", "info": { - "name": "user", - "description": "" + "name": "User", + "description": "", + "singularName": "user", + "pluralName": "users", + "displayName": "User" }, "options": { "draftAndPublish": false @@ -59,7 +62,9 @@ "configurable": false }, "picture": { - "type": "media" + "type": "media", + "multiple": false, + "required": false } } } diff --git a/examples/getstarted/extensions/users-permissions/controllers/users-permissions.js b/examples/getstarted/extensions/users-permissions/controllers/users-permissions.js deleted file mode 100644 index 3ad9178181..0000000000 --- a/examples/getstarted/extensions/users-permissions/controllers/users-permissions.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - customRoute(ctx) { - ctx.body = 'allRight'; - }, -}; diff --git a/examples/getstarted/extensions/users-permissions/models/User.config.js b/examples/getstarted/extensions/users-permissions/models/User.config.js deleted file mode 100644 index 6bc0886f05..0000000000 --- a/examples/getstarted/extensions/users-permissions/models/User.config.js +++ /dev/null @@ -1,38 +0,0 @@ -module.exports = { - layouts: { - edit: [ - [ - { - name: 'email', - size: 6, - }, - { - name: 'username', - size: 6, - }, - ], - [ - { - name: 'password', - size: 6, - }, - ], - [ - { - name: 'picture', - size: 6, - }, - ], - [ - { - name: 'confirmed', - size: 4, - }, - { - name: 'blocked', - size: 4, - }, - ], - ], - }, -}; diff --git a/examples/getstarted/extensions/users-permissions/strapi-server.js b/examples/getstarted/extensions/users-permissions/strapi-server.js new file mode 100644 index 0000000000..235100b090 --- /dev/null +++ b/examples/getstarted/extensions/users-permissions/strapi-server.js @@ -0,0 +1,3 @@ +module.exports = plugin => { + return plugin; +}; diff --git a/packages/core/content-manager/server/content-types/index.js b/packages/core/content-manager/server/content-types/index.js deleted file mode 100644 index 104c4ef24d..0000000000 --- a/packages/core/content-manager/server/content-types/index.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; - -module.exports = []; diff --git a/packages/core/content-manager/strapi-server.js b/packages/core/content-manager/strapi-server.js index e42835ad01..da4fe6d5c7 100644 --- a/packages/core/content-manager/strapi-server.js +++ b/packages/core/content-manager/strapi-server.js @@ -1,7 +1,6 @@ 'use strict'; const bootstrap = require('./server/bootstrap'); -const contentTypes = require('./server/content-types'); const policies = require('./server/policies'); const services = require('./server/services'); const routes = require('./server/routes'); @@ -9,11 +8,9 @@ const controllers = require('./server/controllers'); module.exports = () => { return { - register: () => {}, bootstrap, routes, controllers, - contentTypes, policies, services, }; diff --git a/packages/core/content-type-builder/services/schema-builder/index.js b/packages/core/content-type-builder/services/schema-builder/index.js index 608943d165..adc432a456 100644 --- a/packages/core/content-type-builder/services/schema-builder/index.js +++ b/packages/core/content-type-builder/services/schema-builder/index.js @@ -2,7 +2,6 @@ const path = require('path'); const _ = require('lodash'); -const { capitalize } = require('lodash/fp'); const createSchemaHandler = require('./schema-handler'); const createComponentBuilder = require('./component-builder'); @@ -32,17 +31,20 @@ module.exports = function createBuilder() { const contentType = strapi.contentTypes[key]; let dir; + let filename; if (contentType.plugin) { - dir = `./extensions/${contentType.plugin}/models`; + dir = `./extensions/${contentType.plugin}/content-types/${contentType.info.singularName}`; + filename = 'schema.json'; } else { dir = `./api/${contentType.apiName}/models`; + filename = contentType.__filename__; } return { modelName: contentType.modelName, plugin: contentType.plugin, uid: contentType.uid, - filename: capitalize(`${contentType.info.singularName}.settings.json`), + filename, dir: path.join(strapi.dir, dir), schema: contentType.__schema__, }; diff --git a/packages/core/strapi/lib/Strapi.js b/packages/core/strapi/lib/Strapi.js index 00052182b1..e5fef7a10e 100644 --- a/packages/core/strapi/lib/Strapi.js +++ b/packages/core/strapi/lib/Strapi.js @@ -103,7 +103,7 @@ class Strapi { return this; } catch (error) { - return this.stopWithError(error.message); + return this.stopWithError(error); } } @@ -327,7 +327,7 @@ class Strapi { return; } - if (this.config.autoReload) { + if (this.config.get('autoReload')) { this.server.destroy(); process.send('reload'); } diff --git a/packages/core/strapi/lib/commands/develop.js b/packages/core/strapi/lib/commands/develop.js index 02653e7d9a..db1b517c9c 100644 --- a/packages/core/strapi/lib/commands/develop.js +++ b/packages/core/strapi/lib/commands/develop.js @@ -82,12 +82,11 @@ module.exports = async function({ build, watchAdmin, polling, browser }) { polling, }); - process.on('message', message => { + process.on('message', async message => { switch (message) { case 'isKilled': - strapiInstance.server.destroy(() => { - process.send('kill'); - }); + await strapiInstance.server.destroy(); + process.send('kill'); break; default: // Do nothing. 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 3f4ef0fd47..5c88b8d4d2 100644 --- a/packages/core/strapi/lib/core/domain/content-type/index.js +++ b/packages/core/strapi/lib/core/domain/content-type/index.js @@ -1,6 +1,6 @@ 'use strict'; -const { cloneDeep } = require('lodash/fp'); +const { cloneDeep, kebabCase } = require('lodash/fp'); const _ = require('lodash'); const { hasDraftAndPublish } = require('@strapi/utils').contentTypes; const { @@ -26,7 +26,7 @@ const createContentType = (uid, definition) => { kind: createdContentType.schema.kind || 'collectionType', __schema__: pickSchema(definition.schema), modelType: 'contentType', - modelName: definition.schema.info.singularName, + modelName: kebabCase(definition.schema.info.singularName), connection: 'default', }); diff --git a/packages/core/strapi/lib/core/domain/module/validation.js b/packages/core/strapi/lib/core/domain/module/validation.js index 1178bb15f3..86ad199c62 100644 --- a/packages/core/strapi/lib/core/domain/module/validation.js +++ b/packages/core/strapi/lib/core/domain/module/validation.js @@ -23,7 +23,7 @@ const strapiServerSchema = yup services: yup.object().required(), policies: yup.object().required(), middlewares: yup.object().required(), // may be removed later - contentTypes: yup.array().required(), + contentTypes: yup.object().required(), }) .noUnknown(); diff --git a/packages/core/strapi/lib/core/fs.js b/packages/core/strapi/lib/core/fs.js index 575cc92edf..7a2039a9a9 100644 --- a/packages/core/strapi/lib/core/fs.js +++ b/packages/core/strapi/lib/core/fs.js @@ -1,6 +1,7 @@ 'use strict'; const path = require('path'); +const fs = require('fs'); const fse = require('fs-extra'); /** @@ -10,7 +11,7 @@ module.exports = strapi => { function normalizePath(optPath) { const filePath = Array.isArray(optPath) ? optPath.join('/') : optPath; - const normalizedPath = path.normalize(filePath).replace(/^(\/?\.\.?)+/, ''); + const normalizedPath = path.normalize(filePath).replace(/^\/?(\.\/|\.\.\/)+/, ''); return path.join(strapi.dir, normalizedPath); } @@ -44,6 +45,14 @@ module.exports = strapi => { const removePath = normalizePath(optPath); return fse.remove(removePath); }, + + /** + * Appends a file in strapi app + */ + async appendFile(optPath, data) { + const writePath = normalizePath(optPath); + return fs.appendFileSync(writePath, data); + }, }; return strapiFS; diff --git a/packages/core/strapi/lib/core/load-plugins/index.js b/packages/core/strapi/lib/core/load-plugins/index.js index 058eb85539..3547c15250 100644 --- a/packages/core/strapi/lib/core/load-plugins/index.js +++ b/packages/core/strapi/lib/core/load-plugins/index.js @@ -1,10 +1,11 @@ 'use strict'; -const { join } = require('path'); +const { join, resolve } = require('path'); const { existsSync } = require('fs'); -const { defaultsDeep, getOr } = require('lodash/fp'); +const { defaultsDeep, getOr, get } = require('lodash/fp'); const { env } = require('@strapi/utils'); const loadConfigFile = require('../app-configuration/load-config-file'); +const loadFiles = require('../../load/load-files'); const getEnabledPlugins = require('./get-enabled-plugins'); const defaultPlugin = { @@ -20,7 +21,33 @@ const defaultPlugin = { services: {}, policies: {}, middlewares: {}, - contentTypes: [], + contentTypes: {}, +}; + +const applyUserExtension = async plugins => { + const extensionsDir = resolve(strapi.dir, 'extensions'); + if (!existsSync(extensionsDir)) { + return; + } + + const extendedSchemas = await loadFiles(extensionsDir, '**/content-types/**/schema.json'); + const strapiServers = await loadFiles(extensionsDir, '**/strapi-server.js'); + + for (const pluginName in plugins) { + const plugin = plugins[pluginName]; + // first: load json schema + for (const ctName in plugin.contentTypes) { + const extendedSchema = get([pluginName, 'content-types', ctName, 'schema'], extendedSchemas); + if (extendedSchema) { + plugin.contentTypes[ctName].schema = extendedSchema; + } + } + // second: execute strapi-server extension + const strapiServer = get([pluginName, 'strapi-server'], strapiServers); + if (strapiServer) { + plugins[pluginName] = await strapiServer(plugin); + } + } }; const formatContentTypes = plugins => { @@ -34,7 +61,7 @@ const formatContentTypes = plugins => { } }; -const formatConfig = plugins => { +const applyUserConfig = plugins => { const userPluginConfigPath = join(strapi.dir, 'config', 'plugins.js'); const userPluginsConfig = existsSync(userPluginConfigPath) ? loadConfigFile(userPluginConfigPath) @@ -43,13 +70,18 @@ const formatConfig = plugins => { for (const pluginName in plugins) { const plugin = plugins[pluginName]; const userPluginConfig = getOr({}, `${pluginName}.config`, userPluginsConfig); - const formattedConfig = defaultsDeep(plugin.config.default, userPluginConfig); + const defaultConfig = + typeof plugin.config.default === 'function' + ? plugin.config.default({ env }) + : plugin.config.default; + + const config = defaultsDeep(defaultConfig, userPluginConfig); try { - plugin.config.validator(formattedConfig); + plugin.config.validator(config); } catch (e) { throw new Error(`Error regarding ${pluginName} config: ${e.message}`); } - plugin.config = formattedConfig; + plugin.config = config; } }; @@ -59,12 +91,12 @@ const loadPlugins = async strapi => { for (const pluginName in enabledPlugins) { const enabledPlugin = enabledPlugins[pluginName]; - const loadPluginServer = require(join(enabledPlugin.pathToPlugin, 'strapi-server.js')); - const pluginServer = await loadPluginServer({ env }); + const pluginServer = loadConfigFile(join(enabledPlugin.pathToPlugin, 'strapi-server.js')); plugins[pluginName] = defaultsDeep(defaultPlugin, pluginServer); } // TODO: validate plugin format - formatConfig(plugins); + applyUserConfig(plugins); + await applyUserExtension(plugins); formatContentTypes(plugins); return plugins; diff --git a/packages/core/strapi/lib/core/loaders/bootstrap.js b/packages/core/strapi/lib/core/loaders/bootstrap.js index 2e0fd9c520..59b2cac295 100644 --- a/packages/core/strapi/lib/core/loaders/bootstrap.js +++ b/packages/core/strapi/lib/core/loaders/bootstrap.js @@ -3,6 +3,7 @@ const _ = require('lodash'); const { toLower, kebabCase, camelCase } = require('lodash/fp'); const { getConfigUrls } = require('@strapi/utils'); +const pluralize = require('pluralize'); const { createContentType } = require('../domain/content-type'); const { createCoreApi } = require('../../core-api'); @@ -23,10 +24,10 @@ module.exports = function(strapi) { actions: {}, lifecycles: {}, }; - ct.schema.info = {}; - ct.schema.info.displayName = camelCase(modelName); + + ct.schema.info.displayName = model.info.name; ct.schema.info.singularName = camelCase(modelName); - ct.schema.info.pluralName = `${camelCase(modelName)}s`; + ct.schema.info.pluralName = pluralize(camelCase(modelName)); const createdContentType = createContentType( `api::${apiName}.${kebabCase(ct.schema.info.singularName)}`, @@ -46,19 +47,21 @@ module.exports = function(strapi) { }, {}); // Set controllers. - strapi.controllers = Object.keys(strapi.api || []).reduce((acc, key) => { - for (let index in strapi.api[key].controllers) { - let controller = strapi.api[key].controllers[index]; - acc[index] = controller; + strapi.controllers = Object.keys(strapi.api || []).reduce((acc, apiName) => { + strapi.container.get('controllers').add(`api::${apiName}`, strapi.api[apiName].controllers); + for (let controllerName in strapi.api[apiName].controllers) { + let controller = strapi.api[apiName].controllers[controllerName]; + acc[controllerName] = controller; } return acc; }, {}); // Set services. - strapi.services = Object.keys(strapi.api || []).reduce((acc, key) => { - for (let index in strapi.api[key].services) { - acc[index] = strapi.api[key].services[index]; + strapi.services = Object.keys(strapi.api || []).reduce((acc, apiName) => { + strapi.container.get('services').add(`api::${apiName}`, strapi.api[apiName].services); + for (let serviceName in strapi.api[apiName].services) { + acc[serviceName] = strapi.api[apiName].services[serviceName]; } return acc; @@ -120,6 +123,7 @@ module.exports = function(strapi) { _.forEach(plugin.middlewares, (middleware, middlewareUID) => { const middlewareName = toLower(middlewareUID.split('.')[1]); strapi.plugins[pluginName].middlewares[middlewareName] = middleware; + strapi.middleware[middlewareName] = middleware; }); _.forEach(plugin.controllers, (controller, controllerUID) => { diff --git a/packages/core/strapi/lib/core/registries/content-types.js b/packages/core/strapi/lib/core/registries/content-types.js index 36eefdf26f..3f4b4ca9bf 100644 --- a/packages/core/strapi/lib/core/registries/content-types.js +++ b/packages/core/strapi/lib/core/registries/content-types.js @@ -19,6 +19,17 @@ const { createContentType } = require('../domain/content-type'); // }); // }; +const validateKeySameToSingularName = contentTypes => { + for (const ctName in contentTypes) { + const contentType = contentTypes[ctName]; + if (ctName !== contentType.schema.info.singularName) { + throw new Error( + `The key of the content-type should be the same as its singularName. Found ${ctName} and ${contentType.schema.info.singularName}.` + ); + } + } +}; + const contentTypesRegistry = () => { const contentTypes = {}; @@ -30,13 +41,15 @@ const contentTypesRegistry = () => { return pickBy((ct, ctUID) => ctUID.startsWith(prefix))(contentTypes); }, add(namespace, rawContentTypes) { - rawContentTypes.forEach(rawContentType => { + validateKeySameToSingularName(rawContentTypes); + for (const rawCtName in rawContentTypes) { + const rawContentType = rawContentTypes[rawCtName]; const uid = `${namespace}.${rawContentType.schema.info.singularName}`; if (has(uid, contentTypes)) { - throw new Error(`Content-Type ${uid} has already been registered.`); + throw new Error(`Content-type ${uid} has already been registered.`); } contentTypes[uid] = createContentType(uid, rawContentType); - }); + } }, }; }; diff --git a/packages/core/strapi/package.json b/packages/core/strapi/package.json index 5040920317..08c7fcf68f 100644 --- a/packages/core/strapi/package.json +++ b/packages/core/strapi/package.json @@ -63,6 +63,7 @@ "open": "8.2.1", "ora": "^5.4.0", "package-json": "6.5.0", + "pluralize": "8.0.0", "qs": "^6.10.1", "resolve-cwd": "^3.0.0", "rimraf": "^3.0.2", diff --git a/packages/core/upload/server/content-types/index.js b/packages/core/upload/server/content-types/index.js index 8962dddd6a..e8fb0db122 100644 --- a/packages/core/upload/server/content-types/index.js +++ b/packages/core/upload/server/content-types/index.js @@ -2,8 +2,6 @@ const fileModel = require('../../models/File'); -module.exports = [ - { - schema: fileModel, - }, -]; +module.exports = { + [fileModel.info.singularName]: { schema: fileModel }, +}; diff --git a/packages/core/upload/services/upload.js b/packages/core/upload/services/upload.js index 160ac67773..3b24f88bf5 100644 --- a/packages/core/upload/services/upload.js +++ b/packages/core/upload/services/upload.js @@ -150,7 +150,7 @@ module.exports = ({ strapi }) => ({ }, async uploadFileAndPersist(fileData, { user } = {}) { - const config = strapi.plugins.upload.config; + const config = strapi.config.get('plugin.upload'); const { getDimensions, diff --git a/packages/core/utils/lib/content-types.js b/packages/core/utils/lib/content-types.js index d585ade0c8..ee10b77428 100644 --- a/packages/core/utils/lib/content-types.js +++ b/packages/core/utils/lib/content-types.js @@ -1,7 +1,6 @@ 'use strict'; const _ = require('lodash'); -const pluralize = require('pluralize'); const SINGLE_TYPE = 'singleType'; const COLLECTION_TYPE = 'collectionType'; @@ -120,8 +119,8 @@ const isTypedAttribute = (attribute, type) => { */ const getContentTypeRoutePrefix = contentType => { return isSingleType(contentType) - ? _.kebabCase(contentType.modelName) - : _.kebabCase(pluralize(contentType.modelName)); + ? _.kebabCase(contentType.info.singularName) + : _.kebabCase(contentType.info.pluralName); }; module.exports = { diff --git a/packages/plugins/graphql/strapi-server.js b/packages/plugins/graphql/strapi-server.js index e46e60584c..332afa87ab 100644 --- a/packages/plugins/graphql/strapi-server.js +++ b/packages/plugins/graphql/strapi-server.js @@ -10,6 +10,6 @@ module.exports = (/* strapi, config */) => { services: () => {}, policies: {}, middlewares: {}, - contentTypes: [], + contentTypes: {}, }; }; diff --git a/packages/plugins/i18n/server/content-types/index.js b/packages/plugins/i18n/server/content-types/index.js index 59b68c0b23..7594c7bf7b 100644 --- a/packages/plugins/i18n/server/content-types/index.js +++ b/packages/plugins/i18n/server/content-types/index.js @@ -2,4 +2,6 @@ const localeModel = require('./locale'); -module.exports = [localeModel]; +module.exports = { + [localeModel.schema.info.singularName]: localeModel, +}; diff --git a/packages/plugins/i18n/server/services/core-api.js b/packages/plugins/i18n/server/services/core-api.js index ff4c8be5be..d1d4f9957d 100644 --- a/packages/plugins/i18n/server/services/core-api.js +++ b/packages/plugins/i18n/server/services/core-api.js @@ -199,12 +199,21 @@ const addCreateLocalizationAction = contentType => { const localizationRoute = createLocalizationRoute(contentType); - const coreApiControllerPath = `api.${apiName}.controllers.${modelName}.createLocalization`; - const handler = createLocalizationHandler(contentType); - strapi.config.routes.push(localizationRoute); - _.set(strapi, coreApiControllerPath, handler); + // TODO: to replace with: + // strapi.controllers.extends(`api::${apiName}.${modelName}`, (contr) => ({ + // ...controller, + // createLocalization = createLocalizationHandler(contentType), + // })); + // OR + // strapi.api(apiName).controllers.extends(modelName, (contr) => ({ + // ...controller, + // createLocalization = createLocalizationHandler(contentType), + // })); + + const controller = strapi.container.get('controllers').get(`api::${apiName}.${modelName}`); + controller.createLocalization = createLocalizationHandler(contentType); }; const mergeCustomizer = (dest, src) => { @@ -217,6 +226,7 @@ const mergeCustomizer = (dest, src) => { * Add a graphql schema to the plugin's global graphl schema to be processed * @param {object} schema */ +// TODO: to replace with V4 config getter const addGraphqlSchema = schema => { _.mergeWith(strapi.plugins.i18n.config.schema.graphql, schema, mergeCustomizer); }; diff --git a/packages/plugins/users-permissions/admin/src/components/UsersPermissions/tests/init.test.js b/packages/plugins/users-permissions/admin/src/components/UsersPermissions/tests/init.test.js index 974b4c4136..6481717aa6 100644 --- a/packages/plugins/users-permissions/admin/src/components/UsersPermissions/tests/init.test.js +++ b/packages/plugins/users-permissions/admin/src/components/UsersPermissions/tests/init.test.js @@ -36,7 +36,7 @@ describe('USERS PERMISSIONS | COMPONENTS | UserPermissions | init', () => { application: [{ method: 'GET', path: '/addresses' }], }; - const policies = ['isauthenticated', 'ratelimit', 'custompolicy']; + const policies = ['isAuthenticated', 'rateLimit', 'custompolicy']; const expected = { initialData: permissions, diff --git a/packages/plugins/users-permissions/admin/src/utils/tests/formatPolicies.test.js b/packages/plugins/users-permissions/admin/src/utils/tests/formatPolicies.test.js index a7245220a0..51db91292b 100644 --- a/packages/plugins/users-permissions/admin/src/utils/tests/formatPolicies.test.js +++ b/packages/plugins/users-permissions/admin/src/utils/tests/formatPolicies.test.js @@ -2,12 +2,12 @@ import formatPolicies from '../formatPolicies'; describe('USERS PERMISSIONS | utils | formatPolicies', () => { it('should format the policies correclty', () => { - const policies = ['custompolicies', 'ratelimit', 'isauthenticated']; + const policies = ['customPolicies', 'rateLimit', 'isAuthenticated']; const expected = [ - { label: 'custompolicies', value: 'custompolicies' }, - { label: 'ratelimit', value: 'ratelimit' }, - { label: 'isauthenticated', value: 'isauthenticated' }, + { label: 'customPolicies', value: 'customPolicies' }, + { label: 'rateLimit', value: 'rateLimit' }, + { label: 'isAuthenticated', value: 'isAuthenticated' }, ]; expect(formatPolicies(policies)).toEqual(expected); diff --git a/packages/plugins/users-permissions/config/functions/bootstrap.js b/packages/plugins/users-permissions/config/functions/bootstrap.js index 9fa5532cb2..d4d6865ae5 100644 --- a/packages/plugins/users-permissions/config/functions/bootstrap.js +++ b/packages/plugins/users-permissions/config/functions/bootstrap.js @@ -31,17 +31,14 @@ module.exports = async () => { await getService('users-permissions').initialize(); // TODO: adapt with new extension system - if (!_.get(strapi.plugins['users-permissions'], 'config.jwtSecret')) { + if (!strapi.config.get('plugin.users-permissions.jwtSecret')) { const jwtSecret = uuid(); - _.set(strapi.plugins['users-permissions'], 'config.jwtSecret', jwtSecret); + strapi.config.set('plugin.users-permissions.jwtSecret', jwtSecret), + (strapi.reload.isWatching = false); - strapi.reload.isWatching = false; - - await strapi.fs.writePluginFile( - 'users-permissions', - 'config/jwt.js', - `module.exports = {\n jwtSecret: process.env.JWT_SECRET || '${jwtSecret}'\n};` - ); + if (!process.env.JWT_SECRET) { + await strapi.fs.appendFile('.env', `JWT_SECRET=${jwtSecret}\n`); + } strapi.reload.isWatching = true; } diff --git a/packages/plugins/users-permissions/config/policies/rateLimit.js b/packages/plugins/users-permissions/config/policies/rateLimit.js index 13f0dd493b..29f23ab94e 100644 --- a/packages/plugins/users-permissions/config/policies/rateLimit.js +++ b/packages/plugins/users-permissions/config/policies/rateLimit.js @@ -27,7 +27,7 @@ module.exports = async (ctx, next) => { prefixKey: `${ctx.request.path}:${ctx.request.ip}`, message, }, - strapi.plugins['users-permissions'].config.ratelimit + strapi.config.get('plugin.users-permissions.ratelimit') ) )(ctx, next); }; diff --git a/packages/plugins/users-permissions/config/routes.json b/packages/plugins/users-permissions/config/routes.json index 93995bdad4..f7424d9c8c 100644 --- a/packages/plugins/users-permissions/config/routes.json +++ b/packages/plugins/users-permissions/config/routes.json @@ -176,7 +176,7 @@ "path": "/connect/*", "handler": "auth.connect", "config": { - "policies": ["plugin::users-permissions.ratelimit"], + "policies": ["plugin::users-permissions.rateLimit"], "prefix": "", "description": "Connect a provider", "tag": { @@ -190,7 +190,7 @@ "path": "/auth/local", "handler": "auth.callback", "config": { - "policies": ["plugin::users-permissions.ratelimit"], + "policies": ["plugin::users-permissions.rateLimit"], "prefix": "", "description": "Login a user using the identifiers email and password", "tag": { @@ -204,7 +204,7 @@ "path": "/auth/local/register", "handler": "auth.register", "config": { - "policies": ["plugin::users-permissions.ratelimit"], + "policies": ["plugin::users-permissions.rateLimit"], "prefix": "", "description": "Register a new user with the default role", "tag": { @@ -233,7 +233,7 @@ "path": "/auth/forgot-password", "handler": "auth.forgotPassword", "config": { - "policies": ["plugin::users-permissions.ratelimit"], + "policies": ["plugin::users-permissions.rateLimit"], "prefix": "", "description": "Send the reset password email link", "tag": { @@ -247,7 +247,7 @@ "path": "/auth/reset-password", "handler": "auth.resetPassword", "config": { - "policies": ["plugin::users-permissions.ratelimit"], + "policies": ["plugin::users-permissions.rateLimit"], "prefix": "", "description": "Reset user password with a code (resetToken)", "tag": { diff --git a/packages/plugins/users-permissions/server/config.js b/packages/plugins/users-permissions/server/config.js index fb2d7ea558..d722b040a9 100644 --- a/packages/plugins/users-permissions/server/config.js +++ b/packages/plugins/users-permissions/server/config.js @@ -1,6 +1,15 @@ 'use strict'; module.exports = { - default: {}, + default: ({ env }) => ({ + jwtSecret: env('JWT_SECRET'), + jwt: { + expiresIn: '30d', + }, + ratelimit: { + interval: 60000, + max: 10, + }, + }), validator: () => {}, }; diff --git a/packages/plugins/users-permissions/server/content-types/index.js b/packages/plugins/users-permissions/server/content-types/index.js index 4dd2375a05..29511d65a3 100644 --- a/packages/plugins/users-permissions/server/content-types/index.js +++ b/packages/plugins/users-permissions/server/content-types/index.js @@ -4,14 +4,8 @@ const permissionModel = require('../../models/Permission.settings'); const roleModel = require('../../models/Role.settings'); const userModel = require('../../models/User.settings'); -module.exports = [ - { - schema: permissionModel, - }, - { - schema: roleModel, - }, - { - schema: userModel, - }, -]; +module.exports = { + [permissionModel.info.singularName]: { schema: permissionModel }, + [roleModel.info.singularName]: { schema: roleModel }, + [userModel.info.singularName]: { schema: userModel }, +}; diff --git a/packages/plugins/users-permissions/services/jwt.js b/packages/plugins/users-permissions/services/jwt.js index a7f08463d7..f4c9c4fb19 100644 --- a/packages/plugins/users-permissions/services/jwt.js +++ b/packages/plugins/users-permissions/services/jwt.js @@ -39,27 +39,25 @@ module.exports = ({ strapi }) => ({ }, issue(payload, jwtOptions = {}) { - _.defaults(jwtOptions, strapi.plugins['users-permissions'].config.jwt); + _.defaults(jwtOptions, strapi.config.get('plugin.users-permissions.jwt')); return jwt.sign( _.clone(payload.toJSON ? payload.toJSON() : payload), - _.get(strapi.plugins, ['users-permissions', 'config', 'jwtSecret']), + strapi.config.get('plugin.users-permissions.jwtSecret'), jwtOptions ); }, verify(token) { return new Promise(function(resolve, reject) { - jwt.verify( - token, - _.get(strapi.plugins, ['users-permissions', 'config', 'jwtSecret']), - {}, - function(err, tokenPayload = {}) { - if (err) { - return reject(new Error('Invalid token.')); - } - resolve(tokenPayload); + jwt.verify(token, strapi.config.get('plugin.users-permissions.jwtSecret'), {}, function( + err, + tokenPayload = {} + ) { + if (err) { + return reject(new Error('Invalid token.')); } - ); + resolve(tokenPayload); + }); }); }, }); diff --git a/packages/plugins/users-permissions/strapi-server.js b/packages/plugins/users-permissions/strapi-server.js index fb88a0c22c..407591ed17 100644 --- a/packages/plugins/users-permissions/strapi-server.js +++ b/packages/plugins/users-permissions/strapi-server.js @@ -7,10 +7,11 @@ const services = require('./server/services'); const routes = require('./server/routes'); const controllers = require('./server/controllers'); const middlewares = require('./server/middlewares'); +const config = require('./server/config'); module.exports = () => ({ - register: () => {}, bootstrap, + config, routes, controllers, middlewares,