diff --git a/CHANGELOG.md b/CHANGELOG.md index 39267424e..145cea23c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Toolkit change log +## Version 9.13.0 + - DQA-7528: Allow to block access to files in htaccess. + - DQA-7379: Force max-age in Cache-Control headers. + ## Version 9.12.0 | 10.2.0 - DQA-7395: Replace security-checker with composer audit. - DQA-6756: Create example section in the toolkit documentation. diff --git a/config/runner/toolkit.yml b/config/runner/toolkit.yml index ef6b23361..dde5a33f1 100644 --- a/config/runner/toolkit.yml +++ b/config/runner/toolkit.yml @@ -36,6 +36,7 @@ toolkit: - composer.lock - composer.json remove: + - CHANGELOG.md - CHANGELOG.txt - COPYRIGHT.txt - INSTALL.mysql.txt @@ -50,6 +51,9 @@ toolkit: commands: [ ] dev: commands: [ ] + htaccess: + block: + file-match: '(README\.(md|txt)|CHANGELOG\.(md|txt))$' custom-code-folder: 'lib' npm: theme-task-runner: grunt diff --git a/phpdoc.dist.xml b/phpdoc.dist.xml index 6e787e863..ab2984416 100644 --- a/phpdoc.dist.xml +++ b/phpdoc.dist.xml @@ -9,7 +9,7 @@ docs - + latest diff --git a/src/TaskRunner/Commands/BuildCommands.php b/src/TaskRunner/Commands/BuildCommands.php index 00adfd611..91a450423 100644 --- a/src/TaskRunner/Commands/BuildCommands.php +++ b/src/TaskRunner/Commands/BuildCommands.php @@ -17,6 +17,20 @@ class BuildCommands extends AbstractCommands { + /** + * Comment starting the Toolkit block. + * + * @var string + */ + protected string $blockStart = '# Start Toolkit block.'; + + /** + * Comment ending the Toolkit block. + * + * @var string + */ + protected string $blockEnd = '# End Toolkit block.'; + /** * {@inheritdoc} */ @@ -127,17 +141,17 @@ public function buildDist(array $options = [ 'version' => $tag, 'sha' => $hash, ])); - $tasks[] = $this->taskWriteToFile($options['dist-root'] . '/' . $options['root'] . '/VERSION.txt') + $tasks[] = $this->taskWriteToFile("{$options['dist-root']}/{$options['root']}/VERSION.txt") ->text($tag); // Copy and process drush.yml file. if (file_exists('resources/Drush/drush.yml.dist')) { $tasks[] = $this->taskFilesystemStack() - ->copy('resources/Drush/drush.yml.dist', $options['dist-root'] . '/web/sites/all/drush/drush.yml'); + ->copy('resources/Drush/drush.yml.dist', "{$options['dist-root']}/{$options['root']}/sites/all/drush/drush.yml"); } // Collect and execute list of commands set on local runner.yml. - $commands = $this->getConfig()->get('toolkit.build.dist.commands'); + $commands = $config->get('toolkit.build.dist.commands'); if (!empty($commands)) { $tasks[] = $this->taskExecute($commands); } @@ -145,7 +159,10 @@ public function buildDist(array $options = [ // Remove 'unwanted' files from distribution. $remove = '-name "' . implode('" -o -name "', explode(',', $options['remove'])) . '"'; $tasks[] = $this->taskExecStack() - ->exec("find dist -maxdepth 3 -type f \( $remove \) -exec rm -rf {} +"); + ->exec("find {$options['dist-root']} -maxdepth 3 -type f \( $remove \) -exec rm -rf {} +"); + + // Add custom block to .htaccess file. + $tasks[] = $this->getHtaccessTask("{$options['dist-root']}/{$options['root']}"); // Build and return task collection. return $this->collectionBuilder()->addTaskList($tasks); @@ -210,6 +227,9 @@ public function buildDev(array $options = [ $tasks[] = $this->taskExecute($commands); } + // Add custom block to .htaccess file. + $tasks[] = $this->getHtaccessTask($root); + // Build and return task collection. return $this->collectionBuilder()->addTaskList($tasks); } @@ -368,4 +388,53 @@ public function buildAssets(ConsoleIO $io, array $options = [ } } + /** + * Returns the task for adding custom block to htaccess file. + * + * @param string $root + * The drupal root where the .htaccess file is. + */ + private function getHtaccessTask(string $root) { + return $this->collectionBuilder()->addCode(function () use ($root) { + $htaccess = "$root/.htaccess"; + if (!file_exists($htaccess)) { + return; + } + $htaccessBlock = $this->getHtaccessBlock(); + if (empty($htaccessBlock)) { + return; + } + // Clean up. + $this->taskReplaceBlock($htaccess)->excludeStartEnd() + ->start(PHP_EOL . $this->blockStart)->end($this->blockEnd) + ->content('')->run(); + + // Append Toolkit block to htaccess file. + $this->taskWriteToFile($htaccess)->append()->text($htaccessBlock)->run(); + }); + } + + /** + * Returns the block for the htaccess file. + */ + private function getHtaccessBlock(): string { + $fileMatch = $this->getConfig()->get('toolkit.build.htaccess.block.file-match'); + if (empty($fileMatch)) { + return ''; + } + return <<< EOF + +{$this->blockStart} + + + Require all denied + + + Order allow,deny + + +{$this->blockEnd} +EOF; + } + } diff --git a/src/TaskRunner/Commands/DrupalCommands.php b/src/TaskRunner/Commands/DrupalCommands.php index 6afdba960..4034fc5d4 100644 --- a/src/TaskRunner/Commands/DrupalCommands.php +++ b/src/TaskRunner/Commands/DrupalCommands.php @@ -615,12 +615,15 @@ protected function getToolkitSettingsBlock() \$settings['file_private_path'] = getenv('DRUPAL_PRIVATE_FILE_SYSTEM') !== FALSE ? getenv('DRUPAL_PRIVATE_FILE_SYSTEM') : 'sites/default/private_files'; \$settings['file_temp_path'] = getenv('DRUPAL_FILE_TEMP_PATH') !== FALSE ? getenv('DRUPAL_FILE_TEMP_PATH') : '/tmp'; -// Reverse proxy +// Reverse proxy. if (intval(getenv('DRUPAL_REVERSE_PROXY_ENABLE')) === 1) { - \$settings["reverse_proxy"] = (bool) getenv('DRUPAL_REVERSE_PROXY_ENABLE'); - \$settings["reverse_proxy_addresses"] = explode(',', getenv('DRUPAL_REVERSE_PROXY_ADDRESSES')); + \$settings['reverse_proxy'] = (bool) getenv('DRUPAL_REVERSE_PROXY_ENABLE'); + \$settings['reverse_proxy_addresses'] = explode(',', getenv('DRUPAL_REVERSE_PROXY_ADDRESSES')); } +// Dropsolid requires a value to be set for max-age. +\$config['cache.page.max_age'] = 21600; + {$additionalSettings} // Load environment development override configuration, if available. diff --git a/src/Toolkit.php b/src/Toolkit.php index 40e446983..ab96848fb 100644 --- a/src/Toolkit.php +++ b/src/Toolkit.php @@ -12,7 +12,7 @@ final class Toolkit /** * Constant holding the current version. */ - public const VERSION = '10.2.0'; + public const VERSION = '9.13.0'; /** * Returns the Toolkit root. diff --git a/tests/fixtures/commands/build.yml b/tests/fixtures/commands/build.yml index 36dc30466..6d4751ad5 100644 --- a/tests/fixtures/commands/build.yml +++ b/tests/fixtures/commands/build.yml @@ -93,7 +93,7 @@ [Simulator] Simulating File\Write('dist/web/VERSION.txt') ->text('') [Simulator] Simulating ExecStack() - ->exec('find dist -maxdepth 3 -type f \( -name "CHANGELOG.txt" ... ) -exec rm -rf {} +') + ->exec('find dist -maxdepth 3 -type f \( -name "CHANGELOG.md" ... ) -exec rm -rf {} +') - command: 'toolkit:build-dev' configuration: [] diff --git a/tests/fixtures/commands/drupal-settings-setup.yml b/tests/fixtures/commands/drupal-settings-setup.yml index cee2d76c8..beb784671 100644 --- a/tests/fixtures/commands/drupal-settings-setup.yml +++ b/tests/fixtures/commands/drupal-settings-setup.yml @@ -36,12 +36,15 @@ $settings['file_private_path'] = getenv('DRUPAL_PRIVATE_FILE_SYSTEM') !== FALSE ? getenv('DRUPAL_PRIVATE_FILE_SYSTEM') : 'sites/default/private_files'; $settings['file_temp_path'] = getenv('DRUPAL_FILE_TEMP_PATH') !== FALSE ? getenv('DRUPAL_FILE_TEMP_PATH') : '/tmp'; - // Reverse proxy + // Reverse proxy. if (intval(getenv('DRUPAL_REVERSE_PROXY_ENABLE')) === 1) { - $settings["reverse_proxy"] = (bool) getenv('DRUPAL_REVERSE_PROXY_ENABLE'); - $settings["reverse_proxy_addresses"] = explode(',', getenv('DRUPAL_REVERSE_PROXY_ADDRESSES')); + $settings['reverse_proxy'] = (bool) getenv('DRUPAL_REVERSE_PROXY_ENABLE'); + $settings['reverse_proxy_addresses'] = explode(',', getenv('DRUPAL_REVERSE_PROXY_ADDRESSES')); } + // Dropsolid requires a value to be set for max-age. + $config['cache.page.max_age'] = 21600; + // Load environment development override configuration, if available. @@ -93,12 +96,15 @@ $settings['file_private_path'] = getenv('DRUPAL_PRIVATE_FILE_SYSTEM') !== FALSE ? getenv('DRUPAL_PRIVATE_FILE_SYSTEM') : 'sites/default/private_files'; $settings['file_temp_path'] = getenv('DRUPAL_FILE_TEMP_PATH') !== FALSE ? getenv('DRUPAL_FILE_TEMP_PATH') : '/tmp'; - // Reverse proxy + // Reverse proxy. if (intval(getenv('DRUPAL_REVERSE_PROXY_ENABLE')) === 1) { - $settings["reverse_proxy"] = (bool) getenv('DRUPAL_REVERSE_PROXY_ENABLE'); - $settings["reverse_proxy_addresses"] = explode(',', getenv('DRUPAL_REVERSE_PROXY_ADDRESSES')); + $settings['reverse_proxy'] = (bool) getenv('DRUPAL_REVERSE_PROXY_ENABLE'); + $settings['reverse_proxy_addresses'] = explode(',', getenv('DRUPAL_REVERSE_PROXY_ADDRESSES')); } + // Dropsolid requires a value to be set for max-age. + $config['cache.page.max_age'] = 21600; + $config['cas.settings']['server']['hostname'] = getenv('CAS_HOSTNAME'); $config['cas.settings']['server']['port'] = getenv('CAS_PORT'); @@ -151,12 +157,15 @@ $settings['file_private_path'] = getenv('DRUPAL_PRIVATE_FILE_SYSTEM') !== FALSE ? getenv('DRUPAL_PRIVATE_FILE_SYSTEM') : 'sites/default/private_files'; $settings['file_temp_path'] = getenv('DRUPAL_FILE_TEMP_PATH') !== FALSE ? getenv('DRUPAL_FILE_TEMP_PATH') : '/tmp'; - // Reverse proxy + // Reverse proxy. if (intval(getenv('DRUPAL_REVERSE_PROXY_ENABLE')) === 1) { - $settings["reverse_proxy"] = (bool) getenv('DRUPAL_REVERSE_PROXY_ENABLE'); - $settings["reverse_proxy_addresses"] = explode(',', getenv('DRUPAL_REVERSE_PROXY_ADDRESSES')); + $settings['reverse_proxy'] = (bool) getenv('DRUPAL_REVERSE_PROXY_ENABLE'); + $settings['reverse_proxy_addresses'] = explode(',', getenv('DRUPAL_REVERSE_PROXY_ADDRESSES')); } + // Dropsolid requires a value to be set for max-age. + $config['cache.page.max_age'] = 21600; + // Load environment development override configuration, if available. diff --git a/tests/fixtures/commands/tool.yml b/tests/fixtures/commands/tool.yml index 81d56ff20..be703e049 100644 --- a/tests/fixtures/commands/tool.yml +++ b/tests/fixtures/commands/tool.yml @@ -86,7 +86,7 @@ [WARNING] Failed to get Toolkit version from composer.lock. Minimum version: ^10 - Current version: 10.2.0 + Current version: 9.13.0 Version check: OK - command: toolkit:check-version @@ -99,7 +99,7 @@ > Checking Toolkit version: Minimum version: ^10 - Current version: 10.2.0 + Current version: 9.13.0 Version check: OK - command: toolkit:vendor-list