diff --git a/src/AuditIgnoreReportCommand.php b/src/AuditIgnoreReportCommand.php new file mode 100644 index 0000000000000000000000000000000000000000..1883305be2b484b10f9fd42007c3d6ddca494148 --- /dev/null +++ b/src/AuditIgnoreReportCommand.php @@ -0,0 +1,44 @@ +<?php + +namespace LakeDrops\DrupalEnvironment; + +use LakeDrops\Component\Composer\BaseCommand; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Composer Audit Ignore Report Command for LakeDrops Drupal environments. + * + * @package LakeDrops\DrupalEnvironment + */ +class AuditIgnoreReportCommand extends BaseCommand { + + /** + * {@inheritdoc} + */ + protected function configure(): void { + parent::configure(); + $this + ->setName('lakedrops:auditignorereport') + ->setDescription('Report about status of all ignored CVEs during audit.'); + } + + /** + * {@inheritdoc} + */ + public function getHandlerClass(): string { + return Handler::class; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int { + parent::execute($input, $output); + /** @var Handler $handler */ + $handler = $this->handler; + $handler->auditIgnoreReport(); + return 0; + } + +} diff --git a/src/CommandProvider.php b/src/CommandProvider.php index 3dcc9258c6c122bfe3535f89a4f583767a877961..1e5188a266908c2ce027420a36b26664c681577b 100644 --- a/src/CommandProvider.php +++ b/src/CommandProvider.php @@ -20,6 +20,7 @@ class CommandProvider implements CommandProviderCapability { public function getCommands(): array { return [ new ConfigCommand(), + new AuditIgnoreReportCommand(), ]; } diff --git a/src/Handler.php b/src/Handler.php index a55ee3a1b29e3ee087eeeb40f66dd2ed0b4edb32..7c8a64382c9463734ca501b30991dfd25e8da12e 100644 --- a/src/Handler.php +++ b/src/Handler.php @@ -2,6 +2,7 @@ namespace LakeDrops\DrupalEnvironment; +use GuzzleHttp\Client; use LakeDrops\Component\Composer\BaseHandler; use Symfony\Component\Filesystem\Filesystem; @@ -187,4 +188,47 @@ class Handler extends BaseHandler { } } + public function auditIgnoreReport(): void { + $audit = $this->composer->getConfig()->get('audit'); + if (empty($audit['ignore'])) { + $this->io->info('There are no ignored CVEs in the configuration.'); + return; + } + /** @var \GuzzleHttp\Client $client */ + $client = new Client(); + $ignore = $audit['ignore']; + $report = []; + foreach ($ignore as $item) { + print('.'); + $parts = explode('-', $item); + if (count($parts) < 5 || $parts[0] !== 'DDQG' || $parts[2] !== 'drupal') { + $report[] = $item . ': Not Drupal related'; + continue; + } + $project = json_decode($client->get('https://www.drupal.org/api-d7/node.json?type=project_module&field_project_machine_name=' . $parts[3])->getBody(), TRUE); + if (empty($project['list'])) { + $project = json_decode($client->get('https://www.drupal.org/api-d7/node.json?type=project_theme&field_project_machine_name=' . $parts[3])->getBody(), TRUE); + } + if (empty($project['list'])) { + $report[] = $parts[3] . ': Drupal project not found'; + } + $nid = $project['list'][0]['nid']; + $releases = json_decode($client->get('https://www.drupal.org/api-d7/node.json?type=project_release&field_release_update_status=0&field_release_category=current&field_release_project=' . $nid)->getBody(), TRUE); + if (empty($releases['list'])) { + $report[] = $parts[3] . ': No releases available for Drupal project'; + continue; + } + $used = $parts[4] . (isset($parts[5]) ? '-' . $parts[5] : ''); + $used_version_major = (int) $parts[4][0]; + $available = []; + foreach ($releases['list'] as $release) { + if ((int) $release['field_release_version_major'] >= $used_version_major) { + $available[] = $release['field_release_version']; + } + } + $report[] = $parts[3] . ': ' . $used . ' - ' . implode(' ', $available); + } + print_r($report); + } + }