diff --git a/phpstan-baseline-7.4.neon b/phpstan-baseline-7.4.neon index f7558dc2d..43b377c2e 100644 --- a/phpstan-baseline-7.4.neon +++ b/phpstan-baseline-7.4.neon @@ -54,12 +54,6 @@ parameters: count: 4 path: src/lib/Server/Controller/User.php - - - message: '#^Parameter \#1 \$message of method Psr\\Log\\LoggerInterface\:\:error\(\) expects string, Symfony\\Component\\Security\\Core\\User\\UserInterface\|null given\.$#' - identifier: argument.type - count: 1 - path: src/lib/Server/Security/RestAuthenticator.php - - message: '#^Parameter \#1 \$str of function base64_encode expects string, string\|false given\.$#' identifier: argument.type diff --git a/phpstan-baseline-gte-8.0.neon b/phpstan-baseline-gte-8.0.neon index 5ac4e5089..312247852 100644 --- a/phpstan-baseline-gte-8.0.neon +++ b/phpstan-baseline-gte-8.0.neon @@ -66,11 +66,6 @@ parameters: count: 4 path: src/lib/Server/Controller/User.php - - - message: '#^Parameter \#1 \$message of method Psr\\Log\\LoggerInterface\:\:error\(\) expects string\|Stringable, Symfony\\Component\\Security\\Core\\User\\UserInterface\|null given\.$#' - identifier: argument.type - count: 1 - path: src/lib/Server/Security/RestAuthenticator.php - message: '#^Parameter \#1 \$string of function base64_encode expects string, string\|false given\.$#' diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 5454693ff..abb7cf3ba 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -150,12 +150,6 @@ parameters: count: 1 path: src/bundle/DependencyInjection/Security/RestSessionBasedFactory.php - - - message: '#^Cannot call method isTokenValid\(\) on Symfony\\Component\\Security\\Csrf\\CsrfTokenManagerInterface\|null\.$#' - identifier: method.nonObject - count: 1 - path: src/bundle/EventListener/CsrfListener.php - - message: '#^Method Ibexa\\Bundle\\Rest\\EventListener\\CsrfListener\:\:getSubscribedEvents\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue @@ -2130,24 +2124,6 @@ parameters: count: 1 path: src/lib/Server/Controller/SessionController.php - - - message: '#^Property Ibexa\\Rest\\Server\\Controller\\SessionController\:\:\$csrfTokenManager \(Ibexa\\Rest\\Server\\Security\\CsrfTokenManager\) does not accept Ibexa\\Rest\\Server\\Security\\CsrfTokenManager\|null\.$#' - identifier: assign.propertyType - count: 1 - path: src/lib/Server/Controller/SessionController.php - - - - message: '#^Property Ibexa\\Rest\\Server\\Controller\\SessionController\:\:\$csrfTokenStorage \(Symfony\\Component\\Security\\Csrf\\TokenStorage\\TokenStorageInterface\) does not accept Symfony\\Component\\Security\\Csrf\\TokenStorage\\TokenStorageInterface\|null\.$#' - identifier: assign.propertyType - count: 1 - path: src/lib/Server/Controller/SessionController.php - - - - message: '#^Property Ibexa\\Rest\\Server\\Controller\\SessionController\:\:\$csrfTokenStorage is never read, only written\.$#' - identifier: property.onlyWritten - count: 1 - path: src/lib/Server/Controller/SessionController.php - - message: '#^Method Ibexa\\Rest\\Server\\Controller\\Trash\:\:deleteTrashItem\(\) has parameter \$trashItemId with no type specified\.$#' identifier: missingType.parameter @@ -4392,12 +4368,6 @@ parameters: count: 1 path: src/lib/Server/Security/RestAuthenticator.php - - - message: '#^Ternary operator condition is always true\.$#' - identifier: ternary.alwaysTrue - count: 1 - path: src/lib/Server/Security/RestAuthenticator.php - - message: '#^Method Ibexa\\Rest\\Server\\Security\\RestLogoutHandler\:\:logout\(\) has no return type specified\.$#' identifier: missingType.return @@ -4506,24 +4476,12 @@ parameters: count: 1 path: src/lib/Server/Values/RestContent.php - - - message: '#^Property Ibexa\\Rest\\Server\\Values\\RestContentType\:\:\$fieldDefinitions \(array\\) does not accept array\\|null\.$#' - identifier: assign.propertyType - count: 1 - path: src/lib/Server/Values/RestContentType.php - - message: '#^Property Ibexa\\Rest\\Server\\Values\\RestLocationUpdateStruct\:\:\$hidden \(bool\) does not accept bool\|null\.$#' identifier: assign.propertyType count: 1 path: src/lib/Server/Values/RestLocationUpdateStruct.php - - - message: '#^Property Ibexa\\Rest\\Server\\Values\\RoleAssignment\:\:\$limitation \(Ibexa\\Contracts\\Core\\Repository\\Values\\User\\Limitation\\RoleLimitation\) does not accept Ibexa\\Contracts\\Core\\Repository\\Values\\User\\Limitation\\RoleLimitation\|null\.$#' - identifier: assign.propertyType - count: 1 - path: src/lib/Server/Values/RoleAssignment.php - - message: '#^Access to an undefined property Ibexa\\Rest\\Server\\Values\\SeeOther\:\:\$redirectUri\.$#' identifier: property.notFound diff --git a/src/bundle/EventListener/CsrfListener.php b/src/bundle/EventListener/CsrfListener.php index 93cfa63f7..ad117f2ba 100644 --- a/src/bundle/EventListener/CsrfListener.php +++ b/src/bundle/EventListener/CsrfListener.php @@ -56,7 +56,7 @@ public function __construct( EventDispatcherInterface $eventDispatcher, $csrfEnabled, $csrfTokenIntention, - CsrfTokenManagerInterface $csrfTokenManager = null + ?CsrfTokenManagerInterface $csrfTokenManager = null ) { $this->eventDispatcher = $eventDispatcher; $this->csrfEnabled = $csrfEnabled; @@ -167,6 +167,10 @@ protected function isSessionRoute($route) */ protected function checkCsrfToken(Request $request) { + if ($this->csrfTokenManager === null) { + return false; + } + if (!$request->headers->has(self::CSRF_TOKEN_HEADER)) { return false; } diff --git a/src/contracts/Security/AuthorizationHeaderRESTRequestMatcher.php b/src/contracts/Security/AuthorizationHeaderRESTRequestMatcher.php index df6af354b..29cf83b10 100644 --- a/src/contracts/Security/AuthorizationHeaderRESTRequestMatcher.php +++ b/src/contracts/Security/AuthorizationHeaderRESTRequestMatcher.php @@ -17,13 +17,13 @@ final class AuthorizationHeaderRESTRequestMatcher extends RequestMatcher public function __construct( ?string $headerName = null, - string $path = null, - string $host = null, + ?string $path = null, + ?string $host = null, $methods = null, $ips = null, array $attributes = [], $schemes = null, - int $port = null + ?int $port = null ) { parent::__construct($path, $host, $methods, $ips, $attributes, $schemes, $port); $this->headerName = $headerName; diff --git a/src/lib/Input/Handler/Xml.php b/src/lib/Input/Handler/Xml.php index a30f12b0f..f80400e3c 100644 --- a/src/lib/Input/Handler/Xml.php +++ b/src/lib/Input/Handler/Xml.php @@ -8,6 +8,7 @@ use Ibexa\Contracts\Rest\Exceptions; use Ibexa\Contracts\Rest\Input\Handler; +use InvalidArgumentException; /** * Input format handler base class. @@ -150,6 +151,9 @@ protected function convertDom(\DOMNode $node) ]; $isArray = true; } elseif (!is_string($current[$tagName])) { + if (!is_array($current[$tagName])) { + throw new InvalidArgumentException('Current tag name is not an array as expected.'); + } $current[$tagName][] = $this->convertDom($childNode); } diff --git a/src/lib/Server/Controller/SessionController.php b/src/lib/Server/Controller/SessionController.php index 78adba6b5..7c2d0e13d 100644 --- a/src/lib/Server/Controller/SessionController.php +++ b/src/lib/Server/Controller/SessionController.php @@ -19,42 +19,31 @@ use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Csrf\CsrfToken; -use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface; class SessionController extends Controller { - /** @var \Ibexa\Core\MVC\Symfony\Security\Authentication\AuthenticatorInterface|null */ - private $authenticator; + private ?AuthenticatorInterface $authenticator; - /** @var \Ibexa\Rest\Server\Security\CsrfTokenManager */ - private $csrfTokenManager; + private ?CsrfTokenManager $csrfTokenManager; - /** @var string */ - private $csrfTokenIntention; + private string $csrfTokenIntention; - /** @var \Ibexa\Contracts\Core\Repository\PermissionResolver */ - private $permissionResolver; + private PermissionResolver $permissionResolver; - /** @var \Ibexa\Contracts\Core\Repository\UserService */ - private $userService; - - /** @var \Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface */ - private $csrfTokenStorage; + private UserService $userService; public function __construct( $tokenIntention, PermissionResolver $permissionResolver, UserService $userService, ?AuthenticatorInterface $authenticator = null, - CsrfTokenManager $csrfTokenManager = null, - TokenStorageInterface $csrfTokenStorage = null + ?CsrfTokenManager $csrfTokenManager = null ) { $this->authenticator = $authenticator; $this->csrfTokenIntention = $tokenIntention; $this->csrfTokenManager = $csrfTokenManager; $this->permissionResolver = $permissionResolver; $this->userService = $userService; - $this->csrfTokenStorage = $csrfTokenStorage; } /** diff --git a/src/lib/Server/Security/CsrfTokenManager.php b/src/lib/Server/Security/CsrfTokenManager.php index 8fe54e07d..7cec925e5 100644 --- a/src/lib/Server/Security/CsrfTokenManager.php +++ b/src/lib/Server/Security/CsrfTokenManager.php @@ -25,9 +25,9 @@ class CsrfTokenManager extends BaseCsrfTokenManager private $namespace; public function __construct( - TokenGeneratorInterface $generator = null, - TokenStorageInterface $storage = null, - RequestStack $requestStack = null + ?TokenGeneratorInterface $generator = null, + ?TokenStorageInterface $storage = null, + ?RequestStack $requestStack = null ) { $this->storage = $storage ?: new NativeSessionTokenStorage(); $this->namespace = $this->resolveNamespace($requestStack); @@ -54,7 +54,7 @@ public function hasToken($tokenId) * * @return string */ - private function resolveNamespace(RequestStack $requestStack = null) + private function resolveNamespace(?RequestStack $requestStack = null) { if ($requestStack !== null && ($request = $requestStack->getMainRequest())) { return $request->isSecure() ? 'https-' : ''; diff --git a/src/lib/Server/Security/RestAuthenticator.php b/src/lib/Server/Security/RestAuthenticator.php index 83baed212..e03798eb2 100644 --- a/src/lib/Server/Security/RestAuthenticator.php +++ b/src/lib/Server/Security/RestAuthenticator.php @@ -75,7 +75,7 @@ public function __construct( $providerKey, EventDispatcherInterface $dispatcher, ConfigResolverInterface $configResolver, - LoggerInterface $logger = null + ?LoggerInterface $logger = null ) { $this->tokenStorage = $tokenStorage; $this->authenticationManager = $authenticationManager; @@ -128,7 +128,7 @@ public function authenticate(Request $request) $user = $token->getUser(); if (!$user instanceof IbexaUser) { if ($this->logger) { - $this->logger->error('REST: Authenticated user must be Ibexa\\Core\\MVC\\Symfony\\Security\\User, got ' . is_string($user) ? $user : get_class($user)); + $this->logger->error('REST: Authenticated user must be Ibexa\\Core\\MVC\\Symfony\\Security\\User, got ' . (is_string($user) ? $user : get_class($user))); } $e = new InvalidUserTypeException('Authenticated user is not an Ibexa User.'); @@ -169,7 +169,7 @@ private function attemptAuthentication(Request $request) * * @return bool */ - private function isUserConflict(IbexaUser $user, TokenInterface $previousToken = null) + private function isUserConflict(IbexaUser $user, ?TokenInterface $previousToken = null) { if ($previousToken === null || !$previousToken instanceof UsernamePasswordToken) { return false; diff --git a/src/lib/Server/Values/RestContent.php b/src/lib/Server/Values/RestContent.php index f258d1a0a..6ee258195 100644 --- a/src/lib/Server/Values/RestContent.php +++ b/src/lib/Server/Values/RestContent.php @@ -63,10 +63,10 @@ class RestContent extends RestValue */ public function __construct( ContentInfo $contentInfo, - Location $mainLocation = null, - Content $currentVersion = null, - ContentType $contentType = null, - array $relations = null, + ?Location $mainLocation = null, + ?Content $currentVersion = null, + ?ContentType $contentType = null, + ?array $relations = null, $path = null ) { $this->contentInfo = $contentInfo; diff --git a/src/lib/Server/Values/RestContentType.php b/src/lib/Server/Values/RestContentType.php index 5a101de7f..204008f24 100644 --- a/src/lib/Server/Values/RestContentType.php +++ b/src/lib/Server/Values/RestContentType.php @@ -16,23 +16,15 @@ */ class RestContentType extends RestValue { - /** - * @var \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType - */ - public $contentType; + public ContentType $contentType; - /** - * @var \Ibexa\Contracts\Core\Repository\Values\ContentType\FieldDefinition[] - */ - public $fieldDefinitions; + /** @var \Ibexa\Contracts\Core\Repository\Values\ContentType\FieldDefinition[]|null */ + public ?array $fieldDefinitions; /** - * Construct. - * - * @param \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType $contentType - * @param \Ibexa\Contracts\Core\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions + * @param \Ibexa\Contracts\Core\Repository\Values\ContentType\FieldDefinition[]|null $fieldDefinitions */ - public function __construct(ContentType $contentType, array $fieldDefinitions = null) + public function __construct(ContentType $contentType, ?array $fieldDefinitions = null) { $this->contentType = $contentType; $this->fieldDefinitions = $fieldDefinitions; diff --git a/src/lib/Server/Values/RoleAssignment.php b/src/lib/Server/Values/RoleAssignment.php index 807e441d1..1e52dc7a3 100644 --- a/src/lib/Server/Values/RoleAssignment.php +++ b/src/lib/Server/Values/RoleAssignment.php @@ -21,20 +21,12 @@ class RoleAssignment extends RestValue */ public $roleId; - /** - * Role limitation. - * - * @var \Ibexa\Contracts\Core\Repository\Values\User\Limitation\RoleLimitation - */ - public $limitation; + public ?RoleLimitation $limitation; /** - * Construct. - * * @param mixed $roleId - * @param \Ibexa\Contracts\Core\Repository\Values\User\Limitation\RoleLimitation $limitation */ - public function __construct($roleId, RoleLimitation $limitation = null) + public function __construct($roleId, ?RoleLimitation $limitation = null) { $this->roleId = $roleId; $this->limitation = $limitation;