mirror of
https://github.com/strapi/strapi.git
synced 2025-08-07 00:09:23 +00:00
update branch
Merge branch 'plugin/settings-manager-dev' of github.com:soupette/strapi into plugin/settings-manager-dev
This commit is contained in:
commit
53606ae6c9
@ -1 +1,4 @@
|
||||
{}
|
||||
{
|
||||
"menu.section.global-settings": "Global settings",
|
||||
"menu.section.environments": "Environments"
|
||||
}
|
||||
|
@ -2,8 +2,48 @@
|
||||
"routes": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/",
|
||||
"handler": "SettingsManager.index",
|
||||
"path": "/menu",
|
||||
"handler": "SettingsManager.menu",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/environments",
|
||||
"handler": "SettingsManager.environments",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/:slug",
|
||||
"handler": "SettingsManager.get",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/:slug/:env",
|
||||
"handler": "SettingsManager.get",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/:slug",
|
||||
"handler": "SettingsManager.update",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/:slug/:env",
|
||||
"handler": "SettingsManager.update",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
|
@ -1,25 +1,54 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* SettingsManager.js controller
|
||||
*
|
||||
* @description: A set of functions called "actions" of the `settings-manager` plugin.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
menu: async ctx => {
|
||||
const Service = strapi.plugins['settings-manager'].services.settingsmanager;
|
||||
|
||||
/**
|
||||
* Default action.
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
ctx.send(Service.menu);
|
||||
},
|
||||
|
||||
index: async (ctx) => {
|
||||
// Add your own logic here.
|
||||
environments: async ctx => {
|
||||
const Service = strapi.plugins['settings-manager'].services.settingsmanager;
|
||||
|
||||
// Send 200 `ok`
|
||||
ctx.send({
|
||||
message: 'ok'
|
||||
});
|
||||
}
|
||||
ctx.send({ environments: Service.getEnvironments() });
|
||||
},
|
||||
|
||||
get: async ctx => {
|
||||
const Service = strapi.plugins['settings-manager'].services.settingsmanager;
|
||||
const { slug, env } = ctx.params;
|
||||
|
||||
if (env && _.isEmpty(_.find(Service.getEnvironments(), { name: env }))) return ctx.badData('request.error.environment');
|
||||
|
||||
const model = env ? Service[slug](env) : Service[slug];
|
||||
|
||||
if (_.isUndefined(model)) return ctx.badData('request.error.config');
|
||||
|
||||
ctx.send(model);
|
||||
},
|
||||
|
||||
update: async ctx => {
|
||||
const Service = strapi.plugins['settings-manager'].services.settingsmanager;
|
||||
const { slug, env } = ctx.params;
|
||||
let params = ctx.request.body;
|
||||
|
||||
if (env && _.isEmpty(_.find(Service.getEnvironments(), { name: env }))) return ctx.badData('request.error.environment');
|
||||
|
||||
const model = env ? Service[slug](env) : Service[slug];
|
||||
|
||||
if (_.isUndefined(config)) return ctx.badData('request.error.config');
|
||||
|
||||
const items = Service.getItems(model);
|
||||
|
||||
params = Service.cleanParams(params, items);
|
||||
|
||||
let validationErrors = Service.paramsValidation(params, items);
|
||||
|
||||
if (!_.isEmpty(validationErrors)) {
|
||||
return ctx.badData(null, validationErrors);
|
||||
}
|
||||
|
||||
Service.updateSettings(params, items, env);
|
||||
|
||||
ctx.send();
|
||||
},
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "strapi-plugin-settings-manager",
|
||||
"version": "0.0.0",
|
||||
"description": "This is the description of the plugin.",
|
||||
"version": "0.1.0",
|
||||
"description": "Strapi plugin to manage settings.",
|
||||
"strapi": {
|
||||
"name": "settings-manager",
|
||||
"icon": "ion-document-text",
|
||||
@ -24,20 +24,21 @@
|
||||
"test": "echo Tests are not implemented.",
|
||||
"prepublish": "npm run build"
|
||||
},
|
||||
"dependencies": {},
|
||||
"dependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
"strapi-helper-plugin": "3.0.0-alpha.3"
|
||||
},
|
||||
"author": {
|
||||
"name": "A Strapi developer",
|
||||
"email": "",
|
||||
"url": ""
|
||||
"name": "Strapi team",
|
||||
"email": "hi@strapi.io",
|
||||
"url": "http://strapi.io"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "A Strapi developer",
|
||||
"email": "",
|
||||
"url": ""
|
||||
"name": "Strapi team",
|
||||
"email": "hi@strapi.io",
|
||||
"url": "http://strapi.io"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
|
@ -1,11 +1,344 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* SettingsManager.js service
|
||||
*
|
||||
* @description: A set of functions similar to controller's actions to avoid code duplication.
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
menu: {
|
||||
sections: [
|
||||
{
|
||||
name: 'menu.section.global-settings',
|
||||
items: [
|
||||
{
|
||||
slug: 'general',
|
||||
name: 'menu.item.general',
|
||||
icon: 'globe'
|
||||
},
|
||||
{
|
||||
slug: 'languages',
|
||||
name: 'menu.item.languages',
|
||||
icon: 'language'
|
||||
},
|
||||
{
|
||||
slug: 'advenced',
|
||||
name: 'menu.item.advenced',
|
||||
icon: 'cogs'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'menu.section.environments',
|
||||
items: [
|
||||
{
|
||||
slug: 'databases',
|
||||
name: 'menu.item.databases',
|
||||
icon: 'databases'
|
||||
},
|
||||
{
|
||||
slug: 'security',
|
||||
name: 'menu.item.security',
|
||||
icon: 'shield'
|
||||
},
|
||||
{
|
||||
slug: 'server',
|
||||
name: 'menu.item.server',
|
||||
icon: 'server'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
general: {
|
||||
name: 'form.general',
|
||||
description: 'form.general.desc',
|
||||
sections: [
|
||||
{
|
||||
name: '',
|
||||
items: [
|
||||
{
|
||||
name: 'form.general.name',
|
||||
target: 'package.name',
|
||||
type: 'string',
|
||||
value: strapi.config.name,
|
||||
validations : {
|
||||
maxLength: 255,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'form.general.description',
|
||||
target: 'package.description',
|
||||
type: 'string',
|
||||
value: strapi.config.description,
|
||||
validations : {
|
||||
maxLength: 255,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'form.general.version',
|
||||
target: 'package.version',
|
||||
type: 'string',
|
||||
value: strapi.config.version,
|
||||
validations : {
|
||||
maxLength: 255,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
security: env => {
|
||||
return {
|
||||
name: 'form.security',
|
||||
description: 'form.security.desc',
|
||||
sections: [
|
||||
{
|
||||
name: 'form.security.session',
|
||||
items: [
|
||||
{
|
||||
name: 'form.security.session.key',
|
||||
target: 'security.session.key',
|
||||
type: 'string',
|
||||
value: strapi.config.environments[env].security.session.key
|
||||
},
|
||||
{
|
||||
name: 'form.security.session.maxAge',
|
||||
target: 'security.session.maxAge',
|
||||
type: 'number',
|
||||
value: strapi.config.environments[env].security.session.maxAge
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
items: [
|
||||
{
|
||||
name: 'form.security.xframe',
|
||||
target: 'security.xframe',
|
||||
type: 'enum',
|
||||
value: strapi.config.environments[env].security.xframe,
|
||||
items: [
|
||||
{
|
||||
name: 'server.xframe.deny',
|
||||
value: 'DENY',
|
||||
},
|
||||
{
|
||||
name: 'server.xframe.sameorigin',
|
||||
value: 'SAMEORIGIN',
|
||||
},
|
||||
{
|
||||
name: 'server.xframe.allow-from',
|
||||
value: 'ALLOW-FROM',
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'form.security.xssProtection',
|
||||
target: 'security.xssProtection',
|
||||
type: 'boolean',
|
||||
value: strapi.config.environments[env].security.xssProtection
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'form.security.cors',
|
||||
items: [
|
||||
{
|
||||
name: 'form.security.cors.origin',
|
||||
target: 'security.cors.origin',
|
||||
type: 'string',
|
||||
value: strapi.config.environments[env].security.cors.origin,
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
server: env => {
|
||||
return {
|
||||
name: 'form.server',
|
||||
description: 'form.server.desc',
|
||||
sections: [
|
||||
{
|
||||
name: '',
|
||||
items: [
|
||||
{
|
||||
name: 'form.server.host',
|
||||
target: 'server.host',
|
||||
type: 'string',
|
||||
value: strapi.config.environments[env].server.host
|
||||
},
|
||||
{
|
||||
name: 'form.server.port',
|
||||
target: 'server.port',
|
||||
type: 'number',
|
||||
value: strapi.config.environments[env].server.port
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'form.server.parser',
|
||||
items: [
|
||||
{
|
||||
name: 'form.server.parser.xframe',
|
||||
target: 'server.xframe',
|
||||
type: 'enum',
|
||||
value: strapi.config.environments[env].server.xframe,
|
||||
items: [
|
||||
{
|
||||
name: 'server.xframe.deny',
|
||||
value: 'DENY',
|
||||
},
|
||||
{
|
||||
name: 'server.xframe.sameorigin',
|
||||
value: 'SAMEORIGIN',
|
||||
},
|
||||
{
|
||||
name: 'server.xframe.allow-from',
|
||||
value: 'ALLOW-FROM',
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'form.server.xssProtection',
|
||||
target: 'server.xssProtection',
|
||||
type: 'boolean',
|
||||
value: strapi.config.environments[env].server.xssProtection
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'form.server.cors',
|
||||
items: [
|
||||
{
|
||||
name: 'form.server.cors.origin',
|
||||
target: 'server.cors.origin',
|
||||
type: 'string',
|
||||
value: strapi.config.environments[env].server.cors.origin
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
getEnvironments: () => {
|
||||
return _.map(_.keys(strapi.config.environments), environment => {
|
||||
return {
|
||||
name: environment,
|
||||
active: (strapi.config.environment === environment)
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getItems: model => {
|
||||
let items = [];
|
||||
_.forEach(model.sections, section => items = _.concat(items, section.items));
|
||||
|
||||
return items;
|
||||
},
|
||||
|
||||
cleanParams: (params, items) => {
|
||||
const cleanParams = {};
|
||||
|
||||
_.forEach(items, ({ target }) => _.has(params, target) ? _.set(cleanParams, target, _.get(params, target)) : '');
|
||||
|
||||
return cleanParams;
|
||||
},
|
||||
|
||||
paramsValidation: (params, items) => {
|
||||
let errors = [];
|
||||
|
||||
const checkType = (input, { type, target }) => {
|
||||
if ((type === 'string' || type === 'text') && !_.isString(input)) errors.push({
|
||||
target: target,
|
||||
message: 'form.error.type.string'
|
||||
});
|
||||
|
||||
if (type === 'number' && !_.isNumber(input)) errors.push({
|
||||
target: target,
|
||||
message: 'form.error.type.number'
|
||||
});
|
||||
|
||||
if (type === 'boolean' && !_.isBoolean(input)) errors.push({
|
||||
target: target,
|
||||
message: 'form.error.type.boolean'
|
||||
});
|
||||
};
|
||||
|
||||
const checkValidations = (input, item) => {
|
||||
_.forEach(item.validations, (value, key) => {
|
||||
if (key === 'required' && (_.isNull(input) || _.isEmpty(input) || _.isUndefined(input))) errors.push({
|
||||
target: item.target,
|
||||
message: 'form.error.validation.required'
|
||||
});
|
||||
|
||||
if (key === 'max' && parseInt(input) > value) errors.push({
|
||||
target: item.target,
|
||||
message: 'form.error.validation.max'
|
||||
});
|
||||
|
||||
if (key === 'min' && parseInt(input) < value) errors.push({
|
||||
target: item.target,
|
||||
message: 'form.error.validation.min'
|
||||
});
|
||||
|
||||
if (key === 'maxLength' && input.length > value) errors.push({
|
||||
target: item.target,
|
||||
message: 'form.error.validation.maxLength'
|
||||
});
|
||||
|
||||
if (key === 'minLength' && input.length < value) errors.push({
|
||||
target: item.target,
|
||||
message: 'form.error.validation.minLength'
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
_.forEach(items, item => {
|
||||
if (_.has(params, item.target)) {
|
||||
const input = _.get(params, item.target, null);
|
||||
|
||||
checkType(input, item)
|
||||
checkValidations(input, item)
|
||||
}
|
||||
});
|
||||
|
||||
if (!_.isEmpty(errors)) {
|
||||
const grpTarget = _.groupBy(errors, 'target');
|
||||
|
||||
errors = _.map(grpTarget, (errs, target) => {
|
||||
return {
|
||||
target,
|
||||
messages: _.map(errs, err => err.message)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return errors;
|
||||
},
|
||||
|
||||
updateSettings: (params, items, env = '') => {
|
||||
const appPath = process.cwd();
|
||||
|
||||
_.forEach(items, ({ target }) => {
|
||||
if (_.has(params, target)) {
|
||||
const input = _.get(params, target, null);
|
||||
const [file, ...objPath] = target.split('.');
|
||||
|
||||
let filePath = (file === 'package') ? path.join(appPath, 'package.json') : path.join(appPath, 'config', 'environments', env, `${_.replace(file, '.', '/')}.json`);
|
||||
|
||||
const fileContent = require(filePath);
|
||||
|
||||
_.set(fileContent, objPath, input);
|
||||
|
||||
fs.writeFileSync(filePath, JSON.stringify(fileContent, null, 2), 'utf8');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -51,13 +51,19 @@ module.exports = async function(ctx, next) {
|
||||
}
|
||||
|
||||
// Empty body is considered as `notFound` response.
|
||||
if (!ctx.body) {
|
||||
ctx.notFound();
|
||||
if (_.isUndefined(ctx.body) && _.isUndefined(ctx.status)) {
|
||||
return ctx.notFound();
|
||||
}
|
||||
|
||||
// Format `ctx.body` and `ctx.status`.
|
||||
ctx.status = ctx.body.isBoom ? ctx.body.output.statusCode : ctx.status;
|
||||
ctx.body = ctx.body.isBoom ? ctx.body.output.payload : ctx.body;
|
||||
if (_.isObject(ctx.body)) {
|
||||
if (ctx.body.isBoom && ctx.body.data) {
|
||||
ctx.body.output.payload.data = ctx.body.data;
|
||||
}
|
||||
|
||||
// Format `ctx.body` and `ctx.status`.
|
||||
ctx.status = ctx.body.isBoom ? ctx.body.output.statusCode : ctx.status;
|
||||
ctx.body = ctx.body.isBoom ? ctx.body.output.payload : ctx.body;
|
||||
}
|
||||
|
||||
// Call custom responses.
|
||||
if (_.isFunction(_.get(strapi.config, `responses.${ctx.status}`))) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user