Skip to content

Commit

Permalink
feature #59 Add support for Symfony 5.4 & 6 (chalasr)
Browse files Browse the repository at this point in the history
This PR was merged into the 0.1-dev branch.

Discussion
----------

Add support for Symfony 5.4 & 6

Commits
-------

7d27687 Add support for Symfony 5.4 & 6
  • Loading branch information
chalasr committed Nov 6, 2021
2 parents c8c657e + 7d27687 commit 2711479
Show file tree
Hide file tree
Showing 20 changed files with 284 additions and 119 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ jobs:
tools: composer:v2, cs2pr
extensions: intl, bcmath, curl, openssl, mbstring, pdo, pdo_sqlite

- name: "installing psalm"
run: "composer require vimeo/psalm:^4.6 psalm/plugin-symfony:^2.2 --dev --no-update && composer require --no-update"

- name: "installing dependencies"
run: "composer update --no-interaction --no-progress"

Expand Down
104 changes: 53 additions & 51 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,63 +3,65 @@ name: "unit tests"
on: [ "pull_request", "push" ]

jobs:
unit-tests:
name: "unit tests"

runs-on: "ubuntu-latest"

tests:
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.can-fail }}
strategy:
fail-fast: false
matrix:
symfony-version:
- "5.3.*"
php-version:
- "7.2"
- "7.3"
- "7.4"
- "8.0"
dependencies:
- "lowest"
- "highest"
include:
# Lowest supported stable Symfony branches
- php: 7.2
symfony: 5.3.*
composer-flags: '--prefer-stable'
can-fail: false
# Development Symfony branches
- php: 7.3
symfony: 5.4.*@dev
composer-flags: '--prefer-stable' # Needed to force `lcobucci/jwt` to install a usable version
can-fail: false
- php: 7.4
symfony: 5.4.*@dev
composer-flags: ''
can-fail: false
- php: 8.0
symfony: 5.4.*@dev
composer-flags: ''
can-fail: false
- php: 8.1
symfony: 6.0.*@dev
composer-flags: ''
can-fail: false

steps:
- name: "checkout"
uses: "actions/checkout@v2"
name: "PHP ${{ matrix.php }} - Symfony ${{ matrix.symfony }}${{ matrix.composer-flags != '' && format(' - Composer {0}', matrix.composer-flags) || '' }}"

- name: "installing PHP"
uses: "shivammathur/setup-php@v2"
with:
php-version: "${{ matrix.php-version }}"
tools: composer:v2, cs2pr
extensions: intl, bcmath, curl, openssl, mbstring, pdo, pdo_sqlite
coverage: pcov
ini-values: memory_limit=-1

- name: "caching dependencies"
uses: "actions/cache@v2"
with:
path: |
~/.composer/cache
vendor
key: "php-${{ matrix.php-version }}"
restore-keys: "php-${{ matrix.php-version }}"
steps:
- name: "Checkout"
uses: "actions/checkout@v2"
with:
fetch-depth: 2

- name: "configuring composer platform"
if: (startsWith(matrix.php, '8.0'))
run: composer config platform.php 7.4.99
- name: "Cache Composer packages"
uses: "actions/cache@v2"
with:
path: "~/.composer/cache"
key: "php-${{ matrix.php }}-symfony-${{ matrix.symfony }}-composer-${{ hashFiles('composer.json') }}-flags-${{ matrix.composer-flags }}"
restore-keys: "php-"

- name: "install lowest dependencies"
if: ${{ matrix.dependencies == 'lowest' }}
run: composer update --prefer-lowest --no-interaction --no-progress --prefer-dist
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
php-version: "${{ matrix.php }}"
tools: "composer:v2,flex"

- name: "install highest dependencies"
if: ${{ matrix.dependencies == 'highest' }}
run: |
composer require --no-update symfony/config=${{ matrix.symfony-version }} symfony/http-kernel=${{ matrix.symfony-version }} symfony/dependency-injection=${{ matrix.symfony-version }} symfony/options-resolver=${{ matrix.symfony-version }}
composer require --no-update --dev symfony/framework-bundle=${{ matrix.symfony-version }} symfony/yaml=${{ matrix.symfony-version }}
composer update --no-interaction --no-progress --prefer-dist
- name: "Set Composer stability"
if: "matrix.symfony == '5.4.*@dev' || matrix.symfony == '6.0.*@dev'"
run: "composer config minimum-stability dev"

- name: "installing phpunit"
run: vendor/bin/simple-phpunit install
- name: "Install dependencies"
run: "composer update ${{ matrix.composer-flags }} --prefer-dist"
env:
SYMFONY_REQUIRE: "${{ matrix.symfony }}"

- name: "running unit tests"
run: vendor/bin/simple-phpunit
- name: "Run PHPUnit Tests"
run: "vendor/bin/simple-phpunit"
14 changes: 7 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@
"league/oauth2-server": "^8.0",
"nyholm/psr7": "^1.4",
"psr/http-factory": "^1.0",
"symfony/framework-bundle": "^5.3",
"symfony/framework-bundle": "^5.3|^6.0",
"symfony/polyfill-php81": "^1.22",
"symfony/psr-http-message-bridge": "^2.0",
"symfony/security-bundle": "^5.3"
"symfony/security-bundle": "^5.3|^6.0"
},
"require-dev": {
"ext-pdo": "*",
"ext-pdo_sqlite": "*",
"psalm/plugin-symfony": "^2.2",
"symfony/browser-kit": "^5.3",
"symfony/phpunit-bridge": "^5.3",
"vimeo/psalm": "^4.6"
"symfony/browser-kit": "^5.3|^6.0",
"symfony/phpunit-bridge": "^5.3|^6.0"
},
"autoload": {
"psr-4": { "League\\Bundle\\OAuth2ServerBundle\\": "src/" }
Expand All @@ -47,5 +46,6 @@
"branch-alias": {
"dev-master": "0.1-dev"
}
}
},
"minimum-stability": "dev"
}
1 change: 0 additions & 1 deletion psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
forbidEcho="true"
strictBinaryOperands="true"
phpVersion="7.1"
allowPhpStormGenerics="true"
allowStringToStandInForClass="true"
rememberPropertyAssignmentsAfterCall="false"
checkForThrowsInGlobalScope="true"
Expand Down
2 changes: 1 addition & 1 deletion src/DependencyInjection/LeagueOAuth2ServerExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function load(array $configs, ContainerBuilder $container)
/**
* {@inheritdoc}
*/
public function getAlias()
public function getAlias(): string
{
return 'league_oauth2_server';
}
Expand Down
61 changes: 26 additions & 35 deletions src/DependencyInjection/Security/OAuth2Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,38 @@

namespace League\Bundle\OAuth2ServerBundle\DependencyInjection\Security;

use League\Bundle\OAuth2ServerBundle\Security\Authenticator\OAuth2Authenticator;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AuthenticatorFactoryInterface;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

/**
* @author Mathias Arlaud <[email protected]>
*/
final class OAuth2Factory implements SecurityFactoryInterface, AuthenticatorFactoryInterface
{
public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint): array
{
throw new \LogicException('OAuth2 is not supported when "security.enable_authenticator_manager" is not set to true.');
}

public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string
{
$authenticator = sprintf('security.authenticator.oauth2.%s', $firewallName);

$definition = new ChildDefinition(OAuth2Authenticator::class);
$definition->replaceArgument(2, new Reference($userProviderId));

$container->setDefinition($authenticator, $definition);

return $authenticator;
}

public function getPosition(): string
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;

if (interface_exists(SecurityFactoryInterface::class) && !interface_exists(AuthenticatorFactoryInterface::class)) {
/**
* Wires the "oauth" authenticator from user configuration.
*
* @author Mathias Arlaud <[email protected]>
*/
class OAuth2Factory implements SecurityFactoryInterface
{
return 'pre_auth';
use OAuth2FactoryTrait;
}

public function getKey(): string
} elseif (!method_exists(SecurityExtension::class, 'addAuthenticatorFactory')) {
/**
* Wires the "oauth" authenticator from user configuration.
*
* @author Mathias Arlaud <[email protected]>
*/
class OAuth2Factory implements AuthenticatorFactoryInterface, SecurityFactoryInterface
{
return 'oauth2';
use OAuth2FactoryTrait;
}

public function addConfiguration(NodeDefinition $builder): void
} else {
/**
* Wires the "oauth" authenticator from user configuration.
*
* @author Mathias Arlaud <[email protected]>
*/
class OAuth2Factory implements AuthenticatorFactoryInterface
{
use OAuth2FactoryTrait;
}
}
54 changes: 54 additions & 0 deletions src/DependencyInjection/Security/OAuth2FactoryTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace League\Bundle\OAuth2ServerBundle\DependencyInjection\Security;

use League\Bundle\OAuth2ServerBundle\Security\Authenticator\OAuth2Authenticator;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

/**
* @author Mathias Arlaud <[email protected]>
* @author Robin Chalas <[email protected]>
*/
trait OAuth2FactoryTrait
{
public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint): array
{
throw new \LogicException('OAuth2 is not supported when "security.enable_authenticator_manager" is not set to true.');
}

public function createAuthenticator(ContainerBuilder $container, string $firewallName, array $config, string $userProviderId): string
{
$authenticator = sprintf('security.authenticator.oauth2.%s', $firewallName);

$definition = new ChildDefinition(OAuth2Authenticator::class);
$definition->replaceArgument(2, new Reference($userProviderId));

$container->setDefinition($authenticator, $definition);

return $authenticator;
}

public function getPosition(): string
{
return 'pre_auth';
}

public function getPriority(): int
{
return -10;
}

public function getKey(): string
{
return 'oauth2';
}

public function addConfiguration(NodeDefinition $builder): void
{
}
}
3 changes: 3 additions & 0 deletions src/Entity/Scope.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ final class Scope implements ScopeEntityInterface

/**
* {@inheritdoc}
*
* @return mixed
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return $this->getIdentifier();
Expand Down
14 changes: 13 additions & 1 deletion src/LeagueOAuth2ServerBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use League\Bundle\OAuth2ServerBundle\DependencyInjection\Security\OAuth2Factory;
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\HttpKernel\Bundle\Bundle;

final class LeagueOAuth2ServerBundle extends Bundle
Expand All @@ -30,7 +31,7 @@ public function build(ContainerBuilder $container)
/**
* {@inheritdoc}
*/
public function getContainerExtension()
public function getContainerExtension(): ExtensionInterface
{
return new LeagueOAuth2ServerExtension();
}
Expand All @@ -39,6 +40,17 @@ private function configureSecurityExtension(ContainerBuilder $container): void
{
/** @var SecurityExtension $extension */
$extension = $container->getExtension('security');

if (method_exists($extension, 'addAuthenticatorFactory')) {
$extension->addAuthenticatorFactory(new OAuth2Factory());

return;
}

/**
* @psalm-suppress DeprecatedMethod
* @psalm-suppress InvalidArgument
*/
$extension->addSecurityListenerFactory(new OAuth2Factory());
}

Expand Down
41 changes: 41 additions & 0 deletions src/Security/Authenticator/ForwardCompatAuthenticatorTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace League\Bundle\OAuth2ServerBundle\Security\Authenticator;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;

/** @var \ReflectionNamedType|null $r */
$r = (new \ReflectionMethod(AuthenticatorInterface::class, 'authenticate'))->getReturnType();

if ($r && Passport::class === $r->getName()) {
/**
* @internal
*
* @psalm-suppress UnrecognizedStatement
*/
trait ForwardCompatAuthenticatorTrait
{
public function authenticate(Request $request): Passport
{
return $this->doAuthenticate($request);
}
}
} else {
/**
* @internal
*
* @psalm-suppress UnrecognizedStatement
*/
trait ForwardCompatAuthenticatorTrait
{
public function authenticate(Request $request): PassportInterface
{
return $this->doAuthenticate($request);
}
}
}
Loading

0 comments on commit 2711479

Please sign in to comment.