diff --git a/src/Eccube/Controller/Admin/Store/OwnerStoreController.php b/src/Eccube/Controller/Admin/Store/OwnerStoreController.php index 9fe068412ab..de3c9b352e4 100644 --- a/src/Eccube/Controller/Admin/Store/OwnerStoreController.php +++ b/src/Eccube/Controller/Admin/Store/OwnerStoreController.php @@ -32,6 +32,8 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Validator\ValidatorInterface; /** * @Route("/%eccube_admin_route%/store/plugin/api") @@ -48,6 +50,11 @@ class OwnerStoreController extends AbstractController */ protected $pluginService; + /** + * @var ValidatorInterface + */ + protected ValidatorInterface $validator; + /** * @var ComposerServiceInterface */ @@ -81,6 +88,7 @@ class OwnerStoreController extends AbstractController * @param PluginApiService $pluginApiService * @param BaseInfoRepository $baseInfoRepository * @param CacheUtil $cacheUtil + * @param ValidatorInterface $validatorInterface * * @throws \Doctrine\ORM\NoResultException * @throws \Doctrine\ORM\NonUniqueResultException @@ -92,7 +100,8 @@ public function __construct( SystemService $systemService, PluginApiService $pluginApiService, BaseInfoRepository $baseInfoRepository, - CacheUtil $cacheUtil + CacheUtil $cacheUtil, + ValidatorInterface $validatorInterface ) { $this->pluginRepository = $pluginRepository; $this->pluginService = $pluginService; @@ -100,6 +109,7 @@ public function __construct( $this->pluginApiService = $pluginApiService; $this->BaseInfo = $baseInfoRepository->get(); $this->cacheUtil = $cacheUtil; + $this->validator = $validatorInterface; // TODO: Check the flow of the composer service below $this->composerService = $composerService; @@ -263,13 +273,32 @@ public function apiInstall(Request $request) $pluginCode = $request->get('pluginCode'); - try { - $log = $this->composerService->execRequire('ec-cube/'.$pluginCode); - - return $this->json(['success' => true, 'log' => $log]); - } catch (\Exception $e) { - $log = $e->getMessage(); - log_error($e); + $errors = $this->validator->validate( + $pluginCode, + [ + new Assert\NotBlank(), + new Assert\Regex( + [ + 'pattern' => '/^[a-zA-Z0-9_]+$/', + ] + ), + ] + ); + + if ($errors->count() != 0) { + $log = []; + foreach ($errors as $error) { + $log[] = $error->getMessage(); + } + } else { + try { + $log = $this->composerService->execRequire('ec-cube/'.$pluginCode); + + return $this->json(['success' => true, 'log' => $log]); + } catch (\Exception $e) { + $log = $e->getMessage(); + log_error($e); + } } return $this->json(['success' => false, 'log' => $log], 500); @@ -343,13 +372,53 @@ public function apiUpgrade(Request $request) $pluginCode = $request->get('pluginCode'); $version = $request->get('version'); - try { - $log = $this->composerService->execRequire('ec-cube/'.$pluginCode.':'.$version); + $log = []; + + $errors = $this->validator->validate( + $pluginCode, + [ + new Assert\NotBlank(), + new Assert\Regex( + [ + 'pattern' => '/^[a-zA-Z0-9_]+$/', + ] + ), + ] + ); + + if ($errors->count() != 0) { + foreach ($errors as $error) { + $log[] = $error->getMessage(); + } + } - return $this->json(['success' => true, 'log' => $log]); - } catch (\Exception $e) { - $log = $e->getMessage(); - log_error($e); + $errors = $this->validator->validate( + $version, + [ + new Assert\NotBlank(), + new Assert\Regex( + [ + 'pattern' => '/^[0-9.]+$/', + ] + ), + ] + ); + + if ($errors->count() != 0) { + foreach ($errors as $error) { + $log[] = $error->getMessage(); + } + } + + if (empty($log)) { + try { + $log = $this->composerService->execRequire('ec-cube/'.$pluginCode.':'.$version); + + return $this->json(['success' => true, 'log' => $log]); + } catch (\Exception $e) { + $log = $e->getMessage(); + log_error($e); + } } return $this->json(['success' => false, 'log' => $log], 500); diff --git a/tests/Eccube/Tests/Web/Admin/Store/PluginControllerTest.php b/tests/Eccube/Tests/Web/Admin/Store/PluginControllerTest.php index 4bfdee3a80e..802bc6f9baf 100644 --- a/tests/Eccube/Tests/Web/Admin/Store/PluginControllerTest.php +++ b/tests/Eccube/Tests/Web/Admin/Store/PluginControllerTest.php @@ -49,4 +49,85 @@ public function testSubmit() $this->actual = $this->entityManager->getRepository(\Eccube\Entity\BaseInfo::class)->get()->getPhpPath(); $this->verify(); } + + /** + * 異常系を確認。正常系のインストールはE2Eテストの方で実施 + * + * @dataProvider OwnerStoreInstallParam + * + */ + public function testFailureInstall($param1, $param2, $message) + { + $form = [ + 'pluginCode' => $param1, + 'version' => $param2, + ]; + + $crawler = $this->client->request('POST', + $this->generateUrl('admin_store_plugin_api_install', $form), + [], + [], + [ + 'HTTP_X-Requested-With' => 'XMLHttpRequest', + 'CONTENT_TYPE' => 'application/json', + ] + ); + // ダウンロードできないことを確認 + $this->assertEquals(500, $this->client->getResponse()->getStatusCode()); + // ログを確認 + $this->assertContains($message, json_decode($this->client->getResponse()->getContent())->log); + } + + /** + * 異常系を確認。正常系のアップデートはE2Eテストの方で実施 + * + * @dataProvider OwnerStoreUpgradeParam + * + */ + public function testFailureUpgrade($param1, $param2, $message) + { + $form = [ + 'pluginCode' => $param1, + 'version' => $param2, + ]; + + $crawler = $this->client->request('POST', + $this->generateUrl('admin_store_plugin_api_upgrade', $form), + [], + [], + [ + 'HTTP_X-Requested-With' => 'XMLHttpRequest', + 'CONTENT_TYPE' => 'application/json', + ] + ); + // ダウンロードできないことを確認 + $this->assertEquals(500, $this->client->getResponse()->getStatusCode()); + + // ログを確認 + $this->assertStringContainsString($message, implode(',', json_decode($this->client->getResponse()->getContent())->log)); + } + + /** + * 異常系のテストケース + */ + public function OwnerStoreInstallParam() + { + return [ + ['api42+symfony/yaml:5.3', '4.3.0', '有効な値ではありません。'], + ['', '4.3.0','入力されていません。'], + ]; + } + + /** + * 異常系のテストケース + */ + public function OwnerStoreUpgradeParam() + { + return [ + ['api42+symfony/yaml:5.3', '4.3.0', '有効な値ではありません。'], + ['api42', '4.3.0 symfony/yaml:5.3', '有効な値ではありません。'], + ['api42', '','入力されていません。'], + ['', '4.3.0','入力されていません。'], + ]; + } }