Commit ae931e43 authored by Adam G-H's avatar Adam G-H Committed by Ted Bowman
Browse files

Issue #3299093 by phenaproxima, kunal.sachdev, AjitS: Add validation that...

Issue #3299093 by phenaproxima, kunal.sachdev, AjitS: Add validation that staging directory is writable
parent 5673d3bf
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -67,6 +67,23 @@ class WritableFileSystemValidator implements PreOperationStageValidatorInterface
      $messages[] = $this->t('The vendor directory "@dir" is not writable.', ['@dir' => $dir]);
    }

    // Ensure the staging root is writable. If it doesn't exist, ensure we will
    // be able to create it.
    $dir = $this->pathLocator->getStagingRoot();
    if (!file_exists($dir)) {
      $dir = dirname($dir);
      if (!is_writable($dir)) {
        $messages[] = $this->t('The staging root directory will not able to be created at "@dir".', [
          '@dir' => $dir,
        ]);
      }
    }
    elseif (!is_writable($dir)) {
      $messages[] = $this->t('The staging root directory "@dir" is not writable.', [
        '@dir' => $dir,
      ]);
    }

    if ($messages) {
      $event->addError($messages, $this->t('The file system is not writable.'));
    }
+6 −0
Original line number Diff line number Diff line
@@ -44,6 +44,12 @@ class StageTest extends PackageManagerKernelTestBase {
   * @covers ::getStageDirectory
   */
  public function testGetStageDirectory(): void {
    // In this test, we're working with paths that (probably) don't exist in
    // the file system at all, so we don't want to validate that the file system
    // is writable when creating stages.
    $validator = $this->container->get('package_manager.validator.file_system');
    $this->container->get('event_dispatcher')->removeSubscriber($validator);

    // Don't mirror the active directory from the virtual project into the
    // real file system.
    Beginner::setFixturePath(NULL);
+60 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ namespace Drupal\Tests\package_manager\Kernel;

use Drupal\package_manager\Event\PreCreateEvent;
use Drupal\package_manager\ValidationResult;
use Symfony\Component\Filesystem\Filesystem;

/**
 * Unit tests the file system permissions validator.
@@ -86,4 +87,63 @@ class WritableFileSystemValidatorTest extends PackageManagerKernelTestBase {
    $this->assertResults($expected_results, PreCreateEvent::class);
  }

  /**
   * Data provider for ::testStagingRootPermissions().
   *
   * @return mixed[][]
   *   The test cases.
   */
  public function providerStagingRootPermissions(): array {
    $writable_permission = 0777;
    $non_writable_permission = 0444;
    $summary = t('The file system is not writable.');
    return [
      'writable staging root exists' => [
        $writable_permission,
        [],
        FALSE,
      ],
      'write-protected staging root exists' => [
        $non_writable_permission,
        [
          ValidationResult::createError(['The staging root directory "vfs://root/stage" is not writable.'], $summary),
        ],
        FALSE,
      ],
      'staging root does not exist, parent directory not writable' => [
        $non_writable_permission,
        [
          ValidationResult::createError(['The staging root directory will not able to be created at "vfs://root".'], $summary),
        ],
        TRUE,
      ],
    ];
  }

  /**
   * Tests that the staging root's permissions are validated.
   *
   * @param int $permissions
   *   The file permissions to apply to the staging root, or its parent
   *   directory, depending on the value of $delete_staging_root.
   * @param array $expected_results
   *   The expected validation results.
   * @param bool $delete_staging_root
   *   Whether the staging root directory will exist at all.
   *
   * @dataProvider providerStagingRootPermissions
   */
  public function testStagingRootPermissions(int $permissions, array $expected_results, bool $delete_staging_root): void {
    $dir = $this->container->get('package_manager.path_locator')
      ->getStagingRoot();

    if ($delete_staging_root) {
      $fs = new Filesystem();
      $fs->remove($dir);
      $dir = dirname($dir);
    }
    $this->assertTrue(chmod($dir, $permissions));
    $this->assertResults($expected_results, PreCreateEvent::class);
  }

}