Problem/Motivation

Creating nodes from REST I have detected that I can create new nodes with empty title.

TypedData\Map's implementation of ::isEmpty() does strict type checking, so "" is not considered an empty value and hence passes the NotNull validation.

However, user module implicitly relies on this behaviour as during user_install it creates a user with no name (UID 0). So this means fixing it to treat "" as empty breaks in spectacular fashion.

Because our validation API does not in fact validate required fields, this could lead to data integrity issues and could result in some fairly hairy update hooks to repair broken stuff.

There are other issues in the queue around 'unable to remove empty text fields', probably the same issue as this. E.g. #2349819: String field type doesn't consider empty string as empty value

Proposed resolutions

Two possible fixes:

  1. Sub-class StringItem for username (UsernameItem) and don't consider "" empty in that case. Change Map to consider "" as empty (as well as NULL). Change User to use UsernameItem. The existing UserName constraint will validate users (other than the one created in user_install()). -OR-
  2. Force anonymous user to have a username - e.g. 'anonymous' and make this a reserved username (See #18)
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Status: Needs review » Needs work

The last submitted patch, field_validation-only-test.patch, failed testing.

larowlan’s picture

Issue tags: +Entity Field API
Berdir’s picture

Title: Field validation does not work as expected. » NotNull validation constraint does not fail on empty strings
Assigned: Unassigned » fago

Better title :)

This is really bad, I don't know why we didn't figure this out earlier?

NotNullValidator really is a !== NULL check.

I can currently see two ways to fix this:

a) Make it also fail on empty strings (like the UI which depends on form API for this does).

b) Somehow *reliably* filter out empty field items before running the validation.

The last submitted patch, field_validation-only-test.patch, failed testing.

fago’s picture

Assigned: fago » Unassigned

I think, validation should match the field's isEmpty() logic - so if that fails also this is probably the problem.

NotNullValidator really is a !== NULL check.

Right. I've been already thinking whether it would make sense to provide a custom NotEmpty constraint instead of just relying on symfony ones. Right now, the validator does extra massaging of the values to make empty data structures NULL to make it work, see PropertyContainerMetadata::accept(). So maybe the problem here is just a not good isEmpty() implementations of the field type?

Howsoever, my thought was that NotEmpty constraint could just work with the object and call $typed_data->isEmpty() itself, what should help simplifying the validator logic. Not sure it's related, depending on where the bug really is here.

marthinal’s picture

From Rest I'm updating fields for users. I've detected that the situation is the same. I can update the value of a required field with an empty string and in this way you can remove the data from fields...

I think that this patch fixes the problem, at least for user update and when creating a node. I was testing from the rest client so let's take a look at the results.

Status: Needs review » Needs work

The last submitted patch, 7: 2444585-6.patch, failed testing.

The last submitted patch, 7: field_validation-only-2444585-6-test.patch, failed testing.

larowlan’s picture

Priority: Major » Critical
Issue tags: +Needs Drupal 8 critical triage

Discussed with @webchick, given this involves data loss (see last comment) this may in fact need to be critical.

Feel free to drop back.

larowlan’s picture

Removing the tag

larowlan’s picture

Assigned: Unassigned » larowlan

kicking along as per #6

larowlan’s picture

Status: Needs work » Needs review
FileSize
1.5 KB

I think we have a few issues in the queue around not being able to remove string/text fields in multi-value setups.

This might solve those too.

We might need similar treatments for numeric fields.

Status: Needs review » Needs work

The last submitted patch, 13: notnull-constraint-2444585.2.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
1.14 KB
1.82 KB

Or maybe this approach

Status: Needs review » Needs work

The last submitted patch, 15: notnull-constraint-2444585.15.patch, failed testing.

larowlan’s picture

Issue summary: View changes

gold, user_install() relies on creating an invalid user, with an empty username, despite the UserName constraint considering this invalid.

larowlan’s picture

Status: Needs work » Needs review
FileSize
3.01 KB
4.83 KB

Perhaps we can make anonymous a reserved username
Short of that we can make user-name its own item type, we already did that for password.

dawehner’s picture

+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringItem.php
@@ -100,4 +100,24 @@ public function storageSettingsForm(array &$form, FormStateInterface $form_state
+      if (!$definition->isComputed() && $property->getValue() !== NULL && $property->getValue() !== "") {

How can any of the properties of a StringItem be computed? IMHO I just see value in there, so this maybe need some documentation? Let's also use single quotes :P

Status: Needs review » Needs work

The last submitted patch, 18: notnull-constraint-2444585.16.patch, failed testing.

larowlan’s picture

Assigned: larowlan » Unassigned
Issue summary: View changes

New issue summary

larowlan’s picture

amateescu’s picture

Status: Needs work » Closed (duplicate)

Yes, it's a duplicate of #2349819: String field type doesn't consider empty string as empty value. Let's make sure we bring the test from #7 to the patch over there.

larowlan’s picture

@marthinal can you comment over on #2349819: String field type doesn't consider empty string as empty value so you can be added to credits - ta