Merge branch '4.4'
* 4.4: (23 commits) [HttpFoundation] fix docblock [HttpKernel] Flatten "exception" controller argument if not typed Fix MySQL column type definition. Link the right file depending on the new version [Cache] Redis Tag Aware warn on wrong eviction policy [HttpClient] fix HttpClientDataCollector [HttpKernel] collect bundle classes, not paths [Config] fix id-generation for GlobResource [HttpKernel] dont check cache freshness more than once per process [Finder] Allow ssh2 stream wrapper for sftp [FrameworkBundle] fix wiring of httplug client add FrameworkBundle requirement [SecurityBundle] add tests with empty authenticator [Security] always check the token on non-lazy firewalls [DI] Use reproducible entropy to generate env placeholders [WebProfilerBundle] Require symfony/twig-bundle [Mailer] Add UPGRADE entry about the null transport DSN bumped Symfony version to 4.3.9 updated VERSION for 4.3.8 updated CHANGELOG for 4.3.8 ...
This commit is contained in:
commit
df63cc59f1
@ -7,6 +7,16 @@ in 4.3 minor versions.
|
|||||||
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
|
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
|
||||||
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v4.3.0...v4.3.1
|
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v4.3.0...v4.3.1
|
||||||
|
|
||||||
|
* 4.3.8 (2019-11-13)
|
||||||
|
|
||||||
|
* bug #34344 [Console] Constant STDOUT might be undefined (nicolas-grekas)
|
||||||
|
* security #cve-2019-18886 [Security\Core] throw AccessDeniedException when switch user fails (nicolas-grekas)
|
||||||
|
* security #cve-2019-18888 [Mime] fix guessing mime-types of files with leading dash (nicolas-grekas)
|
||||||
|
* security #cve-2019-11325 [VarExporter] fix exporting some strings (nicolas-grekas)
|
||||||
|
* security #cve-2019-18889 [Cache] forbid serializing AbstractAdapter and TagAwareAdapter instances (nicolas-grekas)
|
||||||
|
* security #cve-2019-18888 [HttpFoundation] fix guessing mime-types of files with leading dash (nicolas-grekas)
|
||||||
|
* security #cve-2019-18887 [HttpKernel] Use constant time comparison in UriSigner (stof)
|
||||||
|
|
||||||
* 4.3.7 (2019-11-11)
|
* 4.3.7 (2019-11-11)
|
||||||
|
|
||||||
* bug #34294 [Workflow] Fix error when we use ValueObject for the marking property (FabienSalles)
|
* bug #34294 [Workflow] Fix error when we use ValueObject for the marking property (FabienSalles)
|
||||||
|
@ -26,8 +26,8 @@ file and directory structure of your application:
|
|||||||
|
|
||||||
Then, upgrade the contents of your console script and your front controller:
|
Then, upgrade the contents of your console script and your front controller:
|
||||||
|
|
||||||
* `bin/console`: https://github.com/symfony/recipes/blob/master/symfony/console/3.3/bin/console
|
* `bin/console`: https://github.com/symfony/recipes/blob/master/symfony/console/4.4/bin/console
|
||||||
* `public/index.php`: https://github.com/symfony/recipes/blob/master/symfony/framework-bundle/3.3/public/index.php
|
* `public/index.php`: https://github.com/symfony/recipes/blob/master/symfony/framework-bundle/4.4/public/index.php
|
||||||
|
|
||||||
Lastly, read the following article to add Symfony Flex to your application and
|
Lastly, read the following article to add Symfony Flex to your application and
|
||||||
upgrade the configuration files: https://symfony.com/doc/current/setup/flex.html
|
upgrade the configuration files: https://symfony.com/doc/current/setup/flex.html
|
||||||
|
@ -164,6 +164,11 @@ Lock
|
|||||||
* Deprecated services `lock.store.flock`, `lock.store.semaphore`, `lock.store.memcached.abstract` and `lock.store.redis.abstract`,
|
* Deprecated services `lock.store.flock`, `lock.store.semaphore`, `lock.store.memcached.abstract` and `lock.store.redis.abstract`,
|
||||||
use `StoreFactory::createStore` instead.
|
use `StoreFactory::createStore` instead.
|
||||||
|
|
||||||
|
Mailer
|
||||||
|
------
|
||||||
|
|
||||||
|
* [BC BREAK] Changed the DSN to use for disabling delivery (using the `NullTransport`) from `smtp://null` to `null://null` (host doesn't matter).
|
||||||
|
|
||||||
Messenger
|
Messenger
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@
|
|||||||
|
|
||||||
<service id="Http\Client\HttpClient" class="Symfony\Component\HttpClient\HttplugClient">
|
<service id="Http\Client\HttpClient" class="Symfony\Component\HttpClient\HttplugClient">
|
||||||
<argument type="service" id="http_client" />
|
<argument type="service" id="http_client" />
|
||||||
<argument type="service" id="Http\Message\ResponseFactory" on-invalid="ignore" />
|
<argument type="service" id="Psr\Http\Message\ResponseFactoryInterface" on-invalid="ignore" />
|
||||||
<argument type="service" id="Http\Message\StreamFactory" on-invalid="ignore" />
|
<argument type="service" id="Psr\Http\Message\StreamFactoryInterface" on-invalid="ignore" />
|
||||||
</service>
|
</service>
|
||||||
</services>
|
</services>
|
||||||
</container>
|
</container>
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
|
||||||
|
|
||||||
|
class AnonymousTest extends AbstractWebTestCase
|
||||||
|
{
|
||||||
|
public function testAnonymous()
|
||||||
|
{
|
||||||
|
$client = $this->createClient(['test_case' => 'Anonymous', 'root_config' => 'config.yml']);
|
||||||
|
|
||||||
|
$client->request('GET', '/');
|
||||||
|
|
||||||
|
$this->assertSame(401, $client->getResponse()->getStatusCode());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AnonymousBundle;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
|
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||||
|
use Symfony\Component\Security\Core\User\UserInterface;
|
||||||
|
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||||
|
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
|
||||||
|
|
||||||
|
class AppCustomAuthenticator extends AbstractGuardAuthenticator
|
||||||
|
{
|
||||||
|
public function supports(Request $request)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCredentials(Request $request)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUser($credentials, UserProviderInterface $userProvider)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkCredentials($credentials, UserInterface $user)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function start(Request $request, AuthenticationException $authException = null)
|
||||||
|
{
|
||||||
|
return new Response($authException->getMessage(), Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsRememberMe()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return [
|
||||||
|
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
|
||||||
|
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
|
||||||
|
];
|
@ -0,0 +1,24 @@
|
|||||||
|
framework:
|
||||||
|
secret: test
|
||||||
|
router: { resource: "%kernel.project_dir%/%kernel.test_case%/routing.yml" }
|
||||||
|
validation: { enabled: true, enable_annotations: true }
|
||||||
|
csrf_protection: true
|
||||||
|
form: true
|
||||||
|
test: ~
|
||||||
|
default_locale: en
|
||||||
|
session:
|
||||||
|
storage_id: session.storage.mock_file
|
||||||
|
profiler: { only_exceptions: false }
|
||||||
|
|
||||||
|
services:
|
||||||
|
Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AnonymousBundle\AppCustomAuthenticator: ~
|
||||||
|
|
||||||
|
security:
|
||||||
|
firewalls:
|
||||||
|
secure:
|
||||||
|
pattern: ^/
|
||||||
|
anonymous: false
|
||||||
|
stateless: true
|
||||||
|
guard:
|
||||||
|
authenticators:
|
||||||
|
- Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AnonymousBundle\AppCustomAuthenticator
|
@ -0,0 +1,5 @@
|
|||||||
|
main:
|
||||||
|
path: /
|
||||||
|
defaults:
|
||||||
|
_controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction
|
||||||
|
path: /app
|
@ -210,7 +210,7 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="key">Name</th>
|
<th class="key">Name</th>
|
||||||
<th>Path</th>
|
<th>Class</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"php": "^7.2.9",
|
"php": "^7.2.9",
|
||||||
"symfony/config": "^4.4|^5.0",
|
"symfony/config": "^4.4|^5.0",
|
||||||
|
"symfony/framework-bundle": "^4.4|^5.0",
|
||||||
"symfony/http-kernel": "^4.4|^5.0",
|
"symfony/http-kernel": "^4.4|^5.0",
|
||||||
"symfony/routing": "^4.4|^5.0",
|
"symfony/routing": "^4.4|^5.0",
|
||||||
"symfony/twig-bundle": "^4.4|^5.0",
|
"symfony/twig-bundle": "^4.4|^5.0",
|
||||||
|
@ -14,6 +14,7 @@ namespace Symfony\Component\Cache\Adapter;
|
|||||||
use Predis\Connection\Aggregate\ClusterInterface;
|
use Predis\Connection\Aggregate\ClusterInterface;
|
||||||
use Predis\Connection\Aggregate\PredisCluster;
|
use Predis\Connection\Aggregate\PredisCluster;
|
||||||
use Predis\Response\Status;
|
use Predis\Response\Status;
|
||||||
|
use Symfony\Component\Cache\CacheItem;
|
||||||
use Symfony\Component\Cache\Exception\InvalidArgumentException;
|
use Symfony\Component\Cache\Exception\InvalidArgumentException;
|
||||||
use Symfony\Component\Cache\Marshaller\DeflateMarshaller;
|
use Symfony\Component\Cache\Marshaller\DeflateMarshaller;
|
||||||
use Symfony\Component\Cache\Marshaller\MarshallerInterface;
|
use Symfony\Component\Cache\Marshaller\MarshallerInterface;
|
||||||
@ -58,6 +59,11 @@ class RedisTagAwareAdapter extends AbstractTagAwareAdapter
|
|||||||
*/
|
*/
|
||||||
private const DEFAULT_CACHE_TTL = 8640000;
|
private const DEFAULT_CACHE_TTL = 8640000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string|null detected eviction policy used on Redis server
|
||||||
|
*/
|
||||||
|
private $redisEvictionPolicy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface $redisClient The redis client
|
* @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface $redisClient The redis client
|
||||||
* @param string $namespace The default namespace
|
* @param string $namespace The default namespace
|
||||||
@ -87,6 +93,13 @@ class RedisTagAwareAdapter extends AbstractTagAwareAdapter
|
|||||||
*/
|
*/
|
||||||
protected function doSave(array $values, int $lifetime, array $addTagData = [], array $delTagData = []): array
|
protected function doSave(array $values, int $lifetime, array $addTagData = [], array $delTagData = []): array
|
||||||
{
|
{
|
||||||
|
$eviction = $this->getRedisEvictionPolicy();
|
||||||
|
if ('noeviction' !== $eviction && 0 !== strpos($eviction, 'volatile-')) {
|
||||||
|
CacheItem::log($this->logger, sprintf('Redis maxmemory-policy setting "%s" is *not* supported by RedisTagAwareAdapter, use "noeviction" or "volatile-*" eviction policies', $eviction));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// serialize values
|
// serialize values
|
||||||
if (!$serialized = $this->marshaller->marshall($values, $failed)) {
|
if (!$serialized = $this->marshaller->marshall($values, $failed)) {
|
||||||
return $failed;
|
return $failed;
|
||||||
@ -260,4 +273,20 @@ EOLUA;
|
|||||||
|
|
||||||
return $newIds;
|
return $newIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getRedisEvictionPolicy(): string
|
||||||
|
{
|
||||||
|
if (null !== $this->redisEvictionPolicy) {
|
||||||
|
return $this->redisEvictionPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->getHosts() as $host) {
|
||||||
|
$info = $host->info('Memory');
|
||||||
|
$info = isset($info['Memory']) ? $info['Memory'] : $info;
|
||||||
|
|
||||||
|
return $this->redisEvictionPolicy = $info['maxmemory_policy'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->redisEvictionPolicy = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ class GlobResource implements \IteratorAggregate, SelfCheckingResourceInterface
|
|||||||
*/
|
*/
|
||||||
public function __construct(string $prefix, string $pattern, bool $recursive, bool $forExclusion = false, array $excludedPrefixes = [])
|
public function __construct(string $prefix, string $pattern, bool $recursive, bool $forExclusion = false, array $excludedPrefixes = [])
|
||||||
{
|
{
|
||||||
|
ksort($excludedPrefixes);
|
||||||
$this->prefix = realpath($prefix) ?: (file_exists($prefix) ? $prefix : false);
|
$this->prefix = realpath($prefix) ?: (file_exists($prefix) ? $prefix : false);
|
||||||
$this->pattern = $pattern;
|
$this->pattern = $pattern;
|
||||||
$this->recursive = $recursive;
|
$this->recursive = $recursive;
|
||||||
@ -62,7 +63,7 @@ class GlobResource implements \IteratorAggregate, SelfCheckingResourceInterface
|
|||||||
*/
|
*/
|
||||||
public function __toString(): string
|
public function __toString(): string
|
||||||
{
|
{
|
||||||
return 'glob.'.$this->prefix.$this->pattern.(int) $this->recursive;
|
return 'glob.'.$this->prefix.(int) $this->recursive.$this->pattern.(int) $this->forExclusion.implode("\0", $this->excludedPrefixes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,6 +24,8 @@ class EnvPlaceholderParameterBag extends ParameterBag
|
|||||||
private $unusedEnvPlaceholders = [];
|
private $unusedEnvPlaceholders = [];
|
||||||
private $providedTypes = [];
|
private $providedTypes = [];
|
||||||
|
|
||||||
|
private static $counter = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@ -49,7 +51,7 @@ class EnvPlaceholderParameterBag extends ParameterBag
|
|||||||
throw new RuntimeException(sprintf('The default value of an env() parameter must be a string or null, but "%s" given to "%s".', \gettype($defaultValue), $name));
|
throw new RuntimeException(sprintf('The default value of an env() parameter must be a string or null, but "%s" given to "%s".', \gettype($defaultValue), $name));
|
||||||
}
|
}
|
||||||
|
|
||||||
$uniqueName = md5($name.uniqid(mt_rand(), true));
|
$uniqueName = md5($name.'_'.self::$counter++);
|
||||||
$placeholder = sprintf('%s_%s_%s', $this->getEnvPlaceholderUniquePrefix(), str_replace(':', '_', $env), $uniqueName);
|
$placeholder = sprintf('%s_%s_%s', $this->getEnvPlaceholderUniquePrefix(), str_replace(':', '_', $env), $uniqueName);
|
||||||
$this->envPlaceholders[$env][$placeholder] = $placeholder;
|
$this->envPlaceholders[$env][$placeholder] = $placeholder;
|
||||||
|
|
||||||
@ -64,7 +66,13 @@ class EnvPlaceholderParameterBag extends ParameterBag
|
|||||||
*/
|
*/
|
||||||
public function getEnvPlaceholderUniquePrefix(): string
|
public function getEnvPlaceholderUniquePrefix(): string
|
||||||
{
|
{
|
||||||
return $this->envPlaceholderUniquePrefix ?? $this->envPlaceholderUniquePrefix = 'env_'.bin2hex(random_bytes(8));
|
if (null === $this->envPlaceholderUniquePrefix) {
|
||||||
|
$reproducibleEntropy = unserialize(serialize($this->parameters));
|
||||||
|
array_walk_recursive($reproducibleEntropy, function (&$v) { $v = null; });
|
||||||
|
$this->envPlaceholderUniquePrefix = 'env_'.substr(md5(serialize($reproducibleEntropy)), -16);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->envPlaceholderUniquePrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -784,7 +784,7 @@ class Finder implements \IteratorAggregate, \Countable
|
|||||||
{
|
{
|
||||||
$dir = rtrim($dir, '/'.\DIRECTORY_SEPARATOR);
|
$dir = rtrim($dir, '/'.\DIRECTORY_SEPARATOR);
|
||||||
|
|
||||||
if (preg_match('#^s?ftp://#', $dir)) {
|
if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) {
|
||||||
$dir .= '/';
|
$dir .= '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +133,7 @@ final class HttpClientDataCollector extends DataCollector
|
|||||||
|
|
||||||
$debugInfo = array_diff_key($info, $baseInfo);
|
$debugInfo = array_diff_key($info, $baseInfo);
|
||||||
$info = array_diff_key($info, $debugInfo) + ['debug_info' => $debugInfo];
|
$info = array_diff_key($info, $debugInfo) + ['debug_info' => $debugInfo];
|
||||||
|
unset($traces[$i]['info']); // break PHP reference used by TraceableHttpClient
|
||||||
$traces[$i]['info'] = $this->cloneVar($info);
|
$traces[$i]['info'] = $this->cloneVar($info);
|
||||||
$traces[$i]['options'] = $this->cloneVar($trace['options']);
|
$traces[$i]['options'] = $this->cloneVar($trace['options']);
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||||||
// - trailing space removal
|
// - trailing space removal
|
||||||
// - case-insensitivity
|
// - case-insensitivity
|
||||||
// - language processing like é == e
|
// - language processing like é == e
|
||||||
$sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol MEDIUMINT NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8_bin, ENGINE = InnoDB";
|
$sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8_bin, ENGINE = InnoDB";
|
||||||
break;
|
break;
|
||||||
case 'sqlite':
|
case 'sqlite':
|
||||||
$sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)";
|
$sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)";
|
||||||
|
@ -34,7 +34,7 @@ class RedisSessionHandler extends AbstractSessionHandler
|
|||||||
* List of available options:
|
* List of available options:
|
||||||
* * prefix: The prefix to use for the keys in order to avoid collision on the Redis server.
|
* * prefix: The prefix to use for the keys in order to avoid collision on the Redis server.
|
||||||
*
|
*
|
||||||
* @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy $redis
|
* @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException When unsupported client or options are passed
|
* @throws \InvalidArgumentException When unsupported client or options are passed
|
||||||
*/
|
*/
|
||||||
|
@ -15,7 +15,7 @@ use Symfony\Component\HttpFoundation\Request;
|
|||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\HttpKernel\Kernel;
|
use Symfony\Component\HttpKernel\Kernel;
|
||||||
use Symfony\Component\HttpKernel\KernelInterface;
|
use Symfony\Component\HttpKernel\KernelInterface;
|
||||||
use Symfony\Component\VarDumper\Caster\LinkStub;
|
use Symfony\Component\VarDumper\Caster\ClassStub;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
@ -28,12 +28,6 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
|
|||||||
* @var KernelInterface
|
* @var KernelInterface
|
||||||
*/
|
*/
|
||||||
private $kernel;
|
private $kernel;
|
||||||
private $hasVarDumper;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->hasVarDumper = class_exists(LinkStub::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the Kernel associated with this Request.
|
* Sets the Kernel associated with this Request.
|
||||||
@ -67,7 +61,7 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
|
|||||||
|
|
||||||
if (isset($this->kernel)) {
|
if (isset($this->kernel)) {
|
||||||
foreach ($this->kernel->getBundles() as $name => $bundle) {
|
foreach ($this->kernel->getBundles() as $name => $bundle) {
|
||||||
$this->data['bundles'][$name] = $this->hasVarDumper ? new LinkStub($bundle->getPath()) : $bundle->getPath();
|
$this->data['bundles'][$name] = new ClassStub(\get_class($bundle));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->data['symfony_state'] = $this->determineSymfonyState();
|
$this->data['symfony_state'] = $this->determineSymfonyState();
|
||||||
|
@ -99,7 +99,7 @@ class ErrorListener implements EventSubscriberInterface
|
|||||||
$r = new \ReflectionFunction(\Closure::fromCallable($event->getController()));
|
$r = new \ReflectionFunction(\Closure::fromCallable($event->getController()));
|
||||||
$r = $r->getParameters()[$k] ?? null;
|
$r = $r->getParameters()[$k] ?? null;
|
||||||
|
|
||||||
if ($r && $r->hasType() && FlattenException::class === $r->getType()->getName()) {
|
if ($r && (!$r->hasType() || FlattenException::class === $r->getType()->getName())) {
|
||||||
$arguments = $event->getArguments();
|
$arguments = $event->getArguments();
|
||||||
$arguments[$k] = FlattenException::createFromThrowable($e);
|
$arguments[$k] = FlattenException::createFromThrowable($e);
|
||||||
$event->setArguments($arguments);
|
$event->setArguments($arguments);
|
||||||
|
@ -66,6 +66,8 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
|
|||||||
private $requestStackSize = 0;
|
private $requestStackSize = 0;
|
||||||
private $resetServices = false;
|
private $resetServices = false;
|
||||||
|
|
||||||
|
private static $freshCache = [];
|
||||||
|
|
||||||
const VERSION = '5.0.0-DEV';
|
const VERSION = '5.0.0-DEV';
|
||||||
const VERSION_ID = 50000;
|
const VERSION_ID = 50000;
|
||||||
const MAJOR_VERSION = 5;
|
const MAJOR_VERSION = 5;
|
||||||
@ -430,7 +432,9 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
|
|||||||
$errorLevel = error_reporting(\E_ALL ^ \E_WARNING);
|
$errorLevel = error_reporting(\E_ALL ^ \E_WARNING);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (file_exists($cachePath) && \is_object($this->container = include $cachePath) && (!$this->debug || $cache->isFresh())) {
|
if (file_exists($cachePath) && \is_object($this->container = include $cachePath)
|
||||||
|
&& (!$this->debug || (self::$freshCache[$k = $cachePath.'.'.$this->environment] ?? self::$freshCache[$k] = $cache->isFresh()))
|
||||||
|
) {
|
||||||
$this->container->set('kernel', $this);
|
$this->container->set('kernel', $this);
|
||||||
error_reporting($errorLevel);
|
error_reporting($errorLevel);
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener;
|
|||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
|
||||||
use Symfony\Component\ErrorHandler\Exception\FlattenException;
|
use Symfony\Component\ErrorHandler\Exception\FlattenException;
|
||||||
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
|
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
|
||||||
@ -158,12 +158,11 @@ class ErrorListenerTest extends TestCase
|
|||||||
$this->assertFalse($dispatcher->hasListeners(KernelEvents::RESPONSE), 'CSP removal listener has been removed');
|
$this->assertFalse($dispatcher->hasListeners(KernelEvents::RESPONSE), 'CSP removal listener has been removed');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testOnControllerArguments()
|
/**
|
||||||
|
* @dataProvider controllerProvider
|
||||||
|
*/
|
||||||
|
public function testOnControllerArguments(callable $controller)
|
||||||
{
|
{
|
||||||
$controller = function (FlattenException $exception) {
|
|
||||||
return new Response('OK: '.$exception->getMessage());
|
|
||||||
};
|
|
||||||
|
|
||||||
$listener = new ErrorListener($controller, $this->createMock(LoggerInterface::class), true);
|
$listener = new ErrorListener($controller, $this->createMock(LoggerInterface::class), true);
|
||||||
|
|
||||||
$kernel = $this->createMock(HttpKernelInterface::class);
|
$kernel = $this->createMock(HttpKernelInterface::class);
|
||||||
@ -181,6 +180,23 @@ class ErrorListenerTest extends TestCase
|
|||||||
|
|
||||||
$this->assertSame('OK: foo', $event->getResponse()->getContent());
|
$this->assertSame('OK: foo', $event->getResponse()->getContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function controllerProvider()
|
||||||
|
{
|
||||||
|
yield [function (FlattenException $exception) {
|
||||||
|
return new Response('OK: '.$exception->getMessage());
|
||||||
|
}];
|
||||||
|
|
||||||
|
yield [function ($exception) {
|
||||||
|
$this->assertInstanceOf(FlattenException::class, $exception);
|
||||||
|
|
||||||
|
return new Response('OK: '.$exception->getMessage());
|
||||||
|
}];
|
||||||
|
|
||||||
|
yield [function (\Throwable $exception) {
|
||||||
|
return new Response('OK: '.$exception->getMessage());
|
||||||
|
}];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestLogger extends Logger implements DebugLoggerInterface
|
class TestLogger extends Logger implements DebugLoggerInterface
|
||||||
|
@ -4,6 +4,7 @@ CHANGELOG
|
|||||||
4.4.0
|
4.4.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
* [BC BREAK] changed the `NullTransport` DSN from `smtp://null` to `null://null`
|
||||||
* [BC BREAK] renamed `SmtpEnvelope` to `Envelope`, renamed `DelayedSmtpEnvelope` to
|
* [BC BREAK] renamed `SmtpEnvelope` to `Envelope`, renamed `DelayedSmtpEnvelope` to
|
||||||
`DelayedEnvelope`
|
`DelayedEnvelope`
|
||||||
* [BC BREAK] changed the syntax for failover and roundrobin DSNs
|
* [BC BREAK] changed the syntax for failover and roundrobin DSNs
|
||||||
|
@ -18,6 +18,7 @@ use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface
|
|||||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||||
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
|
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
|
||||||
use Symfony\Component\Security\Http\AccessMapInterface;
|
use Symfony\Component\Security\Http\AccessMapInterface;
|
||||||
|
use Symfony\Component\Security\Http\Event\LazyResponseEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AccessListener enforces access control rules.
|
* AccessListener enforces access control rules.
|
||||||
@ -49,6 +50,10 @@ class AccessListener
|
|||||||
*/
|
*/
|
||||||
public function __invoke(RequestEvent $event)
|
public function __invoke(RequestEvent $event)
|
||||||
{
|
{
|
||||||
|
if (!$event instanceof LazyResponseEvent && null === $token = $this->tokenStorage->getToken()) {
|
||||||
|
throw new AuthenticationCredentialsNotFoundException('A Token was not found in the TokenStorage.');
|
||||||
|
}
|
||||||
|
|
||||||
$request = $event->getRequest();
|
$request = $event->getRequest();
|
||||||
|
|
||||||
list($attributes) = $this->map->getPatterns($request);
|
list($attributes) = $this->map->getPatterns($request);
|
||||||
@ -57,7 +62,7 @@ class AccessListener
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null === $token = $this->tokenStorage->getToken()) {
|
if ($event instanceof LazyResponseEvent && null === $token = $this->tokenStorage->getToken()) {
|
||||||
throw new AuthenticationCredentialsNotFoundException('A Token was not found in the TokenStorage.');
|
throw new AuthenticationCredentialsNotFoundException('A Token was not found in the TokenStorage.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterfac
|
|||||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||||
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
|
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
|
||||||
use Symfony\Component\Security\Http\AccessMapInterface;
|
use Symfony\Component\Security\Http\AccessMapInterface;
|
||||||
|
use Symfony\Component\Security\Http\Event\LazyResponseEvent;
|
||||||
use Symfony\Component\Security\Http\Firewall\AccessListener;
|
use Symfony\Component\Security\Http\Firewall\AccessListener;
|
||||||
|
|
||||||
class AccessListenerTest extends TestCase
|
class AccessListenerTest extends TestCase
|
||||||
@ -219,7 +220,7 @@ class AccessListenerTest extends TestCase
|
|||||||
->willReturn($request)
|
->willReturn($request)
|
||||||
;
|
;
|
||||||
|
|
||||||
$listener($event);
|
$listener(new LazyResponseEvent($event));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testHandleWhenTheSecurityTokenStorageHasNoToken()
|
public function testHandleWhenTheSecurityTokenStorageHasNoToken()
|
||||||
|
Reference in New Issue
Block a user