diff --git a/packages/strapi-plugin-content-manager/controllers/ContentTypes.js b/packages/strapi-plugin-content-manager/controllers/ContentTypes.js index d7e0570425..1ebfd5549e 100644 --- a/packages/strapi-plugin-content-manager/controllers/ContentTypes.js +++ b/packages/strapi-plugin-content-manager/controllers/ContentTypes.js @@ -106,9 +106,14 @@ module.exports = { return ctx.notFound('contentType.notFound'); } + const schema = service.formatContentTypeSchema(contentType); + let input; try { - input = await createModelConfigurationSchema(contentType).validate(body, { + input = await createModelConfigurationSchema( + contentType, + schema + ).validate(body, { abortEarly: false, stripUnknown: true, strict: true, @@ -130,7 +135,7 @@ module.exports = { const data = { uid, source, - schema: service.formatContentTypeSchema(contentType), + schema, ...contentTypeConfigurations, }; diff --git a/packages/strapi-plugin-content-manager/controllers/Groups.js b/packages/strapi-plugin-content-manager/controllers/Groups.js index 36c54cf0c7..209167b5ed 100644 --- a/packages/strapi-plugin-content-manager/controllers/Groups.js +++ b/packages/strapi-plugin-content-manager/controllers/Groups.js @@ -56,17 +56,23 @@ module.exports = { const group = strapi.groups[uid]; + const ctService = strapi.plugins['content-manager'].services.contenttypes; + if (!group) { return ctx.notFound('group.notFound'); } + const schema = ctService.formatContentTypeSchema(group); let input; try { - input = await createModelConfigurationSchema(group).validate(body, { - abortEarly: false, - stripUnknown: true, - strict: true, - }); + input = await createModelConfigurationSchema(group, schema).validate( + body, + { + abortEarly: false, + stripUnknown: true, + strict: true, + } + ); } catch (error) { return ctx.badRequest(null, { name: 'validationError', @@ -77,12 +83,11 @@ module.exports = { const groupService = strapi.plugins['content-manager'].services.groups; await groupService.setConfiguration(uid, input); - const ctService = strapi.plugins['content-manager'].services.contenttypes; const configurations = await groupService.getConfiguration(uid); const data = { uid, - schema: ctService.formatContentTypeSchema(group), + schema, ...configurations, }; diff --git a/packages/strapi-plugin-content-manager/controllers/validation/model-configuration.js b/packages/strapi-plugin-content-manager/controllers/validation/model-configuration.js index bfcb9dbd92..5f33d50596 100644 --- a/packages/strapi-plugin-content-manager/controllers/validation/model-configuration.js +++ b/packages/strapi-plugin-content-manager/controllers/validation/model-configuration.js @@ -1,30 +1,28 @@ 'use strict'; const yup = require('yup'); - +const { + isListable, + hasRelationAttribute, + hasEditableAttribute, +} = require('../../services/utils/configuration/attributes'); /** * Creates the validation schema for content-type configurations */ -module.exports = model => +module.exports = (model, schema) => yup .object() .shape({ - settings: createSettingsSchema(model), - metadatas: createMetadasSchema(model), - layouts: createLayoutsSchema(model), + settings: createSettingsSchema(model, schema), + metadatas: createMetadasSchema(model, schema), + layouts: createLayoutsSchema(model, schema), }) .noUnknown(); -// TODO: do sth to clean the keys configurable, private etc - -const createSettingsSchema = model => { - const validAttributes = Object.keys(model.allAttributes).filter(key => { - return ( - model.allAttributes[key].type && - !['json', 'password', 'group'].includes(model.allAttributes[key].type) - ); - }); - const attrs = ['id'].concat(validAttributes); +const createSettingsSchema = (model, schema) => { + const validAttributes = Object.keys(schema.attributes).filter(key => + isListable(schema, key) + ); return yup .object() @@ -41,12 +39,12 @@ const createSettingsSchema = model => { // should be reset when the type changes mainField: yup .string() - .oneOf(attrs) + .oneOf(validAttributes) .default('id'), // should be reset when the type changes defaultSortBy: yup .string() - .oneOf(attrs) + .oneOf(validAttributes) .default('id'), defaultSortOrder: yup .string() @@ -56,9 +54,9 @@ const createSettingsSchema = model => { .noUnknown(); }; -const createMetadasSchema = model => { +const createMetadasSchema = (model, schema) => { return yup.object().shape( - ['id'].concat(Object.keys(model.allAttributes)).reduce((acc, key) => { + Object.keys(schema.attributes).reduce((acc, key) => { acc[key] = yup .object() .shape({ @@ -97,18 +95,18 @@ const ARRAY_TEST = { test: val => Array.isArray(val), }; -const createLayoutsSchema = model => { - const validAttributes = Object.keys(model.allAttributes).filter(key => { - return ( - model.allAttributes[key].type && - !['json', 'password', 'group'].includes(model.allAttributes[key].type) - ); - }); +const createLayoutsSchema = (model, schema) => { + const validAttributes = Object.keys(schema.attributes).filter(key => + isListable(schema, key) + ); - const attrs = ['id'].concat(validAttributes); - const relationAttributes = Array.isArray(model.associations) - ? model.associations.map(assoc => assoc.alias) - : []; + const editAttributes = Object.keys(schema.attributes).filter(key => + hasEditableAttribute(schema, key) + ); + + const relationAttributes = Object.keys(schema.attributes).filter(key => + hasRelationAttribute(schema, key) + ); return yup.object().shape({ edit: yup @@ -120,11 +118,7 @@ const createLayoutsSchema = model => { .shape({ name: yup .string() - .oneOf( - Object.keys(model.allAttributes).filter( - key => model.allAttributes[key].type - ) - ) + .oneOf(editAttributes) .required(), size: yup .number() @@ -138,7 +132,7 @@ const createLayoutsSchema = model => { .test(ARRAY_TEST), list: yup .array() - .of(yup.string().oneOf(attrs)) + .of(yup.string().oneOf(validAttributes)) .test(ARRAY_TEST), editRelations: yup .array() diff --git a/packages/strapi-plugin-content-manager/services/utils/configuration/attributes.js b/packages/strapi-plugin-content-manager/services/utils/configuration/attributes.js index 573d9d88d9..dc33f1e5a9 100644 --- a/packages/strapi-plugin-content-manager/services/utils/configuration/attributes.js +++ b/packages/strapi-plugin-content-manager/services/utils/configuration/attributes.js @@ -3,6 +3,10 @@ const _ = require('lodash'); const NON_SORTABLES = ['group', 'json', 'relation']; + +const isListable = (schema, name) => + isSortable(schema, name) && schema.attributes[name].type != 'password'; + const isSortable = (schema, name) => { if (!_.has(schema.attributes, name)) { return false; @@ -49,9 +53,37 @@ const isTimestamp = (schema, name) => { const isRelation = attribute => attribute.type === 'relation'; +const hasRelationAttribute = (schema, name) => { + if (!_.has(schema.attributes, name)) { + return false; + } + + return isRelation(schema.attributes[name]); +}; + +const hasEditableAttribute = (schema, name) => { + if (!_.has(schema.attributes, name)) { + return false; + } + + if (!isVisible(schema, name)) { + return false; + } + + if (isRelation(schema.attributes[name])) { + if (schema.modelType === 'group') return true; + return false; + } + + return true; +}; + module.exports = { isSortable, isVisible, isSearchable, isRelation, + isListable, + hasEditableAttribute, + hasRelationAttribute, }; diff --git a/packages/strapi-plugin-content-manager/services/utils/configuration/layouts.js b/packages/strapi-plugin-content-manager/services/utils/configuration/layouts.js index 4715b3363f..831f4521a4 100644 --- a/packages/strapi-plugin-content-manager/services/utils/configuration/layouts.js +++ b/packages/strapi-plugin-content-manager/services/utils/configuration/layouts.js @@ -1,7 +1,12 @@ 'use strict'; const _ = require('lodash'); -const { isSortable, isVisible, isRelation } = require('./attributes'); +const { + isListable, + isVisible, + hasEditableAttribute, + hasRelationAttribute, +} = require('./attributes'); const DEFAULT_LIST_LENGTH = 4; const MAX_ROW_SIZE = 12; @@ -37,7 +42,7 @@ async function createDefaultLayouts(schema) { function createDefaultListLayout(schema) { return Object.keys(schema.attributes) - .filter(name => isSortable(schema, name)) + .filter(name => isListable(schema, name)) .slice(0, DEFAULT_LIST_LENGTH); } @@ -67,7 +72,7 @@ function syncLayouts(configuration, schema) { const { list = [], editRelations = [], edit = [] } = configuration.layouts || {}; - const cleanList = list.filter(attr => isSortable(schema, attr)); + const cleanList = list.filter(attr => isListable(schema, attr)); const cleanEditRelations = editRelations.filter(attr => hasRelationAttribute(schema, attr) @@ -120,13 +125,13 @@ function syncLayouts(configuration, schema) { // only add valid listable attributes layout.list = _.uniq( layout.list - .concat(newAttributes.filter(key => isSortable(schema, key))) + .concat(newAttributes.filter(key => isListable(schema, key))) .slice(0, DEFAULT_LIST_LENGTH) ); } // add new relations to layout - if (schema.type !== 'group') { + if (schema.modelType !== 'group') { const newRelations = newAttributes.filter(key => hasRelationAttribute(schema, key) ); @@ -171,31 +176,6 @@ const appendToEditLayout = (layout = [], keysToAppend, schema) => { return layout; }; -const hasRelationAttribute = (schema, name) => { - if (!_.has(schema.attributes, name)) { - return false; - } - - return isRelation(schema.attributes[name]); -}; - -const hasEditableAttribute = (schema, name) => { - if (!_.has(schema.attributes, name)) { - return false; - } - - if (!isVisible(schema, name)) { - return false; - } - - if (isRelation(schema.attributes[name])) { - if (schema.modelType === 'group') return true; - return false; - } - - return true; -}; - module.exports = { createDefaultLayouts, syncLayouts, diff --git a/packages/strapi-plugin-content-manager/services/utils/schema.js b/packages/strapi-plugin-content-manager/services/utils/schema.js index 430764c6aa..0d7134550e 100644 --- a/packages/strapi-plugin-content-manager/services/utils/schema.js +++ b/packages/strapi-plugin-content-manager/services/utils/schema.js @@ -4,6 +4,7 @@ const _ = require('lodash'); const pickSchemaFields = model => _.pick(model, [ + 'modelType', 'connection', 'collectionName', 'info',