Problem
User entity validation misses some of the logic from AccountForm::validate(), and the logic is duplicated there. This is critical as the validation logic will be missed from RESTful validation. (see #1696648: [META] Untie content entity validation from form validation)
The missing validation is logic is related only to automatic validation done by FAPI else, i.e. allowed values validation from signature formats or timezones. In alternative to fixing validation only, the completion of the following issues would (most likely) address this issue also:
#2227381: Apply formatters and widgets to User base fields 'name' and 'email'
#1548204: Remove user signature and move it to contrib
Proposed resolution
Convert the logic to entity validation and leverage entity validation in form validation.
Remaining tasks
Implement proposed resolution.
User interface changes
-
API changes
-
| Comment | File | Size | Author |
|---|---|---|---|
| #38 | d8_validate_user.interdiff.txt | 1.19 KB | fago |
| #38 | d8_validate_user.patch | 27.38 KB | fago |
| #34 | d8_validate_user.interdiff.txt | 3.19 KB | fago |
| #34 | d8_validate_user.patch | 27.26 KB | fago |
| #32 | d8_validate_user.patch | 26.79 KB | fago |
Comments
Comment #1
fagoComment #2
larowlanI think I could talk someone with some plugins experience through this
Comment #3
berdirActually, I think we have all of this covered?
User name: Check
User unique: Check
Mail unique: Check
Signature: Check (this is using the field definition max_length, so...)
We also have tests for this in UserValidationTest
However, there are some parts here that better hidden and are not so easy to do. Specifically, that is the part about having to provide the existing password when you want to change the password, username or e-mail. That's dynamic, optional validation depending on the fact whether another field changes or not. I don't think we can deal with that at the moment, and we can also not map that concept to REST at all as far as I can see?
I saw an issue open about this, but this example might be even complexer than that? Assigning to @fago for feedback.
Comment #4
berdirSee also how https://www.drupal.org/node/2227381 removes most of the validation, not yet the signature, but I assume that can be removed as well.
Comment #5
jibranCan we ping @fago about it?
Comment #6
mikey_p commentedInitial patch that adds a validation for signature length and modifies AccountForm::validate() to use the entity validation instead of it's own. I don't think this should be blocked by #2227381: Apply formatters and widgets to User base fields 'name' and 'email' since when that goes through the validation will still be needed and we can just remove the extra lines from AccountForm::validate() that call the entity validations.
Comment #8
berdirWhy add a custom constraint that is doing exactly the same as the one we already have by default? You even updated the test to assert for both?
Comment #9
mikey_p commentedThat makes a lot of sense, I was just trying to keep the error messages consistent with the existing messages. I suppose that would be easy to do with a constraint that uses validatedBy()?
Comment #10
mikey_p commentedRemoved the custom validator for now, I wish it was easier to customize those error messages, but this should work for now.
Not sure what's up with the UserRegistrationTest, I updated the strings, but it's still failing for me.
Comment #11
mikey_p commentedBah, forgot to rebase the old branch. Here's the correct interdiff.
Comment #12
mikey_p commentedComment #14
mikey_p commentedNot sure why I didn't see that earlier.
Comment #15
berdirInteresting, I looked at my patch in the widget issue and I did the same. The problem is that registration and existing users use a different validation message in HEAD. I'm not sure if taken or registered is better, registered kind of feels better to me?
Comment #16
berdirAlso, looks like we have no validation on the signature length as no fixes were necessary for that, maybe we should add a simple check for that to one of the tests, just to make sure that everything is wired together correctly?
Comment #17
mikey_p commentedre #15: Yeah the only place the old string was used in core was in AccountForm.php.
re #16: We already have the test in UserValidationTest. Did you want to add something to UserEditTest?
Comment #18
berdirI think it would be good to have a web test for that as well yes, UserEditTest sounds fine. UserValidationTest does not and can not test that we are calling the validation of the signature in the form and we're calling it on the right values (e.g., making sure that we assign the values first, as we currently have to do that manually).
Comment #19
dawehnerI agree with berdir that a dedicated UI test is helpful.
I love how nice this looks like!
It would be nice to open up a follow up to convert signature into a single TextItem.
Comment #20
mikey_p commentedre #2: I think that's what #1548204: Remove user signature and move it to contrib covers?
Comment #21
dawehner@mikey_p
Cool, just added that as a related issue
Comment #22
mikey_p commentedTest that the form validation calls out to entity validation.
Comment #23
dashaforbes commentedTested Maximum length of user signature:
Comment #24
fagoPatch looks quite good already. @berdir: Yep, that validation logic is mostly already there, just not added in. Afaics only signature format allowed value validation is missing. Corrected the summary.
Looking closer at allowed values - stuff that I see missing else:
- Timezone allowed values validation
- User status allowed values validation(that's covered, as it's a boolean)- Language allowed values validation (applies to all content entities :/)
- Preferred language, preferred_admin_langcode allowed values validation
For fixing the allowed values validation #2329937: Allow definition objects to provide options would be good to have, but I think we should be able to go with the AllowedValues constraint and a respective callback also meanwhile. That said, we might have missed allowed values validation for other entities so far probably also - I'll check them.
Also, it would make sense to validate we've got a filter format when a signature is set, but as filter formats appear to be required only when filter module is enabled it's probably ok to not validate that, i.e. we'd generally make the filter format optional. But then, it's only rendered with formats by comment module - so that whole area is a bit strange.
Interesting special casing here. Looking up the mail base field, it's not required - making that an issue also as it allows removing mail addresses what should not be the case :/ I'm not sure why we allow accounts without mail address anyway? :/
hm, that's indeed interesting as it means it has interesting security implications if you enable REST updates for user accounts. It's tricky, but given the security implications I think that needs to be addressed?
I think it could be solved on REST level only as you need to know the user input in order to be able to validate it. So this sounds like some extra user validation that REST could add in for security?
Comment #25
fagooh, here a quick re-roll fixing some comments and demonstrating missing allowed values for signature formats -> it should fail on that.
Comment #27
fagoFirst patch attached. This should cover everything except
- required mail
- tightened validation for name, mail or password changes
validation. It generally adds in validation for language references, what might cause some tests to fail which go with invalid values. Let's see.
Comment #28
fagoComment #29
fagoComment #31
fagook, addressed the patch fails.
I had some fun with the default value of 'preferred_admin_langcode', which was '' - but that's not a valid language nor NULL. As I explained in #2318605-54: uuid, created, changed, language default value implementations need to be updated a default value of NULL does not work either, so I had to add a work-a-round with a @todo to fix it there instead. Finally I noticed that the form ignores the default value anyway, and does something else: Noted that at #2227381: Apply formatters and widgets to User base fields 'name' and 'email' which should fix that I think. At least, the test respects the default value and should be green now.
Comment #32
fagoAlso added a constraint for the e-mail validation. Given that, this should be complete except for #2418119: REST user updates bypass tightened user account change validation.
As it's not clear how #2418119: REST user updates bypass tightened user account change validation should be solved, I filed it as a separate issue so we can move on here. Please provide your comments regarding this issue there.
Updated patch attached.
Comment #33
klausiPatch looks good, test cases seem sufficient. I agree that we should split off the security issue regarding password changes to #2418119: REST user updates bypass tightened user account change validation. Only some minor nitpicks:
2 violations here, so we should also assert the second message here.
what's up with the signature here, why do we have to populate it manually? Please add a comment.
why do we have to trigger the validation manually here? Why does parent::validate() fail us here? Please add a comment.
Description is missing, like "The machine names of allowed filter formats."
Same here.
And here.
Comment #34
fagoThanks for the review.
4,5,6: Right, I felt like repeating this method description here for internal helpers isn't worth it, but yeah it's coding standard, thus added it.
Addressed 1,2,3 also.
Comment #35
mikey_p commentedShould we add a corresponding section in UserEditTest for each of these validations?
Comment #36
fagoI don't think it's an issue as all of those follow the same code-flow + it's there only temporarily until #2395831: Entity forms skip validation of fields that are not in the EntityFormDisplay fixes it in general.
Comment #37
klausiGreat, almost ready. I missed a couple of nitpicks last time:
@return description missing.
Not really creative, but OK :-P
doc blocks are missing.
Comment #38
fagook, here you go.
Comment #39
klausiLooks good, assuming the testbot comes back green.
Comment #40
effulgentsia commentedYay to see this RTBC! Also, confirmed the criticality of this with the branch maintainers.
Comment #41
alexpottThis issue addresses a critical bug and is allowed per https://www.drupal.org/core/beta-changes. Committed 17c2500 and pushed to 8.0.x. Thanks!
There is an issue to issue this right? #2002180: Entity forms skip validation of fields that are edited without widgets?
Comment #43
fagoThanks! Yep, correct - we could have pointed to that issue here. Anyway, we'll have to work over it there.