Make WordPress Core

Opened 18 months ago

Last modified 18 months ago

#57312 new defect (bug)

pattern validation fails in case of multitype validation using WP JSON REST

Reported by: joeyojoeyo12's profile joeyojoeyo12 Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version:
Component: REST API Keywords:
Focuses: Cc:

Description (last modified by TimothyBlynJacobs)

Just as this https://core.trac.wordpress.org/ticket/56483 question for which I'm still waiting for a reply; I seemingly found another issue when trying to validate the input via oneOf. Concretely, I'm trying to validate that an object has:

  • pattern properties
  • with values being either a ^none$ string or a an array of strings matching another regex, like ^[A-Z][a-z]{5}[0-9]$.

Try to submit your data via the js FormData API which holds an object that should validate against sth like this:

[
    'type' => 'object',
    'patternProperties' => [
        '$[a-z]{5}$' => [
            'type' => [
                'array',
                'string',
            ],
            'pattern' => '^none$',
            'items' => [
                'type' => 'string',
                'pattern' => '^[A-Z][a-z]{5}[0-9]$',
            ],
            'uniqueItems' => true,
            'required' => true,
        ],
    ],
    'additionalProperties' => false,
    'minProperties' => 1,
    'required' => true,
]

If you submit something like:

{
  "my_data":{
    "abcde":"none"
  }
}

It will result in a Bad Request error, telling you that my_data[abcde] does not match with ^none$.

I've tried to use "enum": ["none"] instead of "pattern": "^none$", which is when it also responds with a 400 Bad Request, saying that my_data[abcde] is not none.

Seems like a bug?

Change History (1)

#1 @TimothyBlynJacobs
18 months ago

  • Description modified (diff)

Note: There is a typo on the schema. Your patternProperty definition is using a $ for the start of string declaration instead of a ^. After correcting that, this is the error I'm getting.

my_data[abcde][0] does not match pattern ^[A-Z][a-z]{5}[0-9]$

The REST API needs to support type juggling so when you declare a list of types to support, it will find the first type based match and continue validating against that.

The validator is thus able to accept none as an array and will then proceed to use array validation for which the items keyword applies. However, what you'll want to do is flip the order so a string type will match first.

The pattern keyword only applies to string types, so if an array is passed, it won't try to assert that it matches the ^none$ regex. However, enum can apply to any type. So by setting an enum of [ "none" ] you are declaring that my_data must be a dictionary with 5 letter keys where each value must be "none".

The corrected schema is:

[
	'type'                 => 'object',
	'patternProperties'    => [
		'^[a-z]{5}$' => [
			'type'        => [
				'string',
				'array',
			],
			'pattern'     => '^none$',
			'items'       => [
				'type'    => 'string',
				'pattern' => '^[A-Z][a-z]{5}[0-9]$',
			],
			'uniqueItems' => true,
			'required'    => true,
		],
	],
	'additionalProperties' => false,
	'minProperties'        => 1,
	'required'             => true,
]

However, I'd recommend using oneOf in this case to have a simpler to understand schema.

[
	'type'                 => 'object',
	'patternProperties'    => [
		'^[a-z]{5}$' => [
			'oneOf' => [
				[
					'type' => 'string',
					'enum' => [ 'none' ]
				],
				[
					'type'        => 'array',
					'items'       => [
						'type'    => 'string',
						'pattern' => '^[A-Z][a-z]{5}[0-9]$',
					],
					'uniqueItems' => true,
				]
			],
		],
	],
	'additionalProperties' => false,
	'minProperties'        => 1,
	'required'             => true,
]

It has the side-effect of allowing a type upgrade from a string value to an array. For instance, "Aabcde1" is accepted, not only [ "Aabcde1" ].

Note: See TracTickets for help on using tickets.