mirror of
https://github.com/strapi/strapi.git
synced 2025-09-02 05:13:03 +00:00
Merge pull request #10752 from strapi/v4/plugin-api/extensions
V4/plugin api/extensions
This commit is contained in:
commit
65a89df6f2
@ -2,9 +2,6 @@
|
|||||||
"kind": "collectionType",
|
"kind": "collectionType",
|
||||||
"collectionName": "countries",
|
"collectionName": "countries",
|
||||||
"info": {
|
"info": {
|
||||||
"displayName": "country",
|
|
||||||
"singularName": "country",
|
|
||||||
"pluralName": "countries",
|
|
||||||
"name": "country",
|
"name": "country",
|
||||||
"description": ""
|
"description": ""
|
||||||
},
|
},
|
||||||
|
@ -5,9 +5,12 @@ const path = require('path');
|
|||||||
module.exports = ({ env }) => ({
|
module.exports = ({ env }) => ({
|
||||||
graphql: {
|
graphql: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
config: require('./plugins/graphql')({ env }),
|
config: {
|
||||||
},
|
amountLimit: 50,
|
||||||
i18n: {
|
depthLimit: 10,
|
||||||
config: require('./plugins/i18n')({ env }),
|
apolloServer: {
|
||||||
|
tracing: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
module.exports = ({ env }) => ({
|
|
||||||
amountLimit: 50,
|
|
||||||
depthLimit: 10,
|
|
||||||
apolloServer: {
|
|
||||||
tracing: true,
|
|
||||||
},
|
|
||||||
});
|
|
@ -1 +0,0 @@
|
|||||||
module.exports = ({ env }) => ({});
|
|
@ -1,8 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
// provider: 'cloudinary',
|
|
||||||
// providerOptions: {
|
|
||||||
// cloud_name: 'cloud-name',
|
|
||||||
// api_key: 'api-key',
|
|
||||||
// api_secret: 'api-secret',
|
|
||||||
// },
|
|
||||||
};
|
|
@ -1,3 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
jwtSecret: process.env.JWT_SECRET || 'c4dc6f71-db45-49c6-82d0-9ca91cb93fa2',
|
|
||||||
};
|
|
@ -1,3 +0,0 @@
|
|||||||
module.exports = (ctx, next) => {
|
|
||||||
next();
|
|
||||||
};
|
|
@ -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"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -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',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
@ -2,7 +2,10 @@
|
|||||||
"collectionName": "up_roles",
|
"collectionName": "up_roles",
|
||||||
"info": {
|
"info": {
|
||||||
"name": "role",
|
"name": "role",
|
||||||
"description": ""
|
"description": "",
|
||||||
|
"singularName": "role",
|
||||||
|
"pluralName": "roles",
|
||||||
|
"displayName": "Role"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"draftAndPublish": false
|
"draftAndPublish": false
|
@ -1,8 +1,11 @@
|
|||||||
{
|
{
|
||||||
"collectionName": "up_users",
|
"collectionName": "up_users",
|
||||||
"info": {
|
"info": {
|
||||||
"name": "user",
|
"name": "User",
|
||||||
"description": ""
|
"description": "",
|
||||||
|
"singularName": "user",
|
||||||
|
"pluralName": "users",
|
||||||
|
"displayName": "User"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"draftAndPublish": false
|
"draftAndPublish": false
|
||||||
@ -59,7 +62,9 @@
|
|||||||
"configurable": false
|
"configurable": false
|
||||||
},
|
},
|
||||||
"picture": {
|
"picture": {
|
||||||
"type": "media"
|
"type": "media",
|
||||||
|
"multiple": false,
|
||||||
|
"required": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
customRoute(ctx) {
|
|
||||||
ctx.body = 'allRight';
|
|
||||||
},
|
|
||||||
};
|
|
@ -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,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = plugin => {
|
||||||
|
return plugin;
|
||||||
|
};
|
@ -1,3 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports = [];
|
|
@ -1,7 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const bootstrap = require('./server/bootstrap');
|
const bootstrap = require('./server/bootstrap');
|
||||||
const contentTypes = require('./server/content-types');
|
|
||||||
const policies = require('./server/policies');
|
const policies = require('./server/policies');
|
||||||
const services = require('./server/services');
|
const services = require('./server/services');
|
||||||
const routes = require('./server/routes');
|
const routes = require('./server/routes');
|
||||||
@ -9,11 +8,9 @@ const controllers = require('./server/controllers');
|
|||||||
|
|
||||||
module.exports = () => {
|
module.exports = () => {
|
||||||
return {
|
return {
|
||||||
register: () => {},
|
|
||||||
bootstrap,
|
bootstrap,
|
||||||
routes,
|
routes,
|
||||||
controllers,
|
controllers,
|
||||||
contentTypes,
|
|
||||||
policies,
|
policies,
|
||||||
services,
|
services,
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const { capitalize } = require('lodash/fp');
|
|
||||||
|
|
||||||
const createSchemaHandler = require('./schema-handler');
|
const createSchemaHandler = require('./schema-handler');
|
||||||
const createComponentBuilder = require('./component-builder');
|
const createComponentBuilder = require('./component-builder');
|
||||||
@ -32,17 +31,20 @@ module.exports = function createBuilder() {
|
|||||||
const contentType = strapi.contentTypes[key];
|
const contentType = strapi.contentTypes[key];
|
||||||
|
|
||||||
let dir;
|
let dir;
|
||||||
|
let filename;
|
||||||
if (contentType.plugin) {
|
if (contentType.plugin) {
|
||||||
dir = `./extensions/${contentType.plugin}/models`;
|
dir = `./extensions/${contentType.plugin}/content-types/${contentType.info.singularName}`;
|
||||||
|
filename = 'schema.json';
|
||||||
} else {
|
} else {
|
||||||
dir = `./api/${contentType.apiName}/models`;
|
dir = `./api/${contentType.apiName}/models`;
|
||||||
|
filename = contentType.__filename__;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
modelName: contentType.modelName,
|
modelName: contentType.modelName,
|
||||||
plugin: contentType.plugin,
|
plugin: contentType.plugin,
|
||||||
uid: contentType.uid,
|
uid: contentType.uid,
|
||||||
filename: capitalize(`${contentType.info.singularName}.settings.json`),
|
filename,
|
||||||
dir: path.join(strapi.dir, dir),
|
dir: path.join(strapi.dir, dir),
|
||||||
schema: contentType.__schema__,
|
schema: contentType.__schema__,
|
||||||
};
|
};
|
||||||
|
@ -103,7 +103,7 @@ class Strapi {
|
|||||||
|
|
||||||
return this;
|
return this;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return this.stopWithError(error.message);
|
return this.stopWithError(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,7 +327,7 @@ class Strapi {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.config.autoReload) {
|
if (this.config.get('autoReload')) {
|
||||||
this.server.destroy();
|
this.server.destroy();
|
||||||
process.send('reload');
|
process.send('reload');
|
||||||
}
|
}
|
||||||
|
@ -82,12 +82,11 @@ module.exports = async function({ build, watchAdmin, polling, browser }) {
|
|||||||
polling,
|
polling,
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('message', message => {
|
process.on('message', async message => {
|
||||||
switch (message) {
|
switch (message) {
|
||||||
case 'isKilled':
|
case 'isKilled':
|
||||||
strapiInstance.server.destroy(() => {
|
await strapiInstance.server.destroy();
|
||||||
process.send('kill');
|
process.send('kill');
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { cloneDeep } = require('lodash/fp');
|
const { cloneDeep, kebabCase } = require('lodash/fp');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const { hasDraftAndPublish } = require('@strapi/utils').contentTypes;
|
const { hasDraftAndPublish } = require('@strapi/utils').contentTypes;
|
||||||
const {
|
const {
|
||||||
@ -26,7 +26,7 @@ const createContentType = (uid, definition) => {
|
|||||||
kind: createdContentType.schema.kind || 'collectionType',
|
kind: createdContentType.schema.kind || 'collectionType',
|
||||||
__schema__: pickSchema(definition.schema),
|
__schema__: pickSchema(definition.schema),
|
||||||
modelType: 'contentType',
|
modelType: 'contentType',
|
||||||
modelName: definition.schema.info.singularName,
|
modelName: kebabCase(definition.schema.info.singularName),
|
||||||
connection: 'default',
|
connection: 'default',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ const strapiServerSchema = yup
|
|||||||
services: yup.object().required(),
|
services: yup.object().required(),
|
||||||
policies: yup.object().required(),
|
policies: yup.object().required(),
|
||||||
middlewares: yup.object().required(), // may be removed later
|
middlewares: yup.object().required(), // may be removed later
|
||||||
contentTypes: yup.array().required(),
|
contentTypes: yup.object().required(),
|
||||||
})
|
})
|
||||||
.noUnknown();
|
.noUnknown();
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
const fse = require('fs-extra');
|
const fse = require('fs-extra');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10,7 +11,7 @@ module.exports = strapi => {
|
|||||||
function normalizePath(optPath) {
|
function normalizePath(optPath) {
|
||||||
const filePath = Array.isArray(optPath) ? optPath.join('/') : 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);
|
return path.join(strapi.dir, normalizedPath);
|
||||||
}
|
}
|
||||||
@ -44,6 +45,14 @@ module.exports = strapi => {
|
|||||||
const removePath = normalizePath(optPath);
|
const removePath = normalizePath(optPath);
|
||||||
return fse.remove(removePath);
|
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;
|
return strapiFS;
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { join } = require('path');
|
const { join, resolve } = require('path');
|
||||||
const { existsSync } = require('fs');
|
const { existsSync } = require('fs');
|
||||||
const { defaultsDeep, getOr } = require('lodash/fp');
|
const { defaultsDeep, getOr, get } = require('lodash/fp');
|
||||||
const { env } = require('@strapi/utils');
|
const { env } = require('@strapi/utils');
|
||||||
const loadConfigFile = require('../app-configuration/load-config-file');
|
const loadConfigFile = require('../app-configuration/load-config-file');
|
||||||
|
const loadFiles = require('../../load/load-files');
|
||||||
const getEnabledPlugins = require('./get-enabled-plugins');
|
const getEnabledPlugins = require('./get-enabled-plugins');
|
||||||
|
|
||||||
const defaultPlugin = {
|
const defaultPlugin = {
|
||||||
@ -20,7 +21,33 @@ const defaultPlugin = {
|
|||||||
services: {},
|
services: {},
|
||||||
policies: {},
|
policies: {},
|
||||||
middlewares: {},
|
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 => {
|
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 userPluginConfigPath = join(strapi.dir, 'config', 'plugins.js');
|
||||||
const userPluginsConfig = existsSync(userPluginConfigPath)
|
const userPluginsConfig = existsSync(userPluginConfigPath)
|
||||||
? loadConfigFile(userPluginConfigPath)
|
? loadConfigFile(userPluginConfigPath)
|
||||||
@ -43,13 +70,18 @@ const formatConfig = plugins => {
|
|||||||
for (const pluginName in plugins) {
|
for (const pluginName in plugins) {
|
||||||
const plugin = plugins[pluginName];
|
const plugin = plugins[pluginName];
|
||||||
const userPluginConfig = getOr({}, `${pluginName}.config`, userPluginsConfig);
|
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 {
|
try {
|
||||||
plugin.config.validator(formattedConfig);
|
plugin.config.validator(config);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(`Error regarding ${pluginName} config: ${e.message}`);
|
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) {
|
for (const pluginName in enabledPlugins) {
|
||||||
const enabledPlugin = enabledPlugins[pluginName];
|
const enabledPlugin = enabledPlugins[pluginName];
|
||||||
const loadPluginServer = require(join(enabledPlugin.pathToPlugin, 'strapi-server.js'));
|
const pluginServer = loadConfigFile(join(enabledPlugin.pathToPlugin, 'strapi-server.js'));
|
||||||
const pluginServer = await loadPluginServer({ env });
|
|
||||||
plugins[pluginName] = defaultsDeep(defaultPlugin, pluginServer);
|
plugins[pluginName] = defaultsDeep(defaultPlugin, pluginServer);
|
||||||
}
|
}
|
||||||
// TODO: validate plugin format
|
// TODO: validate plugin format
|
||||||
formatConfig(plugins);
|
applyUserConfig(plugins);
|
||||||
|
await applyUserExtension(plugins);
|
||||||
formatContentTypes(plugins);
|
formatContentTypes(plugins);
|
||||||
|
|
||||||
return plugins;
|
return plugins;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const { toLower, kebabCase, camelCase } = require('lodash/fp');
|
const { toLower, kebabCase, camelCase } = require('lodash/fp');
|
||||||
const { getConfigUrls } = require('@strapi/utils');
|
const { getConfigUrls } = require('@strapi/utils');
|
||||||
|
const pluralize = require('pluralize');
|
||||||
const { createContentType } = require('../domain/content-type');
|
const { createContentType } = require('../domain/content-type');
|
||||||
|
|
||||||
const { createCoreApi } = require('../../core-api');
|
const { createCoreApi } = require('../../core-api');
|
||||||
@ -23,10 +24,10 @@ module.exports = function(strapi) {
|
|||||||
actions: {},
|
actions: {},
|
||||||
lifecycles: {},
|
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.singularName = camelCase(modelName);
|
||||||
ct.schema.info.pluralName = `${camelCase(modelName)}s`;
|
ct.schema.info.pluralName = pluralize(camelCase(modelName));
|
||||||
|
|
||||||
const createdContentType = createContentType(
|
const createdContentType = createContentType(
|
||||||
`api::${apiName}.${kebabCase(ct.schema.info.singularName)}`,
|
`api::${apiName}.${kebabCase(ct.schema.info.singularName)}`,
|
||||||
@ -46,19 +47,21 @@ module.exports = function(strapi) {
|
|||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
// Set controllers.
|
// Set controllers.
|
||||||
strapi.controllers = Object.keys(strapi.api || []).reduce((acc, key) => {
|
strapi.controllers = Object.keys(strapi.api || []).reduce((acc, apiName) => {
|
||||||
for (let index in strapi.api[key].controllers) {
|
strapi.container.get('controllers').add(`api::${apiName}`, strapi.api[apiName].controllers);
|
||||||
let controller = strapi.api[key].controllers[index];
|
for (let controllerName in strapi.api[apiName].controllers) {
|
||||||
acc[index] = controller;
|
let controller = strapi.api[apiName].controllers[controllerName];
|
||||||
|
acc[controllerName] = controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
// Set services.
|
// Set services.
|
||||||
strapi.services = Object.keys(strapi.api || []).reduce((acc, key) => {
|
strapi.services = Object.keys(strapi.api || []).reduce((acc, apiName) => {
|
||||||
for (let index in strapi.api[key].services) {
|
strapi.container.get('services').add(`api::${apiName}`, strapi.api[apiName].services);
|
||||||
acc[index] = strapi.api[key].services[index];
|
for (let serviceName in strapi.api[apiName].services) {
|
||||||
|
acc[serviceName] = strapi.api[apiName].services[serviceName];
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
@ -120,6 +123,7 @@ module.exports = function(strapi) {
|
|||||||
_.forEach(plugin.middlewares, (middleware, middlewareUID) => {
|
_.forEach(plugin.middlewares, (middleware, middlewareUID) => {
|
||||||
const middlewareName = toLower(middlewareUID.split('.')[1]);
|
const middlewareName = toLower(middlewareUID.split('.')[1]);
|
||||||
strapi.plugins[pluginName].middlewares[middlewareName] = middleware;
|
strapi.plugins[pluginName].middlewares[middlewareName] = middleware;
|
||||||
|
strapi.middleware[middlewareName] = middleware;
|
||||||
});
|
});
|
||||||
|
|
||||||
_.forEach(plugin.controllers, (controller, controllerUID) => {
|
_.forEach(plugin.controllers, (controller, controllerUID) => {
|
||||||
|
@ -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 contentTypesRegistry = () => {
|
||||||
const contentTypes = {};
|
const contentTypes = {};
|
||||||
|
|
||||||
@ -30,13 +41,15 @@ const contentTypesRegistry = () => {
|
|||||||
return pickBy((ct, ctUID) => ctUID.startsWith(prefix))(contentTypes);
|
return pickBy((ct, ctUID) => ctUID.startsWith(prefix))(contentTypes);
|
||||||
},
|
},
|
||||||
add(namespace, rawContentTypes) {
|
add(namespace, rawContentTypes) {
|
||||||
rawContentTypes.forEach(rawContentType => {
|
validateKeySameToSingularName(rawContentTypes);
|
||||||
|
for (const rawCtName in rawContentTypes) {
|
||||||
|
const rawContentType = rawContentTypes[rawCtName];
|
||||||
const uid = `${namespace}.${rawContentType.schema.info.singularName}`;
|
const uid = `${namespace}.${rawContentType.schema.info.singularName}`;
|
||||||
if (has(uid, contentTypes)) {
|
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);
|
contentTypes[uid] = createContentType(uid, rawContentType);
|
||||||
});
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
"open": "8.2.1",
|
"open": "8.2.1",
|
||||||
"ora": "^5.4.0",
|
"ora": "^5.4.0",
|
||||||
"package-json": "6.5.0",
|
"package-json": "6.5.0",
|
||||||
|
"pluralize": "8.0.0",
|
||||||
"qs": "^6.10.1",
|
"qs": "^6.10.1",
|
||||||
"resolve-cwd": "^3.0.0",
|
"resolve-cwd": "^3.0.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
const fileModel = require('../../models/File');
|
const fileModel = require('../../models/File');
|
||||||
|
|
||||||
module.exports = [
|
module.exports = {
|
||||||
{
|
[fileModel.info.singularName]: { schema: fileModel },
|
||||||
schema: fileModel,
|
};
|
||||||
},
|
|
||||||
];
|
|
||||||
|
@ -150,7 +150,7 @@ module.exports = ({ strapi }) => ({
|
|||||||
},
|
},
|
||||||
|
|
||||||
async uploadFileAndPersist(fileData, { user } = {}) {
|
async uploadFileAndPersist(fileData, { user } = {}) {
|
||||||
const config = strapi.plugins.upload.config;
|
const config = strapi.config.get('plugin.upload');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
getDimensions,
|
getDimensions,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const pluralize = require('pluralize');
|
|
||||||
|
|
||||||
const SINGLE_TYPE = 'singleType';
|
const SINGLE_TYPE = 'singleType';
|
||||||
const COLLECTION_TYPE = 'collectionType';
|
const COLLECTION_TYPE = 'collectionType';
|
||||||
@ -120,8 +119,8 @@ const isTypedAttribute = (attribute, type) => {
|
|||||||
*/
|
*/
|
||||||
const getContentTypeRoutePrefix = contentType => {
|
const getContentTypeRoutePrefix = contentType => {
|
||||||
return isSingleType(contentType)
|
return isSingleType(contentType)
|
||||||
? _.kebabCase(contentType.modelName)
|
? _.kebabCase(contentType.info.singularName)
|
||||||
: _.kebabCase(pluralize(contentType.modelName));
|
: _.kebabCase(contentType.info.pluralName);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -10,6 +10,6 @@ module.exports = (/* strapi, config */) => {
|
|||||||
services: () => {},
|
services: () => {},
|
||||||
policies: {},
|
policies: {},
|
||||||
middlewares: {},
|
middlewares: {},
|
||||||
contentTypes: [],
|
contentTypes: {},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -2,4 +2,6 @@
|
|||||||
|
|
||||||
const localeModel = require('./locale');
|
const localeModel = require('./locale');
|
||||||
|
|
||||||
module.exports = [localeModel];
|
module.exports = {
|
||||||
|
[localeModel.schema.info.singularName]: localeModel,
|
||||||
|
};
|
||||||
|
@ -199,12 +199,21 @@ const addCreateLocalizationAction = contentType => {
|
|||||||
|
|
||||||
const localizationRoute = createLocalizationRoute(contentType);
|
const localizationRoute = createLocalizationRoute(contentType);
|
||||||
|
|
||||||
const coreApiControllerPath = `api.${apiName}.controllers.${modelName}.createLocalization`;
|
|
||||||
const handler = createLocalizationHandler(contentType);
|
|
||||||
|
|
||||||
strapi.config.routes.push(localizationRoute);
|
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) => {
|
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
|
* Add a graphql schema to the plugin's global graphl schema to be processed
|
||||||
* @param {object} schema
|
* @param {object} schema
|
||||||
*/
|
*/
|
||||||
|
// TODO: to replace with V4 config getter
|
||||||
const addGraphqlSchema = schema => {
|
const addGraphqlSchema = schema => {
|
||||||
_.mergeWith(strapi.plugins.i18n.config.schema.graphql, schema, mergeCustomizer);
|
_.mergeWith(strapi.plugins.i18n.config.schema.graphql, schema, mergeCustomizer);
|
||||||
};
|
};
|
||||||
|
@ -36,7 +36,7 @@ describe('USERS PERMISSIONS | COMPONENTS | UserPermissions | init', () => {
|
|||||||
application: [{ method: 'GET', path: '/addresses' }],
|
application: [{ method: 'GET', path: '/addresses' }],
|
||||||
};
|
};
|
||||||
|
|
||||||
const policies = ['isauthenticated', 'ratelimit', 'custompolicy'];
|
const policies = ['isAuthenticated', 'rateLimit', 'custompolicy'];
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
initialData: permissions,
|
initialData: permissions,
|
||||||
|
@ -2,12 +2,12 @@ import formatPolicies from '../formatPolicies';
|
|||||||
|
|
||||||
describe('USERS PERMISSIONS | utils | formatPolicies', () => {
|
describe('USERS PERMISSIONS | utils | formatPolicies', () => {
|
||||||
it('should format the policies correclty', () => {
|
it('should format the policies correclty', () => {
|
||||||
const policies = ['custompolicies', 'ratelimit', 'isauthenticated'];
|
const policies = ['customPolicies', 'rateLimit', 'isAuthenticated'];
|
||||||
|
|
||||||
const expected = [
|
const expected = [
|
||||||
{ label: 'custompolicies', value: 'custompolicies' },
|
{ label: 'customPolicies', value: 'customPolicies' },
|
||||||
{ label: 'ratelimit', value: 'ratelimit' },
|
{ label: 'rateLimit', value: 'rateLimit' },
|
||||||
{ label: 'isauthenticated', value: 'isauthenticated' },
|
{ label: 'isAuthenticated', value: 'isAuthenticated' },
|
||||||
];
|
];
|
||||||
|
|
||||||
expect(formatPolicies(policies)).toEqual(expected);
|
expect(formatPolicies(policies)).toEqual(expected);
|
||||||
|
@ -31,17 +31,14 @@ module.exports = async () => {
|
|||||||
await getService('users-permissions').initialize();
|
await getService('users-permissions').initialize();
|
||||||
|
|
||||||
// TODO: adapt with new extension system
|
// 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();
|
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;
|
if (!process.env.JWT_SECRET) {
|
||||||
|
await strapi.fs.appendFile('.env', `JWT_SECRET=${jwtSecret}\n`);
|
||||||
await strapi.fs.writePluginFile(
|
}
|
||||||
'users-permissions',
|
|
||||||
'config/jwt.js',
|
|
||||||
`module.exports = {\n jwtSecret: process.env.JWT_SECRET || '${jwtSecret}'\n};`
|
|
||||||
);
|
|
||||||
|
|
||||||
strapi.reload.isWatching = true;
|
strapi.reload.isWatching = true;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ module.exports = async (ctx, next) => {
|
|||||||
prefixKey: `${ctx.request.path}:${ctx.request.ip}`,
|
prefixKey: `${ctx.request.path}:${ctx.request.ip}`,
|
||||||
message,
|
message,
|
||||||
},
|
},
|
||||||
strapi.plugins['users-permissions'].config.ratelimit
|
strapi.config.get('plugin.users-permissions.ratelimit')
|
||||||
)
|
)
|
||||||
)(ctx, next);
|
)(ctx, next);
|
||||||
};
|
};
|
||||||
|
@ -176,7 +176,7 @@
|
|||||||
"path": "/connect/*",
|
"path": "/connect/*",
|
||||||
"handler": "auth.connect",
|
"handler": "auth.connect",
|
||||||
"config": {
|
"config": {
|
||||||
"policies": ["plugin::users-permissions.ratelimit"],
|
"policies": ["plugin::users-permissions.rateLimit"],
|
||||||
"prefix": "",
|
"prefix": "",
|
||||||
"description": "Connect a provider",
|
"description": "Connect a provider",
|
||||||
"tag": {
|
"tag": {
|
||||||
@ -190,7 +190,7 @@
|
|||||||
"path": "/auth/local",
|
"path": "/auth/local",
|
||||||
"handler": "auth.callback",
|
"handler": "auth.callback",
|
||||||
"config": {
|
"config": {
|
||||||
"policies": ["plugin::users-permissions.ratelimit"],
|
"policies": ["plugin::users-permissions.rateLimit"],
|
||||||
"prefix": "",
|
"prefix": "",
|
||||||
"description": "Login a user using the identifiers email and password",
|
"description": "Login a user using the identifiers email and password",
|
||||||
"tag": {
|
"tag": {
|
||||||
@ -204,7 +204,7 @@
|
|||||||
"path": "/auth/local/register",
|
"path": "/auth/local/register",
|
||||||
"handler": "auth.register",
|
"handler": "auth.register",
|
||||||
"config": {
|
"config": {
|
||||||
"policies": ["plugin::users-permissions.ratelimit"],
|
"policies": ["plugin::users-permissions.rateLimit"],
|
||||||
"prefix": "",
|
"prefix": "",
|
||||||
"description": "Register a new user with the default role",
|
"description": "Register a new user with the default role",
|
||||||
"tag": {
|
"tag": {
|
||||||
@ -233,7 +233,7 @@
|
|||||||
"path": "/auth/forgot-password",
|
"path": "/auth/forgot-password",
|
||||||
"handler": "auth.forgotPassword",
|
"handler": "auth.forgotPassword",
|
||||||
"config": {
|
"config": {
|
||||||
"policies": ["plugin::users-permissions.ratelimit"],
|
"policies": ["plugin::users-permissions.rateLimit"],
|
||||||
"prefix": "",
|
"prefix": "",
|
||||||
"description": "Send the reset password email link",
|
"description": "Send the reset password email link",
|
||||||
"tag": {
|
"tag": {
|
||||||
@ -247,7 +247,7 @@
|
|||||||
"path": "/auth/reset-password",
|
"path": "/auth/reset-password",
|
||||||
"handler": "auth.resetPassword",
|
"handler": "auth.resetPassword",
|
||||||
"config": {
|
"config": {
|
||||||
"policies": ["plugin::users-permissions.ratelimit"],
|
"policies": ["plugin::users-permissions.rateLimit"],
|
||||||
"prefix": "",
|
"prefix": "",
|
||||||
"description": "Reset user password with a code (resetToken)",
|
"description": "Reset user password with a code (resetToken)",
|
||||||
"tag": {
|
"tag": {
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
default: {},
|
default: ({ env }) => ({
|
||||||
|
jwtSecret: env('JWT_SECRET'),
|
||||||
|
jwt: {
|
||||||
|
expiresIn: '30d',
|
||||||
|
},
|
||||||
|
ratelimit: {
|
||||||
|
interval: 60000,
|
||||||
|
max: 10,
|
||||||
|
},
|
||||||
|
}),
|
||||||
validator: () => {},
|
validator: () => {},
|
||||||
};
|
};
|
||||||
|
@ -4,14 +4,8 @@ const permissionModel = require('../../models/Permission.settings');
|
|||||||
const roleModel = require('../../models/Role.settings');
|
const roleModel = require('../../models/Role.settings');
|
||||||
const userModel = require('../../models/User.settings');
|
const userModel = require('../../models/User.settings');
|
||||||
|
|
||||||
module.exports = [
|
module.exports = {
|
||||||
{
|
[permissionModel.info.singularName]: { schema: permissionModel },
|
||||||
schema: permissionModel,
|
[roleModel.info.singularName]: { schema: roleModel },
|
||||||
},
|
[userModel.info.singularName]: { schema: userModel },
|
||||||
{
|
};
|
||||||
schema: roleModel,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
schema: userModel,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
@ -39,27 +39,25 @@ module.exports = ({ strapi }) => ({
|
|||||||
},
|
},
|
||||||
|
|
||||||
issue(payload, jwtOptions = {}) {
|
issue(payload, jwtOptions = {}) {
|
||||||
_.defaults(jwtOptions, strapi.plugins['users-permissions'].config.jwt);
|
_.defaults(jwtOptions, strapi.config.get('plugin.users-permissions.jwt'));
|
||||||
return jwt.sign(
|
return jwt.sign(
|
||||||
_.clone(payload.toJSON ? payload.toJSON() : payload),
|
_.clone(payload.toJSON ? payload.toJSON() : payload),
|
||||||
_.get(strapi.plugins, ['users-permissions', 'config', 'jwtSecret']),
|
strapi.config.get('plugin.users-permissions.jwtSecret'),
|
||||||
jwtOptions
|
jwtOptions
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
verify(token) {
|
verify(token) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
jwt.verify(
|
jwt.verify(token, strapi.config.get('plugin.users-permissions.jwtSecret'), {}, function(
|
||||||
token,
|
err,
|
||||||
_.get(strapi.plugins, ['users-permissions', 'config', 'jwtSecret']),
|
tokenPayload = {}
|
||||||
{},
|
) {
|
||||||
function(err, tokenPayload = {}) {
|
if (err) {
|
||||||
if (err) {
|
return reject(new Error('Invalid token.'));
|
||||||
return reject(new Error('Invalid token.'));
|
|
||||||
}
|
|
||||||
resolve(tokenPayload);
|
|
||||||
}
|
}
|
||||||
);
|
resolve(tokenPayload);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -7,10 +7,11 @@ const services = require('./server/services');
|
|||||||
const routes = require('./server/routes');
|
const routes = require('./server/routes');
|
||||||
const controllers = require('./server/controllers');
|
const controllers = require('./server/controllers');
|
||||||
const middlewares = require('./server/middlewares');
|
const middlewares = require('./server/middlewares');
|
||||||
|
const config = require('./server/config');
|
||||||
|
|
||||||
module.exports = () => ({
|
module.exports = () => ({
|
||||||
register: () => {},
|
|
||||||
bootstrap,
|
bootstrap,
|
||||||
|
config,
|
||||||
routes,
|
routes,
|
||||||
controllers,
|
controllers,
|
||||||
middlewares,
|
middlewares,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user