[API] Secure access in shop context to order items, order item units, shipments and payments

This commit is contained in:
Grzegorz Sadowski 2020-11-11 12:37:32 +01:00
parent 89caa88924
commit 15339672f2
No known key found for this signature in database
GPG key ID: EF87FF4E6E3BD364
27 changed files with 1198 additions and 12 deletions

View file

@ -0,0 +1,38 @@
@customer_account
Feature: Being unable to see non-own orders and associated resources
In order to customers follow only their orders
As a Store Owner
I want not to be able to see non-own orders and associated resources by customer
Background:
Given the store operates on a single channel in "United States"
And the store has a "PHP T-Shirt" product
And the store ships everywhere for free
And the store allows paying with "Cash on Delivery"
And I am a logged in customer
And there is a customer "john@example.com" that placed order with "PHP T-Shirt" product to "United States" based billing address with "Free" shipping method and "Cash on Delivery" payment method
@api
Scenario: Being unable to see non-own order
When I try to see the order placed by a customer "john@example.com"
Then I should not be able to see that order
@api
Scenario: Being unable to see non-own order item
When I try to see one of the items from the order placed by a customer "john@example.com"
Then I should not be able to see that item
@api
Scenario: Being unable to see non-own order item unit
When I try to see one of the units from the order placed by a customer "john@example.com"
Then I should not be able to see that unit
@api
Scenario: Being unable to see non-own shipment
When I try to see the shipment of the order placed by a customer "john@example.com"
Then I should not be able to see that shipment
@api
Scenario: Being unable to see non-own payment
When I try to see the payment of the order placed by a customer "john@example.com"
Then I should not be able to see that payment

View file

@ -74,6 +74,17 @@ final class OrderContext implements Context
$this->client->show($order->getTokenValue());
}
/**
* @When I try to see the order placed by a customer :customer
*/
public function iTryToSeeTheOrderPlacedByACustomer(): void
{
/** @var OrderInterface $order */
$order = $this->sharedStorage->get('order');
$this->iViewTheSummaryOfMyOrder($order);
}
/**
* @Then I should be able to access this order's details
*/
@ -265,6 +276,14 @@ final class OrderContext implements Context
);
}
/**
* @Then I should not be able to see that order
*/
public function iShouldNotBeAbleToSeeThatOrder(): void
{
Assert::false($this->responseChecker->isShowSuccessful($this->client->getLastResponse()));
}
private function getAdjustmentsForOrder(): array
{
$response = $this->client->subResourceIndex('adjustments', $this->sharedStorage->get('cart_token'));

View file

@ -0,0 +1,94 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Behat\Context\Api\Shop;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Model\OrderItemUnitInterface;
use Webmozart\Assert\Assert;
final class OrderItemContext implements Context
{
/** @var ApiClientInterface */
private $orderItemsClient;
/** @var ApiClientInterface */
private $orderItemUnitsClient;
/** @var ResponseCheckerInterface */
private $responseChecker;
/** @var SharedStorageInterface */
private $sharedStorage;
public function __construct(
ApiClientInterface $orderItemsClient,
ApiClientInterface $orderItemUnitsClient,
ResponseCheckerInterface $responseChecker,
SharedStorageInterface $sharedStorage
) {
$this->orderItemsClient = $orderItemsClient;
$this->orderItemUnitsClient = $orderItemUnitsClient;
$this->responseChecker = $responseChecker;
$this->sharedStorage = $sharedStorage;
}
/**
* @When I try to see one of the items from the order placed by a customer :customer
*/
public function iTryToSeeOneOfTheItemsFromTheOrderPlacedByACustomer(): void
{
/** @var OrderInterface $order */
$order = $this->sharedStorage->get('order');
/** @var OrderItemInterface $orderItem */
$orderItem = $order->getItems()->first();
$this->orderItemsClient->show((string) $orderItem->getId());
}
/**
* @When I try to see one of the units from the order placed by a customer :customer
*/
public function iTryToSeeOneOfTheUnitsFromTheOrderPlacedByACustomer(): void
{
/** @var OrderInterface $order */
$order = $this->sharedStorage->get('order');
/** @var OrderItemUnitInterface $orderItemUnit */
$orderItemUnit = $order->getItemUnits()->first();
$this->orderItemUnitsClient->show((string) $orderItemUnit->getId());
}
/**
* @Then I should not be able to see that item
*/
public function iShouldNotBeAbleToSeeThatItem(): void
{
Assert::false($this->responseChecker->isShowSuccessful($this->orderItemsClient->getLastResponse()));
}
/**
* @Then I should not be able to see that unit
*/
public function iShouldNotBeAbleToSeeThatUnit(): void
{
Assert::false($this->responseChecker->isShowSuccessful($this->orderItemUnitsClient->getLastResponse()));
}
}

View file

@ -0,0 +1,66 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Behat\Context\Api\Shop;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Webmozart\Assert\Assert;
final class PaymentContext implements Context
{
/** @var ApiClientInterface */
private $paymentsClient;
/** @var ResponseCheckerInterface */
private $responseChecker;
/** @var SharedStorageInterface */
private $sharedStorage;
public function __construct(
ApiClientInterface $paymentsClient,
ResponseCheckerInterface $responseChecker,
SharedStorageInterface $sharedStorage
) {
$this->paymentsClient = $paymentsClient;
$this->responseChecker = $responseChecker;
$this->sharedStorage = $sharedStorage;
}
/**
* @When I try to see the payment of the order placed by a customer :customer
*/
public function iTryToSeeThePaymentOfTheOrderPlacedByACustomer(): void
{
/** @var OrderInterface $order */
$order = $this->sharedStorage->get('order');
/** @var PaymentInterface $payment */
$payment = $order->getPayments()->first();
$this->paymentsClient->show((string) $payment->getId());
}
/**
* @Then I should not be able to see that payment
*/
public function iShouldNotBeAbleToSeeThatPayment(): void
{
Assert::false($this->responseChecker->isShowSuccessful($this->paymentsClient->getLastResponse()));
}
}

View file

@ -0,0 +1,66 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Behat\Context\Api\Shop;
use Behat\Behat\Context\Context;
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\ShipmentInterface;
use Webmozart\Assert\Assert;
final class ShipmentContext implements Context
{
/** @var ApiClientInterface */
private $shipmentsClient;
/** @var ResponseCheckerInterface */
private $responseChecker;
/** @var SharedStorageInterface */
private $sharedStorage;
public function __construct(
ApiClientInterface $shipmentsClient,
ResponseCheckerInterface $responseChecker,
SharedStorageInterface $sharedStorage
) {
$this->shipmentsClient = $shipmentsClient;
$this->responseChecker = $responseChecker;
$this->sharedStorage = $sharedStorage;
}
/**
* @When I try to see the shipment of the order placed by a customer :customer
*/
public function iTryToSeeTheShipmentOfTheOrderPlacedByACustomer(): void
{
/** @var OrderInterface $order */
$order = $this->sharedStorage->get('order');
/** @var ShipmentInterface $shipment */
$shipment = $order->getShipments()->first();
$this->shipmentsClient->show((string) $shipment->getId());
}
/**
* @Then I should not be able to see that shipment
*/
public function iShouldNotBeAbleToSeeThatShipment(): void
{
Assert::false($this->responseChecker->isShowSuccessful($this->shipmentsClient->getLastResponse()));
}
}

View file

@ -146,6 +146,20 @@ final class OrderContext implements Context
$this->thereIsCustomerThatPlacedOrder($customer, $orderNumber);
}
/**
* @Given /^there is a (customer "[^"]+") that placed order with ("[^"]+" product) to ("[^"]+" based billing address) with ("[^"]+" shipping method) and ("[^"]+" payment) method$/
*/
public function thereIsACustomerThatPlacedOrderWithProductToBasedBillingAddressWithShippingMethodAndPaymentMethod(
CustomerInterface $customer,
ProductInterface $product,
AddressInterface $address,
ShippingMethodInterface $shippingMethod,
PaymentMethodInterface $paymentMethod
) {
$this->placeOrder($product, $shippingMethod, $address, $paymentMethod, $customer, 1);
$this->objectManager->flush();
}
/**
* @Given /^the guest customer placed order with ("[^"]+" product) for "([^"]+)" and ("[^"]+" based billing address) with ("[^"]+" shipping method) and ("[^"]+" payment)$/
*/

View file

@ -138,6 +138,26 @@
<argument>shop</argument>
</service>
<service id="sylius.behat.api_platform_client.shop.order_item" class="Sylius\Behat\Client\ApiPlatformClient" parent="sylius.behat.api_platform_client">
<argument>order-items</argument>
<argument>shop</argument>
</service>
<service id="sylius.behat.api_platform_client.shop.order_item_unit" class="Sylius\Behat\Client\ApiPlatformClient" parent="sylius.behat.api_platform_client">
<argument>order-item-units</argument>
<argument>shop</argument>
</service>
<service id="sylius.behat.api_platform_client.shop.payment" class="Sylius\Behat\Client\ApiPlatformClient" parent="sylius.behat.api_platform_client">
<argument>payment</argument>
<argument>shop</argument>
</service>
<service id="sylius.behat.api_platform_client.shop.shipment" class="Sylius\Behat\Client\ApiPlatformClient" parent="sylius.behat.api_platform_client">
<argument>shipment</argument>
<argument>shop</argument>
</service>
<service id="sylius.behat.api_platform_client.admin.taxon" class="Sylius\Behat\Client\ApiPlatformClient" parent="sylius.behat.api_platform_client">
<argument>taxons</argument>
<argument>admin</argument>

View file

@ -18,6 +18,14 @@
<services>
<defaults public="true" />
<service id="sylius.behat.context.api.shop.address" class="Sylius\Behat\Context\Api\Shop\AddressContext">
<argument type="service" id="sylius.behat.api_platform_client.shop.address" />
<argument type="service" id="sylius.behat.api_platform_client.shop.account" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="api_platform.iri_converter" />
<argument type="service" id="sylius.behat.shared_storage" />
</service>
<service id="sylius.behat.context.api.shop.cart" class="Sylius\Behat\Context\Api\Shop\CartContext">
<argument type="service" id="sylius.behat.api_platform_client.shop.cart" />
<argument type="service" id="sylius.behat.api_platform_client.shop.product" />
@ -27,6 +35,16 @@
<argument type="service" id="sylius.product_variant_resolver.default" />
</service>
<service id="sylius.behat.context.api.shop.customer" class="Sylius\Behat\Context\Api\Shop\CustomerContext">
<argument type="service" id="sylius.behat.api_platform_client.shop.account" />
<argument type="service" id="sylius.behat.api_platform_client.shop.order" />
<argument type="service" id="sylius.behat.shared_storage" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="sylius.behat.context.api.shop.registration" />
<argument type="service" id="sylius.behat.context.api.shop.login" />
<argument type="service" id="sylius.behat.context.setup.shop_api_security" />
</service>
<service id="sylius.behat.context.api.shop.promotion" class="Sylius\Behat\Context\Api\Shop\PromotionContext">
<argument type="service" id="sylius.behat.api_platform_client.shop.cart" />
<argument type="service" id="sylius.behat.shared_storage" />
@ -80,21 +98,22 @@
<argument type="service" id="api_platform.iri_converter" />
</service>
<service id="sylius.behat.context.api.shop.customer" class="Sylius\Behat\Context\Api\Shop\CustomerContext">
<argument type="service" id="sylius.behat.api_platform_client.shop.account" />
<argument type="service" id="sylius.behat.api_platform_client.shop.order" />
<argument type="service" id="sylius.behat.shared_storage" />
<service id="sylius.behat.context.api.shop.order_item" class="Sylius\Behat\Context\Api\Shop\OrderItemContext">
<argument type="service" id="sylius.behat.api_platform_client.shop.order_item" />
<argument type="service" id="sylius.behat.api_platform_client.shop.order_item_unit" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="sylius.behat.context.api.shop.registration" />
<argument type="service" id="sylius.behat.context.api.shop.login" />
<argument type="service" id="sylius.behat.context.setup.shop_api_security" />
<argument type="service" id="sylius.behat.shared_storage" />
</service>
<service id="sylius.behat.context.api.shop.address" class="Sylius\Behat\Context\Api\Shop\AddressContext">
<argument type="service" id="sylius.behat.api_platform_client.shop.address" />
<argument type="service" id="sylius.behat.api_platform_client.shop.account" />
<service id="sylius.behat.context.api.shop.payment" class="Sylius\Behat\Context\Api\Shop\PaymentContext">
<argument type="service" id="sylius.behat.api_platform_client.shop.payment" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="sylius.behat.shared_storage" />
</service>
<service id="sylius.behat.context.api.shop.shipment" class="Sylius\Behat\Context\Api\Shop\ShipmentContext">
<argument type="service" id="sylius.behat.api_platform_client.shop.shipment" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="api_platform.iri_converter" />
<argument type="service" id="sylius.behat.shared_storage" />
</service>
</services>

View file

@ -32,11 +32,14 @@ default:
- sylius.behat.context.setup.shop_api_security
- sylius.behat.context.setup.user
- sylius.behat.context.setup.zone
- sylius.behat.context.api.shop.customer
- sylius.behat.context.api.shop.order
- sylius.behat.context.api.shop.order_item
- sylius.behat.context.api.shop.checkout
- sylius.behat.context.api.shop.login
- sylius.behat.context.api.shop.payment
- sylius.behat.context.api.shop.shipment
filters:
tags: "@customer_account && @api"

View file

@ -0,0 +1,62 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\DataProvider;
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
use Sylius\Component\Core\Model\AdminUserInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\Core\Repository\OrderItemRepositoryInterface;
/** @experimental */
final class OrderItemItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
{
/** @var OrderItemRepositoryInterface */
private $orderItemRepository;
/** @var UserContextInterface */
private $userContext;
public function __construct(OrderItemRepositoryInterface $orderItemRepository, UserContextInterface $userContext)
{
$this->orderItemRepository = $orderItemRepository;
$this->userContext = $userContext;
}
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
{
return is_a($resourceClass, OrderItemInterface::class, true);
}
public function getItem(string $resourceClass, $id, string $operationName = null, array $context = [])
{
$user = $this->userContext->getUser();
/** @var CustomerInterface|null $customer */
$customer = $user instanceof ShopUserInterface ? $user->getCustomer() : null;
if ($customer !== null && in_array('ROLE_USER', $user->getRoles(), true)) {
return $this->orderItemRepository->findOneByCustomer($id, $customer);
}
if ($user instanceof AdminUserInterface && in_array('ROLE_API_ACCESS', $user->getRoles(), true)) {
return $this->orderItemRepository->findOneBy(['id' => $id]);
}
return null;
}
}

View file

@ -0,0 +1,64 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\DataProvider;
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
use Sylius\Component\Core\Model\AdminUserInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderItemUnitInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\Core\Repository\OrderItemUnitRepositoryInterface;
/** @experimental */
final class OrderItemUnitItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
{
/** @var OrderItemUnitRepositoryInterface */
private $orderItemUnitRepository;
/** @var UserContextInterface */
private $userContext;
public function __construct(
OrderItemUnitRepositoryInterface $orderItemUnitRepository,
UserContextInterface $userContext
) {
$this->orderItemUnitRepository = $orderItemUnitRepository;
$this->userContext = $userContext;
}
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
{
return is_a($resourceClass, OrderItemUnitInterface::class, true);
}
public function getItem(string $resourceClass, $id, string $operationName = null, array $context = [])
{
$user = $this->userContext->getUser();
/** @var CustomerInterface|null $customer */
$customer = $user instanceof ShopUserInterface ? $user->getCustomer() : null;
if ($customer !== null && in_array('ROLE_USER', $user->getRoles(), true)) {
return $this->orderItemUnitRepository->findOneByCustomer($id, $customer);
}
if ($user instanceof AdminUserInterface && in_array('ROLE_API_ACCESS', $user->getRoles(), true)) {
return $this->orderItemUnitRepository->findOneBy(['id' => $id]);
}
return null;
}
}

View file

@ -0,0 +1,62 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\DataProvider;
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
use Sylius\Component\Core\Model\AdminUserInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\Core\Repository\PaymentRepositoryInterface;
/** @experimental */
final class PaymentItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
{
/** @var PaymentRepositoryInterface */
private $paymentRepository;
/** @var UserContextInterface */
private $userContext;
public function __construct(PaymentRepositoryInterface $paymentRepository, UserContextInterface $userContext)
{
$this->paymentRepository = $paymentRepository;
$this->userContext = $userContext;
}
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
{
return is_a($resourceClass, PaymentInterface::class, true);
}
public function getItem(string $resourceClass, $id, string $operationName = null, array $context = [])
{
$user = $this->userContext->getUser();
/** @var CustomerInterface|null $customer */
$customer = $user instanceof ShopUserInterface ? $user->getCustomer() : null;
if ($customer !== null && in_array('ROLE_USER', $user->getRoles(), true)) {
return $this->paymentRepository->findOneByCustomer($id, $customer);
}
if ($user instanceof AdminUserInterface && in_array('ROLE_API_ACCESS', $user->getRoles(), true)) {
return $this->paymentRepository->findOneBy(['id' => $id]);
}
return null;
}
}

View file

@ -0,0 +1,62 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\DataProvider;
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
use Sylius\Component\Core\Model\AdminUserInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\ShipmentInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\Core\Repository\ShipmentRepositoryInterface;
/** @experimental */
final class ShipmentItemDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
{
/** @var ShipmentRepositoryInterface */
private $shipmentRepository;
/** @var UserContextInterface */
private $userContext;
public function __construct(ShipmentRepositoryInterface $shipmentRepository, UserContextInterface $userContext)
{
$this->shipmentRepository = $shipmentRepository;
$this->userContext = $userContext;
}
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
{
return is_a($resourceClass, ShipmentInterface::class, true);
}
public function getItem(string $resourceClass, $id, string $operationName = null, array $context = [])
{
$user = $this->userContext->getUser();
/** @var CustomerInterface|null $customer */
$customer = $user instanceof ShopUserInterface ? $user->getCustomer() : null;
if ($customer !== null && in_array('ROLE_USER', $user->getRoles(), true)) {
return $this->shipmentRepository->findOneByCustomer($id, $customer);
}
if ($user instanceof AdminUserInterface && in_array('ROLE_API_ACCESS', $user->getRoles(), true)) {
return $this->shipmentRepository->findOneBy(['id' => $id]);
}
return null;
}
}

View file

@ -28,6 +28,30 @@
<tag name="api_platform.item_data_provider" priority="10" />
</service>
<service id="sylius.api.item_data_provider.order_item" class="Sylius\Bundle\ApiBundle\DataProvider\OrderItemItemDataProvider">
<argument type="service" id="sylius.repository.order_item" />
<argument type="service" id="sylius.api.context.user" />
<tag name="api_platform.item_data_provider" priority="10" />
</service>
<service id="sylius.api.item_data_provider.order_item_unit" class="Sylius\Bundle\ApiBundle\DataProvider\OrderItemUnitItemDataProvider">
<argument type="service" id="sylius.repository.order_item_unit" />
<argument type="service" id="sylius.api.context.user" />
<tag name="api_platform.item_data_provider" priority="10" />
</service>
<service id="sylius.api.item_data_provider.payment" class="Sylius\Bundle\ApiBundle\DataProvider\PaymentItemDataProvider">
<argument type="service" id="sylius.repository.payment" />
<argument type="service" id="sylius.api.context.user" />
<tag name="api_platform.item_data_provider" priority="10" />
</service>
<service id="sylius.api.item_data_provider.shipment" class="Sylius\Bundle\ApiBundle\DataProvider\ShipmentItemDataProvider">
<argument type="service" id="sylius.repository.shipment" />
<argument type="service" id="sylius.api.context.user" />
<tag name="api_platform.item_data_provider" priority="10" />
</service>
<service id="sylius.api.collection_data_provider.country" class="Sylius\Bundle\ApiBundle\DataProvider\CountryCollectionDataProvider">
<argument type="service" id="sylius.repository.country" />
<argument type="service" id="sylius.api.context.user" />

View file

@ -0,0 +1,104 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace spec\Sylius\Bundle\ApiBundle\DataProvider;
use PhpSpec\ObjectBehavior;
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Model\AdminUserInterface;
use Sylius\Component\Core\Model\Customer;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\Core\Repository\OrderItemRepositoryInterface;
use Sylius\Component\Resource\Model\ResourceInterface;
final class OrderItemItemDataProviderSpec extends ObjectBehavior
{
function let(OrderItemRepositoryInterface $orderItemRepository, UserContextInterface $userContext): void
{
$this->beConstructedWith($orderItemRepository, $userContext);
}
function it_supports_only_order_item(): void
{
$this->supports(OrderItemInterface::class, 'get')->shouldReturn(true);
$this->supports(ResourceInterface::class, 'get')->shouldReturn(false);
}
function it_provides_order_item_for_shop_user(
OrderItemRepositoryInterface $orderItemRepository,
UserContextInterface $userContext,
ShopUserInterface $shopUser,
CustomerInterface $customer,
OrderItemInterface $orderItem
) {
$userContext->getUser()->willReturn($shopUser);
$shopUser->getCustomer()->willReturn($customer);
$shopUser->getRoles()->willReturn(['ROLE_USER']);
$orderItemRepository
->findOneByCustomer('123', $customer->getWrappedObject())
->willReturn($orderItem)
;
$this->getItem(OrderItemInterface::class, '123')->shouldReturn($orderItem);
}
function it_provides_order_item_for_admin_user(
OrderItemRepositoryInterface $orderItemRepository,
UserContextInterface $userContext,
AdminUserInterface $adminUser,
OrderItemInterface $orderItem
) {
$userContext->getUser()->willReturn($adminUser);
$adminUser->getRoles()->willReturn(['ROLE_API_ACCESS']);
$orderItemRepository->findOneBy(['id' => '123'])->willReturn($orderItem);
$this->getItem(OrderItemInterface::class, '123')->shouldReturn($orderItem);
}
function it_returns_null_if_shop_user_has_no_customer(
OrderItemRepositoryInterface $orderItemRepository,
UserContextInterface $userContext,
ShopUserInterface $shopUser
) {
$userContext->getUser()->willReturn($shopUser);
$shopUser->getCustomer()->willReturn(null);
$shopUser->getRoles()->willReturn(['ROLE_USER']);
$orderItemRepository->findOneByCustomer('123', new Customer())->shouldNotBeCalled();
$this->getItem(OrderItemInterface::class, '123')->shouldReturn(null);
}
function it_returns_null_if_shop_user_does_have_proper_roles(
OrderItemRepositoryInterface $orderItemRepository,
UserContextInterface $userContext,
CustomerInterface $customer,
ShopUserInterface $shopUser
) {
$userContext->getUser()->willReturn($shopUser);
$shopUser->getCustomer()->willReturn($customer);
$shopUser->getRoles()->willReturn(['']);
$orderItemRepository->findOneByCustomer('123', new Customer())->shouldNotBeCalled();
$this->getItem(OrderItemInterface::class, '123')->shouldReturn(null);
}
}

View file

@ -0,0 +1,104 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace spec\Sylius\Bundle\ApiBundle\DataProvider;
use PhpSpec\ObjectBehavior;
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
use Sylius\Component\Core\Model\OrderItemUnitInterface;
use Sylius\Component\Core\Model\AdminUserInterface;
use Sylius\Component\Core\Model\Customer;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\Core\Repository\OrderItemUnitRepositoryInterface;
use Sylius\Component\Resource\Model\ResourceInterface;
final class OrderItemUnitItemDataProviderSpec extends ObjectBehavior
{
function let(OrderItemUnitRepositoryInterface $orderItemUnitRepository, UserContextInterface $userContext): void
{
$this->beConstructedWith($orderItemUnitRepository, $userContext);
}
function it_supports_only_order_item_unit(): void
{
$this->supports(OrderItemUnitInterface::class, 'get')->shouldReturn(true);
$this->supports(ResourceInterface::class, 'get')->shouldReturn(false);
}
function it_provides_order_item_unit_for_shop_user(
OrderItemUnitRepositoryInterface $orderItemUnitRepository,
UserContextInterface $userContext,
ShopUserInterface $shopUser,
CustomerInterface $customer,
OrderItemUnitInterface $orderItemUnit
) {
$userContext->getUser()->willReturn($shopUser);
$shopUser->getCustomer()->willReturn($customer);
$shopUser->getRoles()->willReturn(['ROLE_USER']);
$orderItemUnitRepository
->findOneByCustomer('123', $customer->getWrappedObject())
->willReturn($orderItemUnit)
;
$this->getItem(OrderItemUnitInterface::class, '123')->shouldReturn($orderItemUnit);
}
function it_provides_order_item_unit_for_admin_user(
OrderItemUnitRepositoryInterface $orderItemUnitRepository,
UserContextInterface $userContext,
AdminUserInterface $adminUser,
OrderItemUnitInterface $orderItemUnit
) {
$userContext->getUser()->willReturn($adminUser);
$adminUser->getRoles()->willReturn(['ROLE_API_ACCESS']);
$orderItemUnitRepository->findOneBy(['id' => '123'])->willReturn($orderItemUnit);
$this->getItem(OrderItemUnitInterface::class, '123')->shouldReturn($orderItemUnit);
}
function it_returns_null_if_shop_user_has_no_customer(
OrderItemUnitRepositoryInterface $orderItemUnitRepository,
UserContextInterface $userContext,
ShopUserInterface $shopUser
) {
$userContext->getUser()->willReturn($shopUser);
$shopUser->getCustomer()->willReturn(null);
$shopUser->getRoles()->willReturn(['ROLE_USER']);
$orderItemUnitRepository->findOneByCustomer('123', new Customer())->shouldNotBeCalled();
$this->getItem(OrderItemUnitInterface::class, '123')->shouldReturn(null);
}
function it_returns_null_if_shop_user_does_have_proper_roles(
OrderItemUnitRepositoryInterface $orderItemUnitRepository,
UserContextInterface $userContext,
CustomerInterface $customer,
ShopUserInterface $shopUser
) {
$userContext->getUser()->willReturn($shopUser);
$shopUser->getCustomer()->willReturn($customer);
$shopUser->getRoles()->willReturn(['']);
$orderItemUnitRepository->findOneByCustomer('123', new Customer())->shouldNotBeCalled();
$this->getItem(OrderItemUnitInterface::class, '123')->shouldReturn(null);
}
}

View file

@ -0,0 +1,104 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace spec\Sylius\Bundle\ApiBundle\DataProvider;
use PhpSpec\ObjectBehavior;
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\Component\Core\Model\AdminUserInterface;
use Sylius\Component\Core\Model\Customer;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\Core\Repository\PaymentRepositoryInterface;
use Sylius\Component\Resource\Model\ResourceInterface;
final class PaymentItemDataProviderSpec extends ObjectBehavior
{
function let(PaymentRepositoryInterface $paymentRepository, UserContextInterface $userContext): void
{
$this->beConstructedWith($paymentRepository, $userContext);
}
function it_supports_only_payment(): void
{
$this->supports(PaymentInterface::class, 'get')->shouldReturn(true);
$this->supports(ResourceInterface::class, 'get')->shouldReturn(false);
}
function it_provides_payment_for_shop_user(
PaymentRepositoryInterface $paymentRepository,
UserContextInterface $userContext,
ShopUserInterface $shopUser,
CustomerInterface $customer,
PaymentInterface $payment
) {
$userContext->getUser()->willReturn($shopUser);
$shopUser->getCustomer()->willReturn($customer);
$shopUser->getRoles()->willReturn(['ROLE_USER']);
$paymentRepository
->findOneByCustomer('123', $customer->getWrappedObject())
->willReturn($payment)
;
$this->getItem(PaymentInterface::class, '123')->shouldReturn($payment);
}
function it_provides_payment_for_admin_user(
PaymentRepositoryInterface $paymentRepository,
UserContextInterface $userContext,
AdminUserInterface $adminUser,
PaymentInterface $payment
) {
$userContext->getUser()->willReturn($adminUser);
$adminUser->getRoles()->willReturn(['ROLE_API_ACCESS']);
$paymentRepository->findOneBy(['id' => '123'])->willReturn($payment);
$this->getItem(PaymentInterface::class, '123')->shouldReturn($payment);
}
function it_returns_null_if_shop_user_has_no_customer(
PaymentRepositoryInterface $paymentRepository,
UserContextInterface $userContext,
ShopUserInterface $shopUser
) {
$userContext->getUser()->willReturn($shopUser);
$shopUser->getCustomer()->willReturn(null);
$shopUser->getRoles()->willReturn(['ROLE_USER']);
$paymentRepository->findOneByCustomer('123', new Customer())->shouldNotBeCalled();
$this->getItem(PaymentInterface::class, '123')->shouldReturn(null);
}
function it_returns_null_if_shop_user_does_have_proper_roles(
PaymentRepositoryInterface $paymentRepository,
UserContextInterface $userContext,
CustomerInterface $customer,
ShopUserInterface $shopUser
) {
$userContext->getUser()->willReturn($shopUser);
$shopUser->getCustomer()->willReturn($customer);
$shopUser->getRoles()->willReturn(['']);
$paymentRepository->findOneByCustomer('123', new Customer())->shouldNotBeCalled();
$this->getItem(PaymentInterface::class, '123')->shouldReturn(null);
}
}

View file

@ -0,0 +1,104 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace spec\Sylius\Bundle\ApiBundle\DataProvider;
use PhpSpec\ObjectBehavior;
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
use Sylius\Component\Core\Model\ShipmentInterface;
use Sylius\Component\Core\Model\AdminUserInterface;
use Sylius\Component\Core\Model\Customer;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\Core\Repository\ShipmentRepositoryInterface;
use Sylius\Component\Resource\Model\ResourceInterface;
final class ShipmentItemDataProviderSpec extends ObjectBehavior
{
function let(ShipmentRepositoryInterface $shipmentRepository, UserContextInterface $userContext): void
{
$this->beConstructedWith($shipmentRepository, $userContext);
}
function it_supports_only_shipment(): void
{
$this->supports(ShipmentInterface::class, 'get')->shouldReturn(true);
$this->supports(ResourceInterface::class, 'get')->shouldReturn(false);
}
function it_provides_shipment_for_shop_user(
ShipmentRepositoryInterface $shipmentRepository,
UserContextInterface $userContext,
ShopUserInterface $shopUser,
CustomerInterface $customer,
ShipmentInterface $shipment
) {
$userContext->getUser()->willReturn($shopUser);
$shopUser->getCustomer()->willReturn($customer);
$shopUser->getRoles()->willReturn(['ROLE_USER']);
$shipmentRepository
->findOneByCustomer('123', $customer->getWrappedObject())
->willReturn($shipment)
;
$this->getItem(ShipmentInterface::class, '123')->shouldReturn($shipment);
}
function it_provides_shipment_for_admin_user(
ShipmentRepositoryInterface $shipmentRepository,
UserContextInterface $userContext,
AdminUserInterface $adminUser,
ShipmentInterface $shipment
) {
$userContext->getUser()->willReturn($adminUser);
$adminUser->getRoles()->willReturn(['ROLE_API_ACCESS']);
$shipmentRepository->findOneBy(['id' => '123'])->willReturn($shipment);
$this->getItem(ShipmentInterface::class, '123')->shouldReturn($shipment);
}
function it_returns_null_if_shop_user_has_no_customer(
ShipmentRepositoryInterface $shipmentRepository,
UserContextInterface $userContext,
ShopUserInterface $shopUser
) {
$userContext->getUser()->willReturn($shopUser);
$shopUser->getCustomer()->willReturn(null);
$shopUser->getRoles()->willReturn(['ROLE_USER']);
$shipmentRepository->findOneByCustomer('123', new Customer())->shouldNotBeCalled();
$this->getItem(ShipmentInterface::class, '123')->shouldReturn(null);
}
function it_returns_null_if_shop_user_does_have_proper_roles(
ShipmentRepositoryInterface $shipmentRepository,
UserContextInterface $userContext,
CustomerInterface $customer,
ShopUserInterface $shopUser
) {
$userContext->getUser()->willReturn($shopUser);
$shopUser->getCustomer()->willReturn($customer);
$shopUser->getRoles()->willReturn(['']);
$shipmentRepository->findOneByCustomer('123', new Customer())->shouldNotBeCalled();
$this->getItem(ShipmentInterface::class, '123')->shouldReturn(null);
}
}

View file

@ -0,0 +1,36 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Bundle\CoreBundle\Doctrine\ORM;
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Repository\OrderItemRepositoryInterface;
class OrderItemRepository extends EntityRepository implements OrderItemRepositoryInterface
{
public function findOneByCustomer($id, CustomerInterface $customer): ?OrderItemInterface
{
return $this->createQueryBuilder('o')
->innerJoin('o.order', 'ord')
->innerJoin('ord.customer', 'customer')
->andWhere('o.id = :id')
->andWhere('customer = :customer')
->setParameter('id', $id)
->setParameter('customer', $customer)
->getQuery()
->getOneOrNullResult()
;
}
}

View file

@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Bundle\CoreBundle\Doctrine\ORM;
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderItemUnitInterface;
use Sylius\Component\Core\Repository\OrderItemUnitRepositoryInterface;
class OrderItemUnitRepository extends EntityRepository implements OrderItemUnitRepositoryInterface
{
public function findOneByCustomer($id, CustomerInterface $customer): ?OrderItemUnitInterface
{
return $this->createQueryBuilder('o')
->innerJoin('o.orderItem', 'orderItem')
->innerJoin('orderItem.order', 'ord')
->innerJoin('ord.customer', 'customer')
->andWhere('o.id = :id')
->andWhere('customer = :customer')
->setParameter('id', $id)
->setParameter('customer', $customer)
->getQuery()
->getOneOrNullResult()
;
}
}

View file

@ -15,6 +15,7 @@ namespace Sylius\Bundle\CoreBundle\Doctrine\ORM;
use Doctrine\ORM\QueryBuilder;
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\Component\Core\Repository\PaymentRepositoryInterface;
@ -39,4 +40,18 @@ class PaymentRepository extends EntityRepository implements PaymentRepositoryInt
->getOneOrNullResult()
;
}
public function findOneByCustomer($id, CustomerInterface $customer): ?PaymentInterface
{
return $this->createQueryBuilder('o')
->innerJoin('o.order', 'ord')
->innerJoin('ord.customer', 'customer')
->andWhere('o.id = :id')
->andWhere('customer = :customer')
->setParameter('id', $id)
->setParameter('customer', $customer)
->getQuery()
->getOneOrNullResult()
;
}
}

View file

@ -15,6 +15,7 @@ namespace Sylius\Bundle\CoreBundle\Doctrine\ORM;
use Doctrine\ORM\QueryBuilder;
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\ShipmentInterface;
use Sylius\Component\Core\Repository\ShipmentRepositoryInterface;
@ -40,6 +41,20 @@ class ShipmentRepository extends EntityRepository implements ShipmentRepositoryI
;
}
public function findOneByCustomer($id, CustomerInterface $customer): ?ShipmentInterface
{
return $this->createQueryBuilder('o')
->innerJoin('o.order', 'ord')
->innerJoin('ord.customer', 'customer')
->andWhere('o.id = :id')
->andWhere('customer = :customer')
->setParameter('id', $id)
->setParameter('customer', $customer)
->getQuery()
->getOneOrNullResult()
;
}
public function findByName(string $name, string $locale): array
{
return $this->createQueryBuilder('o')

View file

@ -11,9 +11,11 @@ sylius_order:
order_item:
classes:
model: Sylius\Component\Core\Model\OrderItem
repository: Sylius\Bundle\CoreBundle\Doctrine\ORM\OrderItemRepository
order_item_unit:
classes:
model: Sylius\Component\Core\Model\OrderItemUnit
repository: Sylius\Bundle\CoreBundle\Doctrine\ORM\OrderItemUnitRepository
order_sequence:
classes:
model: Sylius\Component\Core\Model\OrderSequence

View file

@ -0,0 +1,23 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Component\Core\Repository;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
interface OrderItemRepositoryInterface extends RepositoryInterface
{
public function findOneByCustomer($id, CustomerInterface $customer): ?OrderItemInterface;
}

View file

@ -0,0 +1,23 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Component\Core\Repository;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderItemUnitInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
interface OrderItemUnitRepositoryInterface extends RepositoryInterface
{
public function findOneByCustomer($id, CustomerInterface $customer): ?OrderItemUnitInterface;
}

View file

@ -14,6 +14,7 @@ declare(strict_types=1);
namespace Sylius\Component\Core\Repository;
use Doctrine\ORM\QueryBuilder;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
@ -22,4 +23,6 @@ interface PaymentRepositoryInterface extends RepositoryInterface
public function createListQueryBuilder(): QueryBuilder;
public function findOneByOrderId($paymentId, $orderId): ?PaymentInterface;
public function findOneByCustomer($id, CustomerInterface $customer): ?PaymentInterface;
}

View file

@ -14,6 +14,7 @@ declare(strict_types=1);
namespace Sylius\Component\Core\Repository;
use Doctrine\ORM\QueryBuilder;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\ShipmentInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
@ -23,6 +24,8 @@ interface ShipmentRepositoryInterface extends RepositoryInterface
public function findOneByOrderId($shipmentId, $orderId): ?ShipmentInterface;
public function findOneByCustomer($id, CustomerInterface $customer): ?ShipmentInterface;
/**
* @return array|ShipmentInterface[]
*/