Skip to content

symfony 6 (requires SF 5.3+) #119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 18, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 11 additions & 15 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,21 @@ env:
matrix:
fast_finish: true
include:
# Test the latest stable release
- php: 7.2
env: PHPSTAN=true COMPOSER1=true
- php: 7.4
env: COVERAGE=true PHPUNIT_FLAGS="-v --coverage-text" TESTNOSECURITYBUNDLE=true
# Test latest stable features
- php: 8.1
env: PHPSTAN=true COVERAGE=true PHPUNIT_FLAGS="-v --coverage-text"

# Test LTS versions.
- php: 7.4
env: DEPENDENCIES="symfony/lts:^4"
- php: 8.0

# Latest commit to master
# Test the oldest possible release - SF 5.4, PHP 7.4, without security-bundle
- php: 7.4
env: STABILITY="dev"
env: PHPSTAN=true COMPOSER1=true TESTNOSECURITYBUNDLE=true COMPOSER_FLAGS="--prefer-stable --prefer-lowest"

allow_failures:
# Minimum supported dependencies with the latest and oldest PHP version
- php: 7.4
- php: 8.1
env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" SYMFONY_DEPRECATIONS_HELPER="weak_vendors"
- php: 7.2
- php: 7.4
env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" SYMFONY_DEPRECATIONS_HELPER="weak_vendors"
# Dev-master is allowed to fail.
- env: STABILITY="dev"
Expand All @@ -52,11 +48,11 @@ script:
- composer validate --strict --no-check-lock
# simple-phpunit is the PHPUnit wrapper provided by the PHPUnit Bridge component and
# it helps with testing legacy code and deprecations (composer require symfony/phpunit-bridge)
#- ./vendor/bin/simple-phpunit $PHPUNIT_FLAGS
- ./vendor/bin/simple-phpunit $PHPUNIT_FLAGS
- if [[ $PHPSTAN == true ]]; then composer phpstan; fi
- ./vendor/bin/phpunit --coverage-clover build/logs/clover.xml
#- ./vendor/bin/phpunit --coverage-clover build/logs/clover.xml
# Let's test without the security bundle
- if [[ $TESTNOSECURITYBUNDLE == true ]]; then composer remove --dev symfony/security-bundle && phpunit Tests/NoSecurityBundleTest.php; fi
- if [[ $TESTNOSECURITYBUNDLE == true ]]; then composer remove --dev symfony/security-bundle && ./vendor/bin/simple-phpunit Tests/NoSecurityBundleTest.php; fi

after_script:
- ./vendor/bin/php-coveralls -v
19 changes: 13 additions & 6 deletions Controller/GraphQL/LoginController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
namespace TheCodingMachine\GraphQLite\Bundle\Controller\GraphQL;


use RuntimeException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
Expand All @@ -22,7 +25,7 @@ class LoginController
*/
private $userProvider;
/**
* @var UserPasswordEncoderInterface
* @var UserPasswordHasherInterface
*/
private $passwordEncoder;
/**
Expand All @@ -42,7 +45,7 @@ class LoginController
*/
private $eventDispatcher;

public function __construct(UserProviderInterface $userProvider, UserPasswordEncoderInterface $passwordEncoder, TokenStorageInterface $tokenStorage, SessionInterface $session, EventDispatcherInterface $eventDispatcher, string $firewallName)
public function __construct(UserProviderInterface $userProvider, UserPasswordHasherInterface $passwordEncoder, TokenStorageInterface $tokenStorage, SessionInterface $session, EventDispatcherInterface $eventDispatcher, string $firewallName)
{
$this->userProvider = $userProvider;
$this->passwordEncoder = $passwordEncoder;
Expand All @@ -58,12 +61,16 @@ public function __construct(UserProviderInterface $userProvider, UserPasswordEnc
public function login(string $userName, string $password, Request $request): UserInterface
{
try {
$user = $this->userProvider->loadUserByUsername($userName);
} catch (UsernameNotFoundException $e) {
$user = $this->userProvider->loadUserByIdentifier($userName);
} catch (UserNotFoundException $e) {
// FIXME: should we return null instead???
throw InvalidUserPasswordException::create($e);
}

if (!$user instanceof PasswordAuthenticatedUserInterface) {
throw new RuntimeException('$user has to implements ' . PasswordAuthenticatedUserInterface::class);
}

if (!$this->passwordEncoder->isPasswordValid($user, $password)) {
throw InvalidUserPasswordException::create();
}
Expand All @@ -72,7 +79,7 @@ public function login(string $userName, string $password, Request $request): Use

// Handle getting or creating the user entity likely with a posted form
// The third parameter "main" can change according to the name of your firewall in security.yml
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$token = new UsernamePasswordToken($user, 'main', $user->getRoles());
$this->tokenStorage->setToken($token);

// If the firewall name is not main, then the set value would be instead:
Expand Down
6 changes: 3 additions & 3 deletions DependencyInjection/GraphQLiteCompilerPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Symfony\Component\Cache\Adapter\ApcuAdapter;
use Symfony\Component\Cache\Adapter\PhpFilesAdapter;
use Symfony\Component\Cache\Psr16Cache;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use TheCodingMachine\GraphQLite\Mappers\StaticClassListTypeMapperFactory;
use Webmozart\Assert\Assert;
use function class_exists;
Expand All @@ -33,7 +34,6 @@
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use TheCodingMachine\CacheUtils\ClassBoundCache;
use TheCodingMachine\CacheUtils\ClassBoundCacheContract;
Expand Down Expand Up @@ -104,7 +104,7 @@ public function process(ContainerBuilder $container): void
$disableLogin = false;
if ($container->getParameter('graphqlite.security.enable_login') === 'auto'
&& (!$container->has($firewallConfigServiceName) ||
!$container->has(UserPasswordEncoderInterface::class) ||
!$container->has(UserPasswordHasherInterface::class) ||
!$container->has(TokenStorageInterface::class) ||
!$container->has(SessionInterface::class)
)) {
Expand All @@ -122,7 +122,7 @@ public function process(ContainerBuilder $container): void
if (!$container->has(SessionInterface::class)) {
throw new GraphQLException('In order to enable the login/logout mutations (via the graphqlite.security.enable_login parameter), you need to enable session support (via the "framework.session.enabled" config parameter).');
}
if (!$container->has(UserPasswordEncoderInterface::class) || !$container->has(TokenStorageInterface::class) || !$container->has($firewallConfigServiceName)) {
if (!$container->has(UserPasswordHasherInterface::class) || !$container->has(TokenStorageInterface::class) || !$container->has($firewallConfigServiceName)) {
throw new GraphQLException('In order to enable the login/logout mutations (via the graphqlite.security.enable_login parameter), you need to install the security bundle. Please be sure to correctly configure the user provider (in the security.providers configuration settings)');
}
}
Expand Down
2 changes: 1 addition & 1 deletion DependencyInjection/GraphQLiteExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
class GraphQLiteExtension extends Extension
{

public function getAlias()
public function getAlias(): string
{
return 'graphqlite';
}
Expand Down
3 changes: 2 additions & 1 deletion GraphQLiteBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace TheCodingMachine\GraphQLite\Bundle;

use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use TheCodingMachine\GraphQLite\Bundle\DependencyInjection\GraphQLiteExtension;
use TheCodingMachine\GraphQLite\Bundle\DependencyInjection\OverblogGraphiQLEndpointWiringPass;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
Expand All @@ -20,7 +21,7 @@ public function build(ContainerBuilder $container): void
$container->addCompilerPass(new OverblogGraphiQLEndpointWiringPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -1);
}

public function getContainerExtension()
public function getContainerExtension(): ?ExtensionInterface
{
if (null === $this->extension) {
$this->extension = new GraphQLiteExtension();
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@

# GraphQLite bundle

Symfony 4 bundle for the thecodingmachine/graphqlite package.
Symfony 5 bundle for the thecodingmachine/graphqlite package.

See [thecodingmachine/graphqlite](https://github.com/thecodingmachine/graphqlite)
8 changes: 4 additions & 4 deletions Tests/FunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

namespace TheCodingMachine\GraphQLite\Bundle\Tests;

use Symfony\Component\Security\Core\User\InMemoryUser;
use function json_decode;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\User\User;
use TheCodingMachine\GraphQLite\Bundle\Controller\GraphQLiteController;
use TheCodingMachine\GraphQLite\GraphQLRuntimeException as GraphQLException;
use TheCodingMachine\GraphQLite\Schema;
Expand Down Expand Up @@ -545,9 +545,9 @@ public function testMaxQueryDepth(): void
private function logIn(ContainerInterface $container)
{
// put a token into the storage so the final calls can function
$user = new User('foo', 'pass');
$token = new UsernamePasswordToken($user, '', 'provider', ['ROLE_USER']);
$container->get('security.token_storage')->setToken($token);
$user = new InMemoryUser('foo', 'pass');
$token = new UsernamePasswordToken($user, 'provider', ['ROLE_USER']);
$container->get('security.untracked_token_storage')->setToken($token);
}

/**
Expand Down
25 changes: 16 additions & 9 deletions Tests/GraphQLiteTestingKernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Bundle\SecurityBundle\SecurityBundle;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler;
use Symfony\Component\HttpKernel\Kernel;
use TheCodingMachine\GraphQLite\Bundle\GraphQLiteBundle;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\User\InMemoryUser;
use function class_exists;
use function serialize;

class GraphQLiteTestingKernel extends Kernel
class GraphQLiteTestingKernel extends Kernel implements CompilerPassInterface
{
use MicroKernelTrait;

Expand Down Expand Up @@ -84,7 +84,7 @@ public function __construct(bool $enableSession = true,
$this->typesNamespace = $typesNamespace;
}

public function registerBundles()
public function registerBundles(): iterable
{
$bundles = [ new FrameworkBundle() ];
if (class_exists(SecurityBundle::class)) {
Expand Down Expand Up @@ -112,13 +112,14 @@ public function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
if ($this->enableSession) {
$frameworkConf['session'] =[
'enabled' => true,
'handler_id' => NullSessionHandler::class
'storage_factory_id' => 'session.storage.factory.mock_file',
];
}

$container->loadFromExtension('framework', $frameworkConf);
if ($this->enableSecurity) {
$container->loadFromExtension('security', array(
'enable_authenticator_manager' => true,
'providers' => [
'in_memory' => [
'memory' => [
Expand All @@ -143,12 +144,11 @@ public function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
],
'firewalls' => [
'main' => [
'anonymous' => true,
'provider' => 'in_memory'
]
],
'encoders' => [
User::class => 'plaintext',
'password_hashers' => [
InMemoryUser::class => 'plaintext',
],
));
}
Expand Down Expand Up @@ -196,8 +196,15 @@ protected function configureRoutes(/*RoutingConfigurator*/ $routes)
$routes->import(__DIR__.'/../Resources/config/routes.xml');
}

public function getCacheDir()
public function getCacheDir(): string
{
return __DIR__.'/../cache/'.($this->enableSession?'withSession':'withoutSession').$this->enableLogin.($this->enableSecurity?'withSecurity':'withoutSecurity').$this->enableMe.'_'.($this->introspection?'withIntrospection':'withoutIntrospection').'_'.$this->maximumQueryComplexity.'_'.$this->maximumQueryDepth.'_'.md5(serialize($this->controllersNamespace).'_'.md5(serialize($this->typesNamespace)));
}

public function process(ContainerBuilder $container): void
{
if ($container->hasDefinition('security.untracked_token_storage')) {
$container->getDefinition('security.untracked_token_storage')->setPublic(true);
}
}
}
16 changes: 8 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,28 @@
}
],
"require" : {
"php" : ">=7.2",
"php" : ">=7.4",
"ext-json": "*",
"thecodingmachine/graphqlite" : "^5.0",
"thecodingmachine/graphqlite-symfony-validator-bridge" : "^5.0",
"symfony/framework-bundle": "^4.2 || ^5",
"symfony/validator": "^4.2 || ^5",
"symfony/translation": "^4.2 || ^5",
"symfony/framework-bundle": "^5.4 || ^6",
"symfony/validator": "^5.4 || ^6",
"symfony/translation": "^5.4 || ^6",
"doctrine/annotations": "^1.13",
"symfony/psr-http-message-bridge": "^2.0",
"nyholm/psr7": "^1.1",
"laminas/laminas-diactoros": "^2.2.2",
"overblog/graphiql-bundle": "^0.1.2 | ^0.2",
"thecodingmachine/cache-utils": "^1",
"symfony/console": "^4.1.9 | ^5"
"symfony/console": "^5.4 || ^6"
},
"require-dev": {
"symfony/security-bundle": "^4.2 || ^5",
"symfony/yaml": "^4.2 || ^5",
"symfony/security-bundle": "^5.4 || ^6",
"symfony/yaml": "^5.4 || ^6",
"phpstan/phpstan": "^0.12.90",
"beberlei/porpaginas": "^1.2",
"php-coveralls/php-coveralls": "^2.1.0",
"symfony/phpunit-bridge": "^5.3",
"symfony/phpunit-bridge": "^5.4 || ^6",
"thecodingmachine/phpstan-strict-rules": "^v0.12.1",
"composer/package-versions-deprecated": "^1.8",
"phpstan/phpstan-webmozart-assert": "^0.12.12"
Expand Down