diff --git a/.gitattributes b/.gitattributes index 84c7add0..14c3c359 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,3 @@ /Tests export-ignore /phpunit.xml.dist export-ignore -/.gitattributes export-ignore -/.gitignore export-ignore +/.git* export-ignore diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..4689c4da --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,8 @@ +Please do not submit any Pull Requests here. They will be closed. +--- + +Please submit your PR here instead: +https://github.com/symfony/symfony + +This repository is what we call a "subtree split": a read-only subset of that main repository. +We're looking forward to your PR there! diff --git a/.github/workflows/close-pull-request.yml b/.github/workflows/close-pull-request.yml new file mode 100644 index 00000000..e55b4781 --- /dev/null +++ b/.github/workflows/close-pull-request.yml @@ -0,0 +1,20 @@ +name: Close Pull Request + +on: + pull_request_target: + types: [opened] + +jobs: + run: + runs-on: ubuntu-latest + steps: + - uses: superbrothers/close-pull-request@v3 + with: + comment: | + Thanks for your Pull Request! We love contributions. + + However, you should instead open your PR on the main repository: + https://github.com/symfony/symfony + + This repository is what we call a "subtree split": a read-only subset of that main repository. + We're looking forward to your PR there! diff --git a/Authentication/RememberMe/CacheTokenVerifier.php b/Authentication/RememberMe/CacheTokenVerifier.php index e4f1362a..3930ac8d 100644 --- a/Authentication/RememberMe/CacheTokenVerifier.php +++ b/Authentication/RememberMe/CacheTokenVerifier.php @@ -18,21 +18,17 @@ */ class CacheTokenVerifier implements TokenVerifierInterface { - private CacheItemPoolInterface $cache; - private int $outdatedTokenTtl; - private string $cacheKeyPrefix; - /** * @param int $outdatedTokenTtl How long the outdated token should still be considered valid. Defaults * to 60, which matches how often the PersistentRememberMeHandler will at * most refresh tokens. Increasing to more than that is not recommended, * but you may use a lower value. */ - public function __construct(CacheItemPoolInterface $cache, int $outdatedTokenTtl = 60, string $cacheKeyPrefix = 'rememberme-stale-') - { - $this->cache = $cache; - $this->outdatedTokenTtl = $outdatedTokenTtl; - $this->cacheKeyPrefix = $cacheKeyPrefix; + public function __construct( + private CacheItemPoolInterface $cache, + private int $outdatedTokenTtl = 60, + private string $cacheKeyPrefix = 'rememberme-stale-', + ) { } public function verifyToken(PersistentTokenInterface $token, #[\SensitiveParameter] string $tokenValue): bool diff --git a/Authentication/RememberMe/PersistentToken.php b/Authentication/RememberMe/PersistentToken.php index f473ccb7..0f391c23 100644 --- a/Authentication/RememberMe/PersistentToken.php +++ b/Authentication/RememberMe/PersistentToken.php @@ -18,31 +18,28 @@ */ final class PersistentToken implements PersistentTokenInterface { - private string $class; - private string $userIdentifier; - private string $series; - private string $tokenValue; private \DateTimeImmutable $lastUsed; - public function __construct(string $class, string $userIdentifier, string $series, #[\SensitiveParameter] string $tokenValue, \DateTimeInterface $lastUsed) - { - if (empty($class)) { + public function __construct( + private string $class, + private string $userIdentifier, + private string $series, + #[\SensitiveParameter] private string $tokenValue, + \DateTimeInterface $lastUsed, + ) { + if (!$class) { throw new \InvalidArgumentException('$class must not be empty.'); } if ('' === $userIdentifier) { throw new \InvalidArgumentException('$userIdentifier must not be empty.'); } - if (empty($series)) { + if (!$series) { throw new \InvalidArgumentException('$series must not be empty.'); } - if (empty($tokenValue)) { + if (!$tokenValue) { throw new \InvalidArgumentException('$tokenValue must not be empty.'); } - $this->class = $class; - $this->userIdentifier = $userIdentifier; - $this->series = $series; - $this->tokenValue = $tokenValue; $this->lastUsed = \DateTimeImmutable::createFromInterface($lastUsed); } diff --git a/Authentication/Token/AbstractToken.php b/Authentication/Token/AbstractToken.php index 36d64766..67d992ce 100644 --- a/Authentication/Token/AbstractToken.php +++ b/Authentication/Token/AbstractToken.php @@ -125,7 +125,7 @@ public function hasAttribute(string $name): bool public function getAttribute(string $name): mixed { if (!\array_key_exists($name, $this->attributes)) { - throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.', $name)); + throw new \InvalidArgumentException(\sprintf('This token has no "%s" attribute.', $name)); } return $this->attributes[$name]; @@ -146,7 +146,7 @@ public function __toString(): string $roles[] = $role; } - return sprintf('%s(user="%s", roles="%s")', $class, $this->getUserIdentifier(), implode(', ', $roles)); + return \sprintf('%s(user="%s", roles="%s")', $class, $this->getUserIdentifier(), implode(', ', $roles)); } /** diff --git a/Authentication/Token/PreAuthenticatedToken.php b/Authentication/Token/PreAuthenticatedToken.php index a216d4c1..5c092404 100644 --- a/Authentication/Token/PreAuthenticatedToken.php +++ b/Authentication/Token/PreAuthenticatedToken.php @@ -20,13 +20,14 @@ */ class PreAuthenticatedToken extends AbstractToken { - private string $firewallName; - /** * @param string[] $roles */ - public function __construct(UserInterface $user, string $firewallName, array $roles = []) - { + public function __construct( + UserInterface $user, + private string $firewallName, + array $roles = [], + ) { parent::__construct($roles); if ('' === $firewallName) { @@ -34,7 +35,6 @@ public function __construct(UserInterface $user, string $firewallName, array $ro } $this->setUser($user); - $this->firewallName = $firewallName; } public function getFirewallName(): string diff --git a/Authentication/Token/RememberMeToken.php b/Authentication/Token/RememberMeToken.php index ad218f1b..dfbe20ec 100644 --- a/Authentication/Token/RememberMeToken.php +++ b/Authentication/Token/RememberMeToken.php @@ -21,29 +21,26 @@ */ class RememberMeToken extends AbstractToken { - private string $secret; - private string $firewallName; + private ?string $secret = null; /** - * @param string $secret A secret used to make sure the token is created by the app and not by a malicious client - * * @throws \InvalidArgumentException */ - public function __construct(UserInterface $user, string $firewallName, #[\SensitiveParameter] string $secret) - { + public function __construct( + UserInterface $user, + private string $firewallName, + ) { parent::__construct($user->getRoles()); - if (!$secret) { - throw new InvalidArgumentException('A non-empty secret is required.'); + if (\func_num_args() > 2) { + trigger_deprecation('symfony/security-core', '7.2', 'The "$secret" argument of "%s()" is deprecated.', __METHOD__); + $this->secret = func_get_arg(2); } if (!$firewallName) { throw new InvalidArgumentException('$firewallName must not be empty.'); } - $this->firewallName = $firewallName; - $this->secret = $secret; - $this->setUser($user); } @@ -52,13 +49,19 @@ public function getFirewallName(): string return $this->firewallName; } + /** + * @deprecated since Symfony 7.2 + */ public function getSecret(): string { - return $this->secret; + trigger_deprecation('symfony/security-core', '7.2', 'The "%s()" method is deprecated.', __METHOD__); + + return $this->secret ??= base64_encode(random_bytes(8)); } public function __serialize(): array { + // $this->firewallName should be kept at index 1 for compatibility with payloads generated before Symfony 8 return [$this->secret, $this->firewallName, parent::__serialize()]; } diff --git a/Authentication/Token/Storage/UsageTrackingTokenStorage.php b/Authentication/Token/Storage/UsageTrackingTokenStorage.php index 8a4069e7..4255491d 100644 --- a/Authentication/Token/Storage/UsageTrackingTokenStorage.php +++ b/Authentication/Token/Storage/UsageTrackingTokenStorage.php @@ -24,14 +24,12 @@ */ final class UsageTrackingTokenStorage implements TokenStorageInterface, ServiceSubscriberInterface { - private TokenStorageInterface $storage; - private ContainerInterface $container; private bool $enableUsageTracking = false; - public function __construct(TokenStorageInterface $storage, ContainerInterface $container) - { - $this->storage = $storage; - $this->container = $container; + public function __construct( + private TokenStorageInterface $storage, + private ContainerInterface $container, + ) { } public function getToken(): ?TokenInterface diff --git a/Authentication/Token/SwitchUserToken.php b/Authentication/Token/SwitchUserToken.php index fb632a61..c4e69766 100644 --- a/Authentication/Token/SwitchUserToken.php +++ b/Authentication/Token/SwitchUserToken.php @@ -20,7 +20,6 @@ */ class SwitchUserToken extends UsernamePasswordToken { - private TokenInterface $originalToken; private ?string $originatedFromUri = null; /** @@ -29,11 +28,15 @@ class SwitchUserToken extends UsernamePasswordToken * * @throws \InvalidArgumentException */ - public function __construct(UserInterface $user, string $firewallName, array $roles, TokenInterface $originalToken, ?string $originatedFromUri = null) - { + public function __construct( + UserInterface $user, + string $firewallName, + array $roles, + private TokenInterface $originalToken, + ?string $originatedFromUri = null, + ) { parent::__construct($user, $firewallName, $roles); - $this->originalToken = $originalToken; $this->originatedFromUri = $originatedFromUri; } diff --git a/Authentication/Token/UsernamePasswordToken.php b/Authentication/Token/UsernamePasswordToken.php index 74e24a21..40beb003 100644 --- a/Authentication/Token/UsernamePasswordToken.php +++ b/Authentication/Token/UsernamePasswordToken.php @@ -20,10 +20,11 @@ */ class UsernamePasswordToken extends AbstractToken { - private string $firewallName; - - public function __construct(UserInterface $user, string $firewallName, array $roles = []) - { + public function __construct( + UserInterface $user, + private string $firewallName, + array $roles = [], + ) { parent::__construct($roles); if ('' === $firewallName) { @@ -31,7 +32,6 @@ public function __construct(UserInterface $user, string $firewallName, array $ro } $this->setUser($user); - $this->firewallName = $firewallName; } public function getFirewallName(): string diff --git a/Authorization/AccessDecisionManager.php b/Authorization/AccessDecisionManager.php index 4a56f943..3e42c4bf 100644 --- a/Authorization/AccessDecisionManager.php +++ b/Authorization/AccessDecisionManager.php @@ -32,7 +32,6 @@ final class AccessDecisionManager implements AccessDecisionManagerInterface VoterInterface::ACCESS_ABSTAIN => true, ]; - private iterable $voters; private array $votersCacheAttributes = []; private array $votersCacheObject = []; private AccessDecisionStrategyInterface $strategy; @@ -40,9 +39,10 @@ final class AccessDecisionManager implements AccessDecisionManagerInterface /** * @param iterable $voters An array or an iterator of VoterInterface instances */ - public function __construct(iterable $voters = [], ?AccessDecisionStrategyInterface $strategy = null) - { - $this->voters = $voters; + public function __construct( + private iterable $voters = [], + ?AccessDecisionStrategyInterface $strategy = null, + ) { $this->strategy = $strategy ?? new AffirmativeStrategy(); } @@ -53,7 +53,7 @@ public function decide(TokenInterface $token, array $attributes, mixed $object = { // Special case for AccessListener, do not remove the right side of the condition before 6.0 if (\count($attributes) > 1 && !$allowMultipleAttributes) { - throw new InvalidArgumentException(sprintf('Passing more than one Security attribute to "%s()" is not supported.', __METHOD__)); + throw new InvalidArgumentException(\sprintf('Passing more than one Security attribute to "%s()" is not supported.', __METHOD__)); } return $this->strategy->decide( @@ -69,7 +69,7 @@ private function collectResults(TokenInterface $token, array $attributes, mixed foreach ($this->getVoters($attributes, $object) as $voter) { $result = $voter->vote($token, $object, $attributes); if (!\is_int($result) || !(self::VALID_VOTES[$result] ?? false)) { - throw new \LogicException(sprintf('"%s::vote()" must return one of "%s" constants ("ACCESS_GRANTED", "ACCESS_DENIED" or "ACCESS_ABSTAIN"), "%s" returned.', get_debug_type($voter), VoterInterface::class, var_export($result, true))); + throw new \LogicException(\sprintf('"%s::vote()" must return one of "%s" constants ("ACCESS_GRANTED", "ACCESS_DENIED" or "ACCESS_ABSTAIN"), "%s" returned.', get_debug_type($voter), VoterInterface::class, var_export($result, true))); } yield $result; diff --git a/Authorization/ExpressionLanguage.php b/Authorization/ExpressionLanguage.php index a48d8148..846d2cf6 100644 --- a/Authorization/ExpressionLanguage.php +++ b/Authorization/ExpressionLanguage.php @@ -15,7 +15,7 @@ use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; if (!class_exists(BaseExpressionLanguage::class)) { - throw new \LogicException(sprintf('The "%s" class requires the "ExpressionLanguage" component. Try running "composer require symfony/expression-language".', ExpressionLanguage::class)); + throw new \LogicException(\sprintf('The "%s" class requires the "ExpressionLanguage" component. Try running "composer require symfony/expression-language".', ExpressionLanguage::class)); } else { // Help opcache.preload discover always-needed symbols class_exists(ExpressionLanguageProvider::class); diff --git a/Authorization/ExpressionLanguageProvider.php b/Authorization/ExpressionLanguageProvider.php index d3e2dac0..2e558c21 100644 --- a/Authorization/ExpressionLanguageProvider.php +++ b/Authorization/ExpressionLanguageProvider.php @@ -28,7 +28,7 @@ public function getFunctions(): array new ExpressionFunction('is_fully_authenticated', fn () => '$token && $auth_checker->isGranted("IS_AUTHENTICATED_FULLY")', fn (array $variables) => $variables['token'] && $variables['auth_checker']->isGranted('IS_AUTHENTICATED_FULLY')), - new ExpressionFunction('is_granted', fn ($attributes, $object = 'null') => sprintf('$auth_checker->isGranted(%s, %s)', $attributes, $object), fn (array $variables, $attributes, $object = null) => $variables['auth_checker']->isGranted($attributes, $object)), + new ExpressionFunction('is_granted', fn ($attributes, $object = 'null') => \sprintf('$auth_checker->isGranted(%s, %s)', $attributes, $object), fn (array $variables, $attributes, $object = null) => $variables['auth_checker']->isGranted($attributes, $object)), new ExpressionFunction('is_remember_me', fn () => '$token && $auth_checker->isGranted("IS_REMEMBERED")', fn (array $variables) => $variables['token'] && $variables['auth_checker']->isGranted('IS_REMEMBERED')), ]; diff --git a/Authorization/Strategy/AffirmativeStrategy.php b/Authorization/Strategy/AffirmativeStrategy.php index ecd74b20..fb316fd3 100644 --- a/Authorization/Strategy/AffirmativeStrategy.php +++ b/Authorization/Strategy/AffirmativeStrategy.php @@ -24,11 +24,9 @@ */ final class AffirmativeStrategy implements AccessDecisionStrategyInterface, \Stringable { - private bool $allowIfAllAbstainDecisions; - - public function __construct(bool $allowIfAllAbstainDecisions = false) - { - $this->allowIfAllAbstainDecisions = $allowIfAllAbstainDecisions; + public function __construct( + private bool $allowIfAllAbstainDecisions = false, + ) { } public function decide(\Traversable $results): bool diff --git a/Authorization/Strategy/ConsensusStrategy.php b/Authorization/Strategy/ConsensusStrategy.php index 489b3428..bff56513 100644 --- a/Authorization/Strategy/ConsensusStrategy.php +++ b/Authorization/Strategy/ConsensusStrategy.php @@ -32,13 +32,10 @@ */ final class ConsensusStrategy implements AccessDecisionStrategyInterface, \Stringable { - private bool $allowIfAllAbstainDecisions; - private bool $allowIfEqualGrantedDeniedDecisions; - - public function __construct(bool $allowIfAllAbstainDecisions = false, bool $allowIfEqualGrantedDeniedDecisions = true) - { - $this->allowIfAllAbstainDecisions = $allowIfAllAbstainDecisions; - $this->allowIfEqualGrantedDeniedDecisions = $allowIfEqualGrantedDeniedDecisions; + public function __construct( + private bool $allowIfAllAbstainDecisions = false, + private bool $allowIfEqualGrantedDeniedDecisions = true, + ) { } public function decide(\Traversable $results): bool diff --git a/Authorization/Strategy/PriorityStrategy.php b/Authorization/Strategy/PriorityStrategy.php index 9599950c..d7f566ad 100644 --- a/Authorization/Strategy/PriorityStrategy.php +++ b/Authorization/Strategy/PriorityStrategy.php @@ -25,11 +25,9 @@ */ final class PriorityStrategy implements AccessDecisionStrategyInterface, \Stringable { - private bool $allowIfAllAbstainDecisions; - - public function __construct(bool $allowIfAllAbstainDecisions = false) - { - $this->allowIfAllAbstainDecisions = $allowIfAllAbstainDecisions; + public function __construct( + private bool $allowIfAllAbstainDecisions = false, + ) { } public function decide(\Traversable $results): bool diff --git a/Authorization/Strategy/UnanimousStrategy.php b/Authorization/Strategy/UnanimousStrategy.php index 1f3b85c5..d47d8994 100644 --- a/Authorization/Strategy/UnanimousStrategy.php +++ b/Authorization/Strategy/UnanimousStrategy.php @@ -24,11 +24,9 @@ */ final class UnanimousStrategy implements AccessDecisionStrategyInterface, \Stringable { - private bool $allowIfAllAbstainDecisions; - - public function __construct(bool $allowIfAllAbstainDecisions = false) - { - $this->allowIfAllAbstainDecisions = $allowIfAllAbstainDecisions; + public function __construct( + private bool $allowIfAllAbstainDecisions = false, + ) { } public function decide(\Traversable $results): bool diff --git a/Authorization/TraceableAccessDecisionManager.php b/Authorization/TraceableAccessDecisionManager.php index cb44dce4..0b82eb3a 100644 --- a/Authorization/TraceableAccessDecisionManager.php +++ b/Authorization/TraceableAccessDecisionManager.php @@ -25,17 +25,15 @@ */ class TraceableAccessDecisionManager implements AccessDecisionManagerInterface { - private AccessDecisionManagerInterface $manager; private ?AccessDecisionStrategyInterface $strategy = null; /** @var iterable */ private iterable $voters = []; private array $decisionLog = []; // All decision logs private array $currentLog = []; // Logs being filled in - public function __construct(AccessDecisionManagerInterface $manager) - { - $this->manager = $manager; - + public function __construct( + private AccessDecisionManagerInterface $manager, + ) { // The strategy and voters are stored in a private properties of the decorated service if (property_exists($manager, 'strategy')) { $reflection = new \ReflectionProperty($manager::class, 'strategy'); @@ -87,7 +85,7 @@ public function getStrategy(): string if (null === $this->strategy) { return '-'; } - if (method_exists($this->strategy, '__toString')) { + if ($this->strategy instanceof \Stringable) { return (string) $this->strategy; } diff --git a/Authorization/Voter/AuthenticatedVoter.php b/Authorization/Voter/AuthenticatedVoter.php index d7b2b224..a0011868 100644 --- a/Authorization/Voter/AuthenticatedVoter.php +++ b/Authorization/Voter/AuthenticatedVoter.php @@ -33,11 +33,9 @@ class AuthenticatedVoter implements CacheableVoterInterface public const IS_REMEMBERED = 'IS_REMEMBERED'; public const PUBLIC_ACCESS = 'PUBLIC_ACCESS'; - private AuthenticationTrustResolverInterface $authenticationTrustResolver; - - public function __construct(AuthenticationTrustResolverInterface $authenticationTrustResolver) - { - $this->authenticationTrustResolver = $authenticationTrustResolver; + public function __construct( + private AuthenticationTrustResolverInterface $authenticationTrustResolver, + ) { } public function vote(TokenInterface $token, mixed $subject, array $attributes): int diff --git a/Authorization/Voter/ExpressionVoter.php b/Authorization/Voter/ExpressionVoter.php index 6de9c954..bab32830 100644 --- a/Authorization/Voter/ExpressionVoter.php +++ b/Authorization/Voter/ExpressionVoter.php @@ -26,17 +26,12 @@ */ class ExpressionVoter implements CacheableVoterInterface { - private ExpressionLanguage $expressionLanguage; - private AuthenticationTrustResolverInterface $trustResolver; - private AuthorizationCheckerInterface $authChecker; - private ?RoleHierarchyInterface $roleHierarchy; - - public function __construct(ExpressionLanguage $expressionLanguage, AuthenticationTrustResolverInterface $trustResolver, AuthorizationCheckerInterface $authChecker, ?RoleHierarchyInterface $roleHierarchy = null) - { - $this->expressionLanguage = $expressionLanguage; - $this->trustResolver = $trustResolver; - $this->authChecker = $authChecker; - $this->roleHierarchy = $roleHierarchy; + public function __construct( + private ExpressionLanguage $expressionLanguage, + private AuthenticationTrustResolverInterface $trustResolver, + private AuthorizationCheckerInterface $authChecker, + private ?RoleHierarchyInterface $roleHierarchy = null, + ) { } public function supportsAttribute(string $attribute): bool diff --git a/Authorization/Voter/RoleHierarchyVoter.php b/Authorization/Voter/RoleHierarchyVoter.php index 3535ca11..110faa03 100644 --- a/Authorization/Voter/RoleHierarchyVoter.php +++ b/Authorization/Voter/RoleHierarchyVoter.php @@ -22,12 +22,10 @@ */ class RoleHierarchyVoter extends RoleVoter { - private RoleHierarchyInterface $roleHierarchy; - - public function __construct(RoleHierarchyInterface $roleHierarchy, string $prefix = 'ROLE_') - { - $this->roleHierarchy = $roleHierarchy; - + public function __construct( + private RoleHierarchyInterface $roleHierarchy, + string $prefix = 'ROLE_', + ) { parent::__construct($prefix); } diff --git a/Authorization/Voter/RoleVoter.php b/Authorization/Voter/RoleVoter.php index dbf50478..3c65fb63 100644 --- a/Authorization/Voter/RoleVoter.php +++ b/Authorization/Voter/RoleVoter.php @@ -20,11 +20,9 @@ */ class RoleVoter implements CacheableVoterInterface { - private string $prefix; - - public function __construct(string $prefix = 'ROLE_') - { - $this->prefix = $prefix; + public function __construct( + private string $prefix = 'ROLE_', + ) { } public function vote(TokenInterface $token, mixed $subject, array $attributes): int @@ -38,10 +36,8 @@ public function vote(TokenInterface $token, mixed $subject, array $attributes): } $result = VoterInterface::ACCESS_DENIED; - foreach ($roles as $role) { - if ($attribute === $role) { - return VoterInterface::ACCESS_GRANTED; - } + if (\in_array($attribute, $roles, true)) { + return VoterInterface::ACCESS_GRANTED; } } diff --git a/Authorization/Voter/TraceableVoter.php b/Authorization/Voter/TraceableVoter.php index 412bb976..1abc7c70 100644 --- a/Authorization/Voter/TraceableVoter.php +++ b/Authorization/Voter/TraceableVoter.php @@ -24,13 +24,10 @@ */ class TraceableVoter implements CacheableVoterInterface { - private VoterInterface $voter; - private EventDispatcherInterface $eventDispatcher; - - public function __construct(VoterInterface $voter, EventDispatcherInterface $eventDispatcher) - { - $this->voter = $voter; - $this->eventDispatcher = $eventDispatcher; + public function __construct( + private VoterInterface $voter, + private EventDispatcherInterface $eventDispatcher, + ) { } public function vote(TokenInterface $token, mixed $subject, array $attributes): int diff --git a/CHANGELOG.md b/CHANGELOG.md index 47b4a210..7cf09c70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ CHANGELOG ========= +7.2 +--- + + * Make `AccessDecisionStrategyTestCase` compatible with PHPUnit 10+ + * Add `$token` argument to `UserCheckerInterface::checkPostAuth()` + * Deprecate argument `$secret` of `RememberMeToken` + * Deprecate returning an empty string in `UserInterface::getUserIdentifier()` 7.0 --- diff --git a/Event/AuthenticationEvent.php b/Event/AuthenticationEvent.php index 6fca50d4..f1683558 100644 --- a/Event/AuthenticationEvent.php +++ b/Event/AuthenticationEvent.php @@ -21,15 +21,13 @@ */ class AuthenticationEvent extends Event { - private TokenInterface $authenticationToken; - - public function __construct(TokenInterface $token) - { - $this->authenticationToken = $token; + public function __construct( + private TokenInterface $token, + ) { } public function getAuthenticationToken(): TokenInterface { - return $this->authenticationToken; + return $this->token; } } diff --git a/Event/VoteEvent.php b/Event/VoteEvent.php index 1b1d6a33..edc66b36 100644 --- a/Event/VoteEvent.php +++ b/Event/VoteEvent.php @@ -23,17 +23,12 @@ */ final class VoteEvent extends Event { - private VoterInterface $voter; - private mixed $subject; - private array $attributes; - private int $vote; - - public function __construct(VoterInterface $voter, mixed $subject, array $attributes, int $vote) - { - $this->voter = $voter; - $this->subject = $subject; - $this->attributes = $attributes; - $this->vote = $vote; + public function __construct( + private VoterInterface $voter, + private mixed $subject, + private array $attributes, + private int $vote, + ) { } public function getVoter(): VoterInterface diff --git a/Exception/LazyResponseException.php b/Exception/LazyResponseException.php index e26a3347..a354e68e 100644 --- a/Exception/LazyResponseException.php +++ b/Exception/LazyResponseException.php @@ -20,11 +20,9 @@ */ class LazyResponseException extends \Exception implements ExceptionInterface { - private Response $response; - - public function __construct(Response $response) - { - $this->response = $response; + public function __construct( + private Response $response, + ) { } public function getResponse(): Response diff --git a/Exception/TooManyLoginAttemptsAuthenticationException.php b/Exception/TooManyLoginAttemptsAuthenticationException.php index da1a1a7a..7bb74d64 100644 --- a/Exception/TooManyLoginAttemptsAuthenticationException.php +++ b/Exception/TooManyLoginAttemptsAuthenticationException.php @@ -19,11 +19,9 @@ */ class TooManyLoginAttemptsAuthenticationException extends AuthenticationException { - private ?int $threshold; - - public function __construct(?int $threshold = null) - { - $this->threshold = $threshold; + public function __construct( + private ?int $threshold = null, + ) { } public function getMessageData(): array diff --git a/README.md b/README.md index 5bb87c3c..fc50dcc6 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ so called user providers that hold the users credentials. Getting Started --------------- -``` -$ composer require symfony/security-core +```bash +composer require symfony/security-core ``` ```php @@ -41,7 +41,7 @@ if (!$accessDecisionManager->decide($token, ['ROLE_ADMIN'])) { Sponsor ------- -The Security component for Symfony 7.0 is [backed][1] by [SymfonyCasts][2]. +The Security component for Symfony 7.1 is [backed][1] by [SymfonyCasts][2]. Learn Symfony faster by watching real projects being built and actively coding along with them. SymfonyCasts bridges that learning gap, bringing you video diff --git a/Resources/translations/security.bg.xlf b/Resources/translations/security.bg.xlf index 7fdd4252..5c49168c 100644 --- a/Resources/translations/security.bg.xlf +++ b/Resources/translations/security.bg.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Твърде много неуспешни опити за вход, моля опитайте отново след %minutes% минути. + Твърде много неуспешни опити за вход, моля опитайте отново след %minutes% минути. diff --git a/Resources/translations/security.cs.xlf b/Resources/translations/security.cs.xlf index a37e34e1..213d2975 100644 --- a/Resources/translations/security.cs.xlf +++ b/Resources/translations/security.cs.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Příliš mnoho neúspěšných pokusů o přihlášení, zkuste to prosím znovu za %minutes% minutu.|Příliš mnoho neúspěšných pokusů o přihlášení, zkuste to prosím znovu za %minutes% minuty.|Příliš mnoho neúspěšných pokusů o přihlášení, zkuste to prosím znovu za %minutes% minut. + Příliš mnoho neúspěšných pokusů o přihlášení, zkuste to prosím znovu za %minutes% minutu.|Příliš mnoho neúspěšných pokusů o přihlášení, zkuste to prosím znovu za %minutes% minuty.|Příliš mnoho neúspěšných pokusů o přihlášení, zkuste to prosím znovu za %minutes% minut. diff --git a/Resources/translations/security.fa.xlf b/Resources/translations/security.fa.xlf index 897c34b8..548fd35b 100644 --- a/Resources/translations/security.fa.xlf +++ b/Resources/translations/security.fa.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - تعداد دفعات تلاش برای ورود بیش از حد زیاد است، لطفا پس از %minutes% دقیقه دوباره تلاش کنید. + تعداد دفعات تلاش برای ورود بیش از حد زیاد است، لطفا پس از %minutes% دقیقه دوباره تلاش کنید. diff --git a/Resources/translations/security.he.xlf b/Resources/translations/security.he.xlf index b1d6afd4..1cf02a4e 100644 --- a/Resources/translations/security.he.xlf +++ b/Resources/translations/security.he.xlf @@ -4,15 +4,15 @@ An authentication exception occurred. - שגיאה באימות + התרחשה שגיאה באימות. Authentication credentials could not be found. - פרטי זיהוי לא נמצאו. + פרטי הזיהוי לא נמצאו. Authentication request could not be processed due to a system problem. - לא ניתן היה לעבד את בקשת אימות בגלל בעיית מערכת. + לא ניתן היה לעבד את בקשת האימות בגלל בעיית מערכת. Invalid credentials. @@ -20,7 +20,7 @@ Cookie has already been used by someone else. - עוגיה כבר שומשה. + עוגיה כבר שומשה על ידי מישהו אחר. Not privileged to request the resource. @@ -32,15 +32,15 @@ No authentication provider found to support the authentication token. - לא נמצא ספק אימות המתאימה לבקשה. + לא נמצא ספק אימות המתאים לבקשה. No session available, it either timed out or cookies are not enabled. - אין סיישן זמין, או שתם הזמן הקצוב או העוגיות אינן מופעלות. + אין מפגש זמין, תם הזמן הקצוב או שהעוגיות אינן מופעלות. No token could be found. - הטוקן לא נמצא. + אסימון לא נמצא. Username could not be found. @@ -72,11 +72,11 @@ Too many failed login attempts, please try again in %minutes% minute. - יותר מדי ניסיונות כניסה כושלים, אנא נסה שוב בוד %minutes% דקה. + יותר מדי ניסיונות כניסה כושלים, אנא נסה שוב בעוד %minutes% דקה. Too many failed login attempts, please try again in %minutes% minutes. - יותר מדי ניסיונות כניסה כושלים, אנא נסה שוב בעוד %minutes% דקות. + יותר מדי ניסיונות כניסה כושלים, אנא נסה שוב בעוד %minutes% דקות. diff --git a/Resources/translations/security.it.xlf b/Resources/translations/security.it.xlf index ef250923..72eace25 100644 --- a/Resources/translations/security.it.xlf +++ b/Resources/translations/security.it.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Troppi tentativi di accesso falliti, riprova tra %minutes% minuti. + Troppi tentativi di login falliti, riprova tra %minutes% minuti. diff --git a/Resources/translations/security.lv.xlf b/Resources/translations/security.lv.xlf index fdf0a096..c431ed40 100644 --- a/Resources/translations/security.lv.xlf +++ b/Resources/translations/security.lv.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Pārāk daudz neveiksmīgu autentifikācijas mēģinājumu, lūdzu, mēģiniet vēlreiz pēc %minutes% minūtes.|Pārāk daudz neveiksmīgu autentifikācijas mēģinājumu, lūdzu, mēģiniet vēlreiz pēc %minutes% minūtēm. + Pārāk daudz neveiksmīgu autentifikācijas mēģinājumu, lūdzu, mēģiniet vēlreiz pēc %minutes% minūtēm. diff --git a/Resources/translations/security.nl.xlf b/Resources/translations/security.nl.xlf index 4549d9f1..49b7aa78 100644 --- a/Resources/translations/security.nl.xlf +++ b/Resources/translations/security.nl.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Te veel mislukte inlogpogingen, probeer het over %minutes% minuten opnieuw. + Te veel onjuiste inlogpogingen, probeer het opnieuw over %minutes% minuten. diff --git a/Resources/translations/security.sk.xlf b/Resources/translations/security.sk.xlf index b08757de..3820bdcc 100644 --- a/Resources/translations/security.sk.xlf +++ b/Resources/translations/security.sk.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minútu.|Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minúty.|Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minút. + Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minútu.|Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minúty.|Príliš veľa neúspešných pokusov o prihlásenie, skúste to prosím znova o %minutes% minút. diff --git a/Resources/translations/security.sl.xlf b/Resources/translations/security.sl.xlf index 7d051400..2b7a592b 100644 --- a/Resources/translations/security.sl.xlf +++ b/Resources/translations/security.sl.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minuto.|Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minut. + Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minuto.|Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minuti.|Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minute.|Preveč neuspešnih poskusov prijave, poskusite znova čez %minutes% minut. diff --git a/Resources/translations/security.sq.xlf b/Resources/translations/security.sq.xlf index 44f129e3..2ea88824 100644 --- a/Resources/translations/security.sq.xlf +++ b/Resources/translations/security.sq.xlf @@ -20,7 +20,7 @@ Cookie has already been used by someone else. - Cookie është përdorur tashmë nga dikush tjetër. + “Cookie” është përdorur tashmë nga dikush tjetër. Not privileged to request the resource. @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Shumë përpjekje të pasuksesshme për t'u identifikuar, ju lutemi provoni përsëri pas %minutes% minutash. + Shumë përpjekje të dështuara për identifikim, ju lutemi provoni përsëri pas %minutes% minutash. diff --git a/Resources/translations/security.sr_Cyrl.xlf b/Resources/translations/security.sr_Cyrl.xlf index c4e58def..2192fe6e 100644 --- a/Resources/translations/security.sr_Cyrl.xlf +++ b/Resources/translations/security.sr_Cyrl.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Превише неуспешних покушаја пријављивања, покушајте поново за %minutes% минут.|Превише неуспешних покушаја пријављивања, покушајте поново за %minutes% минута.|Превише неуспешних покушаја пријављивања, покушајте поново за %minutes% минута. + Превише неуспешних покушаја пријављивања, покушајте поново за %minutes% минут.|Превише неуспешних покушаја пријављивања, покушајте поново за %minutes% минута. diff --git a/Resources/translations/security.sr_Latn.xlf b/Resources/translations/security.sr_Latn.xlf index ad0774f9..6a925c5b 100644 --- a/Resources/translations/security.sr_Latn.xlf +++ b/Resources/translations/security.sr_Latn.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Previše neuspešnih pokušaja prijavljivanja, pokušajte ponovo za %minutes% minut.|Previše neuspešnih pokušaja prijavljivanja, pokušajte ponovo za %minutes% minuta.|Previše neuspešnih pokušaja prijavljivanja, pokušajte ponovo za %minutes% minuta. + Previše neuspešnih pokušaja prijavljivanja, pokušajte ponovo za %minutes% minut.|Previše neuspešnih pokušaja prijavljivanja, pokušajte ponovo za %minutes% minuta. diff --git a/Resources/translations/security.tl.xlf b/Resources/translations/security.tl.xlf index c02222de..aa47f179 100644 --- a/Resources/translations/security.tl.xlf +++ b/Resources/translations/security.tl.xlf @@ -72,11 +72,11 @@ Too many failed login attempts, please try again in %minutes% minute. - Napakaraming nabigong mga pagtatangka sa pag-login, pakisubukan ulit sa% minuto% minuto. + Napakaraming nabigong mga pagtatangka sa pag-login, pakisubukan ulit matapos ang %minutes% minuto. Too many failed login attempts, please try again in %minutes% minutes. - Napakaraming nabigong pagtatangka ng pag-login, mangyaring subukang muli sa loob ng %minutes% minuto.|Napakaraming nabigong pagtatangka ng pag-login, mangyaring subukang muli sa loob ng %minutes% minuto. + Napakaraming nabigong mga pagtatangka sa pag-login, pakisubukan ulit matapos ang %minutes% minuto. diff --git a/Resources/translations/security.tr.xlf b/Resources/translations/security.tr.xlf index 4cfc1cb9..57b2b2a2 100644 --- a/Resources/translations/security.tr.xlf +++ b/Resources/translations/security.tr.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Çok fazla başarısız giriş denemesi, lütfen %minutes% dakika sonra tekrar deneyin.|Çok fazla başarısız giriş denemesi, lütfen %minutes% dakika sonra tekrar deneyin. + Çok fazla başarısız giriş denemesi, lütfen %minutes% dakika sonra tekrar deneyin. diff --git a/Resources/translations/security.zh_CN.xlf b/Resources/translations/security.zh_CN.xlf index 9954d866..01fe7009 100644 --- a/Resources/translations/security.zh_CN.xlf +++ b/Resources/translations/security.zh_CN.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - 登录尝试失败次数过多,请在 %minutes% 分钟后再试。|登录尝试失败次数过多,请在 %minutes% 分钟后再试。 + 登录尝试失败次数过多,请在 %minutes% 分钟后重试。 diff --git a/Resources/translations/security.zh_TW.xlf b/Resources/translations/security.zh_TW.xlf index 097ce997..5368a35d 100644 --- a/Resources/translations/security.zh_TW.xlf +++ b/Resources/translations/security.zh_TW.xlf @@ -16,7 +16,7 @@ Invalid credentials. - 無效的憑證。 + 登入憑證無效。 Cookie has already been used by someone else. @@ -24,43 +24,43 @@ Not privileged to request the resource. - 沒有權限請求此資源。 + 無權請求此資源。 Invalid CSRF token. - 無效的 CSRF token 。 + 無效的 CSRF token。 No authentication provider found to support the authentication token. - 沒有找到支持此 token 的身份驗證服務提供方。 + 找不到支援此 token 的身分驗證服務提供方。 No session available, it either timed out or cookies are not enabled. - Session 不可用。回話超時或沒有啓用 cookies 。 + 沒有工作階段,可能是超過時間,或者是未啟用 Cookies。 No token could be found. - 找不到 token 。 + 找不到 token。 Username could not be found. - 找不到用戶名。 + 找不到使用者名稱。 Account has expired. - 賬號已逾期。 + 帳號已經過期。 Credentials have expired. - 憑證已逾期。 + 憑證已經過期。 Account is disabled. - 賬號已被禁用。 + 帳號已被停用。 Account is locked. - 賬號已被鎖定。 + 帳號已被鎖定。 Too many failed login attempts, please try again later. @@ -68,15 +68,15 @@ Invalid or expired login link. - 失效或過期的登入鏈接。 + 登入連結無效或過期。 Too many failed login attempts, please try again in %minutes% minute. - 登錄失敗的次數過多,請在%minutes%分鐘後再試。 + 登入失敗的次數過多,請 %minutes% 分鐘後再試。 Too many failed login attempts, please try again in %minutes% minutes. - 嘗試登入失敗次數過多,請 %minutes% 分鐘後再試。|嘗試登入失敗次數過多,請 %minutes% 分鐘後再試。 + 登入嘗試次數過多,請 %minutes% 分鐘後再試。 diff --git a/Role/RoleHierarchy.php b/Role/RoleHierarchy.php index 15c5750d..a2a58457 100644 --- a/Role/RoleHierarchy.php +++ b/Role/RoleHierarchy.php @@ -21,15 +21,12 @@ class RoleHierarchy implements RoleHierarchyInterface /** @var array> */ protected array $map; - private array $hierarchy; - /** * @param array> $hierarchy */ - public function __construct(array $hierarchy) - { - $this->hierarchy = $hierarchy; - + public function __construct( + private array $hierarchy, + ) { $this->buildRoleMap(); } diff --git a/Signature/ExpiredSignatureStorage.php b/Signature/ExpiredSignatureStorage.php index 20803b97..62026644 100644 --- a/Signature/ExpiredSignatureStorage.php +++ b/Signature/ExpiredSignatureStorage.php @@ -18,13 +18,10 @@ */ final class ExpiredSignatureStorage { - private CacheItemPoolInterface $cache; - private int $lifetime; - - public function __construct(CacheItemPoolInterface $cache, int $lifetime) - { - $this->cache = $cache; - $this->lifetime = $lifetime; + public function __construct( + private CacheItemPoolInterface $cache, + private int $lifetime, + ) { } public function countUsages(string $hash): int diff --git a/Signature/SignatureHasher.php b/Signature/SignatureHasher.php index 3f86fce0..903f5b34 100644 --- a/Signature/SignatureHasher.php +++ b/Signature/SignatureHasher.php @@ -25,28 +25,21 @@ */ class SignatureHasher { - private PropertyAccessorInterface $propertyAccessor; - private array $signatureProperties; - private string $secret; - private ?ExpiredSignatureStorage $expiredSignaturesStorage; - private ?int $maxUses; - /** * @param array $signatureProperties Properties of the User; the hash is invalidated if these properties change * @param ExpiredSignatureStorage|null $expiredSignaturesStorage If provided, secures a sequence of hashes that are expired * @param int|null $maxUses Used together with $expiredSignatureStorage to allow a maximum usage of a hash */ - public function __construct(PropertyAccessorInterface $propertyAccessor, array $signatureProperties, #[\SensitiveParameter] string $secret, ?ExpiredSignatureStorage $expiredSignaturesStorage = null, ?int $maxUses = null) - { + public function __construct( + private PropertyAccessorInterface $propertyAccessor, + private array $signatureProperties, + #[\SensitiveParameter] private string $secret, + private ?ExpiredSignatureStorage $expiredSignaturesStorage = null, + private ?int $maxUses = null, + ) { if (!$secret) { throw new InvalidArgumentException('A non-empty secret is required.'); } - - $this->propertyAccessor = $propertyAccessor; - $this->signatureProperties = $signatureProperties; - $this->secret = $secret; - $this->expiredSignaturesStorage = $expiredSignaturesStorage; - $this->maxUses = $maxUses; } /** @@ -94,7 +87,7 @@ public function verifySignatureHash(UserInterface $user, int $expires, string $h if ($this->expiredSignaturesStorage && $this->maxUses) { if ($this->expiredSignaturesStorage->countUsages($hash) >= $this->maxUses) { - throw new ExpiredSignatureException(sprintf('Signature can only be used "%d" times.', $this->maxUses)); + throw new ExpiredSignatureException(\sprintf('Signature can only be used "%d" times.', $this->maxUses)); } $this->expiredSignaturesStorage->incrementUsages($hash); @@ -118,7 +111,7 @@ public function computeSignatureHash(UserInterface $user, int $expires): string } if (!\is_scalar($value) && !$value instanceof \Stringable) { - throw new \InvalidArgumentException(sprintf('The property path "%s" on the user object "%s" must return a value that can be cast to a string, but "%s" was returned.', $property, $user::class, get_debug_type($value))); + throw new \InvalidArgumentException(\sprintf('The property path "%s" on the user object "%s" must return a value that can be cast to a string, but "%s" was returned.', $property, $user::class, get_debug_type($value))); } hash_update($fieldsHash, ':'.base64_encode($value)); } diff --git a/Test/AccessDecisionStrategyTestCase.php b/Test/AccessDecisionStrategyTestCase.php index bf2a2b9a..792e7779 100644 --- a/Test/AccessDecisionStrategyTestCase.php +++ b/Test/AccessDecisionStrategyTestCase.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Security\Core\Test; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManager; @@ -29,6 +30,7 @@ abstract class AccessDecisionStrategyTestCase extends TestCase * * @param VoterInterface[] $voters */ + #[DataProvider('provideStrategyTests')] final public function testDecide(AccessDecisionStrategyInterface $strategy, array $voters, bool $expected) { $token = $this->createMock(TokenInterface::class); @@ -64,11 +66,9 @@ final protected static function getVoters(int $grants, int $denies, int $abstain final protected static function getVoter(int $vote): VoterInterface { return new class($vote) implements VoterInterface { - private int $vote; - - public function __construct(int $vote) - { - $this->vote = $vote; + public function __construct( + private int $vote, + ) { } public function vote(TokenInterface $token, $subject, array $attributes): int diff --git a/Tests/Authentication/AuthenticationTrustResolverTest.php b/Tests/Authentication/AuthenticationTrustResolverTest.php index 3e0a8d50..fc559983 100644 --- a/Tests/Authentication/AuthenticationTrustResolverTest.php +++ b/Tests/Authentication/AuthenticationTrustResolverTest.php @@ -72,7 +72,7 @@ protected function getRememberMeToken() { $user = new InMemoryUser('wouter', '', ['ROLE_USER']); - return new RememberMeToken($user, 'main', 'secret'); + return new RememberMeToken($user, 'main'); } } diff --git a/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.php b/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.php index 45fd046a..6fc2ab15 100644 --- a/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.php +++ b/Tests/Authentication/RememberMe/InMemoryTokenProviderTest.php @@ -31,8 +31,7 @@ public function testCreateNewToken() public function testLoadTokenBySeriesThrowsNotFoundException() { $this->expectException(TokenNotFoundException::class); - $provider = new InMemoryTokenProvider(); - $provider->loadTokenBySeries('foo'); + (new InMemoryTokenProvider())->loadTokenBySeries('foo'); } public function testUpdateToken() @@ -50,12 +49,14 @@ public function testUpdateToken() public function testDeleteToken() { - $this->expectException(TokenNotFoundException::class); $provider = new InMemoryTokenProvider(); $token = new PersistentToken('foo', 'foo', 'foo', 'foo', new \DateTimeImmutable()); $provider->createNewToken($token); $provider->deleteTokenBySeries('foo'); + + $this->expectException(TokenNotFoundException::class); + $provider->loadTokenBySeries('foo'); } } diff --git a/Tests/Authentication/Token/RememberMeTokenTest.php b/Tests/Authentication/Token/RememberMeTokenTest.php index a63d481b..b0cdbaf1 100644 --- a/Tests/Authentication/Token/RememberMeTokenTest.php +++ b/Tests/Authentication/Token/RememberMeTokenTest.php @@ -20,22 +20,22 @@ class RememberMeTokenTest extends TestCase public function testConstructor() { $user = $this->getUser(); - $token = new RememberMeToken($user, 'fookey', 'foo'); + $token = new RememberMeToken($user, 'fookey'); $this->assertEquals('fookey', $token->getFirewallName()); - $this->assertEquals('foo', $token->getSecret()); $this->assertEquals(['ROLE_FOO'], $token->getRoleNames()); $this->assertSame($user, $token->getUser()); } - public function testConstructorSecretCannotBeEmptyString() + /** + * @group legacy + */ + public function testSecret() { - $this->expectException(\InvalidArgumentException::class); - new RememberMeToken( - $this->getUser(), - '', - '' - ); + $user = $this->getUser(); + $token = new RememberMeToken($user, 'fookey', 'foo'); + + $this->assertEquals('foo', $token->getSecret()); } protected function getUser($roles = ['ROLE_FOO']) diff --git a/Tests/Authentication/Token/Storage/UsageTrackingTokenStorageTest.php b/Tests/Authentication/Token/Storage/UsageTrackingTokenStorageTest.php index 3d7c7904..72e1665a 100644 --- a/Tests/Authentication/Token/Storage/UsageTrackingTokenStorageTest.php +++ b/Tests/Authentication/Token/Storage/UsageTrackingTokenStorageTest.php @@ -13,9 +13,10 @@ use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\Security\Core\Authentication\Token\NullToken; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; use Symfony\Component\Security\Core\Authentication\Token\Storage\UsageTrackingTokenStorage; @@ -25,28 +26,14 @@ class UsageTrackingTokenStorageTest extends TestCase { public function testGetSetToken() { - $sessionAccess = 0; - $sessionLocator = new class(['request_stack' => function () use (&$sessionAccess) { - $session = $this->createMock(SessionInterface::class); - - $request = new Request(); - $request->setSession($session); - $requestStack = $this->getMockBuilder(RequestStack::class)->onlyMethods(['getSession'])->getMock(); - $requestStack->push($request); - $requestStack->expects($this->any())->method('getSession')->willReturnCallback(function () use ($session, &$sessionAccess) { - ++$sessionAccess; - - $session->expects($this->once()) - ->method('getMetadataBag'); - - return $session; - }); - - return $requestStack; - }]) implements ContainerInterface { - use ServiceLocatorTrait; - }; $tokenStorage = new TokenStorage(); + $session = new Session(); + $request = new Request(); + $request->setSession($session); + $requestStack = new RequestStack(); + $requestStack->push($request); + $sessionLocator = new ContainerBuilder(); + $sessionLocator->set('request_stack', $requestStack); $trackingStorage = new UsageTrackingTokenStorage($tokenStorage, $sessionLocator); $this->assertNull($trackingStorage->getToken()); @@ -55,15 +42,15 @@ public function testGetSetToken() $trackingStorage->setToken($token); $this->assertSame($token, $trackingStorage->getToken()); $this->assertSame($token, $tokenStorage->getToken()); - $this->assertSame(0, $sessionAccess); + $this->assertSame(0, $session->getUsageIndex()); $trackingStorage->enableUsageTracking(); $this->assertSame($token, $trackingStorage->getToken()); - $this->assertSame(1, $sessionAccess); + $this->assertSame(1, $session->getUsageIndex()); $trackingStorage->disableUsageTracking(); $this->assertSame($token, $trackingStorage->getToken()); - $this->assertSame(1, $sessionAccess); + $this->assertSame(1, $session->getUsageIndex()); } public function testWithoutMainRequest() diff --git a/Tests/Authorization/AccessDecisionManagerTest.php b/Tests/Authorization/AccessDecisionManagerTest.php index b06a7a79..f0a49788 100644 --- a/Tests/Authorization/AccessDecisionManagerTest.php +++ b/Tests/Authorization/AccessDecisionManagerTest.php @@ -39,7 +39,7 @@ public function testVoterCalls() $this->getUnexpectedVoter(), ]; - $strategy = new class() implements AccessDecisionStrategyInterface { + $strategy = new class implements AccessDecisionStrategyInterface { public function decide(\Traversable $results): bool { $i = 0; diff --git a/Tests/Authorization/ExpressionLanguageTest.php b/Tests/Authorization/ExpressionLanguageTest.php index 8cc4810a..1a4db41e 100644 --- a/Tests/Authorization/ExpressionLanguageTest.php +++ b/Tests/Authorization/ExpressionLanguageTest.php @@ -50,7 +50,7 @@ public static function provider() $user = new InMemoryUser('username', 'password', $roles); $noToken = null; - $rememberMeToken = new RememberMeToken($user, 'firewall-name', 'firewall'); + $rememberMeToken = new RememberMeToken($user, 'firewall-name'); $usernamePasswordToken = new UsernamePasswordToken($user, 'firewall-name', $roles); return [ diff --git a/Tests/Authorization/TraceableAccessDecisionManagerTest.php b/Tests/Authorization/TraceableAccessDecisionManagerTest.php index cefe8dbc..8797d74d 100644 --- a/Tests/Authorization/TraceableAccessDecisionManagerTest.php +++ b/Tests/Authorization/TraceableAccessDecisionManagerTest.php @@ -116,7 +116,7 @@ public static function provideObjectsAndLogs(): \Generator 'result' => true, 'voterDetails' => [], ]], - 'attributes' => [12], + [12], 12345, [], true, @@ -197,7 +197,7 @@ public function testAccessDecisionManagerCalledByVoter() ->expects($this->any()) ->method('vote') ->willReturnCallback(function (TokenInterface $token, $subject, array $attributes) use ($sut, $voter1) { - $vote = \in_array('attr1', $attributes) ? VoterInterface::ACCESS_GRANTED : VoterInterface::ACCESS_ABSTAIN; + $vote = \in_array('attr1', $attributes, true) ? VoterInterface::ACCESS_GRANTED : VoterInterface::ACCESS_ABSTAIN; $sut->addVoterVote($voter1, $attributes, $vote); return $vote; @@ -207,7 +207,7 @@ public function testAccessDecisionManagerCalledByVoter() ->expects($this->any()) ->method('vote') ->willReturnCallback(function (TokenInterface $token, $subject, array $attributes) use ($sut, $voter2) { - if (\in_array('attr2', $attributes)) { + if (\in_array('attr2', $attributes, true)) { $vote = null == $subject ? VoterInterface::ACCESS_GRANTED : VoterInterface::ACCESS_DENIED; } else { $vote = VoterInterface::ACCESS_ABSTAIN; @@ -222,7 +222,7 @@ public function testAccessDecisionManagerCalledByVoter() ->expects($this->any()) ->method('vote') ->willReturnCallback(function (TokenInterface $token, $subject, array $attributes) use ($sut, $voter3) { - if (\in_array('attr2', $attributes) && $subject) { + if (\in_array('attr2', $attributes, true) && $subject) { $vote = $sut->decide($token, $attributes) ? VoterInterface::ACCESS_GRANTED : VoterInterface::ACCESS_DENIED; } else { $vote = VoterInterface::ACCESS_ABSTAIN; diff --git a/Tests/Authorization/Voter/AuthenticatedVoterTest.php b/Tests/Authorization/Voter/AuthenticatedVoterTest.php index 88544c08..ed894b3a 100644 --- a/Tests/Authorization/Voter/AuthenticatedVoterTest.php +++ b/Tests/Authorization/Voter/AuthenticatedVoterTest.php @@ -90,7 +90,7 @@ protected function getToken($authenticated) $user = new InMemoryUser('wouter', '', ['ROLE_USER']); if ('fully' === $authenticated) { - $token = new class() extends AbstractToken { + $token = new class extends AbstractToken { public function getCredentials() { } @@ -101,7 +101,7 @@ public function getCredentials() } if ('remembered' === $authenticated) { - return new RememberMeToken($user, 'foo', 'bar'); + return new RememberMeToken($user, 'foo'); } if ('impersonated' === $authenticated) { diff --git a/Tests/Authorization/Voter/VoterTest.php b/Tests/Authorization/Voter/VoterTest.php index 80c3f4a0..602c61ab 100644 --- a/Tests/Authorization/Voter/VoterTest.php +++ b/Tests/Authorization/Voter/VoterTest.php @@ -41,7 +41,7 @@ public static function getTests(): array [$voter, ['DELETE'], VoterInterface::ACCESS_ABSTAIN, new \stdClass(), 'ACCESS_ABSTAIN if no attribute is supported'], - [$voter, ['EDIT'], VoterInterface::ACCESS_ABSTAIN, new class() {}, 'ACCESS_ABSTAIN if class is not supported'], + [$voter, ['EDIT'], VoterInterface::ACCESS_ABSTAIN, new class {}, 'ACCESS_ABSTAIN if class is not supported'], [$voter, ['EDIT'], VoterInterface::ACCESS_ABSTAIN, null, 'ACCESS_ABSTAIN if object is null'], @@ -67,8 +67,7 @@ public function testVoteWithTypeError() { $this->expectException(\TypeError::class); $this->expectExceptionMessage('Should error'); - $voter = new TypeErrorVoterTest_Voter(); - $voter->vote($this->token, new \stdClass(), ['EDIT']); + (new TypeErrorVoterTest_Voter())->vote($this->token, new \stdClass(), ['EDIT']); } } diff --git a/Tests/Resources/TranslationFilesTest.php b/Tests/Resources/TranslationFilesTest.php index 6bd9a21d..695cdd98 100644 --- a/Tests/Resources/TranslationFilesTest.php +++ b/Tests/Resources/TranslationFilesTest.php @@ -26,7 +26,7 @@ public function testTranslationFileIsValid($filePath) $errors = XliffUtils::validateSchema($document); - $this->assertCount(0, $errors, sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message')))); + $this->assertCount(0, $errors, \sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message')))); } /** @@ -39,7 +39,7 @@ public function testTranslationFileIsValidWithoutEntityLoader($filePath) $errors = XliffUtils::validateSchema($document); - $this->assertCount(0, $errors, sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message')))); + $this->assertCount(0, $errors, \sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message')))); } public static function provideTranslationFiles() diff --git a/Tests/Role/LegacyRoleTest.php b/Tests/Role/LegacyRoleTest.php index 44c95667..238d5664 100644 --- a/Tests/Role/LegacyRoleTest.php +++ b/Tests/Role/LegacyRoleTest.php @@ -18,7 +18,7 @@ class LegacyRoleTest extends TestCase { public function testPayloadFromV4CanBeUnserialized() { - $serialized = 'C:74:"Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken":236:{a:3:{i:0;N;i:1;s:4:"main";i:2;a:5:{i:0;s:2:"sf";i:1;b:1;i:2;a:1:{i:0;O:41:"Symfony\Component\Security\Core\Role\Role":1:{s:47:"Symfony\Component\Security\Core\Role\Role'."\0".'role'."\0".'";s:9:"ROLE_USER";}}i:3;a:0:{}i:4;a:1:{i:0;s:9:"ROLE_USER";}}}}'; + $serialized = 'C:74:"Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken":236:{a:3:{i:0;N;i:1;s:4:"main";i:2;a:5:{i:0;s:2:"sf";i:1;b:1;i:2;a:1:{i:0;O:41:"Symfony\Component\Security\Core\Role\Role":1:{s:47:"'."\0".'Symfony\Component\Security\Core\Role\Role'."\0".'role";s:9:"ROLE_USER";}}i:3;a:0:{}i:4;a:1:{i:0;s:9:"ROLE_USER";}}}}'; $token = unserialize($serialized); diff --git a/Tests/User/ChainUserProviderTest.php b/Tests/User/ChainUserProviderTest.php index 0b95bf8f..3f6d223d 100644 --- a/Tests/User/ChainUserProviderTest.php +++ b/Tests/User/ChainUserProviderTest.php @@ -47,7 +47,6 @@ public function testLoadUserByIdentifier() public function testLoadUserByIdentifierThrowsUserNotFoundException() { - $this->expectException(UserNotFoundException::class); $provider1 = $this->createMock(InMemoryUserProvider::class); $provider1 ->expects($this->once()) @@ -65,6 +64,9 @@ public function testLoadUserByIdentifierThrowsUserNotFoundException() ; $provider = new ChainUserProvider([$provider1, $provider2]); + + $this->expectException(UserNotFoundException::class); + $provider->loadUserByIdentifier('foo'); } @@ -141,7 +143,6 @@ public function testRefreshUserAgain() public function testRefreshUserThrowsUnsupportedUserException() { - $this->expectException(UnsupportedUserException::class); $provider1 = $this->createMock(InMemoryUserProvider::class); $provider1 ->expects($this->once()) @@ -169,6 +170,9 @@ public function testRefreshUserThrowsUnsupportedUserException() ; $provider = new ChainUserProvider([$provider1, $provider2]); + + $this->expectException(UnsupportedUserException::class); + $provider->refreshUser($this->createMock(UserInterface::class)); } diff --git a/Tests/User/InMemoryUserCheckerTest.php b/Tests/User/InMemoryUserCheckerTest.php index 8b01e5f0..25107723 100644 --- a/Tests/User/InMemoryUserCheckerTest.php +++ b/Tests/User/InMemoryUserCheckerTest.php @@ -35,7 +35,6 @@ public function testCheckPostAuthPass() public function testCheckPreAuthDisabled() { $this->expectException(DisabledException::class); - $checker = new InMemoryUserChecker(); - $checker->checkPreAuth(new InMemoryUser('John', 'password', [], false)); + (new InMemoryUserChecker())->checkPreAuth(new InMemoryUser('John', 'password', [], false)); } } diff --git a/Tests/User/InMemoryUserProviderTest.php b/Tests/User/InMemoryUserProviderTest.php index 1a843e4e..98afb3b4 100644 --- a/Tests/User/InMemoryUserProviderTest.php +++ b/Tests/User/InMemoryUserProviderTest.php @@ -62,16 +62,17 @@ public function testCreateUser() public function testCreateUserAlreadyExist() { - $this->expectException(\LogicException::class); $provider = new InMemoryUserProvider(); $provider->createUser(new InMemoryUser('fabien', 'foo')); + + $this->expectException(\LogicException::class); + $provider->createUser(new InMemoryUser('fabien', 'foo')); } public function testLoadUserByIdentifierDoesNotExist() { $this->expectException(UserNotFoundException::class); - $provider = new InMemoryUserProvider(); - $provider->loadUserByIdentifier('fabien'); + (new InMemoryUserProvider())->loadUserByIdentifier('fabien'); } } diff --git a/Tests/Validator/Constraints/UserPasswordValidatorTestCase.php b/Tests/Validator/Constraints/UserPasswordValidatorTestCase.php index ccf556a0..c78f6b5f 100644 --- a/Tests/Validator/Constraints/UserPasswordValidatorTestCase.php +++ b/Tests/Validator/Constraints/UserPasswordValidatorTestCase.php @@ -113,13 +113,14 @@ public static function emptyPasswordData() public function testUserIsNotValid() { - $this->expectException(ConstraintDefinitionException::class); $user = new \stdClass(); $this->tokenStorage = $this->createTokenStorage($user); $this->validator = $this->createValidator(); $this->validator->initialize($this->context); + $this->expectException(ConstraintDefinitionException::class); + $this->validator->validate('secret', new UserPassword()); } diff --git a/User/ChainUserChecker.php b/User/ChainUserChecker.php index f889d35d..67fd76b9 100644 --- a/User/ChainUserChecker.php +++ b/User/ChainUserChecker.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Security\Core\User; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; + final class ChainUserChecker implements UserCheckerInterface { /** @@ -27,10 +29,16 @@ public function checkPreAuth(UserInterface $user): void } } - public function checkPostAuth(UserInterface $user): void + public function checkPostAuth(UserInterface $user /*, TokenInterface $token*/): void { + $token = 1 < \func_num_args() ? func_get_arg(1) : null; + foreach ($this->checkers as $checker) { - $checker->checkPostAuth($user); + if ($token instanceof TokenInterface) { + $checker->checkPostAuth($user, $token); + } else { + $checker->checkPostAuth($user); + } } } } diff --git a/User/ChainUserProvider.php b/User/ChainUserProvider.php index cef93a2d..21e2e618 100644 --- a/User/ChainUserProvider.php +++ b/User/ChainUserProvider.php @@ -26,14 +26,12 @@ */ class ChainUserProvider implements UserProviderInterface, PasswordUpgraderInterface { - private iterable $providers; - /** * @param iterable $providers */ - public function __construct(iterable $providers) - { - $this->providers = $providers; + public function __construct( + private iterable $providers, + ) { } /** @@ -58,7 +56,7 @@ public function loadUserByIdentifier(string $identifier): UserInterface } } - $ex = new UserNotFoundException(sprintf('There is no user with identifier "%s".', $identifier)); + $ex = new UserNotFoundException(\sprintf('There is no user with identifier "%s".', $identifier)); $ex->setUserIdentifier($identifier); throw $ex; } @@ -84,12 +82,12 @@ public function refreshUser(UserInterface $user): UserInterface if ($supportedUserFound) { $username = $user->getUserIdentifier(); - $e = new UserNotFoundException(sprintf('There is no user with name "%s".', $username)); + $e = new UserNotFoundException(\sprintf('There is no user with name "%s".', $username)); $e->setUserIdentifier($username); throw $e; - } else { - throw new UnsupportedUserException(sprintf('There is no user provider for user "%s". Shouldn\'t the "supportsClass()" method of your user provider return true for this classname?', get_debug_type($user))); } + + throw new UnsupportedUserException(\sprintf('There is no user provider for user "%s". Shouldn\'t the "supportsClass()" method of your user provider return true for this classname?', get_debug_type($user))); } public function supportsClass(string $class): bool diff --git a/User/InMemoryUser.php b/User/InMemoryUser.php index c319e1f9..b14bc077 100644 --- a/User/InMemoryUser.php +++ b/User/InMemoryUser.php @@ -22,20 +22,18 @@ final class InMemoryUser implements UserInterface, PasswordAuthenticatedUserInterface, EquatableInterface, \Stringable { private string $username; - private ?string $password; - private bool $enabled; - private array $roles; - public function __construct(?string $username, ?string $password, array $roles = [], bool $enabled = true) - { + public function __construct( + ?string $username, + private ?string $password, + private array $roles = [], + private bool $enabled = true, + ) { if ('' === $username || null === $username) { throw new \InvalidArgumentException('The username cannot be empty.'); } $this->username = $username; - $this->password = $password; - $this->enabled = $enabled; - $this->roles = $roles; } public function __toString(): string @@ -90,8 +88,8 @@ public function isEqualTo(UserInterface $user): bool return false; } - $currentRoles = array_map('strval', (array) $this->getRoles()); - $newRoles = array_map('strval', (array) $user->getRoles()); + $currentRoles = array_map('strval', $this->getRoles()); + $newRoles = array_map('strval', $user->getRoles()); $rolesChanged = \count($currentRoles) !== \count($newRoles) || \count($currentRoles) !== \count(array_intersect($currentRoles, $newRoles)); if ($rolesChanged) { return false; diff --git a/User/InMemoryUserProvider.php b/User/InMemoryUserProvider.php index 04bf682a..db6267a5 100644 --- a/User/InMemoryUserProvider.php +++ b/User/InMemoryUserProvider.php @@ -55,7 +55,7 @@ public function __construct(array $users = []) public function createUser(UserInterface $user): void { if (!$user instanceof InMemoryUser) { - throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_debug_type($user))); + throw new UnsupportedUserException(\sprintf('Instances of "%s" are not supported.', get_debug_type($user))); } $userIdentifier = strtolower($user->getUserIdentifier()); @@ -76,7 +76,7 @@ public function loadUserByIdentifier(string $identifier): UserInterface public function refreshUser(UserInterface $user): UserInterface { if (!$user instanceof InMemoryUser) { - throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_debug_type($user))); + throw new UnsupportedUserException(\sprintf('Instances of "%s" are not supported.', get_debug_type($user))); } $storedUser = $this->getUser($user->getUserIdentifier()); @@ -98,7 +98,7 @@ public function supportsClass(string $class): bool private function getUser(string $username): InMemoryUser { if (!isset($this->users[strtolower($username)])) { - $ex = new UserNotFoundException(sprintf('Username "%s" does not exist.', $username)); + $ex = new UserNotFoundException(\sprintf('Username "%s" does not exist.', $username)); $ex->setUserIdentifier($username); throw $ex; diff --git a/User/MissingUserProvider.php b/User/MissingUserProvider.php index cf6102aa..9869259a 100644 --- a/User/MissingUserProvider.php +++ b/User/MissingUserProvider.php @@ -28,7 +28,7 @@ class MissingUserProvider implements UserProviderInterface */ public function __construct(string $firewall) { - throw new InvalidConfigurationException(sprintf('"%s" firewall requires a user provider but none was defined.', $firewall)); + throw new InvalidConfigurationException(\sprintf('"%s" firewall requires a user provider but none was defined.', $firewall)); } public function loadUserByUsername(string $username): UserInterface diff --git a/User/OidcUser.php b/User/OidcUser.php index 490a3ec2..bcce363f 100644 --- a/User/OidcUser.php +++ b/User/OidcUser.php @@ -45,7 +45,7 @@ public function __construct( private ?\DateTimeInterface $updatedAt = null, // Additional Claims (https://openid.net/specs/openid-connect-core-1_0.html#AdditionalClaims) - ...$additionalClaims + ...$additionalClaims, ) { if (null === $sub || '' === $sub) { throw new \InvalidArgumentException('The "sub" claim cannot be empty.'); diff --git a/User/UserCheckerInterface.php b/User/UserCheckerInterface.php index 480ba7b5..2dc748aa 100644 --- a/User/UserCheckerInterface.php +++ b/User/UserCheckerInterface.php @@ -35,5 +35,5 @@ public function checkPreAuth(UserInterface $user): void; * * @throws AccountStatusException */ - public function checkPostAuth(UserInterface $user): void; + public function checkPostAuth(UserInterface $user /*, TokenInterface $token*/): void; } diff --git a/User/UserInterface.php b/User/UserInterface.php index 50f8fb0f..e6078399 100644 --- a/User/UserInterface.php +++ b/User/UserInterface.php @@ -56,6 +56,8 @@ public function eraseCredentials(): void; /** * Returns the identifier for this user (e.g. username or email address). + * + * @return non-empty-string */ public function getUserIdentifier(): string; } diff --git a/Validator/Constraints/UserPasswordValidator.php b/Validator/Constraints/UserPasswordValidator.php index 3d6c7637..04c7e1ff 100644 --- a/Validator/Constraints/UserPasswordValidator.php +++ b/Validator/Constraints/UserPasswordValidator.php @@ -22,13 +22,10 @@ class UserPasswordValidator extends ConstraintValidator { - private TokenStorageInterface $tokenStorage; - private PasswordHasherFactoryInterface $hasherFactory; - - public function __construct(TokenStorageInterface $tokenStorage, PasswordHasherFactoryInterface $hasherFactory) - { - $this->tokenStorage = $tokenStorage; - $this->hasherFactory = $hasherFactory; + public function __construct( + private TokenStorageInterface $tokenStorage, + private PasswordHasherFactoryInterface $hasherFactory, + ) { } public function validate(mixed $password, Constraint $constraint): void @@ -52,7 +49,7 @@ public function validate(mixed $password, Constraint $constraint): void $user = $this->tokenStorage->getToken()->getUser(); if (!$user instanceof PasswordAuthenticatedUserInterface) { - throw new ConstraintDefinitionException(sprintf('The "%s" class must implement the "%s" interface.', PasswordAuthenticatedUserInterface::class, get_debug_type($user))); + throw new ConstraintDefinitionException(\sprintf('The "%s" class must implement the "%s" interface.', get_debug_type($user), PasswordAuthenticatedUserInterface::class)); } $hasher = $this->hasherFactory->getPasswordHasher($user); diff --git a/composer.json b/composer.json index bb6c4d50..0aaff1e3 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ ], "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/event-dispatcher-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3", "symfony/password-hasher": "^6.4|^7.0" @@ -25,6 +26,7 @@ "psr/container": "^1.1|^2.0", "psr/cache": "^1.0|^2.0|^3.0", "symfony/cache": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", "symfony/event-dispatcher": "^6.4|^7.0", "symfony/expression-language": "^6.4|^7.0", "symfony/http-foundation": "^6.4|^7.0", @@ -35,6 +37,7 @@ "psr/log": "^1|^2|^3" }, "conflict": { + "symfony/dependency-injection": "<6.4", "symfony/event-dispatcher": "<6.4", "symfony/http-foundation": "<6.4", "symfony/ldap": "<6.4",