Problem/Motivation
The implementation of PasswordItem::preSave() contains multiple errors.
if ($entity->isNew()) {
$this->value = \Drupal::service('password')->hash(trim($this->value));
if (!$this->value) {
throw new EntityMalformedException('The entity does not have a password.');
}
}
If an empty string is passed as password value for a new entity, the value that gets stored is the hash of an empty string. So the value is set instead of throwing an Exception with 'The entity does not have a password.'.
Now to something really dangerous:
The PasswordItem is a normal field. For example it can be used to store a password on an entity that implements a custom web service. Therefor this field could be translatable.
Saving an empty password on an existing entity means keeping the password that is stored in database.
if (!$entity->isNew()) {
// If the password is empty, that means it was not changed, so use the
// original password.
if (empty($this->value)) {
$this->value = $entity->original->{$this->getFieldDefinition()->getName()}->value;
}
}
What happens here is that all passwords of all translations are set to the value of the "untranslated" entity on save!
Proposed resolution
PasswordItem::preSave() needs to be completely rewritten to deal with Translations and to remove the code that is erroneous even for untranslated password fields.
Remaining tasks
Review the existing patch.
User interface changes
none
API changes
none
Data model changes
none