diff --git a/UPGRADE-6.2.md b/UPGRADE-6.2.md index 60c5b84b43793..015dde43b155f 100644 --- a/UPGRADE-6.2.md +++ b/UPGRADE-6.2.md @@ -14,10 +14,15 @@ HttpFoundation * Deprecate `Request::getContentType()`, use `Request::getContentTypeFormat()` instead +Ldap +---- + + * Deprecate `{username}` parameter use in favour of `{user_identifier}` + Mailer --------- +------ -* Deprecate the `OhMySMTP` transport, use `MailPace` instead + * Deprecate the `OhMySMTP` transport, use `MailPace` instead Security -------- diff --git a/src/Symfony/Component/Ldap/CHANGELOG.md b/src/Symfony/Component/Ldap/CHANGELOG.md index 297ff65e0d445..eb4df15c95e57 100644 --- a/src/Symfony/Component/Ldap/CHANGELOG.md +++ b/src/Symfony/Component/Ldap/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +6.2 +--- + + * Deprecate `{username}` parameter use in favour of `{user_identifier}` + 6.1 --- diff --git a/src/Symfony/Component/Ldap/Security/CheckLdapCredentialsListener.php b/src/Symfony/Component/Ldap/Security/CheckLdapCredentialsListener.php index 19b7f7af1f2d6..5cfed46007b5e 100644 --- a/src/Symfony/Component/Ldap/Security/CheckLdapCredentialsListener.php +++ b/src/Symfony/Component/Ldap/Security/CheckLdapCredentialsListener.php @@ -83,17 +83,17 @@ public function onCheckPassport(CheckPassportEvent $event) } else { throw new LogicException('Using the "query_string" config without using a "search_dn" and a "search_password" is not supported.'); } - $username = $ldap->escape($user->getUserIdentifier(), '', LdapInterface::ESCAPE_FILTER); - $query = str_replace('{username}', $username, $ldapBadge->getQueryString()); + $identifier = $ldap->escape($user->getUserIdentifier(), '', LdapInterface::ESCAPE_FILTER); + $query = str_replace('{user_identifier}', $identifier, $ldapBadge->getQueryString()); $result = $ldap->query($ldapBadge->getDnString(), $query)->execute(); if (1 !== $result->count()) { - throw new BadCredentialsException('The presented username is invalid.'); + throw new BadCredentialsException('The presented user identifier is invalid.'); } $dn = $result[0]->getDn(); } else { - $username = $ldap->escape($user->getUserIdentifier(), '', LdapInterface::ESCAPE_DN); - $dn = str_replace('{username}', $username, $ldapBadge->getDnString()); + $identifier = $ldap->escape($user->getUserIdentifier(), '', LdapInterface::ESCAPE_DN); + $dn = str_replace('{user_identifier}', $identifier, $ldapBadge->getDnString()); } $ldap->bind($dn, $presentedPassword); diff --git a/src/Symfony/Component/Ldap/Security/LdapAuthenticator.php b/src/Symfony/Component/Ldap/Security/LdapAuthenticator.php index f3de1f9310d28..c2999e9efc6f1 100644 --- a/src/Symfony/Component/Ldap/Security/LdapAuthenticator.php +++ b/src/Symfony/Component/Ldap/Security/LdapAuthenticator.php @@ -42,7 +42,7 @@ class LdapAuthenticator implements AuthenticationEntryPointInterface, Interactiv private string $searchPassword; private string $queryString; - public function __construct(AuthenticatorInterface $authenticator, string $ldapServiceId, string $dnString = '{username}', string $searchDn = '', string $searchPassword = '', string $queryString = '') + public function __construct(AuthenticatorInterface $authenticator, string $ldapServiceId, string $dnString = '{user_identifier}', string $searchDn = '', string $searchPassword = '', string $queryString = '') { $this->authenticator = $authenticator; $this->ldapServiceId = $ldapServiceId; diff --git a/src/Symfony/Component/Ldap/Security/LdapBadge.php b/src/Symfony/Component/Ldap/Security/LdapBadge.php index 4f78a39f9d0ba..2f8b1d7bd307d 100644 --- a/src/Symfony/Component/Ldap/Security/LdapBadge.php +++ b/src/Symfony/Component/Ldap/Security/LdapBadge.php @@ -31,12 +31,20 @@ class LdapBadge implements BadgeInterface private string $searchPassword; private ?string $queryString; - public function __construct(string $ldapServiceId, string $dnString = '{username}', string $searchDn = '', string $searchPassword = '', string $queryString = null) + public function __construct(string $ldapServiceId, string $dnString = '{user_identifier}', string $searchDn = '', string $searchPassword = '', string $queryString = null) { $this->ldapServiceId = $ldapServiceId; + $dnString = str_replace('{username}', '{user_identifier}', $dnString, $replaceCount); + if ($replaceCount > 0) { + trigger_deprecation('symfony/ldap', '6.2', 'Using "{username}" parameter in LDAP configuration is deprecated, consider using "{user_identifier}" instead.'); + } $this->dnString = $dnString; $this->searchDn = $searchDn; $this->searchPassword = $searchPassword; + $queryString = str_replace('{username}', '{user_identifier}', $queryString ?? '', $replaceCount); + if ($replaceCount > 0) { + trigger_deprecation('symfony/ldap', '6.2', 'Using "{username}" parameter in LDAP configuration is deprecated, consider using "{user_identifier}" instead.'); + } $this->queryString = $queryString; } diff --git a/src/Symfony/Component/Ldap/Security/LdapUser.php b/src/Symfony/Component/Ldap/Security/LdapUser.php index 71cc96355d848..6e1b1ceb09869 100644 --- a/src/Symfony/Component/Ldap/Security/LdapUser.php +++ b/src/Symfony/Component/Ldap/Security/LdapUser.php @@ -24,19 +24,19 @@ class LdapUser implements UserInterface, PasswordAuthenticatedUserInterface, EquatableInterface { private Entry $entry; - private string $username; + private string $identifier; private ?string $password; private array $roles; private array $extraFields; - public function __construct(Entry $entry, string $username, #[\SensitiveParameter] ?string $password, array $roles = [], array $extraFields = []) + public function __construct(Entry $entry, string $identifier, #[\SensitiveParameter] ?string $password, array $roles = [], array $extraFields = []) { - if (!$username) { + if (!$identifier) { throw new \InvalidArgumentException('The username cannot be empty.'); } $this->entry = $entry; - $this->username = $username; + $this->identifier = $identifier; $this->password = $password; $this->roles = $roles; $this->extraFields = $extraFields; @@ -81,7 +81,7 @@ public function getUsername(): string public function getUserIdentifier(): string { - return $this->username; + return $this->identifier; } /** diff --git a/src/Symfony/Component/Ldap/Security/LdapUserProvider.php b/src/Symfony/Component/Ldap/Security/LdapUserProvider.php index 3d028f5cb7995..01cfb0907ac28 100644 --- a/src/Symfony/Component/Ldap/Security/LdapUserProvider.php +++ b/src/Symfony/Component/Ldap/Security/LdapUserProvider.php @@ -81,7 +81,11 @@ public function loadUserByIdentifier(string $identifier): UserInterface } $identifier = $this->ldap->escape($identifier, '', LdapInterface::ESCAPE_FILTER); - $query = str_replace(['{username}', '{user_identifier}'], $identifier, $this->defaultSearch); + $query = str_replace('{username}', '{user_identifier}', $this->defaultSearch, $replaceCount); + if ($replaceCount > 0) { + trigger_deprecation('symfony/ldap', '6.2', 'Using "{username}" parameter in LDAP configuration is deprecated, consider using "{user_identifier}" instead.'); + } + $query = str_replace('{user_identifier}', $identifier, $query); $search = $this->ldap->query($this->baseDn, $query, ['filter' => 0 == \count($this->extraFields) ? '*' : $this->extraFields]); $entries = $search->execute(); diff --git a/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php b/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php index 1ff3503cac2de..cf1e614e94305 100644 --- a/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php +++ b/src/Symfony/Component/Ldap/Tests/Security/CheckLdapCredentialsListenerTest.php @@ -127,6 +127,43 @@ public function testBindFailureShouldThrowAnException() $listener->onCheckPassport($this->createEvent()); } + /** + * @group legacy + * + * @dataProvider queryForDnProvider + */ + public function testLegacyQueryForDn(string $dnString, string $queryString) + { + $collection = new class([new Entry('')]) extends \ArrayObject implements CollectionInterface { + public function toArray(): array + { + return $this->getArrayCopy(); + } + }; + + $query = $this->createMock(QueryInterface::class); + $query->expects($this->once())->method('execute')->willReturn($collection); + + $this->ldap + ->method('bind') + ->withConsecutive( + ['elsa', 'test1234A$'] + ); + $this->ldap->expects($this->any())->method('escape')->with('Wouter', '', LdapInterface::ESCAPE_FILTER)->willReturn('wouter'); + $this->ldap->expects($this->once())->method('query')->with('{user_identifier}', 'wouter_test')->willReturn($query); + + $listener = $this->createListener(); + $listener->onCheckPassport($this->createEvent('s3cr3t', new LdapBadge('app.ldap', $dnString, 'elsa', 'test1234A$', $queryString))); + } + + public function queryForDnProvider(): iterable + { + yield ['{username}', '{username}_test']; + yield ['{user_identifier}', '{username}_test']; + yield ['{username}', '{user_identifier}_test']; + yield ['{user_identifier}', '{user_identifier}_test']; + } + public function testQueryForDn() { $collection = new class([new Entry('')]) extends \ArrayObject implements CollectionInterface { @@ -145,16 +182,16 @@ public function toArray(): array ['elsa', 'test1234A$'] ); $this->ldap->expects($this->any())->method('escape')->with('Wouter', '', LdapInterface::ESCAPE_FILTER)->willReturn('wouter'); - $this->ldap->expects($this->once())->method('query')->with('{username}', 'wouter_test')->willReturn($query); + $this->ldap->expects($this->once())->method('query')->with('{user_identifier}', 'wouter_test')->willReturn($query); $listener = $this->createListener(); - $listener->onCheckPassport($this->createEvent('s3cr3t', new LdapBadge('app.ldap', '{username}', 'elsa', 'test1234A$', '{username}_test'))); + $listener->onCheckPassport($this->createEvent('s3cr3t', new LdapBadge('app.ldap', '{user_identifier}', 'elsa', 'test1234A$', '{user_identifier}_test'))); } public function testEmptyQueryResultShouldThrowAnException() { $this->expectException(BadCredentialsException::class); - $this->expectExceptionMessage('The presented username is invalid.'); + $this->expectExceptionMessage('The presented user identifier is invalid.'); $collection = $this->createMock(CollectionInterface::class); @@ -170,7 +207,7 @@ public function testEmptyQueryResultShouldThrowAnException() $this->ldap->expects($this->once())->method('query')->willReturn($query); $listener = $this->createListener(); - $listener->onCheckPassport($this->createEvent('s3cr3t', new LdapBadge('app.ldap', '{username}', 'elsa', 'test1234A$', '{username}_test'))); + $listener->onCheckPassport($this->createEvent('s3cr3t', new LdapBadge('app.ldap', '{user_identifier}', 'elsa', 'test1234A$', '{user_identifier}_test'))); } private function createEvent($password = 's3cr3t', $ldapBadge = null) diff --git a/src/Symfony/Component/Ldap/Tests/Security/LdapUserProviderTest.php b/src/Symfony/Component/Ldap/Tests/Security/LdapUserProviderTest.php index 083d0b7e8d7b1..4db7757ee4683 100644 --- a/src/Symfony/Component/Ldap/Tests/Security/LdapUserProviderTest.php +++ b/src/Symfony/Component/Ldap/Tests/Security/LdapUserProviderTest.php @@ -27,7 +27,7 @@ */ class LdapUserProviderTest extends TestCase { - public function testLoadUserByUsernameFailsIfCantConnectToLdap() + public function testLoadUserByIdentifierFailsIfCantConnectToLdap() { $this->expectException(ConnectionException::class); @@ -42,7 +42,7 @@ public function testLoadUserByUsernameFailsIfCantConnectToLdap() $provider->loadUserByIdentifier('foo'); } - public function testLoadUserByUsernameFailsIfNoLdapEntries() + public function testLoadUserByIdentifierFailsIfNoLdapEntries() { $this->expectException(UserNotFoundException::class); @@ -74,7 +74,7 @@ public function testLoadUserByUsernameFailsIfNoLdapEntries() $provider->loadUserByIdentifier('foo'); } - public function testLoadUserByUsernameFailsIfMoreThanOneLdapEntry() + public function testLoadUserByIdentifierFailsIfMoreThanOneLdapEntry() { $this->expectException(UserNotFoundException::class); @@ -106,7 +106,7 @@ public function testLoadUserByUsernameFailsIfMoreThanOneLdapEntry() $provider->loadUserByIdentifier('foo'); } - public function testLoadUserByUsernameFailsIfMoreThanOneLdapPasswordsInEntry() + public function testLoadUserByIdentifierFailsIfMoreThanOneLdapPasswordsInEntry() { $this->expectException(InvalidArgumentException::class); @@ -143,11 +143,11 @@ public function testLoadUserByUsernameFailsIfMoreThanOneLdapPasswordsInEntry() ->willReturn($query) ; - $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={username})', 'userpassword'); + $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={user_identifier})', 'userpassword'); $this->assertInstanceOf(LdapUser::class, $provider->loadUserByIdentifier('foo')); } - public function testLoadUserByUsernameShouldNotFailIfEntryHasNoUidKeyAttribute() + public function testLoadUserByIdentifierShouldNotFailIfEntryHasNoUidKeyAttribute() { $result = $this->createMock(CollectionInterface::class); $query = $this->createMock(QueryInterface::class); @@ -179,11 +179,11 @@ public function testLoadUserByUsernameShouldNotFailIfEntryHasNoUidKeyAttribute() ->willReturn($query) ; - $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={username})'); + $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={user_identifier})'); $this->assertInstanceOf(LdapUser::class, $provider->loadUserByIdentifier('foo')); } - public function testLoadUserByUsernameFailsIfEntryHasNoPasswordAttribute() + public function testLoadUserByIdentifierFailsIfEntryHasNoPasswordAttribute() { $this->expectException(InvalidArgumentException::class); @@ -217,11 +217,11 @@ public function testLoadUserByUsernameFailsIfEntryHasNoPasswordAttribute() ->willReturn($query) ; - $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={username})', 'userpassword'); + $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={user_identifier})', 'userpassword'); $this->assertInstanceOf(LdapUser::class, $provider->loadUserByIdentifier('foo')); } - public function testLoadUserByUsernameIsSuccessfulWithoutPasswordAttribute() + public function testLoadUserByIdentifierIsSuccessfulWithoutPasswordAttribute() { $result = $this->createMock(CollectionInterface::class); $query = $this->createMock(QueryInterface::class); @@ -257,7 +257,7 @@ public function testLoadUserByUsernameIsSuccessfulWithoutPasswordAttribute() $this->assertInstanceOf(LdapUser::class, $provider->loadUserByIdentifier('foo')); } - public function testLoadUserByUsernameIsSuccessfulWithoutPasswordAttributeAndWrongCase() + public function testLoadUserByIdentifierIsSuccessfulWithoutPasswordAttributeAndWrongCase() { $result = $this->createMock(CollectionInterface::class); $query = $this->createMock(QueryInterface::class); @@ -293,7 +293,7 @@ public function testLoadUserByUsernameIsSuccessfulWithoutPasswordAttributeAndWro $this->assertSame('foo', $provider->loadUserByIdentifier('Foo')->getUserIdentifier()); } - public function testLoadUserByUsernameIsSuccessfulWithPasswordAttribute() + public function testLoadUserByIdentifierIsSuccessfulWithPasswordAttribute() { $result = $this->createMock(CollectionInterface::class); $query = $this->createMock(QueryInterface::class); @@ -329,14 +329,14 @@ public function testLoadUserByUsernameIsSuccessfulWithPasswordAttribute() ->willReturn($query) ; - $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={username})', 'userpassword', ['email']); + $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={user_identifier})', 'userpassword', ['email']); $this->assertInstanceOf(LdapUser::class, $provider->loadUserByIdentifier('foo')); } public function testRefreshUserShouldReturnUserWithSameProperties() { $ldap = $this->createMock(LdapInterface::class); - $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={username})', 'userpassword', ['email']); + $provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={user_identifier})', 'userpassword', ['email']); $user = new LdapUser(new Entry('foo'), 'foo', 'bar', ['ROLE_DUMMY'], ['email' => 'foo@symfony.com']); diff --git a/src/Symfony/Component/Ldap/composer.json b/src/Symfony/Component/Ldap/composer.json index 0d8c9db8f365b..a2ab982ea63f8 100644 --- a/src/Symfony/Component/Ldap/composer.json +++ b/src/Symfony/Component/Ldap/composer.json @@ -18,6 +18,7 @@ "require": { "php": ">=8.1", "ext-ldap": "*", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/options-resolver": "^5.4|^6.0" }, "require-dev": {
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: