Merge branch '5.2' into 5.x

* 5.2:
  Added additional file existence check on temporary file cleanup for dumpFile method
  fix lexing inline sequences/mappings with trailing whitespaces
  Added test for issue 39229
  Bump Symfony version to 5.2.1
  Update VERSION for 5.2.0
  Update CHANGELOG for 5.2.0
  [Security] [DX] Automatically add PasswordUpgradeBadge + default support() impl in AbstractFormLoginAuthenticator
  [Console] Enable hyperlinks in Konsole/Yakuake
This commit is contained in:
Alexander M. Turek 2020-11-30 18:27:11 +01:00
commit 4f59d2f7c4
9 changed files with 124 additions and 5 deletions

View File

@ -7,6 +7,30 @@ in 5.2 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 between two versions, go to https://github.com/symfony/symfony/compare/v5.2.0...v5.2.1
* 5.2.0 (2020-11-30)
* feature #39213 [Security] [DX] Automatically add PasswordUpgradeBadge + default support() impl in AbstractFormLoginAuthenticator (wouterj)
* bug #39166 [Messenger] Fix mssql compatibility for doctrine transport. (bill moll)
* bug #39210 [DoctrineBridge] Fix form EntityType with filter on UID (jderusse)
* bug #39211 [HttpClient] fix binding to network interfaces (nicolas-grekas)
* bug #39129 [DependencyInjection] Fix circular in DI with lazy + byContruct loop (jderusse)
* feature #39153 [Security] Automatically register custom authenticator as entry_point (if supported) (wouterj)
* bug #39068 [DependencyInjection][Translator] Silent deprecation triggered by libxml_disable_entity_loader (jderusse)
* bug #39119 [Form] prevent duplicated error message for file upload limits (xabbuh)
* bug #39099 [Form] ignore the pattern attribute for textareas (xabbuh)
* feature #39118 [DoctrineBridge] Require doctrine/persistence 2 (greg0ire)
* feature #39128 [HttpFoundation] Deprecate BinaryFileResponse::create() (derrabus)
* bug #39154 [Yaml] fix lexing strings containing escaped quotation characters (xabbuh)
* bug #39187 [Security] Support for SwitchUserToken instances serialized with 4.4/5.1 (derrabus)
* bug #39180 [Serializer] Fix denormalizing scalar with UnwrappingDenormalizer (camilledejoye)
* bug #38597 [PhpUnitBridge] Fix qualification of deprecations triggered by the debug class loader (fancyweb)
* bug #39160 [Console] Use a partial buffer in SymfonyStyle (jderusse)
* bug #39168 [Console] Fix console closing tag (jderusse)
* bug #39155 [VarDumper] fix casting resources turned into objects on PHP 8 (nicolas-grekas)
* bug #39131 [Cache] Fix CI because of Couchbase version (jderusse)
* bug #39115 [HttpClient] don't fallback to HTTP/1.1 when HTTP/2 streams break (nicolas-grekas)
* bug #33763 [Yaml] fix lexing nested sequences/mappings (xabbuh)
* 5.2.0-RC2 (2020-11-21)
* bug #39113 [DoctrineBridge] drop binary variants of UID types (nicolas-grekas)

View File

@ -95,7 +95,8 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
public function apply(string $text)
{
if (null === $this->handlesHrefGracefully) {
$this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') && !getenv('KONSOLE_VERSION');
$this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR')
&& (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100);
}
if (null !== $this->href && $this->handlesHrefGracefully) {

View File

@ -667,7 +667,9 @@ class Filesystem
$this->rename($tmpFile, $filename, true);
} finally {
@unlink($tmpFile);
if (file_exists($tmpFile)) {
@unlink($tmpFile);
}
}
}

View File

@ -32,6 +32,20 @@ abstract class AbstractLoginFormAuthenticator extends AbstractAuthenticator impl
*/
abstract protected function getLoginUrl(Request $request): string;
/**
* {@inheritdoc}
*
* Override to change the request conditions that have to be
* matched in order to handle the login form submit.
*
* This default implementation handles all POST requests to the
* login path (@see getLoginUrl()).
*/
public function supports(Request $request): bool
{
return $request->isMethod('POST') && $this->getLoginUrl($request) === $request->getPathInfo();
}
/**
* Override to change what happens after a bad username/password is submitted.
*/

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\Security\Http\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CustomCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\UserPassportInterface;
@ -65,6 +66,10 @@ class CheckCredentialsListener implements EventSubscriberInterface
$badge->markResolved();
if (!$passport->hasBadge(PasswordUpgradeBadge::class)) {
$passport->addBadge(new PasswordUpgradeBadge($presentedPassword));
}
return;
}

View File

@ -17,6 +17,7 @@ use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CustomCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
@ -113,6 +114,54 @@ class CheckCredentialsListenerTest extends TestCase
$this->listener->checkPassport($event);
}
public function testAddsPasswordUpgradeBadge()
{
$encoder = $this->createMock(PasswordEncoderInterface::class);
$encoder->expects($this->any())->method('isPasswordValid')->with('encoded-password', 'ThePa$$word')->willReturn(true);
$this->encoderFactory->expects($this->any())->method('getEncoder')->with($this->identicalTo($this->user))->willReturn($encoder);
$passport = new Passport(new UserBadge('wouter', function () { return $this->user; }), new PasswordCredentials('ThePa$$word'));
$this->listener->checkPassport($this->createEvent($passport));
$this->assertTrue($passport->hasBadge(PasswordUpgradeBadge::class));
$this->assertEquals('ThePa$$word', $passport->getBadge(PasswordUpgradeBadge::class)->getAndErasePlaintextPassword());
}
public function testAddsNoPasswordUpgradeBadgeIfItAlreadyExists()
{
$encoder = $this->createMock(PasswordEncoderInterface::class);
$encoder->expects($this->any())->method('isPasswordValid')->with('encoded-password', 'ThePa$$word')->willReturn(true);
$this->encoderFactory->expects($this->any())->method('getEncoder')->with($this->identicalTo($this->user))->willReturn($encoder);
$passport = $this->getMockBuilder(Passport::class)
->setMethods(['addBadge'])
->setConstructorArgs([new UserBadge('wouter', function () { return $this->user; }), new PasswordCredentials('ThePa$$word'), [new PasswordUpgradeBadge('ThePa$$word')]])
->getMock();
$passport->expects($this->never())->method('addBadge')->with($this->isInstanceOf(PasswordUpgradeBadge::class));
$this->listener->checkPassport($this->createEvent($passport));
}
public function testAddsNoPasswordUpgradeBadgeIfPasswordIsInvalid()
{
$encoder = $this->createMock(PasswordEncoderInterface::class);
$encoder->expects($this->any())->method('isPasswordValid')->with('encoded-password', 'ThePa$$word')->willReturn(false);
$this->encoderFactory->expects($this->any())->method('getEncoder')->with($this->identicalTo($this->user))->willReturn($encoder);
$passport = $this->getMockBuilder(Passport::class)
->setMethods(['addBadge'])
->setConstructorArgs([new UserBadge('wouter', function () { return $this->user; }), new PasswordCredentials('ThePa$$word'), [new PasswordUpgradeBadge('ThePa$$word')]])
->getMock();
$passport->expects($this->never())->method('addBadge')->with($this->isInstanceOf(PasswordUpgradeBadge::class));
$this->listener->checkPassport($this->createEvent($passport));
}
private function createEvent($passport)
{
return new CheckPassportEvent($this->createMock(AuthenticatorInterface::class), $passport);

View File

@ -435,7 +435,8 @@ class CliDumper extends AbstractDumper
}
if (null === $this->handlesHrefGracefully) {
$this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') && !getenv('KONSOLE_VERSION');
$this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR')
&& (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100);
}
if (isset($attr['ellipsis'], $attr['ellipsis-type'])) {

View File

@ -749,11 +749,11 @@ class Parser
try {
if ('' !== $value && '{' === $value[0]) {
$cursor = \strlen($this->currentLine) - \strlen($value);
$cursor = \strlen(rtrim($this->currentLine)) - \strlen(rtrim($value));
return Inline::parse($this->lexInlineMapping($cursor), $flags, $this->refs);
} elseif ('' !== $value && '[' === $value[0]) {
$cursor = \strlen($this->currentLine) - \strlen($value);
$cursor = \strlen(rtrim($this->currentLine)) - \strlen(rtrim($value));
return Inline::parse($this->lexInlineSequence($cursor), $flags, $this->refs);
}

View File

@ -2670,6 +2670,29 @@ YAML;
);
}
public function testMultipleWhitespaceAtEndOfLine()
{
$yaml = "\nfoo:\n arguments: [ '@bar' ] \n";
$this->assertSame(
[
'foo' => [
'arguments' => ['@bar'],
],
],
$this->parser->parse($yaml)
);
$yaml = "\nfoo:\n bar: {} \n";
$this->assertSame(
[
'foo' => [
'bar' => [],
],
],
$this->parser->parse($yaml)
);
}
/**
* This is a regression test for a bug where a YAML block with a nested multiline string using | was parsed without
* a trailing \n when a shorter YAML document was parsed before.