Problem/Motivation
The tests are currently failing. One of the failure cases is this:
1. Register a user. Add an alternative email address.
2. Register a second user. It is possible to set the email address for this second user to the alternative email address of the first user.
I have tried to debug this, and it seems that the UserMailUnique constraint, which calls UniqueFieldValueValidator.php, does not get its query altered.
When I change an email address, alternative_user_emails_entity_query_user_alter() is called as part of AlternativeUserEmailsValidator, but it is not called for UniqueFieldValidator.
I am wondering if this is because this module uses a specific hook (entity_query_user_alter()), while the query in UniqueFieldValueValidator looks like this:
// Check if any item values for this field already exist in other entities.
$query = $this->entityTypeManager
->getStorage($entity_type_id)
->getAggregateQuery()
->accessCheck(FALSE)
->condition($field_name, $item_values, 'IN')
->groupBy("$field_name.$property_name");
if (!$is_new) {
$entity_id = $entity->id();
$query->condition($id_key, $entity_id, '<>');
}
$results = $query->execute();
Any insight or guesses you have would be much appreciated.
Issue fork alternative_user_emails-3425655
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
ptmkenny commentedOk, I made some progress debugging this.
To core's UniqueFieldValueValidator query,
I manually added the query alter:
By manually executing the query alter, the query returns the correct result (in this case, the correct result is the primary email address of the other user account that has the alternate email address that you are attempting to register).
However, the validator still fails because of the results evaluation logic:
What happens here is that core compares whether the email address to be registered (which is an alternate email address) is a duplicate value of the primary email address of the account that has the alternate email address registered. This check fails, but it should pass.
So perhaps the best approach is to override UserMailUnique with a custom validator?
Comment #3
jonathanshawYou're right, we've got smacked by #2478663: UniqueFieldValueValidator works only with single value fields.
That sounds like a sane and maintainable solution. It was kind of neat before that just altering the entity query took care of validation magically, but a custom validator is fine.
Comment #5
ptmkenny commentedOk, it turns out we can use hook_validation_constraint_alter() to replace the UserMailUnique constraint with the AlternativeUserEmailsUnique constraint already provided by this module, and the tests now pass.
I did a little refactor to break the validation loop as soon as a bad (duplicate) email is found.
@jonathanshaw What do you think of this solution?
Comment #6
ptmkenny commentedComment #7
jonathanshawIt's a good solution.
However AltenativeUserEmailsValidator does this:
so the tests shouldn't be passing, which is a little concerning.
I don't see why we can't just remove that whole early return block. What's the harm if people want to use this validator somewhere else, that's up to them.
Comment #8
ptmkenny commentedOh, the reason the tests are passing is because I refactored that block into a method:
We can remove it, though. As you said people should be free to use the validator as they like.
Comment #9
ptmkenny commentedComment #11
ptmkenny commentedComment #12
jonathanshawThis message: 'The alternative email address %value is already associated with another user account.' is no longer quite right if this validator is being used on the core 'mail' field as well.
Comment #15
ptmkenny commentedOk, I removed "alternative" from the string!
That was definitely an oversight.