Merge branch '1.13' into 1.14

* 1.13:
  [CS][DX] Refactor
  Review fixes
  Note order token length parametrization
  [Core][Api] Use the order token length parameter when generating the token
  [Core] Add order token length to configuration
  Note user token length changes
  [User] Update default token length to 64 from 16
  [User] Change the upper limits of token length
This commit is contained in:
Grzegorz Sadowski 2024-06-17 13:46:36 +02:00
commit 84fa99dda2
No known key found for this signature in database
GPG key ID: EF87FF4E6E3BD364
11 changed files with 107 additions and 19 deletions

View file

@ -1,3 +1,32 @@
# UPGRADING FROM `v1.12.17` TO `v1.12.18`
1. Due to concerns about brute forcing user's reset and verification tokens,
the upper limit of 40 has been changed to 255 and their default length has been changed from 16 to 64.
If you prefer shorter (or longer) tokens, you can change their length via the configuration:
```yml
sylius_user:
resources:
_user_:
user:
resetting:
token:
length: 128
verification:
token:
length: 12
```
where `_user_` can be `admin`, `shop`, `oauth`, or your own custom user type.
1. The order token length has been parametrized and is now configurable, instead of being hardcoded to `10`.
When not specified its default value is `64`.
The new parameter can be set by configuration:
```yml
sylius_core:
order_token_length: 128
```
# UPGRADING FROM `v1.12.16` TO `v1.12.17`
1. Due to a bug that was causing wrong calculation of available stock during completing a payment [REF](https://github.com/Sylius/Sylius/issues/16160),

View file

@ -36,6 +36,7 @@ final class PickupCartHandler implements MessageHandlerInterface
private ObjectManager $orderManager,
private RandomnessGeneratorInterface $generator,
private CustomerRepositoryInterface $customerRepository,
private int $tokenLength = 64,
) {
}
@ -61,7 +62,7 @@ final class PickupCartHandler implements MessageHandlerInterface
}
if (null === $activeCart->getTokenValue()) {
$activeCart->setTokenValue($pickupCart->tokenValue ?? $this->generator->generateUriSafeString(10));
$activeCart->setTokenValue($pickupCart->tokenValue ?? $this->generateTokenValue());
$this->orderManager->persist($activeCart);
}
@ -74,7 +75,7 @@ final class PickupCartHandler implements MessageHandlerInterface
$channel,
$customer,
$this->getLocaleCode($pickupCart->getLocaleCode(), $channel),
$pickupCart->tokenValue ?? $this->generator->generateUriSafeString(10),
$pickupCart->tokenValue ?? $this->generateTokenValue(),
);
$this->orderManager->persist($cart);
@ -111,4 +112,9 @@ final class PickupCartHandler implements MessageHandlerInterface
return $localeCode;
}
private function generateTokenValue(): string
{
return $this->generator->generateUriSafeString($this->tokenLength);
}
}

View file

@ -36,6 +36,7 @@
<argument type="service" id="sylius.manager.order" />
<argument type="service" id="sylius.random_generator" />
<argument type="service" id="sylius.repository.customer" />
<argument>%sylius_core.order_token_length%</argument>
<tag name="messenger.message_handler" bus="sylius.command_bus" />
<tag name="messenger.message_handler" bus="sylius_default.bus"/>
</service>

View file

@ -31,6 +31,8 @@ use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
final class PickupCartHandlerSpec extends ObjectBehavior
{
private const TOKEN_LENGTH = 20;
function let(
OrderFactoryInterface $cartFactory,
OrderRepositoryInterface $cartRepository,
@ -46,6 +48,7 @@ final class PickupCartHandlerSpec extends ObjectBehavior
$orderManager,
$generator,
$customerRepository,
self::TOKEN_LENGTH,
);
}
@ -77,7 +80,7 @@ final class PickupCartHandlerSpec extends ObjectBehavior
$cartRepository->findLatestNotEmptyCartByChannelAndCustomer($channel, $customer)->willReturn(null);
$generator->generateUriSafeString(10)->willReturn('urisafestr');
$generator->generateUriSafeString(self::TOKEN_LENGTH)->willReturn('urisafestr');
$locale->getCode()->willReturn('en_US');
$channel->getLocales()->willReturn(new ArrayCollection([$locale->getWrappedObject()]));
@ -111,7 +114,7 @@ final class PickupCartHandlerSpec extends ObjectBehavior
$cartRepository->findLatestNotEmptyCartByChannelAndCustomer($channel, $customer)->willReturn(null);
$generator->generateUriSafeString(10)->willReturn('urisafestr');
$generator->generateUriSafeString(self::TOKEN_LENGTH)->willReturn('urisafestr');
$locale->getCode()->willReturn('en_US');
$channel->getLocales()->willReturn(new ArrayCollection([$locale->getWrappedObject()]));
@ -165,7 +168,7 @@ final class PickupCartHandlerSpec extends ObjectBehavior
$customerRepository->findOneBy(['email' => 'sample@email.com'])->willReturn($customer);
$generator->generateUriSafeString(10)->willReturn('urisafestr');
$generator->generateUriSafeString(self::TOKEN_LENGTH)->willReturn('urisafestr');
$cartRepository->findLatestNotEmptyCartByChannelAndCustomer($channel, $customer)->willReturn($cart);
$orderManager->persist($cart);
@ -191,7 +194,7 @@ final class PickupCartHandlerSpec extends ObjectBehavior
$cartRepository->findLatestNotEmptyCartByChannelAndCustomer($channel, Argument::any())->shouldNotBeCalled(null);
$generator->generateUriSafeString(10)->willReturn('urisafestr');
$generator->generateUriSafeString(self::TOKEN_LENGTH)->willReturn('urisafestr');
$locale->getCode()->willReturn('en_US');
$channel->getLocales()->willReturn(new ArrayCollection([$locale->getWrappedObject()]));
@ -223,7 +226,7 @@ final class PickupCartHandlerSpec extends ObjectBehavior
$cartRepository->findLatestNotEmptyCartByChannelAndCustomer($channel, Argument::any())->shouldNotBeCalled(null);
$generator->generateUriSafeString(10)->willReturn('urisafestr');
$generator->generateUriSafeString(self::TOKEN_LENGTH)->willReturn('urisafestr');
$locale->getCode()->willReturn('en_US');
$cartFactory->createNewCart($channel, null, 'en_US', 'urisafestr')->willReturn($cart);
@ -253,7 +256,7 @@ final class PickupCartHandlerSpec extends ObjectBehavior
$cartRepository->findLatestNotEmptyCartByChannelAndCustomer($channel, Argument::any())->shouldNotBeCalled(null);
$generator->generateUriSafeString(10)->willReturn('urisafestr');
$generator->generateUriSafeString(self::TOKEN_LENGTH)->willReturn('urisafestr');
$cartFactory->createNewCart($channel, null, 'en_US', 'urisafestr')->willReturn($cart);

View file

@ -62,6 +62,10 @@ final class Configuration implements ConfigurationInterface
->setDeprecated('sylius/sylius', '1.10', 'The "%path%.%node%" parameter is deprecated and will be removed in 2.0.')
->defaultFalse()
->end()
->integerNode('order_token_length')
->defaultValue(64)
->min(1)->max(255)
->end()
->integerNode('max_int_value')->defaultValue(2147483647)->end()
->arrayNode('orders_statistics')
->children()

View file

@ -70,6 +70,7 @@ final class SyliusCoreExtension extends AbstractResourceExtension implements Pre
$container->setParameter('sylius_core.taxation.shipping_address_based_taxation', $config['shipping_address_based_taxation']);
$container->setParameter('sylius_core.order_by_identifier', $config['order_by_identifier']);
$container->setParameter('sylius_core.order_token_length', $config['order_token_length']);
$container->setParameter('sylius_core.catalog_promotions.batch_size', $config['catalog_promotions']['batch_size']);
$container->setParameter('sylius_core.price_history.batch_size', $config['price_history']['batch_size']);
$container->setParameter('sylius_core.orders_statistics.intervals_map', $config['orders_statistics']['intervals_map'] ?? []);

View file

@ -156,6 +156,7 @@
<service id="sylius.unique_id_based_order_token_assigner" class="Sylius\Component\Core\TokenAssigner\UniqueIdBasedOrderTokenAssigner">
<argument type="service" id="sylius.random_generator" />
<argument>%sylius_core.order_token_length%</argument>
</service>
<service id="Sylius\Component\Core\TokenAssigner\OrderTokenAssignerInterface" alias="sylius.unique_id_based_order_token_assigner" />

View file

@ -184,6 +184,42 @@ final class ConfigurationTest extends TestCase
);
}
/** @test */
public function it_has_a_set_default_order_token_length(): void
{
$this->assertProcessedConfigurationEquals(
[[]],
['order_token_length' => 64],
'order_token_length',
);
}
/** @test */
public function it_allows_changing_the_order_token_length(): void
{
$this->assertProcessedConfigurationEquals(
[['order_token_length' => 128]],
['order_token_length' => 128],
'order_token_length',
);
}
/** @test */
public function it_throws_exception_when_order_token_length_is_invalid(): void
{
$this->assertConfigurationIsInvalid([['order_token_length' => 'string']]);
$this->assertConfigurationIsInvalid(
[['order_token_length' => 0]],
'/Should be greater than or equal to 1$/',
true,
);
$this->assertConfigurationIsInvalid(
[['order_token_length' => 256]],
'/Should be less than or equal to 255$/',
true,
);
}
/** @test */
public function it_throws_an_exception_if_value_other_then_integer_is_declared_as_batch_size(): void
{

View file

@ -84,8 +84,8 @@ final class Configuration implements ConfigurationInterface
->end()
->end()
->integerNode('length')
->defaultValue(16)
->min(1)->max(40)
->defaultValue(64)
->min(1)->max(255)
->end()
->scalarNode('field_name')
->defaultValue('passwordResetToken')
@ -131,8 +131,8 @@ final class Configuration implements ConfigurationInterface
->addDefaultsIfNotSet()
->children()
->integerNode('length')
->defaultValue(16)
->min(1)->max(40)
->defaultValue(64)
->min(1)->max(255)
->end()
->scalarNode('field_name')
->defaultValue('emailVerificationToken')

View file

@ -18,13 +18,15 @@ use Sylius\Component\Resource\Generator\RandomnessGeneratorInterface;
final class UniqueIdBasedOrderTokenAssigner implements OrderTokenAssignerInterface
{
public function __construct(private RandomnessGeneratorInterface $generator)
{
public function __construct(
private RandomnessGeneratorInterface $generator,
private int $tokenLength = 64,
) {
}
public function assignTokenValue(OrderInterface $order): void
{
$order->setTokenValue($this->generator->generateUriSafeString(10));
$order->setTokenValue($this->generator->generateUriSafeString($this->tokenLength));
}
public function assignTokenValueIfNotSet(OrderInterface $order): void

View file

@ -21,9 +21,11 @@ use Sylius\Component\Resource\Generator\RandomnessGeneratorInterface;
final class UniqueIdBasedOrderTokenAssignerSpec extends ObjectBehavior
{
private const TOKEN_LENGTH = 32;
public function let(RandomnessGeneratorInterface $generator)
{
$this->beConstructedWith($generator);
$this->beConstructedWith($generator, self::TOKEN_LENGTH);
}
function it_is_an_order_token_assigner(): void
@ -34,16 +36,19 @@ final class UniqueIdBasedOrderTokenAssignerSpec extends ObjectBehavior
function it_assigns_a_token_value_for_order(RandomnessGeneratorInterface $generator, OrderInterface $order): void
{
$order->getTokenValue()->willReturn(null);
$generator->generateUriSafeString(10)->willReturn('yahboiiiii');
$generator->generateUriSafeString(self::TOKEN_LENGTH)->willReturn('yahboiiiii');
$order->setTokenValue('yahboiiiii')->shouldBeCalled();
$this->assignTokenValue($order);
$this->assignTokenValueIfNotSet($order);
}
function it_does_nothing_if_token_is_already_assigned(RandomnessGeneratorInterface $generator, OrderInterface $order)
{
function it_does_nothing_if_token_is_already_assigned(
RandomnessGeneratorInterface $generator,
OrderInterface $order,
): void {
$order->getTokenValue()->willReturn('yahboiiiii');
$generator->generateUriSafeString(Argument::any())->shouldNotBeCalled();
$order->setTokenValue(Argument::any())->shouldNotBeCalled();
$this->assignTokenValueIfNotSet($order);