vendor/shopware/core/Framework/Store/Api/StoreController.php line 170

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\Store\Api;
  3. use GuzzleHttp\Exception\ClientException;
  4. use GuzzleHttp\Exception\ConnectException;
  5. use Shopware\Core\Framework\Api\Context\AdminApiSource;
  6. use Shopware\Core\Framework\Api\Context\Exception\InvalidContextSourceException;
  7. use Shopware\Core\Framework\Api\Context\Exception\InvalidContextSourceUserException;
  8. use Shopware\Core\Framework\Context;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  12. use Shopware\Core\Framework\Feature;
  13. use Shopware\Core\Framework\Plugin\PluginEntity;
  14. use Shopware\Core\Framework\Plugin\PluginManagementService;
  15. use Shopware\Core\Framework\Routing\Annotation\Since;
  16. use Shopware\Core\Framework\Store\Exception\CanNotDownloadPluginManagedByComposerException;
  17. use Shopware\Core\Framework\Store\Exception\StoreApiException;
  18. use Shopware\Core\Framework\Store\Exception\StoreInvalidCredentialsException;
  19. use Shopware\Core\Framework\Store\Exception\StoreNotAvailableException;
  20. use Shopware\Core\Framework\Store\Exception\StoreTokenMissingException;
  21. use Shopware\Core\Framework\Store\Services\AbstractExtensionDataProvider;
  22. use Shopware\Core\Framework\Store\Services\StoreClient;
  23. use Shopware\Core\Framework\Validation\DataBag\QueryDataBag;
  24. use Shopware\Core\System\User\UserEntity;
  25. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  26. use Symfony\Component\HttpFoundation\JsonResponse;
  27. use Symfony\Component\HttpFoundation\Request;
  28. use Symfony\Component\HttpFoundation\Response;
  29. use Symfony\Component\Routing\Annotation\Route;
  30. /**
  31.  * @internal
  32.  * @Route(defaults={"_routeScope"={"api"}})
  33.  */
  34. class StoreController extends AbstractController
  35. {
  36.     private StoreClient $storeClient;
  37.     private EntityRepositoryInterface $pluginRepo;
  38.     private PluginManagementService $pluginManagementService;
  39.     private AbstractExtensionDataProvider $extensionDataProvider;
  40.     private EntityRepositoryInterface $userRepository;
  41.     public function __construct(
  42.         StoreClient $storeClient,
  43.         EntityRepositoryInterface $pluginRepo,
  44.         PluginManagementService $pluginManagementService,
  45.         EntityRepositoryInterface $userRepository,
  46.         AbstractExtensionDataProvider $extensionDataProvider
  47.     ) {
  48.         $this->storeClient $storeClient;
  49.         $this->pluginRepo $pluginRepo;
  50.         $this->pluginManagementService $pluginManagementService;
  51.         $this->userRepository $userRepository;
  52.         $this->extensionDataProvider $extensionDataProvider;
  53.     }
  54.     /**
  55.      * @deprecated tag:v6.5.0 - Will be removed without replacement
  56.      *
  57.      * @Since("6.0.0.0")
  58.      * @Route("/api/_action/store/ping", name="api.custom.store.ping", methods={"GET"})
  59.      */
  60.     public function pingStoreAPI(): Response
  61.     {
  62.         Feature::triggerDeprecationOrThrow(
  63.             'v6.5.0.0',
  64.             'Route "api.custom.store.ping" is deprecated and will be removed without replacement.'
  65.         );
  66.         try {
  67.             $this->storeClient->ping();
  68.         } catch (ClientException ConnectException $exception) {
  69.             throw new StoreNotAvailableException();
  70.         }
  71.         return new Response();
  72.     }
  73.     /**
  74.      * @Since("6.0.0.0")
  75.      * @Route("/api/_action/store/login", name="api.custom.store.login", methods={"POST"})
  76.      */
  77.     public function login(Request $requestContext $context): JsonResponse
  78.     {
  79.         $shopwareId $request->request->get('shopwareId');
  80.         $password $request->request->get('password');
  81.         if (!\is_string($shopwareId) || !\is_string($password)) {
  82.             throw new StoreInvalidCredentialsException();
  83.         }
  84.         try {
  85.             $this->storeClient->loginWithShopwareId($shopwareId$password$context);
  86.         } catch (ClientException $exception) {
  87.             throw new StoreApiException($exception);
  88.         }
  89.         return new JsonResponse();
  90.     }
  91.     /**
  92.      * @Since("6.0.0.0")
  93.      * @Route("/api/_action/store/checklogin", name="api.custom.store.checklogin", methods={"POST"})
  94.      */
  95.     public function checkLogin(Context $context): Response
  96.     {
  97.         try {
  98.             // Throws StoreTokenMissingException if no token is present
  99.             $this->getUserStoreToken($context);
  100.             $userInfo $this->storeClient->userInfo($context);
  101.             return new JsonResponse([
  102.                 'userInfo' => $userInfo,
  103.             ]);
  104.         } catch (StoreTokenMissingException|ClientException $exception) {
  105.             return new JsonResponse([
  106.                 'userInfo' => null,
  107.             ]);
  108.         }
  109.     }
  110.     /**
  111.      * @Since("6.0.0.0")
  112.      * @Route("/api/_action/store/logout", name="api.custom.store.logout", methods={"POST"})
  113.      */
  114.     public function logout(Context $context): Response
  115.     {
  116.         $context->scope(Context::SYSTEM_SCOPE, function ($context): void {
  117.             $this->userRepository->update([['id' => $context->getSource()->getUserId(), 'storeToken' => null]], $context);
  118.         });
  119.         return new Response();
  120.     }
  121.     /**
  122.      * @deprecated tag:v6.5.0 Unused method will be removed
  123.      * @Since("6.0.0.0")
  124.      * @Route("/api/_action/store/licenses", name="api.custom.store.licenses", methods={"GET"})
  125.      */
  126.     public function getLicenseList(Context $context): JsonResponse
  127.     {
  128.         Feature::triggerDeprecationOrThrow(
  129.             'v6.5.0.0',
  130.             Feature::deprecatedMethodMessage(__CLASS____METHOD__'v6.5.0.0')
  131.         );
  132.         try {
  133.             $licenseList $this->storeClient->getLicenseList($context);
  134.         } catch (ClientException $exception) {
  135.             throw new StoreApiException($exception);
  136.         }
  137.         return new JsonResponse([
  138.             'items' => $licenseList,
  139.             'total' => \count($licenseList),
  140.         ]);
  141.     }
  142.     /**
  143.      * @Since("6.0.0.0")
  144.      * @Route("/api/_action/store/updates", name="api.custom.store.updates", methods={"GET"})
  145.      */
  146.     public function getUpdateList(Context $context): JsonResponse
  147.     {
  148.         $extensions $this->extensionDataProvider->getInstalledExtensions($contextfalse);
  149.         try {
  150.             $updatesList $this->storeClient->getExtensionUpdateList($extensions$context);
  151.         } catch (ClientException $exception) {
  152.             throw new StoreApiException($exception);
  153.         }
  154.         return new JsonResponse([
  155.             'items' => $updatesList,
  156.             'total' => \count($updatesList),
  157.         ]);
  158.     }
  159.     /**
  160.      * @deprecated tag:v6.5.0 - Will be removed, use ExtensionStoreActionsController::downloadExtension() instead
  161.      * @Since("6.0.0.0")
  162.      * @Route("/api/_action/store/download", name="api.custom.store.download", methods={"GET"})
  163.      */
  164.     public function downloadPlugin(QueryDataBag $queryDataBagContext $context): JsonResponse
  165.     {
  166.         Feature::triggerDeprecationOrThrow(
  167.             'v6.5.0.0',
  168.             Feature::deprecatedMethodMessage(__CLASS____METHOD__'v6.5.0.0''ExtensionStoreActionsController::downloadExtension()')
  169.         );
  170.         $pluginName = (string) $queryDataBag->get('pluginName');
  171.         $criteria = new Criteria();
  172.         $criteria->addFilter(new EqualsFilter('plugin.name'$pluginName));
  173.         /** @var PluginEntity|null $plugin */
  174.         $plugin $this->pluginRepo->search($criteria$context)->first();
  175.         if ($plugin !== null && $plugin->getManagedByComposer()) {
  176.             throw new CanNotDownloadPluginManagedByComposerException('can not downloads plugins managed by composer from store api');
  177.         }
  178.         try {
  179.             $data $this->storeClient->getDownloadDataForPlugin($pluginName$context);
  180.         } catch (ClientException $exception) {
  181.             throw new StoreApiException($exception);
  182.         }
  183.         $this->pluginManagementService->downloadStorePlugin($data$context);
  184.         return new JsonResponse(nullResponse::HTTP_OK);
  185.     }
  186.     /**
  187.      * @Since("6.0.0.0")
  188.      * @Route("/api/_action/store/license-violations", name="api.custom.store.license-violations", methods={"POST"})
  189.      */
  190.     public function getLicenseViolations(Request $requestContext $context): JsonResponse
  191.     {
  192.         $extensions $this->extensionDataProvider->getInstalledExtensions($contextfalse);
  193.         $indexedExtensions = [];
  194.         foreach ($extensions as $extension) {
  195.             $name $extension->getName();
  196.             $indexedExtensions[$name] = [
  197.                 'name' => $name,
  198.                 'version' => $extension->getVersion(),
  199.                 'active' => $extension->getActive(),
  200.             ];
  201.         }
  202.         try {
  203.             $violations $this->storeClient->getLicenseViolations($context$indexedExtensions$request->getHost());
  204.         } catch (ClientException $exception) {
  205.             throw new StoreApiException($exception);
  206.         }
  207.         return new JsonResponse([
  208.             'items' => $violations,
  209.             'total' => \count($violations),
  210.         ]);
  211.     }
  212.     /**
  213.      * @Since("6.0.0.0")
  214.      * @Route("/api/_action/store/plugin/search", name="api.action.store.plugin.search", methods={"POST"})
  215.      */
  216.     public function searchPlugins(Request $requestContext $context): Response
  217.     {
  218.         $extensions $this->extensionDataProvider->getInstalledExtensions($contextfalse);
  219.         try {
  220.             $this->storeClient->checkForViolations($context$extensions$request->getHost());
  221.         } catch (\Exception $e) {
  222.         }
  223.         return new JsonResponse([
  224.             'total' => $extensions->count(),
  225.             'items' => $extensions,
  226.         ]);
  227.     }
  228.     protected function getUserStoreToken(Context $context): string
  229.     {
  230.         $contextSource $context->getSource();
  231.         if (!$contextSource instanceof AdminApiSource) {
  232.             throw new InvalidContextSourceException(AdminApiSource::class, \get_class($contextSource));
  233.         }
  234.         $userId $contextSource->getUserId();
  235.         if ($userId === null) {
  236.             throw new InvalidContextSourceUserException(\get_class($contextSource));
  237.         }
  238.         /** @var UserEntity|null $user */
  239.         $user $this->userRepository->search(new Criteria([$userId]), $context)->first();
  240.         if ($user === null) {
  241.             throw new StoreTokenMissingException();
  242.         }
  243.         $storeToken $user->getStoreToken();
  244.         if ($storeToken === null) {
  245.             throw new StoreTokenMissingException();
  246.         }
  247.         return $storeToken;
  248.     }
  249. }