Commit b6e74cf3 authored by catch's avatar catch
Browse files

Issue #3238227 by alexpott:...

Issue #3238227 by alexpott: \Drupal\Core\Field\Plugin\Field\FieldType\PasswordItem causes deprecation errors on PHP 8.1
parent f680e8ea
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -523,6 +523,16 @@ field.value.string_long:
      type: text
      label: 'Value'

# Schema for the configuration of the Password field type.

field.storage_settings.password:
  type: field.storage_settings.string
  label: 'Password settings'

field.field_settings.password:
  type: mapping
  label: 'Password settings'

# Schema for the configuration of the URI field type.

field.storage_settings.uri:
+5 −7
Original line number Diff line number Diff line
@@ -46,6 +46,11 @@ public function preSave() {
      // Reset the pre_hashed value since it has now been used.
      $this->pre_hashed = FALSE;
    }
    elseif (!$entity->isNew() && empty($this->value)) {
      // If the password is empty, that means it was not changed, so use the
      // original password.
      $this->value = $entity->original->{$this->getFieldDefinition()->getName()}->value;
    }
    elseif ($entity->isNew() || (strlen(trim($this->value)) > 0 && $this->value != $entity->original->{$this->getFieldDefinition()->getName()}->value)) {
      // Allow alternate password hashing schemes.
      $this->value = \Drupal::service('password')->hash(trim($this->value));
@@ -55,13 +60,6 @@ public function preSave() {
      }
    }

    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;
      }
    }
    // Ensure that the existing password is unset to minimise risks of it
    // getting serialized and stored somewhere.
    $this->existing = NULL;
+189 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\KernelTests\Core\Field\FieldType;

use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Password\PasswordInterface;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\field\Kernel\FieldKernelTestBase;

/**
 * @coversDefaultClass \Drupal\Core\Field\Plugin\Field\FieldType\PasswordItem
 * @group Field
 */
class PasswordItemTest extends FieldKernelTestBase {

  /**
   * A field storage to use in this test class.
   *
   * @var \Drupal\field\Entity\FieldStorageConfig
   */
  protected $fieldStorage;

  /**
   * The field used in this test class.
   *
   * @var \Drupal\field\Entity\FieldConfig
   */
  protected $field;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();

    $this->fieldStorage = FieldStorageConfig::create([
      'field_name' => 'test_field',
      'entity_type' => 'entity_test',
      'type' => 'password',
    ]);
    $this->fieldStorage->save();

    $this->field = FieldConfig::create([
      'field_storage' => $this->fieldStorage,
      'bundle' => 'entity_test',
      'required' => TRUE,
    ]);
    $this->field->save();
  }

  /**
   * @covers ::preSave
   */
  public function testPreSavePreHashed() {
    $entity = EntityTest::create([
      'name' => $this->randomString(),
    ]);
    $entity->test_field = 'this_is_not_a_real_hash';
    $entity->test_field->pre_hashed = TRUE;

    $entity->save();
    $this->assertSame('this_is_not_a_real_hash', $entity->test_field->value);
    $this->assertFalse($entity->test_field->pre_hashed);
  }

  /**
   * @covers ::preSave
   */
  public function testPreSaveNewNull() {
    $entity = EntityTest::create([
      'name' => $this->randomString(),
    ]);
    $entity->test_field = NULL;

    $entity->save();
    $this->assertNull($entity->test_field->value);
  }

  /**
   * @covers ::preSave
   */
  public function testPreSaveNewEmptyString() {
    $entity = EntityTest::create([
      'name' => $this->randomString(),
    ]);
    $entity->test_field = '';

    $entity->save();

    // The string starts with the portable password string and is a hash of an
    // empty string.
    $this->assertStringStartsWith('$S$', $entity->test_field->value);
    $this->assertTrue($this->container->get('password')->check('', $entity->test_field->value));
  }

  /**
   * @covers ::preSave
   */
  public function testPreSaveNewMultipleSpacesString() {
    $entity = EntityTest::create([
      'name' => $this->randomString(),
    ]);
    $entity->test_field = '       ';

    $entity->save();

    // The string starts with the portable password string and is a hash of an
    // empty string.
    $this->assertStringStartsWith('$S$', $entity->test_field->value);
    $this->assertTrue($this->container->get('password')->check('', $entity->test_field->value));
  }

  /**
   * @covers ::preSave
   */
  public function testPreSaveExistingNull() {
    $entity = EntityTest::create();
    $entity->test_field = $this->randomString();
    $entity->save();

    $this->assertNotNull($entity->test_field->value);

    $entity->test_field = NULL;
    $entity->save();

    $this->assertNull($entity->test_field->value);
  }

  /**
   * @covers ::preSave
   */
  public function testPreSaveExistingEmptyString() {
    $entity = EntityTest::create();
    $entity->test_field = $this->randomString();
    $entity->save();

    $hashed_password = $entity->test_field->value;

    $entity->test_field = '';
    $entity->save();

    $this->assertSame($hashed_password, $entity->test_field->value);
  }

  /**
   * @covers ::preSave
   */
  public function testPreSaveExistingMultipleSpacesString() {
    $entity = EntityTest::create();
    $entity->test_field = $this->randomString();
    $entity->save();

    $entity->test_field = '     ';
    $entity->save();

    // @todo Fix this bug in https://www.drupal.org/project/i/3238399.
    $this->assertSame('     ', $entity->test_field->value);
  }

  /**
   * @covers ::preSave
   */
  public function testPreSaveExceptionNew() {
    $entity = EntityTest::create();
    $entity->test_field = str_repeat('a', PasswordInterface::PASSWORD_MAX_LENGTH + 1);
    $this->expectException(EntityStorageException::class);
    $this->expectExceptionMessage('The entity does not have a password');
    $entity->save();
  }

  /**
   * @covers ::preSave
   */
  public function testPreSaveExceptionExisting() {
    $entity = EntityTest::create();
    $entity->test_field = 'will_be_hashed';
    $entity->save();

    $this->assertNotEquals('will_be_hashed', $entity->test_field->value);

    $this->expectException(EntityStorageException::class);
    $this->expectExceptionMessage('The entity does not have a password');
    $entity->test_field = str_repeat('a', PasswordInterface::PASSWORD_MAX_LENGTH + 1);
    $entity->save();
  }

}