config_preview_deploy-1.0.0-alpha3/src/Access/PreviewEnvironmentAccess.php

src/Access/PreviewEnvironmentAccess.php
<?php

declare(strict_types=1);

namespace Drupal\config_preview_deploy\Access;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Access\AccessResultInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;

/**
 * Access controller for preview environment features.
 */
class PreviewEnvironmentAccess {

  /**
   * The config factory service.
   */
  protected ConfigFactoryInterface $configFactory;

  /**
   * Constructs a PreviewEnvironmentAccess object.
   */
  public function __construct(ConfigFactoryInterface $configFactory) {
    $this->configFactory = $configFactory;
  }

  /**
   * Checks access for deploy form.
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The user account.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   The access result.
   */
  public function deployFormAccess(AccountInterface $account): AccessResultInterface {
    $result = $this->isProduction()
      ? AccessResult::forbidden('Deploy form not available on production environments.')
      : AccessResult::allowedIfHasPermission($account, 'deploy config from preview');

    // Add cache dependency on config that affects production detection.
    return $result->addCacheableDependency($this->configFactory->get('config_preview_deploy.settings'));
  }

  /**
   * Checks access for rebase form.
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The user account.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   The access result.
   */
  public function rebaseFormAccess(AccountInterface $account): AccessResultInterface {
    $result = $this->isProduction()
      ? AccessResult::forbidden('Rebase form not available on production environments.')
      : AccessResult::allowedIfHasPermission($account, 'deploy config from preview');

    // Add cache dependency on config that affects production detection.
    return $result->addCacheableDependency($this->configFactory->get('config_preview_deploy.settings'));
  }

  /**
   * Checks access for download diff.
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The user account.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   The access result.
   */
  public function downloadDiffAccess(AccountInterface $account): AccessResultInterface {
    $result = $this->isProduction()
      ? AccessResult::forbidden('Download diff not available on production environments.')
      : AccessResult::allowedIfHasPermission($account, 'deploy config from preview');

    // Add cache dependency on config that affects production detection.
    return $result->addCacheableDependency($this->configFactory->get('config_preview_deploy.settings'));
  }

  /**
   * Checks access for changes tab.
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The user account.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   The access result.
   */
  public function changesAccess(AccountInterface $account): AccessResultInterface {
    $result = $this->isProduction()
      ? AccessResult::forbidden('Changes tab not available on production environments.')
      : AccessResult::allowedIfHasPermission($account, 'deploy config from preview');

    // Add cache dependency on config that affects production detection.
    return $result->addCacheableDependency($this->configFactory->get('config_preview_deploy.settings'));
  }

  /**
   * Checks if the current environment is production.
   *
   * @return bool
   *   TRUE if this is a production environment.
   */
  public function isProduction(): bool {
    // Check environment variable first.
    $envVar = getenv('DRUPAL_CONFIG_PREVIEW_DEPLOY_IS_PRODUCTION');
    if ($envVar && filter_var($envVar, FILTER_VALIDATE_BOOLEAN)) {
      return TRUE;
    }

    // Check if current domain matches configured production URL.
    $config = $this->configFactory->get('config_preview_deploy.settings');
    $productionUrl = $config->get('production_url');

    if (empty($productionUrl)) {
      return FALSE;
    }

    // Get current site's base URL using admin path to avoid frontend domain
    // overrides.
    $currentUrl = Url::fromRoute('system.admin', [], ['absolute' => TRUE])->toString();

    // Extract base URL (scheme + host + port + base path) from both URLs.
    $currentBase = $this->extractBaseUrl($currentUrl);
    $productionBase = $this->extractBaseUrl($productionUrl);

    return $currentBase === $productionBase;
  }

  /**
   * Extract base URL from a full URL.
   *
   * This extracts scheme, host, and port only, ignoring paths.
   * This handles reverse proxy setups where the internal hostname
   * may differ from the external URL.
   *
   * @param string $url
   *   The full URL to extract base from.
   *
   * @return string
   *   The base URL (scheme://host[:port]).
   */
  protected function extractBaseUrl(string $url): string {
    $parsed = parse_url($url);

    if (!$parsed || !isset($parsed['scheme']) || !isset($parsed['host'])) {
      return '';
    }

    $base = $parsed['scheme'] . '://' . $parsed['host'];

    // Include port if it's not the default for the scheme.
    if (isset($parsed['port'])) {
      $defaultPorts = ['http' => 80, 'https' => 443];
      if (!isset($defaultPorts[$parsed['scheme']]) || $parsed['port'] !== $defaultPorts[$parsed['scheme']]) {
        $base .= ':' . $parsed['port'];
      }
    }

    return $base;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc