From 728edf36bf4242fe43c04ccdf442b6808e1b4032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Machulda?= Date: Mon, 30 Nov 2020 00:58:52 +0100 Subject: [PATCH 1/8] [Console] Enable hyperlinks in Konsole/Yakuake --- .../Component/Console/Formatter/OutputFormatterStyle.php | 3 ++- src/Symfony/Component/VarDumper/Dumper/CliDumper.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatterStyle.php b/src/Symfony/Component/Console/Formatter/OutputFormatterStyle.php index 272c3e6a27..7cb6116b44 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatterStyle.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatterStyle.php @@ -166,7 +166,8 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface $unsetCodes = []; 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->foreground) { diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php index af5cafc67e..013a69dd98 100644 --- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php @@ -439,7 +439,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'])) { From 27450c0bb4827ea7ab354307f05d79b3f1365197 Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Sat, 28 Nov 2020 16:34:29 +0100 Subject: [PATCH 2/8] [Security] [DX] Automatically add PasswordUpgradeBadge + default support() impl in AbstractFormLoginAuthenticator --- .../AbstractLoginFormAuthenticator.php | 14 ++++++ .../CheckCredentialsListener.php | 5 ++ .../CheckCredentialsListenerTest.php | 49 +++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/src/Symfony/Component/Security/Http/Authenticator/AbstractLoginFormAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/AbstractLoginFormAuthenticator.php index 24c7405ea9..aeaf1d17cd 100644 --- a/src/Symfony/Component/Security/Http/Authenticator/AbstractLoginFormAuthenticator.php +++ b/src/Symfony/Component/Security/Http/Authenticator/AbstractLoginFormAuthenticator.php @@ -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. */ diff --git a/src/Symfony/Component/Security/Http/EventListener/CheckCredentialsListener.php b/src/Symfony/Component/Security/Http/EventListener/CheckCredentialsListener.php index e2d3f86b8f..c1f649b089 100644 --- a/src/Symfony/Component/Security/Http/EventListener/CheckCredentialsListener.php +++ b/src/Symfony/Component/Security/Http/EventListener/CheckCredentialsListener.php @@ -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; } diff --git a/src/Symfony/Component/Security/Http/Tests/EventListener/CheckCredentialsListenerTest.php b/src/Symfony/Component/Security/Http/Tests/EventListener/CheckCredentialsListenerTest.php index 5dc411bef0..e903dcd22c 100644 --- a/src/Symfony/Component/Security/Http/Tests/EventListener/CheckCredentialsListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/EventListener/CheckCredentialsListenerTest.php @@ -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); From d5477fe2fabd31495d33418f8ad0f0bf097d04fb Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 30 Nov 2020 06:53:11 +0100 Subject: [PATCH 3/8] Update CHANGELOG for 5.2.0 --- CHANGELOG-5.2.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CHANGELOG-5.2.md b/CHANGELOG-5.2.md index 2a83a9f8b5..ff8c81c448 100644 --- a/CHANGELOG-5.2.md +++ b/CHANGELOG-5.2.md @@ -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) From 25acc0b5dfab28e51a40ba9d57033993a42c5f08 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 30 Nov 2020 06:54:18 +0100 Subject: [PATCH 4/8] Update VERSION for 5.2.0 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 3522aaa770..285507a21e 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -74,12 +74,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - const VERSION = '5.2.0-DEV'; + const VERSION = '5.2.0'; const VERSION_ID = 50200; const MAJOR_VERSION = 5; const MINOR_VERSION = 2; const RELEASE_VERSION = 0; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '07/2021'; const END_OF_LIFE = '07/2021'; From 6440b70b3124036b44f6b7af5e9d23e9226f2dc0 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 30 Nov 2020 06:59:51 +0100 Subject: [PATCH 5/8] Bump Symfony version to 5.2.1 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 285507a21e..9f6971378c 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -74,12 +74,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - const VERSION = '5.2.0'; - const VERSION_ID = 50200; + const VERSION = '5.2.1-DEV'; + const VERSION_ID = 50201; const MAJOR_VERSION = 5; const MINOR_VERSION = 2; - const RELEASE_VERSION = 0; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 1; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '07/2021'; const END_OF_LIFE = '07/2021'; From b562a54e5376583e4a260e64cbcd83c8ecb4d465 Mon Sep 17 00:00:00 2001 From: Nyholm Date: Mon, 30 Nov 2020 11:43:40 +0100 Subject: [PATCH 6/8] Added test for issue 39229 --- .../Component/Yaml/Tests/ParserTest.php | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index a9715151f1..3f228a4576 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -2671,6 +2671,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. From 66bc898f611efad4a64f7f938c678cc1a0abe4ed Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 30 Nov 2020 13:47:21 +0100 Subject: [PATCH 7/8] fix lexing inline sequences/mappings with trailing whitespaces --- src/Symfony/Component/Yaml/Parser.php | 4 ++-- src/Symfony/Component/Yaml/Tests/ParserTest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 0c4a76e2b1..56322c387d 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -741,11 +741,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); } diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 3f228a4576..cea3d3f330 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -2683,7 +2683,7 @@ YAML; $this->parser->parse($yaml) ); - $yaml = "\nfoo:\n bar: {}\n"; + $yaml = "\nfoo:\n bar: {} \n"; $this->assertSame( [ 'foo' => [ From 520a10c221da946e8874378a30085c5e9d4d80b5 Mon Sep 17 00:00:00 2001 From: gechetspr Date: Mon, 30 Nov 2020 15:04:35 +0200 Subject: [PATCH 8/8] Added additional file existence check on temporary file cleanup for dumpFile method --- src/Symfony/Component/Filesystem/Filesystem.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 95e4a80107..e20972caee 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -695,7 +695,9 @@ class Filesystem $this->rename($tmpFile, $filename, true); } finally { - @unlink($tmpFile); + if (file_exists($tmpFile)) { + @unlink($tmpFile); + } } }