Skip to content

Commit

Permalink
Validate array type of types for object without a name when used in c…
Browse files Browse the repository at this point in the history
…ombination with a block type (#1171)

* [default-layout] Fix unique keys and add propTypes for SchemaErrorReporter

* [schema] Don't allow object types without a name when used with a block type
  • Loading branch information
skogsmaskin committed Feb 1, 2019
1 parent 8953864 commit 15ab1f2
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'
import PropTypes from 'prop-types'
import schema from 'part:@sanity/base/schema'
import {SchemaErrors} from './SchemaErrors'
import SchemaErrors from './SchemaErrors'

function renderPath(path) {
return path
Expand Down
43 changes: 34 additions & 9 deletions packages/@sanity/default-layout/src/components/SchemaErrors.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
import React from 'react'
import styles from './styles/SchemaErrors.css'
import PropTypes from 'prop-types'
import ErrorIcon from 'part:@sanity/base/error-icon'
import WarningIcon from 'part:@sanity/base/warning-icon'
import generateHelpUrl from '@sanity/generate-help-url'
import styles from './styles/SchemaErrors.css'

function renderPath(path) {
return path
.map(segment => {
.map((segment, i) => {
const key = `s_${i}`
if (segment.kind === 'type') {
return (
<span className={styles.segment}>
<span className={styles.segment} key={key}>
<span key="name" className={styles.pathSegmentTypeName}>
{segment.name}
</span>
&ensp;<span key="type" className={styles.pathSegmentTypeType}>
&ensp;
<span key="type" className={styles.pathSegmentTypeType}>
{segment.type}
</span>
</span>
)
}
if (segment.kind === 'property') {
return (
<span className={styles.segment}>
<span className={styles.segment} key={key}>
<span className={styles.pathSegmentProperty}>{segment.name}</span>
</span>
)
}
if (segment.kind === 'type') {
return (
<span className={styles.segment}>
<span className={styles.segment} key={key}>
<span key="name" className={styles.pathSegmentTypeName}>
{segment.name}
</span>
Expand All @@ -43,19 +46,19 @@ function renderPath(path) {
.filter(Boolean)
}

export function SchemaErrors(props) {
function SchemaErrors(props) {
const {problemGroups} = props
return (
<div className={styles.root}>
<h2 className={styles.title}>Uh oh… found errors in schema</h2>
<ul className={styles.list}>
{problemGroups.map((group, i) => {
return (
<li key={i} className={styles.listItem}>
<li key={`g_${i}`} className={styles.listItem}>
<h2 className={styles.path}>{renderPath(group.path)}</h2>
<ul className={styles.problems}>
{group.problems.map((problem, j) => (
<li key={j} className={styles[`problem_${problem.severity}`]}>
<li key={`g_${i}_p_${j}`} className={styles[`problem_${problem.severity}`]}>
<div className={styles.problemSeverity}>
<span className={styles.problemSeverityIcon}>
{problem.severity === 'error' && <ErrorIcon />}
Expand All @@ -70,6 +73,7 @@ export function SchemaErrors(props) {
className={styles.problemLink}
href={generateHelpUrl(problem.helpId)}
target="_blank"
rel="noopener noreferrer"
>
View documentation
</a>
Expand All @@ -85,3 +89,24 @@ export function SchemaErrors(props) {
</div>
)
}

SchemaErrors.propTypes = {
problemGroups: PropTypes.arrayOf(
PropTypes.shape({
path: PropTypes.arrayOf(
PropTypes.shape({
kind: PropTypes.string,
type: PropTypes.string,
name: PropTypes.string
})
),
problems: PropTypes.arrayOf(
PropTypes.shape({
severity: PropTypes.string
})
)
}).isRequired
).isRequired
}

export default SchemaErrors
17 changes: 16 additions & 1 deletion packages/@sanity/schema/src/sanity/validation/types/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,25 @@ export default (typeDef, visitorContext) => {
HELP_IDS.ARRAY_OF_INVALID
)
])
const of = ofIsArray ? typeDef.of : []

// Don't allow object types without a name in block arrays
const hasObjectTypesWithoutName = of.some(
type => type.type === 'object' && typeof type.name === 'undefined'
)
const hasBlockType = of.some(ofType => ofType.type === 'block')
if (hasBlockType && hasObjectTypesWithoutName) {
problems.push(
error(
"The array type's 'of' property can't have an object type without a 'name' property as member, when the 'block' type is also a member of that array.",
HELP_IDS.ARRAY_OF_INVALID
)
)
}

return {
...typeDef,
of: (ofIsArray ? typeDef.of : []).map(visitorContext.visit),
of: of.map(visitorContext.visit),
_problems: problems
}
}

0 comments on commit 15ab1f2

Please sign in to comment.