diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 185a99b2..cc36d784 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -13,7 +13,7 @@ jobs: uses: "nucleos/actions/.github/workflows/continuous-integration.yml@main" with: PHP_EXTENSIONS: "mbstring, json, mongodb" - SYMFONY_VERSIONS: "5.4" + SYMFONY_VERSIONS: "5.4, 6.0" SYMFONY_KERNEL: "Nucleos\\UserAdminBundle\\Tests\\App\\AppKernel" secrets: CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN }}" diff --git a/composer.json b/composer.json index d076e19d..77a88409 100644 --- a/composer.json +++ b/composer.json @@ -39,28 +39,29 @@ "php": "^8.0", "ext-json": "*", "nucleos/user-bundle": "^2.0", + "psr/container": "^1.0 || ^2.0", "psr/log": "^1.0 || ^2.0 || ^3.0", "sonata-project/admin-bundle": "^4.8.1", "sonata-project/doctrine-extensions": "^1.5.1", - "symfony/asset": "^5.4", - "symfony/config": "^5.4", - "symfony/dependency-injection": "^5.4", - "symfony/event-dispatcher": "^5.4", - "symfony/event-dispatcher-contracts": "^1.0 || ^2.0", - "symfony/form": "^5.4", - "symfony/framework-bundle": "^5.4", - "symfony/http-foundation": "^5.4", - "symfony/http-kernel": "^5.4", - "symfony/options-resolver": "^5.4", - "symfony/routing": "^5.4", + "symfony/asset": "^5.4 || ^6.0", + "symfony/config": "^5.4 || ^6.0", + "symfony/dependency-injection": "^5.4 || ^6.0", + "symfony/event-dispatcher": "^5.4 || ^6.0", + "symfony/event-dispatcher-contracts": "^1.0 || ^2.0 || ^3.0", + "symfony/form": "^5.4 || ^6.0", + "symfony/framework-bundle": "^5.4 || ^6.0", + "symfony/http-foundation": "^5.4 || ^6.0", + "symfony/http-kernel": "^5.4 || ^6.0", + "symfony/options-resolver": "^5.4 || ^6.0", + "symfony/routing": "^5.4 || ^6.0", "symfony/security-acl": "^3.0", - "symfony/security-core": "^5.4", - "symfony/security-csrf": "^5.4", - "symfony/security-http": "^5.4", - "symfony/translation": "^5.4", - "symfony/translation-contracts": "^1.0 || ^2.0", - "symfony/twig-bridge": "^5.4", - "symfony/twig-bundle": "^5.4", + "symfony/security-core": "^5.4 || ^6.0", + "symfony/security-csrf": "^5.4 || ^6.0", + "symfony/security-http": "^5.4 || ^6.0", + "symfony/translation": "^5.4 || ^6.0", + "symfony/translation-contracts": "^1.0 || ^2.0 || ^3.0", + "symfony/twig-bridge": "^5.4 || ^6.0", + "symfony/twig-bundle": "^5.4 || ^6.0", "twig/extra-bundle": "^3.0", "twig/twig": "^2.14 || ^3.1" }, @@ -70,10 +71,10 @@ "ergebnis/composer-normalize": "^2.0.1", "knplabs/knp-menu": "^2.3 || ^3.0", "sonata-project/doctrine-orm-admin-bundle": "^4.0", - "symfony/browser-kit": "^5.4", - "symfony/doctrine-bridge": "^5.4", - "symfony/intl": "^5.3", - "symfony/yaml": "^5.4" + "symfony/browser-kit": "^5.4 || ^6.0", + "symfony/doctrine-bridge": "^5.4 || ^6.0", + "symfony/intl": "^5.4 || ^6.0", + "symfony/yaml": "^5.4 || ^6.0" }, "conflict": { "doctrine/doctrine-bundle": "<1.12", @@ -91,6 +92,9 @@ } }, "config": { + "allow-plugins": { + "ergebnis/composer-normalize": true + }, "sort-packages": true } } diff --git a/src/Action/ResetAction.php b/src/Action/ResetAction.php index 0a7800fa..0d63bdd3 100644 --- a/src/Action/ResetAction.php +++ b/src/Action/ResetAction.php @@ -57,7 +57,7 @@ final class ResetAction private TranslatorInterface $translator; - private Session $session; + private ?Session $session = null; private int $resetTtl; @@ -76,7 +76,7 @@ public function __construct( UserManager $userManager, LoginManager $loginManager, TranslatorInterface $translator, - Session $session, + ?object $session, int $resetTtl, string $firewallName ) { @@ -89,7 +89,7 @@ public function __construct( $this->userManager = $userManager; $this->loginManager = $loginManager; $this->translator = $translator; - $this->session = $session; + $this->session = $session instanceof Session ? $session : null; $this->resetTtl = $resetTtl; $this->firewallName = $firewallName; $this->logger = new NullLogger(); @@ -126,7 +126,9 @@ public function __invoke(Request $request, string $token): Response $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $this->session->getFlashBag()->add( + $session = $this->session ?? $request->getSession(); + + $session->getFlashBag()->add( 'success', $this->translator->trans('resetting.flash.success', [], 'NucleosUserBundle') ); diff --git a/src/Resources/config/action.php b/src/Resources/config/action.php index 05fb7dd2..905c0607 100644 --- a/src/Resources/config/action.php +++ b/src/Resources/config/action.php @@ -66,7 +66,7 @@ service('nucleos_user.user_manager'), service('nucleos_user.security.login_manager'), service('translator'), - service('session'), + service('session')->nullOnInvalid(), '%nucleos_user.resetting.retry_ttl%', '%nucleos_user.firewall_name%', ]) diff --git a/tests/Action/LoginActionTest.php b/tests/Action/LoginActionTest.php index a9d3b3b8..450a34b4 100644 --- a/tests/Action/LoginActionTest.php +++ b/tests/Action/LoginActionTest.php @@ -77,7 +77,7 @@ final class LoginActionTest extends TestCase protected $csrfTokenManager; /** - * @var MockObject&FormFactoryInterface + * @var FormFactoryInterface&MockObject */ protected $formFactory; diff --git a/tests/Action/RequestActionTest.php b/tests/Action/RequestActionTest.php index 3763ba5e..74761161 100644 --- a/tests/Action/RequestActionTest.php +++ b/tests/Action/RequestActionTest.php @@ -53,7 +53,7 @@ final class RequestActionTest extends TestCase protected $templateRegistry; /** - * @var MockObject&FormFactoryInterface + * @var FormFactoryInterface&MockObject */ private $formFactory; @@ -97,6 +97,13 @@ public function testUnauthenticated(): void ->method('isGranted') ->willReturn(false) ; + + $this->templateRegistry + ->method('getTemplate') + ->with('layout') + ->willReturn('base.html.twig') + ; + $view = $this->createMock(FormView::class); $form = $this->createMock(FormInterface::class); diff --git a/tests/Action/SendEmailActionTest.php b/tests/Action/SendEmailActionTest.php index b505bc96..3c63ba36 100644 --- a/tests/Action/SendEmailActionTest.php +++ b/tests/Action/SendEmailActionTest.php @@ -24,6 +24,7 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Security\Core\Exception\UserNotFoundException; use Symfony\Component\Security\Core\User\UserProviderInterface; final class SendEmailActionTest extends TestCase @@ -39,7 +40,7 @@ final class SendEmailActionTest extends TestCase protected $userManager; /** - * @var ResettingMailer&MockObject + * @var MockObject&ResettingMailer */ protected $mailer; @@ -68,10 +69,16 @@ protected function setUp(): void $this->userManager = $this->createMock(UserManager::class); $this->mailer = $this->createMock(ResettingMailer::class); $this->tokenGenerator = $this->createMock(TokenGenerator::class); - $this->userProvider = $this->getMockBuilder(UserProviderInterface::class) - ->addMethods(['loadUserByIdentifier']) - ->getMockForAbstractClass() - ; + + if (method_exists(UserProviderInterface::class, 'loadUserByIdentifier')) { + $this->userProvider = $this->getMockBuilder(UserProviderInterface::class) + ->addMethods(['loadUserByIdentifier']) + ->getMockForAbstractClass() + ; + } else { + $this->userProvider = $this->createMock(UserProviderInterface::class); + } + $this->resetTtl = 60; $this->fromEmail = 'noreply@localhost'; $this->container = $this->createMock(ContainerBuilder::class); @@ -84,7 +91,7 @@ public function testUnknownUsername(): void $this->userProvider ->method('loadUserByIdentifier') ->with('bar') - ->willReturn(null) + ->willThrowException(new UserNotFoundException()) ; $this->urlGenerator diff --git a/tests/App/AppKernel.php b/tests/App/AppKernel.php index 8370be9e..d8a4e668 100644 --- a/tests/App/AppKernel.php +++ b/tests/App/AppKernel.php @@ -26,10 +26,9 @@ use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Bundle\SecurityBundle\SecurityBundle; use Symfony\Bundle\TwigBundle\TwigBundle; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Symfony\Component\HttpKernel\Kernel; -use Symfony\Component\Routing\RouteCollectionBuilder; +use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; use Twig\Extra\TwigExtraBundle\TwigExtraBundle; final class AppKernel extends Kernel @@ -73,17 +72,31 @@ public function getProjectDir(): string return __DIR__; } - protected function configureRoutes(RouteCollectionBuilder $routes): void + protected function configureRoutes(RoutingConfigurator $routes): void { - $routes->import('@SonataAdminBundle/Resources/config/routing/sonata_admin.xml', '/admin'); - $routes->import('.', '/admin', 'sonata_admin'); - $routes->import(__DIR__.'/../../src/Resources/config/routing/admin_security.php'); - $routes->import(__DIR__.'/../../src/Resources/config/routing/admin_resetting.php'); + $routes->import('@SonataAdminBundle/Resources/config/routing/sonata_admin.xml') + ->prefix('/admin') + ; + $routes->import('.', 'sonata_admin') + ->prefix('/admin') + ; + $routes->import('@NucleosUserBundle/Resources/config/routing/security.php'); + $routes->import('@NucleosUserBundle/Resources/config/routing/change_password.php'); + $routes->import('@NucleosUserBundle/Resources/config/routing/resetting.php') + ->prefix('/resetting') + ; + + $routes->import('@NucleosUserAdminBundle/Resources/config/routing/admin_security.php') + ->prefix('/admin') + ; + $routes->import('@NucleosUserAdminBundle/Resources/config/routing/admin_resetting.php') + ->prefix('/admin/resetting') + ; } - protected function configureContainer(ContainerBuilder $containerBuilder, LoaderInterface $loader): void + protected function configureContainer(ContainerConfigurator $container): void { - $loader->load(__DIR__.'/config/config.php'); + $container->import(__DIR__.'/config/config.php'); } private function getBaseDir(): string diff --git a/tests/Security/RolesBuilder/AdminRolesBuilderTest.php b/tests/Security/RolesBuilder/AdminRolesBuilderTest.php index d8f25eb1..d2bdc206 100644 --- a/tests/Security/RolesBuilder/AdminRolesBuilderTest.php +++ b/tests/Security/RolesBuilder/AdminRolesBuilderTest.php @@ -34,12 +34,12 @@ final class AdminRolesBuilderTest extends TestCase private $securityHandler; /** - * @var MockObject&AuthorizationCheckerInterface + * @var AuthorizationCheckerInterface&MockObject */ private $authorizationChecker; /** - * @var MockObject&AdminInterface + * @var AdminInterface&MockObject */ private $admin; @@ -89,7 +89,7 @@ protected function setUp(): void public function testGetPermissionLabels(): void { $this->translator->method('trans') - ->willReturn(static::returnArgument(0)) + ->willReturnArgument(0) ; $this->securityHandler->method('getBaseRole') @@ -139,7 +139,7 @@ public function testGetPermissionLabels(): void public function testGetRoles(): void { $this->translator->method('trans') - ->willReturn(static::returnArgument(0)) + ->willReturnArgument(0) ; $this->securityHandler->method('getBaseRole') diff --git a/tests/Security/RolesBuilder/SecurityRolesBuilderTest.php b/tests/Security/RolesBuilder/SecurityRolesBuilderTest.php index fe4189fc..17a18d27 100644 --- a/tests/Security/RolesBuilder/SecurityRolesBuilderTest.php +++ b/tests/Security/RolesBuilder/SecurityRolesBuilderTest.php @@ -24,12 +24,12 @@ final class SecurityRolesBuilderTest extends TestCase { /** - * @var MockObject&AuthorizationCheckerInterface + * @var AuthorizationCheckerInterface&MockObject */ private $authorizationChecker; /** - * @var MockObject&AdminInterface + * @var AdminInterface&MockObject */ private $admin; diff --git a/tests/Twig/RolesMatrixRuntimeTest.php b/tests/Twig/RolesMatrixRuntimeTest.php index 2f9c830f..444bc00f 100644 --- a/tests/Twig/RolesMatrixRuntimeTest.php +++ b/tests/Twig/RolesMatrixRuntimeTest.php @@ -13,6 +13,7 @@ namespace Nucleos\UserAdminBundle\Tests\Twig; +use ArrayIterator; use Nucleos\UserAdminBundle\Security\RolesBuilder\MatrixRolesBuilderInterface; use Nucleos\UserAdminBundle\Twig\RolesMatrixRuntime; use PHPUnit\Framework\MockObject\MockObject; @@ -28,12 +29,12 @@ final class RolesMatrixRuntimeTest extends TestCase private $rolesBuilder; /** - * @var MockObject&Environment + * @var Environment&MockObject */ private $environment; /** - * @var MockObject&FormView + * @var FormView&MockObject */ private $formView; @@ -96,7 +97,7 @@ public function testRenderRolesList(): void $this->formView ->method('getIterator') - ->willReturn([$form]) + ->willReturn(new ArrayIterator([$form])) ; $this->environment @@ -139,7 +140,7 @@ public function testRenderRolesListWithoutFormValue(): void $this->formView ->method('getIterator') - ->willReturn([$form]) + ->willReturn(new ArrayIterator([$form])) ; $this->environment @@ -240,7 +241,7 @@ public function testRenderMatrix(): void $this->formView ->expects(static::once()) ->method('getIterator') - ->willReturn([$form]) + ->willReturn(new ArrayIterator([$form])) ; $this->environment @@ -297,7 +298,7 @@ public function testRenderMatrixFormVarsNotSet(): void $this->formView ->expects(static::once()) ->method('getIterator') - ->willReturn([$form]) + ->willReturn(new ArrayIterator([$form])) ; $this->environment